Merge branch 'master' into macharena

This commit is contained in:
Colin Davidson
2024-09-24 02:32:06 -07:00
597 changed files with 17453 additions and 6717 deletions
+33 -3
View File
@@ -144,6 +144,9 @@ buffer_grow :: proc(b: ^Buffer, n: int, loc := #caller_location) {
}
buffer_write_at :: proc(b: ^Buffer, p: []byte, offset: int, loc := #caller_location) -> (n: int, err: io.Error) {
if len(p) == 0 {
return 0, nil
}
b.last_read = .Invalid
if offset < 0 {
err = .Invalid_Offset
@@ -246,10 +249,13 @@ buffer_read_ptr :: proc(b: ^Buffer, ptr: rawptr, size: int) -> (n: int, err: io.
}
buffer_read_at :: proc(b: ^Buffer, p: []byte, offset: int) -> (n: int, err: io.Error) {
if len(p) == 0 {
return 0, nil
}
b.last_read = .Invalid
if uint(offset) >= len(b.buf) {
err = .Invalid_Offset
err = .EOF
return
}
n = copy(p, b.buf[offset:])
@@ -310,6 +316,27 @@ buffer_unread_rune :: proc(b: ^Buffer) -> io.Error {
return nil
}
buffer_seek :: proc(b: ^Buffer, offset: i64, whence: io.Seek_From) -> (i64, io.Error) {
abs: i64
switch whence {
case .Start:
abs = offset
case .Current:
abs = i64(b.off) + offset
case .End:
abs = i64(len(b.buf)) + offset
case:
return 0, .Invalid_Whence
}
abs_int := int(abs)
if abs_int < 0 {
return 0, .Invalid_Offset
}
b.last_read = .Invalid
b.off = abs_int
return abs, nil
}
buffer_read_bytes :: proc(b: ^Buffer, delim: byte) -> (line: []byte, err: io.Error) {
i := index_byte(b.buf[b.off:], delim)
@@ -395,14 +422,17 @@ _buffer_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, offse
return io._i64_err(buffer_write(b, p))
case .Write_At:
return io._i64_err(buffer_write_at(b, p, int(offset)))
case .Seek:
n, err = buffer_seek(b, offset, whence)
return
case .Size:
n = i64(buffer_capacity(b))
n = i64(buffer_length(b))
return
case .Destroy:
buffer_destroy(b)
return
case .Query:
return io.query_utility({.Read, .Read_At, .Write, .Write_At, .Size, .Destroy})
return io.query_utility({.Read, .Read_At, .Write, .Write_At, .Seek, .Size, .Destroy, .Query})
}
return 0, .Empty
}
+5 -7
View File
@@ -334,7 +334,7 @@ Inputs:
Returns:
- index: The index of the byte `c`, or -1 if it was not found.
*/
index_byte :: proc(s: []byte, c: byte) -> (index: int) #no_bounds_check {
index_byte :: proc "contextless" (s: []byte, c: byte) -> (index: int) #no_bounds_check {
i, l := 0, len(s)
// Guard against small strings. On modern systems, it is ALWAYS
@@ -469,18 +469,16 @@ Inputs:
Returns:
- index: The index of the byte `c`, or -1 if it was not found.
*/
last_index_byte :: proc(s: []byte, c: byte) -> int #no_bounds_check {
last_index_byte :: proc "contextless" (s: []byte, c: byte) -> int #no_bounds_check {
i := len(s)
// Guard against small strings. On modern systems, it is ALWAYS
// worth vectorizing assuming there is a hardware vector unit, and
// the data size is large enough.
if i < SIMD_REG_SIZE_128 {
if i > 0 { // Handle s == nil.
for /**/; i >= 0; i -= 1 {
if s[i] == c {
return i
}
#reverse for ch, j in s {
if ch == c {
return j
}
}
return -1
+9 -2
View File
@@ -9,10 +9,11 @@ Reader :: struct {
prev_rune: int, // previous reading index of rune or < 0
}
reader_init :: proc(r: ^Reader, s: []byte) {
reader_init :: proc(r: ^Reader, s: []byte) -> io.Stream {
r.s = s
r.i = 0
r.prev_rune = -1
return reader_to_stream(r)
}
reader_to_stream :: proc(r: ^Reader) -> (s: io.Stream) {
@@ -33,6 +34,9 @@ reader_size :: proc(r: ^Reader) -> i64 {
}
reader_read :: proc(r: ^Reader, p: []byte) -> (n: int, err: io.Error) {
if len(p) == 0 {
return 0, nil
}
if r.i >= i64(len(r.s)) {
return 0, .EOF
}
@@ -42,6 +46,9 @@ reader_read :: proc(r: ^Reader, p: []byte) -> (n: int, err: io.Error) {
return
}
reader_read_at :: proc(r: ^Reader, p: []byte, off: i64) -> (n: int, err: io.Error) {
if len(p) == 0 {
return 0, nil
}
if off < 0 {
return 0, .Invalid_Offset
}
@@ -97,7 +104,6 @@ reader_unread_rune :: proc(r: ^Reader) -> io.Error {
return nil
}
reader_seek :: proc(r: ^Reader, offset: i64, whence: io.Seek_From) -> (i64, io.Error) {
r.prev_rune = -1
abs: i64
switch whence {
case .Start:
@@ -114,6 +120,7 @@ reader_seek :: proc(r: ^Reader, offset: i64, whence: io.Seek_From) -> (i64, io.E
return 0, .Invalid_Offset
}
r.i = abs
r.prev_rune = -1
return abs, nil
}
reader_write_to :: proc(r: ^Reader, w: io.Writer) -> (n: i64, err: io.Error) {
+8
View File
@@ -98,6 +98,14 @@ when ODIN_OS == .Haiku {
ERANGE :: B_POSIX_ERROR_BASE + 17
}
when ODIN_OS == .JS {
_ :: libc
_get_errno :: proc "c" () -> ^int {
@(static) errno: int
return &errno
}
}
// Odin has no way to make an identifier "errno" behave as a function call to
// read the value, or to produce an lvalue such that you can assign a different
// error value to errno. To work around this, just expose it as a function like
+25 -1
View File
@@ -89,6 +89,30 @@ when ODIN_OS == .Linux {
}
}
when ODIN_OS == .JS {
fpos_t :: struct #raw_union { _: [16]char, _: longlong, _: double, }
_IOFBF :: 0
_IOLBF :: 1
_IONBF :: 2
BUFSIZ :: 1024
EOF :: int(-1)
FOPEN_MAX :: 1000
FILENAME_MAX :: 4096
L_tmpnam :: 20
SEEK_SET :: 0
SEEK_CUR :: 1
SEEK_END :: 2
TMP_MAX :: 308915776
}
when ODIN_OS == .OpenBSD || ODIN_OS == .NetBSD {
fpos_t :: distinct i64
@@ -368,7 +392,7 @@ to_stream :: proc(file: ^FILE) -> io.Stream {
return 0, .Empty
case .Query:
return io.query_utility({ .Close, .Flush, .Read, .Read_At, .Write, .Write_At, .Seek, .Size })
return io.query_utility({ .Close, .Flush, .Read, .Read_At, .Write, .Write_At, .Seek, .Size, .Query })
}
return
}
+10
View File
@@ -10,6 +10,9 @@ when ODIN_OS == .Windows {
foreign import libc "system:c"
}
@(require)
import "base:runtime"
when ODIN_OS == .Windows {
RAND_MAX :: 0x7fff
@@ -145,6 +148,10 @@ aligned_alloc :: #force_inline proc "c" (alignment, size: size_t) -> rawptr {
_aligned_malloc :: proc(size, alignment: size_t) -> rawptr ---
}
return _aligned_malloc(size=size, alignment=alignment)
} else when ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32 {
context = runtime.default_context()
data, _ := runtime.mem_alloc_bytes(auto_cast size, auto_cast alignment)
return raw_data(data)
} else {
foreign libc {
aligned_alloc :: proc(alignment, size: size_t) -> rawptr ---
@@ -160,6 +167,9 @@ aligned_free :: #force_inline proc "c" (ptr: rawptr) {
_aligned_free :: proc(ptr: rawptr) ---
}
_aligned_free(ptr)
} else when ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32 {
context = runtime.default_context()
runtime.mem_free(ptr)
} else {
free(ptr)
}
+1
View File
@@ -12,6 +12,7 @@ when ODIN_OS == .Windows {
foreign import libc "system:c"
}
@(default_calling_convention="c")
foreign libc {
// 7.24.2 Copying functions
memcpy :: proc(s1, s2: rawptr, n: size_t) -> rawptr ---
+2 -2
View File
@@ -45,7 +45,7 @@ when ODIN_OS == .Windows {
}
}
when ODIN_OS == .Linux || ODIN_OS == .FreeBSD || ODIN_OS == .Darwin || ODIN_OS == .OpenBSD || ODIN_OS == .NetBSD || ODIN_OS == .Haiku {
when ODIN_OS == .Linux || ODIN_OS == .FreeBSD || ODIN_OS == .Darwin || ODIN_OS == .OpenBSD || ODIN_OS == .NetBSD || ODIN_OS == .Haiku || ODIN_OS == .JS {
@(default_calling_convention="c")
foreign libc {
// 7.27.2 Time manipulation functions
@@ -79,7 +79,7 @@ when ODIN_OS == .Linux || ODIN_OS == .FreeBSD || ODIN_OS == .Darwin || ODIN_OS =
} else {
@(private) LDIFFTIME :: "difftime"
@(private) LMKTIME :: "mktime"
@(private) LTIME :: "ltime"
@(private) LTIME :: "time"
@(private) LCTIME :: "ctime"
@(private) LGMTIME :: "gmtime"
@(private) LLOCALTIME :: "localtime"
+1 -1
View File
@@ -14,7 +14,7 @@ when ODIN_OS == .Windows {
wctrans_t :: distinct wchar_t
wctype_t :: distinct ushort
} else when ODIN_OS == .Linux {
} else when ODIN_OS == .Linux || ODIN_OS == .JS {
wctrans_t :: distinct intptr_t
wctype_t :: distinct ulong
+90
View File
@@ -0,0 +1,90 @@
/*
Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
Made available under Odin's BSD-3 license.
List of contributors:
Jeroen van Rijn: Initial implementation.
Ginger Bill: Cosmetic changes.
A small GZIP implementation as an example.
*/
/*
Example:
import "core:bytes"
import "core:os"
import "core:compress"
import "core:fmt"
// Small GZIP file with fextra, fname and fcomment present.
@private
TEST: []u8 = {
0x1f, 0x8b, 0x08, 0x1c, 0xcb, 0x3b, 0x3a, 0x5a,
0x02, 0x03, 0x07, 0x00, 0x61, 0x62, 0x03, 0x00,
0x63, 0x64, 0x65, 0x66, 0x69, 0x6c, 0x65, 0x6e,
0x61, 0x6d, 0x65, 0x00, 0x54, 0x68, 0x69, 0x73,
0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x63, 0x6f,
0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0x2b, 0x48,
0xac, 0xcc, 0xc9, 0x4f, 0x4c, 0x01, 0x00, 0x15,
0x6a, 0x2c, 0x42, 0x07, 0x00, 0x00, 0x00,
}
main :: proc() {
// Set up output buffer.
buf := bytes.Buffer{}
stdout :: proc(s: string) {
os.write_string(os.stdout, s)
}
stderr :: proc(s: string) {
os.write_string(os.stderr, s)
}
args := os.args
if len(args) < 2 {
stderr("No input file specified.\n")
err := load(data=TEST, buf=&buf, known_gzip_size=len(TEST))
if err == nil {
stdout("Displaying test vector: ")
stdout(bytes.buffer_to_string(&buf))
stdout("\n")
} else {
fmt.printf("gzip.load returned %v\n", err)
}
bytes.buffer_destroy(&buf)
os.exit(0)
}
// The rest are all files.
args = args[1:]
err: Error
for file in args {
if file == "-" {
// Read from stdin
s := os.stream_from_handle(os.stdin)
ctx := &compress.Context_Stream_Input{
input = s,
}
err = load(ctx, &buf)
} else {
err = load(file, &buf)
}
if err != nil {
if err != E_General.File_Not_Found {
stderr("File not found: ")
stderr(file)
stderr("\n")
os.exit(1)
}
stderr("GZIP returned an error.\n")
bytes.buffer_destroy(&buf)
os.exit(2)
}
stdout(bytes.buffer_to_string(&buf))
}
bytes.buffer_destroy(&buf)
}
*/
package compress_gzip
-89
View File
@@ -1,89 +0,0 @@
//+build ignore
package compress_gzip
/*
Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
Made available under Odin's BSD-3 license.
List of contributors:
Jeroen van Rijn: Initial implementation.
Ginger Bill: Cosmetic changes.
A small GZIP implementation as an example.
*/
import "core:bytes"
import "core:os"
import "core:compress"
import "core:fmt"
// Small GZIP file with fextra, fname and fcomment present.
@private
TEST: []u8 = {
0x1f, 0x8b, 0x08, 0x1c, 0xcb, 0x3b, 0x3a, 0x5a,
0x02, 0x03, 0x07, 0x00, 0x61, 0x62, 0x03, 0x00,
0x63, 0x64, 0x65, 0x66, 0x69, 0x6c, 0x65, 0x6e,
0x61, 0x6d, 0x65, 0x00, 0x54, 0x68, 0x69, 0x73,
0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x63, 0x6f,
0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0x2b, 0x48,
0xac, 0xcc, 0xc9, 0x4f, 0x4c, 0x01, 0x00, 0x15,
0x6a, 0x2c, 0x42, 0x07, 0x00, 0x00, 0x00,
}
main :: proc() {
// Set up output buffer.
buf := bytes.Buffer{}
stdout :: proc(s: string) {
os.write_string(os.stdout, s)
}
stderr :: proc(s: string) {
os.write_string(os.stderr, s)
}
args := os.args
if len(args) < 2 {
stderr("No input file specified.\n")
err := load(data=TEST, buf=&buf, known_gzip_size=len(TEST))
if err == nil {
stdout("Displaying test vector: ")
stdout(bytes.buffer_to_string(&buf))
stdout("\n")
} else {
fmt.printf("gzip.load returned %v\n", err)
}
bytes.buffer_destroy(&buf)
os.exit(0)
}
// The rest are all files.
args = args[1:]
err: Error
for file in args {
if file == "-" {
// Read from stdin
s := os.stream_from_handle(os.stdin)
ctx := &compress.Context_Stream_Input{
input = s,
}
err = load(ctx, &buf)
} else {
err = load(file, &buf)
}
if err != nil {
if err != E_General.File_Not_Found {
stderr("File not found: ")
stderr(file)
stderr("\n")
os.exit(1)
}
stderr("GZIP returned an error.\n")
bytes.buffer_destroy(&buf)
os.exit(2)
}
stdout(bytes.buffer_to_string(&buf))
}
bytes.buffer_destroy(&buf)
}
+1 -2
View File
@@ -4,7 +4,6 @@
which is an English word model.
*/
// package shoco is an implementation of the shoco short string compressor
package compress_shoco
DEFAULT_MODEL :: Shoco_Model {
@@ -145,4 +144,4 @@ DEFAULT_MODEL :: Shoco_Model {
{ 0xc0000000, 2, 4, { 25, 22, 19, 16, 16, 16, 16, 16 }, { 15, 7, 7, 7, 0, 0, 0, 0 }, 0xe0, 0xc0 },
{ 0xe0000000, 4, 8, { 23, 19, 15, 11, 8, 5, 2, 0 }, { 31, 15, 15, 15, 7, 7, 7, 3 }, 0xf0, 0xe0 },
},
}
}
+2 -2
View File
@@ -8,7 +8,7 @@
An implementation of [shoco](https://github.com/Ed-von-Schleck/shoco) by Christian Schramm.
*/
// package shoco is an implementation of the shoco short string compressor
// package shoco is an implementation of the shoco short string compressor.
package compress_shoco
import "base:intrinsics"
@@ -308,4 +308,4 @@ compress_string :: proc(input: string, model := DEFAULT_MODEL, allocator := cont
resize(&buf, length) or_return
return buf[:length], result
}
compress :: proc{compress_string_to_buffer, compress_string}
compress :: proc{compress_string_to_buffer, compress_string}
+50
View File
@@ -0,0 +1,50 @@
/*
Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
Made available under Odin's BSD-3 license.
List of contributors:
Jeroen van Rijn: Initial implementation.
An example of how to use `zlib.inflate`.
*/
/*
Example:
package main
import "core:bytes"
import "core:fmt"
main :: proc() {
ODIN_DEMO := []u8{
120, 218, 101, 144, 65, 110, 131, 48, 16, 69, 215, 246, 41, 190, 44, 69, 73, 32, 148, 182,
75, 75, 28, 32, 251, 46, 217, 88, 238, 0, 86, 192, 32, 219, 36, 170, 170, 172, 122, 137,
238, 122, 197, 30, 161, 70, 162, 20, 81, 203, 139, 25, 191, 255, 191, 60, 51, 40, 125, 81,
53, 33, 144, 15, 156, 155, 110, 232, 93, 128, 208, 189, 35, 89, 117, 65, 112, 222, 41, 99,
33, 37, 6, 215, 235, 195, 17, 239, 156, 197, 170, 118, 170, 131, 44, 32, 82, 164, 72, 240,
253, 245, 249, 129, 12, 185, 224, 76, 105, 61, 118, 99, 171, 66, 239, 38, 193, 35, 103, 85,
172, 66, 127, 33, 139, 24, 244, 235, 141, 49, 204, 223, 76, 208, 205, 204, 166, 7, 173, 60,
97, 159, 238, 37, 214, 41, 105, 129, 167, 5, 102, 27, 152, 173, 97, 178, 129, 73, 129, 231,
5, 230, 27, 152, 175, 225, 52, 192, 127, 243, 170, 157, 149, 18, 121, 142, 115, 109, 227, 122,
64, 87, 114, 111, 161, 49, 182, 6, 181, 158, 162, 226, 206, 167, 27, 215, 246, 48, 56, 99,
67, 117, 16, 47, 13, 45, 35, 151, 98, 231, 75, 1, 173, 90, 61, 101, 146, 71, 136, 244,
170, 218, 145, 176, 123, 45, 173, 56, 113, 134, 191, 51, 219, 78, 235, 95, 28, 249, 253, 7,
159, 150, 133, 125,
}
OUTPUT_SIZE :: 432
buf: bytes.Buffer
// We can pass ", true" to inflate a raw DEFLATE stream instead of a ZLIB wrapped one.
err := inflate(input=ODIN_DEMO, buf=&buf, expected_output_size=OUTPUT_SIZE)
defer bytes.buffer_destroy(&buf)
if err != nil {
fmt.printf("\nError: %v\n", err)
}
s := bytes.buffer_to_string(&buf)
fmt.printf("Input: %v bytes, output (%v bytes):\n%v\n", len(ODIN_DEMO), len(s), s)
assert(len(s) == OUTPUT_SIZE)
}
*/
package compress_zlib
-47
View File
@@ -1,47 +0,0 @@
//+build ignore
package compress_zlib
/*
Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
Made available under Odin's BSD-3 license.
List of contributors:
Jeroen van Rijn: Initial implementation.
An example of how to use `zlib.inflate`.
*/
import "core:bytes"
import "core:fmt"
main :: proc() {
ODIN_DEMO := []u8{
120, 218, 101, 144, 65, 110, 131, 48, 16, 69, 215, 246, 41, 190, 44, 69, 73, 32, 148, 182,
75, 75, 28, 32, 251, 46, 217, 88, 238, 0, 86, 192, 32, 219, 36, 170, 170, 172, 122, 137,
238, 122, 197, 30, 161, 70, 162, 20, 81, 203, 139, 25, 191, 255, 191, 60, 51, 40, 125, 81,
53, 33, 144, 15, 156, 155, 110, 232, 93, 128, 208, 189, 35, 89, 117, 65, 112, 222, 41, 99,
33, 37, 6, 215, 235, 195, 17, 239, 156, 197, 170, 118, 170, 131, 44, 32, 82, 164, 72, 240,
253, 245, 249, 129, 12, 185, 224, 76, 105, 61, 118, 99, 171, 66, 239, 38, 193, 35, 103, 85,
172, 66, 127, 33, 139, 24, 244, 235, 141, 49, 204, 223, 76, 208, 205, 204, 166, 7, 173, 60,
97, 159, 238, 37, 214, 41, 105, 129, 167, 5, 102, 27, 152, 173, 97, 178, 129, 73, 129, 231,
5, 230, 27, 152, 175, 225, 52, 192, 127, 243, 170, 157, 149, 18, 121, 142, 115, 109, 227, 122,
64, 87, 114, 111, 161, 49, 182, 6, 181, 158, 162, 226, 206, 167, 27, 215, 246, 48, 56, 99,
67, 117, 16, 47, 13, 45, 35, 151, 98, 231, 75, 1, 173, 90, 61, 101, 146, 71, 136, 244,
170, 218, 145, 176, 123, 45, 173, 56, 113, 134, 191, 51, 219, 78, 235, 95, 28, 249, 253, 7,
159, 150, 133, 125,
}
OUTPUT_SIZE :: 432
buf: bytes.Buffer
// We can pass ", true" to inflate a raw DEFLATE stream instead of a ZLIB wrapped one.
err := inflate(input=ODIN_DEMO, buf=&buf, expected_output_size=OUTPUT_SIZE)
defer bytes.buffer_destroy(&buf)
if err != nil {
fmt.printf("\nError: %v\n", err)
}
s := bytes.buffer_to_string(&buf)
fmt.printf("Input: %v bytes, output (%v bytes):\n%v\n", len(ODIN_DEMO), len(s), s)
assert(len(s) == OUTPUT_SIZE)
}
+1 -1
View File
@@ -1,4 +1,4 @@
//+vet !using-param
#+vet !using-param
package compress_zlib
/*
+60 -14
View File
@@ -1,5 +1,6 @@
package container_dynamic_bit_array
import "base:builtin"
import "base:intrinsics"
import "core:mem"
@@ -18,7 +19,7 @@ NUM_BITS :: 64
Bit_Array :: struct {
bits: [dynamic]u64,
bias: int,
max_index: int,
length: int,
free_pointer: bool,
}
@@ -52,9 +53,9 @@ Returns:
*/
iterate_by_all :: proc (it: ^Bit_Array_Iterator) -> (set: bool, index: int, ok: bool) {
index = it.word_idx * NUM_BITS + int(it.bit_idx) + it.array.bias
if index > it.array.max_index { return false, 0, false }
if index >= it.array.length + it.array.bias { return false, 0, false }
word := it.array.bits[it.word_idx] if len(it.array.bits) > it.word_idx else 0
word := it.array.bits[it.word_idx] if builtin.len(it.array.bits) > it.word_idx else 0
set = (word >> it.bit_idx & 1) == 1
it.bit_idx += 1
@@ -106,22 +107,22 @@ Returns:
*/
@(private="file")
iterate_internal_ :: proc (it: ^Bit_Array_Iterator, $ITERATE_SET_BITS: bool) -> (index: int, ok: bool) {
word := it.array.bits[it.word_idx] if len(it.array.bits) > it.word_idx else 0
word := it.array.bits[it.word_idx] if builtin.len(it.array.bits) > it.word_idx else 0
when ! ITERATE_SET_BITS { word = ~word }
// If the word is empty or we have already gone over all the bits in it,
// b.bit_idx is greater than the index of any set bit in the word,
// meaning that word >> b.bit_idx == 0.
for it.word_idx < len(it.array.bits) && word >> it.bit_idx == 0 {
for it.word_idx < builtin.len(it.array.bits) && word >> it.bit_idx == 0 {
it.word_idx += 1
it.bit_idx = 0
word = it.array.bits[it.word_idx] if len(it.array.bits) > it.word_idx else 0
word = it.array.bits[it.word_idx] if builtin.len(it.array.bits) > it.word_idx else 0
when ! ITERATE_SET_BITS { word = ~word }
}
// If we are iterating the set bits, reaching the end of the array means we have no more bits to check
when ITERATE_SET_BITS {
if it.word_idx >= len(it.array.bits) {
if it.word_idx >= builtin.len(it.array.bits) {
return 0, false
}
}
@@ -135,7 +136,7 @@ iterate_internal_ :: proc (it: ^Bit_Array_Iterator, $ITERATE_SET_BITS: bool) ->
it.bit_idx = 0
it.word_idx += 1
}
return index, index <= it.array.max_index
return index, index < it.array.length + it.array.bias
}
/*
Gets the state of a bit in the bit-array
@@ -160,7 +161,7 @@ get :: proc(ba: ^Bit_Array, #any_int index: uint) -> (res: bool, ok: bool) #opti
If we `get` a bit that doesn't fit in the Bit Array, it's naturally `false`.
This early-out prevents unnecessary resizing.
*/
if leg_index + 1 > len(ba.bits) { return false, true }
if leg_index + 1 > builtin.len(ba.bits) { return false, true }
val := u64(1 << uint(bit_index))
res = ba.bits[leg_index] & val == val
@@ -208,7 +209,7 @@ set :: proc(ba: ^Bit_Array, #any_int index: uint, set_to: bool = true, allocator
resize_if_needed(ba, leg_index) or_return
ba.max_index = max(idx, ba.max_index)
ba.length = max(1 + idx, ba.length)
if set_to {
ba.bits[leg_index] |= 1 << uint(bit_index)
@@ -261,6 +262,9 @@ unsafe_unset :: proc(b: ^Bit_Array, bit: int) #no_bounds_check {
/*
A helper function to create a Bit Array with optional bias, in case your smallest index is non-zero (including negative).
The range of bits created by this procedure is `min_index..<max_index`, and the
array will be able to expand beyond `max_index` if needed.
*Allocates (`new(Bit_Array) & make(ba.bits)`)*
Inputs:
@@ -275,7 +279,7 @@ create :: proc(max_index: int, min_index: int = 0, allocator := context.allocato
context.allocator = allocator
size_in_bits := max_index - min_index
if size_in_bits < 1 { return {}, false }
if size_in_bits < 0 { return {}, false }
legs := size_in_bits >> INDEX_SHIFT
if size_in_bits & INDEX_MASK > 0 {legs+=1}
@@ -284,7 +288,7 @@ create :: proc(max_index: int, min_index: int = 0, allocator := context.allocato
res = new(Bit_Array)
res.bits = bits
res.bias = min_index
res.max_index = max_index
res.length = max_index - min_index
res.free_pointer = true
return
}
@@ -299,6 +303,48 @@ clear :: proc(ba: ^Bit_Array) {
mem.zero_slice(ba.bits[:])
}
/*
Gets the length of set and unset valid bits in the Bit_Array.
Inputs:
- ba: The target Bit_Array
Returns:
- length: The length of valid bits.
*/
len :: proc(ba: ^Bit_Array) -> (length: int) {
if ba == nil { return }
return ba.length
}
/*
Shrinks the Bit_Array's backing storage to the smallest possible size.
Inputs:
- ba: The target Bit_Array
*/
shrink :: proc(ba: ^Bit_Array) #no_bounds_check {
if ba == nil { return }
legs_needed := builtin.len(ba.bits)
for i := legs_needed - 1; i >= 0; i -= 1 {
if ba.bits[i] == 0 {
legs_needed -= 1
} else {
break
}
}
if legs_needed == builtin.len(ba.bits) {
return
}
ba.length = 0
if legs_needed > 0 {
if legs_needed > 1 {
ba.length = (legs_needed - 1) * NUM_BITS
}
ba.length += NUM_BITS - int(intrinsics.count_leading_zeros(ba.bits[legs_needed - 1]))
}
resize(&ba.bits, legs_needed)
builtin.shrink(&ba.bits)
}
/*
Deallocates the Bit_Array and its backing storage
Inputs:
@@ -321,8 +367,8 @@ resize_if_needed :: proc(ba: ^Bit_Array, legs: int, allocator := context.allocat
context.allocator = allocator
if legs + 1 > len(ba.bits) {
if legs + 1 > builtin.len(ba.bits) {
resize(&ba.bits, legs + 1)
}
return len(ba.bits) > legs
return builtin.len(ba.bits) > legs
}
+4 -4
View File
@@ -1,8 +1,8 @@
/*
The Bit Array can be used in several ways:
- By default you don't need to instantiate a Bit Array:
By default you don't need to instantiate a Bit Array.
Example:
package test
import "core:fmt"
@@ -22,8 +22,8 @@ The Bit Array can be used in several ways:
destroy(&bits)
}
- A Bit Array can optionally allow for negative indices, if the minimum value was given during creation:
A Bit Array can optionally allow for negative indices, if the minimum value was given during creation.
Example:
package test
import "core:fmt"
+9 -6
View File
@@ -1,22 +1,22 @@
/*
Package list implements an intrusive doubly-linked list.
An intrusive container requires a `Node` to be embedded in your own structure, like this:
An intrusive container requires a `Node` to be embedded in your own structure, like this.
Example:
My_String :: struct {
node: list.Node,
value: string,
}
Embedding the members of a `list.Node` in your structure with the `using` keyword is also allowed:
Embedding the members of a `list.Node` in your structure with the `using` keyword is also allowed.
Example:
My_String :: struct {
using node: list.Node,
value: string,
}
Here is a full example:
Here is a full example.
Example:
package test
import "core:fmt"
@@ -42,5 +42,8 @@ Here is a full example:
value: string,
}
Output:
Hello
World
*/
package container_intrusive_list
+7 -3
View File
@@ -139,9 +139,13 @@ clear :: proc "contextless" (a: ^$A/Small_Array($N, $T)) {
resize(a, 0)
}
push_back_elems :: proc "contextless" (a: ^$A/Small_Array($N, $T), items: ..T) {
n := copy(a.data[a.len:], items[:])
a.len += n
push_back_elems :: proc "contextless" (a: ^$A/Small_Array($N, $T), items: ..T) -> bool {
if a.len + builtin.len(items) <= cap(a^) {
n := copy(a.data[a.len:], items[:])
a.len += n
return true
}
return false
}
inject_at :: proc "contextless" (a: ^$A/Small_Array($N, $T), item: T, index: int) -> bool #no_bounds_check {
+1 -1
View File
@@ -1,4 +1,4 @@
//+build amd64
#+build amd64
package aes_hw_intel
import "core:sys/info"
+1 -1
View File
@@ -20,7 +20,7 @@
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//+build amd64
#+build amd64
package aes_hw_intel
import "base:intrinsics"
@@ -20,7 +20,7 @@
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//+build amd64
#+build amd64
package aes_hw_intel
import "base:intrinsics"
@@ -1,4 +1,4 @@
//+build amd64
#+build amd64
package chacha20_simd256
import "base:intrinsics"
@@ -1,4 +1,4 @@
//+build !amd64
#+build !amd64
package chacha20_simd256
import "base:intrinsics"
+35 -36
View File
@@ -10,49 +10,48 @@ algorithm.
WARNING: Reusing the same key + iv to seal (encrypt) multiple messages
results in catastrophic loss of security for most algorithms.
```odin
package aead_example
Example:
package aead_example
import "core:bytes"
import "core:crypto"
import "core:crypto/aead"
import "core:bytes"
import "core:crypto"
import "core:crypto/aead"
main :: proc() {
algo := aead.Algorithm.XCHACHA20POLY1305
main :: proc() {
algo := aead.Algorithm.XCHACHA20POLY1305
// The example added associated data, and plaintext.
aad_str := "Get your ass in gear boys."
pt_str := "They're immanetizing the Eschaton."
// The example added associated data, and plaintext.
aad_str := "Get your ass in gear boys."
pt_str := "They're immanetizing the Eschaton."
aad := transmute([]byte)aad_str
plaintext := transmute([]byte)pt_str
pt_len := len(plaintext)
aad := transmute([]byte)aad_str
plaintext := transmute([]byte)pt_str
pt_len := len(plaintext)
// Generate a random key for the purposes of illustration.
key := make([]byte, aead.KEY_SIZES[algo])
defer delete(key)
crypto.rand_bytes(key)
// Generate a random key for the purposes of illustration.
key := make([]byte, aead.KEY_SIZES[algo])
defer delete(key)
crypto.rand_bytes(key)
// `ciphertext || tag`, is a common way data is transmitted, so
// demonstrate that.
buf := make([]byte, pt_len + aead.TAG_SIZES[algo])
defer delete(buf)
ciphertext, tag := buf[:pt_len], buf[pt_len:]
// `ciphertext || tag`, is a common way data is transmitted, so
// demonstrate that.
buf := make([]byte, pt_len + aead.TAG_SIZES[algo])
defer delete(buf)
ciphertext, tag := buf[:pt_len], buf[pt_len:]
// Seal the AAD + Plaintext.
iv := make([]byte, aead.IV_SIZES[algo])
defer delete(iv)
crypto.rand_bytes(iv) // Random IVs are safe with XChaCha20-Poly1305.
aead.seal(algo, ciphertext, tag, key, iv, aad, plaintext)
// Seal the AAD + Plaintext.
iv := make([]byte, aead.IV_SIZES[algo])
defer delete(iv)
crypto.rand_bytes(iv) // Random IVs are safe with XChaCha20-Poly1305.
aead.seal(algo, ciphertext, tag, key, iv, aad, plaintext)
// Open the AAD + Ciphertext.
opened_pt := buf[:pt_len]
if ok := aead.open(algo, opened_pt, key, iv, aad, ciphertext, tag); !ok {
panic("aead example: failed to open")
// Open the AAD + Ciphertext.
opened_pt := buf[:pt_len]
if ok := aead.open(algo, opened_pt, key, iv, aad, ciphertext, tag); !ok {
panic("aead example: failed to open")
}
assert(bytes.equal(opened_pt, plaintext))
}
assert(bytes.equal(opened_pt, plaintext))
}
```
*/
package aead
package aead
+3 -3
View File
@@ -2,9 +2,9 @@
package aes implements the AES block cipher and some common modes.
See:
- https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.197-upd1.pdf
- https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38a.pdf
- https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf
- [[ https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.197-upd1.pdf ]]
- [[ https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38a.pdf ]]
- [[ https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf ]]
*/
package aes
+1 -1
View File
@@ -1,4 +1,4 @@
//+build amd64
#+build amd64
package aes
import "base:intrinsics"
+1 -1
View File
@@ -1,4 +1,4 @@
//+build amd64
#+build amd64
package aes
import "base:intrinsics"
+1 -1
View File
@@ -1,4 +1,4 @@
//+build amd64
#+build amd64
package aes
import "base:intrinsics"
+1 -1
View File
@@ -1,4 +1,4 @@
//+build !amd64
#+build !amd64
package aes
@(private = "file")
+1 -1
View File
@@ -1,4 +1,4 @@
//+build amd64
#+build amd64
package aes
import "core:crypto/_aes/hw_intel"
+2 -2
View File
@@ -2,8 +2,8 @@
package blake2b implements the BLAKE2b hash algorithm.
See:
- https://datatracker.ietf.org/doc/html/rfc7693
- https://www.blake2.net
- [[ https://datatracker.ietf.org/doc/html/rfc7693 ]]
- [[ https://www.blake2.net ]]
*/
package blake2b
+2 -2
View File
@@ -2,8 +2,8 @@
package blake2s implements the BLAKE2s hash algorithm.
See:
- https://datatracker.ietf.org/doc/html/rfc7693
- https://www.blake2.net/
- [[ https://datatracker.ietf.org/doc/html/rfc7693 ]]
- [[ https://www.blake2.net/ ]]
*/
package blake2s
+2 -2
View File
@@ -2,8 +2,8 @@
package chacha20 implements the ChaCha20 and XChaCha20 stream ciphers.
See:
- https://datatracker.ietf.org/doc/html/rfc8439
- https://datatracker.ietf.org/doc/draft-irtf-cfrg-xchacha/03/
- [[ https://datatracker.ietf.org/doc/html/rfc8439 ]]
- [[ https://datatracker.ietf.org/doc/draft-irtf-cfrg-xchacha/03/ ]]
*/
package chacha20
@@ -4,8 +4,8 @@ AEAD_XChaCha20_Poly1305 Authenticated Encryption with Additional Data
algorithms.
See:
- https://www.rfc-editor.org/rfc/rfc8439
- https://datatracker.ietf.org/doc/html/draft-arciszewski-xchacha-03
- [[ https://www.rfc-editor.org/rfc/rfc8439 ]]
- [[ https://datatracker.ietf.org/doc/html/draft-arciszewski-xchacha-03 ]]
*/
package chacha20poly1305
+3 -3
View File
@@ -2,9 +2,9 @@
package ed25519 implements the Ed25519 EdDSA signature algorithm.
See:
- https://datatracker.ietf.org/doc/html/rfc8032
- https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-5.pdf
- https://eprint.iacr.org/2020/1244.pdf
- [[ https://datatracker.ietf.org/doc/html/rfc8032 ]]
- [[ https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-5.pdf ]]
- [[ https://eprint.iacr.org/2020/1244.pdf ]]
*/
package ed25519
+28 -30
View File
@@ -17,46 +17,44 @@ accomplish common tasks.
A third optional boolean parameter controls if the file is streamed
(default), or or read at once.
```odin
package hash_example
Example:
package hash_example
import "core:crypto/hash"
import "core:crypto/hash"
main :: proc() {
input := "Feed the fire."
main :: proc() {
input := "Feed the fire."
// Compute the digest, using the high level API.
returned_digest := hash.hash(hash.Algorithm.SHA512_256, input)
defer delete(returned_digest)
// Compute the digest, using the high level API.
returned_digest := hash.hash(hash.Algorithm.SHA512_256, input)
defer delete(returned_digest)
// Variant that takes a destination buffer, instead of returning
// the digest.
digest := make([]byte, hash.DIGEST_SIZES[hash.Algorithm.BLAKE2B]) // @note: Destination buffer has to be at least as big as the digest size of the hash.
defer delete(digest)
hash.hash(hash.Algorithm.BLAKE2B, input, digest)
}
```
// Variant that takes a destination buffer, instead of returning
// the digest.
digest := make([]byte, hash.DIGEST_SIZES[hash.Algorithm.BLAKE2B]) // @note: Destination buffer has to be at least as big as the digest size of the hash.
defer delete(digest)
hash.hash(hash.Algorithm.BLAKE2B, input, digest)
}
A generic low level API is provided supporting the init/update/final interface
that is typical with cryptographic hash function implementations.
```odin
package hash_example
Example:
package hash_example
import "core:crypto/hash"
import "core:crypto/hash"
main :: proc() {
input := "Let the cinders burn."
main :: proc() {
input := "Let the cinders burn."
// Compute the digest, using the low level API.
ctx: hash.Context
digest := make([]byte, hash.DIGEST_SIZES[hash.Algorithm.SHA3_512])
defer delete(digest)
// Compute the digest, using the low level API.
ctx: hash.Context
digest := make([]byte, hash.DIGEST_SIZES[hash.Algorithm.SHA3_512])
defer delete(digest)
hash.init(&ctx, hash.Algorithm.SHA3_512)
hash.update(&ctx, transmute([]byte)input)
hash.final(&ctx, digest)
}
```
hash.init(&ctx, hash.Algorithm.SHA3_512)
hash.update(&ctx, transmute([]byte)input)
hash.final(&ctx, digest)
}
*/
package crypto_hash
package crypto_hash
+4 -38
View File
@@ -1,16 +1,15 @@
package crypto_hash
/*
Copyright 2021 zhibog
Made available under the BSD-3 license.
Copyright 2021 zhibog
Made available under the BSD-3 license.
List of contributors:
zhibog, dotbmp: Initial implementation.
List of contributors:
zhibog, dotbmp: Initial implementation.
*/
import "core:io"
import "core:mem"
import "core:os"
// hash_bytes will hash the given input and return the computed digest
// in a newly allocated slice.
@@ -87,36 +86,3 @@ hash_stream :: proc(
return dst, io.Error.None
}
// hash_file will read the file provided by the given handle and return the
// computed digest in a newly allocated slice.
hash_file :: proc(
algorithm: Algorithm,
hd: os.Handle,
load_at_once := false,
allocator := context.allocator,
) -> (
[]byte,
io.Error,
) {
if !load_at_once {
return hash_stream(algorithm, os.stream_from_handle(hd), allocator)
}
buf, ok := os.read_entire_file(hd, allocator)
if !ok {
return nil, io.Error.Unknown
}
defer delete(buf, allocator)
return hash_bytes(algorithm, buf, allocator), io.Error.None
}
hash :: proc {
hash_stream,
hash_file,
hash_bytes,
hash_string,
hash_bytes_to_buffer,
hash_string_to_buffer,
}
+10
View File
@@ -0,0 +1,10 @@
#+build freestanding
package crypto_hash
hash :: proc {
hash_stream,
hash_bytes,
hash_string,
hash_bytes_to_buffer,
hash_string_to_buffer,
}
+38
View File
@@ -0,0 +1,38 @@
#+build !freestanding
package crypto_hash
import "core:io"
import "core:os"
// hash_file will read the file provided by the given handle and return the
// computed digest in a newly allocated slice.
hash_file :: proc(
algorithm: Algorithm,
hd: os.Handle,
load_at_once := false,
allocator := context.allocator,
) -> (
[]byte,
io.Error,
) {
if !load_at_once {
return hash_stream(algorithm, os.stream_from_handle(hd), allocator)
}
buf, ok := os.read_entire_file(hd, allocator)
if !ok {
return nil, io.Error.Unknown
}
defer delete(buf, allocator)
return hash_bytes(algorithm, buf, allocator), io.Error.None
}
hash :: proc {
hash_stream,
hash_file,
hash_bytes,
hash_string,
hash_bytes_to_buffer,
hash_string_to_buffer,
}
+1 -1
View File
@@ -2,7 +2,7 @@
package hkdf implements the HKDF HMAC-based Extract-and-Expand Key
Derivation Function.
See: https://www.rfc-editor.org/rfc/rfc5869
See: [[ https://www.rfc-editor.org/rfc/rfc5869 ]]
*/
package hkdf
+1 -1
View File
@@ -2,7 +2,7 @@
package hmac implements the HMAC MAC algorithm.
See:
- https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.198-1.pdf
- [[ https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.198-1.pdf ]]
*/
package hmac
+1 -1
View File
@@ -2,7 +2,7 @@
package kmac implements the KMAC MAC algorithm.
See:
- https://nvlpubs.nist.gov/nistpubs/specialpublications/nist.sp.800-185.pdf
- [[ https://nvlpubs.nist.gov/nistpubs/specialpublications/nist.sp.800-185.pdf ]]
*/
package kmac
+2 -2
View File
@@ -5,8 +5,8 @@ WARNING: The MD5 algorithm is known to be insecure and should only be
used for interoperating with legacy applications.
See:
- https://eprint.iacr.org/2005/075
- https://datatracker.ietf.org/doc/html/rfc1321
- [[ https://eprint.iacr.org/2005/075 ]]
- [[ https://datatracker.ietf.org/doc/html/rfc1321 ]]
*/
package md5
+3 -3
View File
@@ -5,9 +5,9 @@ WARNING: The SHA1 algorithm is known to be insecure and should only be
used for interoperating with legacy applications.
See:
- https://eprint.iacr.org/2017/190
- https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf
- https://datatracker.ietf.org/doc/html/rfc3174
- [[ https://eprint.iacr.org/2017/190 ]]
- [[ https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf ]]
- [[ https://datatracker.ietf.org/doc/html/rfc3174 ]]
*/
package sha1
+1 -1
View File
@@ -1,7 +1,7 @@
/*
package pbkdf2 implements the PBKDF2 password-based key derivation function.
See: https://www.rfc-editor.org/rfc/rfc2898
See: [[ https://www.rfc-editor.org/rfc/rfc2898 ]]
*/
package pbkdf2
+1 -1
View File
@@ -2,7 +2,7 @@
package poly1305 implements the Poly1305 one-time MAC algorithm.
See:
- https://datatracker.ietf.org/doc/html/rfc8439
- [[ https://datatracker.ietf.org/doc/html/rfc8439 ]]
*/
package poly1305
+1 -1
View File
@@ -1,4 +1,4 @@
//+build freebsd, openbsd, netbsd
#+build freebsd, openbsd, netbsd
package crypto
foreign import libc "system:c"
+7 -7
View File
@@ -1,10 +1,10 @@
//+build !linux
//+build !windows
//+build !openbsd
//+build !freebsd
//+build !netbsd
//+build !darwin
//+build !js
#+build !linux
#+build !windows
#+build !openbsd
#+build !freebsd
#+build !netbsd
#+build !darwin
#+build !js
package crypto
HAS_RAND_BYTES :: false
+1 -1
View File
@@ -2,7 +2,7 @@
package ristretto255 implement the ristretto255 prime-order group.
See:
- https://www.rfc-editor.org/rfc/rfc9496
- [[ https://www.rfc-editor.org/rfc/rfc9496 ]]
*/
package ristretto255
+2 -2
View File
@@ -2,8 +2,8 @@
package sha2 implements the SHA2 hash algorithm family.
See:
- https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf
- https://datatracker.ietf.org/doc/html/rfc3874
- [[ https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf ]]
- [[ https://datatracker.ietf.org/doc/html/rfc3874 ]]
*/
package sha2
+1 -1
View File
@@ -6,7 +6,7 @@ pre-standardization Keccak algorithm is required, it can be found in
crypto/legacy/keccak.
See:
- https://nvlpubs.nist.gov/nistpubs/fips/nist.fips.202.pdf
- [[ https://nvlpubs.nist.gov/nistpubs/fips/nist.fips.202.pdf ]]
*/
package sha3
+2 -2
View File
@@ -4,8 +4,8 @@ package shake implements the SHAKE and cSHAKE XOF algorithm families.
The SHA3 hash algorithm can be found in the crypto/sha3.
See:
- https://nvlpubs.nist.gov/nistpubs/fips/nist.fips.202.pdf
- https://nvlpubs.nist.gov/nistpubs/specialpublications/nist.sp.800-185.pdf
- [[ https://nvlpubs.nist.gov/nistpubs/fips/nist.fips.202.pdf ]]
- [[ https://nvlpubs.nist.gov/nistpubs/specialpublications/nist.sp.800-185.pdf ]]
*/
package shake
+9 -4
View File
@@ -1,3 +1,12 @@
/*
package siphash Implements the SipHash hashing algorithm.
Use the specific procedures for a certain setup. The generic procedures will default to Siphash 2-4.
See:
- [[ https://github.com/veorq/SipHash ]]
- [[ https://www.aumasson.jp/siphash/siphash.pdf ]]
*/
package siphash
/*
@@ -6,10 +15,6 @@ package siphash
List of contributors:
zhibog: Initial implementation.
Implementation of the SipHash hashing algorithm, as defined at <https://github.com/veorq/SipHash> and <https://www.aumasson.jp/siphash/siphash.pdf>
Use the specific procedures for a certain setup. The generic procdedures will default to Siphash 2-4
*/
import "core:crypto"
+1 -1
View File
@@ -2,7 +2,7 @@
package sm3 implements the SM3 hash algorithm.
See:
- https://datatracker.ietf.org/doc/html/draft-sca-cfrg-sm3-02
- [[ https://datatracker.ietf.org/doc/html/draft-sca-cfrg-sm3-02 ]]
*/
package sm3
+1 -1
View File
@@ -2,7 +2,7 @@
package tuplehash implements the TupleHash and TupleHashXOF algorithms.
See:
- https://nvlpubs.nist.gov/nistpubs/specialpublications/nist.sp.800-185.pdf
- [[ https://nvlpubs.nist.gov/nistpubs/specialpublications/nist.sp.800-185.pdf ]]
*/
package tuplehash
+1 -1
View File
@@ -3,7 +3,7 @@ package x25519 implements the X25519 (aka curve25519) Elliptic-Curve
Diffie-Hellman key exchange protocol.
See:
- https://www.rfc-editor.org/rfc/rfc7748
- [[ https://www.rfc-editor.org/rfc/rfc7748 ]]
*/
package x25519
+2 -2
View File
@@ -1,5 +1,5 @@
//+private file
//+build linux, darwin
#+private file
#+build linux, darwin
package debug_trace
import "base:intrinsics"
+3 -1
View File
@@ -1,4 +1,6 @@
//+build !windows !linux !darwin
#+build !windows
#+build !linux
#+build !darwin
package debug_trace
import "base:runtime"
+2 -2
View File
@@ -1,5 +1,5 @@
//+private
//+build windows
#+private
#+build windows
package debug_trace
import "base:intrinsics"
+1 -2
View File
@@ -4,7 +4,6 @@ Package `core:dynlib` implements loading of shared libraries/DLLs and their symb
The behaviour of dynamically loaded libraries is specific to the target platform of the program.
For in depth detail on the underlying behaviour please refer to your target platform's documentation.
See `example` directory for an example library exporting 3 symbols and a host program loading them automatically
by defining a symbol table struct.
For a full example, see: [[ core/dynlib/example; https://github.com/odin-lang/Odin/tree/master/core/dynlib/example ]]
*/
package dynlib
+2 -2
View File
@@ -1,5 +1,5 @@
//+build js
//+private
#+build js
#+private
package dynlib
_load_library :: proc(path: string, global_symbols := false) -> (Library, bool) {
+2 -2
View File
@@ -1,5 +1,5 @@
//+build linux, darwin, freebsd, openbsd, netbsd
//+private
#+build linux, darwin, freebsd, openbsd, netbsd
#+private
package dynlib
import "core:os"
+2 -2
View File
@@ -1,5 +1,5 @@
//+build windows
//+private
#+build windows
#+private
package dynlib
import win32 "core:sys/windows"
+3 -3
View File
@@ -13,8 +13,8 @@ If your terminal supports 24-bit true color mode, you can also do this:
fmt.println(ansi.CSI + ansi.FG_COLOR_24_BIT + ";0;255;255" + ansi.SGR + "Hellope!" + ansi.CSI + ansi.RESET + ansi.SGR)
For more information, see:
1. https://en.wikipedia.org/wiki/ANSI_escape_code
2. https://www.vt100.net/docs/vt102-ug/chapter5.html
3. https://invisible-island.net/xterm/ctlseqs/ctlseqs.html
- [[ https://en.wikipedia.org/wiki/ANSI_escape_code ]]
- [[ https://www.vt100.net/docs/vt102-ug/chapter5.html ]]
- [[ https://invisible-island.net/xterm/ctlseqs/ctlseqs.html ]]
*/
package ansi
+11 -27
View File
@@ -675,10 +675,6 @@ _unmarshal_map :: proc(d: Decoder, v: any, ti: ^reflect.Type_Info, hdr: Header,
return
case reflect.Type_Info_Map:
if !reflect.is_string(t.key) {
return _unsupported(v, hdr)
}
raw_map := (^mem.Raw_Map)(v.data)
if raw_map.allocator.procedure == nil {
raw_map.allocator = context.allocator
@@ -695,43 +691,31 @@ _unmarshal_map :: proc(d: Decoder, v: any, ti: ^reflect.Type_Info, hdr: Header,
new_len := uintptr(min(scap, runtime.map_len(raw_map^)+length))
runtime.map_reserve_dynamic(raw_map, t.map_info, new_len) or_return
}
// Temporary memory to unmarshal keys into before inserting them into the map.
// Temporary memory to unmarshal values into before inserting them into the map.
elem_backing := mem.alloc_bytes_non_zeroed(t.value.size, t.value.align, context.temp_allocator) or_return
defer delete(elem_backing, context.temp_allocator)
map_backing_value := any{raw_data(elem_backing), t.value.id}
for idx := 0; unknown || idx < length; idx += 1 {
// Decode key, keys can only be strings.
key: string
if keyv, kerr := decode_key(d, v); unknown && kerr == .Break {
break
} else if kerr != nil {
err = kerr
return
} else {
key = keyv
}
// Temporary memory to unmarshal keys into.
key_backing := mem.alloc_bytes_non_zeroed(t.key.size, t.key.align, context.temp_allocator) or_return
defer delete(key_backing, context.temp_allocator)
key_backing_value := any{raw_data(key_backing), t.key.id}
for idx := 0; unknown || idx < length; idx += 1 {
if unknown || idx > scap {
// Reserve space for new element so we can return allocator errors.
new_len := uintptr(runtime.map_len(raw_map^)+1)
runtime.map_reserve_dynamic(raw_map, t.map_info, new_len) or_return
}
mem.zero_slice(key_backing)
_unmarshal_value(d, key_backing_value, _decode_header(r) or_return) or_return
mem.zero_slice(elem_backing)
_unmarshal_value(d, map_backing_value, _decode_header(r) or_return) or_return
key_ptr := rawptr(&key)
key_cstr: cstring
if reflect.is_cstring(t.key) {
assert_safe_for_cstring(key)
key_cstr = cstring(raw_data(key))
key_ptr = &key_cstr
}
set_ptr := runtime.__dynamic_map_set_without_hash(raw_map, t.map_info, key_ptr, map_backing_value.data)
set_ptr := runtime.__dynamic_map_set_without_hash(raw_map, t.map_info, key_backing_value.data, map_backing_value.data)
// We already reserved space for it, so this shouldn't fail.
assert(set_ptr != nil)
}
+96
View File
@@ -0,0 +1,96 @@
/*
package csv reads and writes comma-separated values (CSV) files.
This package supports the format described in [[ RFC 4180; https://tools.ietf.org/html/rfc4180.html ]]
Example:
package main
import "core:fmt"
import "core:encoding/csv"
import "core:os"
// Requires keeping the entire CSV file in memory at once
iterate_csv_from_string :: proc(filename: string) {
r: csv.Reader
r.trim_leading_space = true
r.reuse_record = true // Without it you have to delete(record)
r.reuse_record_buffer = true // Without it you have to each of the fields within it
defer csv.reader_destroy(&r)
csv_data, ok := os.read_entire_file(filename)
if ok {
csv.reader_init_with_string(&r, string(csv_data))
} else {
fmt.printfln("Unable to open file: %v", filename)
return
}
defer delete(csv_data)
for r, i, err in csv.iterator_next(&r) {
if err != nil { /* Do something with error */ }
for f, j in r {
fmt.printfln("Record %v, field %v: %q", i, j, f)
}
}
}
// Reads the CSV as it's processed (with a small buffer)
iterate_csv_from_stream :: proc(filename: string) {
fmt.printfln("Hellope from %v", filename)
r: csv.Reader
r.trim_leading_space = true
r.reuse_record = true // Without it you have to delete(record)
r.reuse_record_buffer = true // Without it you have to each of the fields within it
defer csv.reader_destroy(&r)
handle, err := os.open(filename)
if err != nil {
fmt.eprintfln("Error opening file: %v", filename)
return
}
defer os.close(handle)
csv.reader_init(&r, os.stream_from_handle(handle))
for r, i in csv.iterator_next(&r) {
for f, j in r {
fmt.printfln("Record %v, field %v: %q", i, j, f)
}
}
fmt.printfln("Error: %v", csv.iterator_last_error(r))
}
// Read all records at once
read_csv_from_string :: proc(filename: string) {
r: csv.Reader
r.trim_leading_space = true
r.reuse_record = true // Without it you have to delete(record)
r.reuse_record_buffer = true // Without it you have to each of the fields within it
defer csv.reader_destroy(&r)
csv_data, ok := os.read_entire_file(filename)
if ok {
csv.reader_init_with_string(&r, string(csv_data))
} else {
fmt.printfln("Unable to open file: %v", filename)
return
}
defer delete(csv_data)
records, err := csv.read_all(&r)
if err != nil { /* Do something with CSV parse error */ }
defer {
for rec in records {
delete(rec)
}
delete(records)
}
for r, i in records {
for f, j in r {
fmt.printfln("Record %v, field %v: %q", i, j, f)
}
}
}
*/
package encoding_csv
-88
View File
@@ -1,88 +0,0 @@
//+build ignore
package encoding_csv
import "core:fmt"
import "core:encoding/csv"
import "core:os"
// Requires keeping the entire CSV file in memory at once
iterate_csv_from_string :: proc(filename: string) {
r: csv.Reader
r.trim_leading_space = true
r.reuse_record = true // Without it you have to delete(record)
r.reuse_record_buffer = true // Without it you have to each of the fields within it
defer csv.reader_destroy(&r)
if csv_data, ok := os.read_entire_file(filename); ok {
csv.reader_init_with_string(&r, string(csv_data))
defer delete(csv_data)
} else {
fmt.printfln("Unable to open file: %v", filename)
return
}
for r, i, err in csv.iterator_next(&r) {
if err != nil { /* Do something with error */ }
for f, j in r {
fmt.printfln("Record %v, field %v: %q", i, j, f)
}
}
}
// Reads the CSV as it's processed (with a small buffer)
iterate_csv_from_stream :: proc(filename: string) {
fmt.printfln("Hellope from %v", filename)
r: csv.Reader
r.trim_leading_space = true
r.reuse_record = true // Without it you have to delete(record)
r.reuse_record_buffer = true // Without it you have to each of the fields within it
defer csv.reader_destroy(&r)
handle, err := os.open(filename)
if err != nil {
fmt.eprintfln("Error opening file: %v", filename)
return
}
defer os.close(handle)
csv.reader_init(&r, os.stream_from_handle(handle))
for r, i in csv.iterator_next(&r) {
for f, j in r {
fmt.printfln("Record %v, field %v: %q", i, j, f)
}
}
fmt.printfln("Error: %v", csv.iterator_last_error(r))
}
// Read all records at once
read_csv_from_string :: proc(filename: string) {
r: csv.Reader
r.trim_leading_space = true
r.reuse_record = true // Without it you have to delete(record)
r.reuse_record_buffer = true // Without it you have to each of the fields within it
defer csv.reader_destroy(&r)
if csv_data, ok := os.read_entire_file(filename); ok {
csv.reader_init_with_string(&r, string(csv_data))
defer delete(csv_data)
} else {
fmt.printfln("Unable to open file: %v", filename)
return
}
records, err := csv.read_all(&r)
if err != nil { /* Do something with CSV parse error */ }
defer {
for rec in records {
delete(rec)
}
delete(records)
}
for r, i in records {
for f, j in r {
fmt.printfln("Record %v, field %v: %q", i, j, f)
}
}
}
+2 -2
View File
@@ -1,5 +1,5 @@
// package csv reads and writes comma-separated values (CSV) files.
// This package supports the format described in RFC 4180 <https://tools.ietf.org/html/rfc4180.html>
// This package supports the format described in [[ RFC 4180; https://tools.ietf.org/html/rfc4180.html ]]
package encoding_csv
import "core:bufio"
@@ -484,4 +484,4 @@ _read_record :: proc(r: ^Reader, dst: ^[dynamic]string, allocator := context.all
r.fields_per_record = len(dst)
}
return dst[:], err
}
}
+13 -12
View File
@@ -2,22 +2,23 @@
Package endian implements a simple translation between bytes and numbers with
specific endian encodings.
buf: [100]u8
put_u16(buf[:], .Little, 16) or_return
Example:
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
// 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.
// 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
// 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.
// 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
field := get_u16(buf[:], .Big) or_return
*/
package encoding_endian
+16 -14
View File
@@ -1,24 +1,26 @@
package encoding_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.
*/
/*
A unicode entity encoder/decoder.
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 ]]
*/
package encoding_unicode_entity
import "core:unicode/utf8"
import "core:unicode"
import "core:strings"
@@ -353,4 +355,4 @@ _handle_xml_special :: proc(t: ^Tokenizer, builder: ^strings.Builder, options: X
}
return false, .None
}
}
+1 -1
View File
@@ -42,7 +42,7 @@ XML_NAME_TO_RUNE_MAX_LENGTH :: 31
Input:
entity_name - a string, like "copy" that describes a user-encoded Unicode entity as used in XML.
Output:
Returns:
"decoded" - The decoded rune if found by name, or -1 otherwise.
"ok" - true if found, false if not.
+89 -83
View File
@@ -1,83 +1,89 @@
// Implementation of the HxA 3D asset format
// HxA is a interchangeable graphics asset format.
// Designed by Eskil Steenberg. @quelsolaar / eskil 'at' obsession 'dot' se / www.quelsolaar.com
//
// Author of this Odin package: Ginger Bill
//
// Following comment is copied from the original C-implementation
// ---------
// -Does the world need another Graphics file format?
// Unfortunately, Yes. All existing formats are either too large and complicated to be implemented from
// scratch, or don't have some basic features needed in modern computer graphics.
// -Who is this format for?
// For people who want a capable open Graphics format that can be implemented from scratch in
// a few hours. It is ideal for graphics researchers, game developers or other people who
// wants to build custom graphics pipelines. Given how easy it is to parse and write, it
// should be easy to write utilities that process assets to preform tasks like: generating
// normals, light-maps, tangent spaces, Error detection, GPU optimization, LOD generation,
// and UV mapping.
// -Why store images in the format when there are so many good image formats already?
// Yes there are, but only for 2D RGB/RGBA images. A lot of computer graphics rendering rely
// on 1D, 3D, cube, multilayer, multi channel, floating point bitmap buffers. There almost no
// formats for this kind of data. Also 3D files that reference separate image files rely on
// file paths, and this often creates issues when the assets are moved. By including the
// texture data in the files directly the assets become self contained.
// -Why doesn't the format support <insert whatever>?
// Because the entire point is to make a format that can be implemented. Features like NURBSs,
// Construction history, or BSP trees would make the format too large to serve its purpose.
// The facilities of the formats to store meta data should make the format flexible enough
// for most uses. Adding HxA support should be something anyone can do in a days work.
//
// Structure:
// ----------
// HxA is designed to be extremely simple to parse, and is therefore based around conventions. It has
// a few basic structures, and depending on how they are used they mean different things. This means
// that you can implement a tool that loads the entire file, modifies the parts it cares about and
// leaves the rest intact. It is also possible to write a tool that makes all data in the file
// editable without the need to understand its use. It is also possible for anyone to use the format
// to store data axillary data. Anyone who wants to store data not covered by a convention can submit
// a convention to extend the format. There should never be a convention for storing the same data in
// two differed ways.
// The data is story in a number of nodes that are stored in an array. Each node stores an array of
// meta data. Meta data can describe anything you want, and a lot of conventions will use meta data
// to store additional information, for things like transforms, lights, shaders and animation.
// Data for Vertices, Corners, Faces, and Pixels are stored in named layer stacks. Each stack consists
// of a number of named layers. All layers in the stack have the same number of elements. Each layer
// describes one property of the primitive. Each layer can have multiple channels and each layer can
// store data of a different type.
//
// HaX stores 3 kinds of nodes
// - Pixel data.
// - Polygon geometry data.
// - Meta data only.
//
// Pixel Nodes stores pixels in a layer stack. A layer may store things like Albedo, Roughness,
// Reflectance, Light maps, Masks, Normal maps, and Displacement. Layers use the channels of the
// layers to store things like color. The length of the layer stack is determined by the type and
// dimensions stored in the
//
// Geometry data is stored in 3 separate layer stacks for: vertex data, corner data and face data. The
// vertex data stores things like verities, blend shapes, weight maps, and vertex colors. The first
// layer in a vertex stack has to be a 3 channel layer named "position" describing the base position
// of the vertices. The corner stack describes data per corner or edge of the polygons. It can be used
// for things like UV, normals, and adjacency. The first layer in a corner stack has to be a 1 channel
// integer layer named "index" describing the vertices used to form polygons. The last value in each
// polygon has a negative - 1 index to indicate the end of the polygon.
//
// Example:
// A quad and a tri with the vertex index:
// [0, 1, 2, 3] [1, 4, 2]
// is stored:
// [0, 1, 2, -4, 1, 4, -3]
// The face stack stores values per face. the length of the face stack has to match the number of
// negative values in the index layer in the corner stack. The face stack can be used to store things
// like material index.
//
// Storage
// -------
// All data is stored in little endian byte order with no padding. The layout mirrors the structs
// defined below with a few exceptions. All names are stored as a 8-bit unsigned integer indicating
// the length of the name followed by that many characters. Termination is not stored in the file.
// Text strings stored in meta data are stored the same way as names, but instead of a 8-bit unsigned
// integer a 32-bit unsigned integer is used.
package encoding_hxa
/*
Implementation of the HxA 3D asset format
HxA is a interchangeable graphics asset format.
Designed by Eskil Steenberg. @quelsolaar / eskil 'at' obsession 'dot' se / www.quelsolaar.com
Author of this Odin package: Ginger Bill
Following comment is copied from the original C-implementation
---------
- Does the world need another Graphics file format?
Unfortunately, Yes. All existing formats are either too large and complicated to be implemented from
scratch, or don't have some basic features needed in modern computer graphics.
- Who is this format for?
For people who want a capable open Graphics format that can be implemented from scratch in
a few hours. It is ideal for graphics researchers, game developers or other people who
wants to build custom graphics pipelines. Given how easy it is to parse and write, it
should be easy to write utilities that process assets to preform tasks like: generating
normals, light-maps, tangent spaces, Error detection, GPU optimization, LOD generation,
and UV mapping.
- Why store images in the format when there are so many good image formats already?
Yes there are, but only for 2D RGB/RGBA images. A lot of computer graphics rendering rely
on 1D, 3D, cube, multilayer, multi channel, floating point bitmap buffers. There almost no
formats for this kind of data. Also 3D files that reference separate image files rely on
file paths, and this often creates issues when the assets are moved. By including the
texture data in the files directly the assets become self contained.
- Why doesn't the format support <insert whatever>?
Because the entire point is to make a format that can be implemented. Features like NURBSs,
Construction history, or BSP trees would make the format too large to serve its purpose.
The facilities of the formats to store meta data should make the format flexible enough
for most uses. Adding HxA support should be something anyone can do in a days work.
Structure:
----------
HxA is designed to be extremely simple to parse, and is therefore based around conventions. It has
a few basic structures, and depending on how they are used they mean different things. This means
that you can implement a tool that loads the entire file, modifies the parts it cares about and
leaves the rest intact. It is also possible to write a tool that makes all data in the file
editable without the need to understand its use. It is also possible for anyone to use the format
to store data axillary data. Anyone who wants to store data not covered by a convention can submit
a convention to extend the format. There should never be a convention for storing the same data in
two differed ways.
The data is story in a number of nodes that are stored in an array. Each node stores an array of
meta data. Meta data can describe anything you want, and a lot of conventions will use meta data
to store additional information, for things like transforms, lights, shaders and animation.
Data for Vertices, Corners, Faces, and Pixels are stored in named layer stacks. Each stack consists
of a number of named layers. All layers in the stack have the same number of elements. Each layer
describes one property of the primitive. Each layer can have multiple channels and each layer can
store data of a different type.
HaX stores 3 kinds of nodes
- Pixel data.
- Polygon geometry data.
- Meta data only.
Pixel Nodes stores pixels in a layer stack. A layer may store things like Albedo, Roughness,
Reflectance, Light maps, Masks, Normal maps, and Displacement. Layers use the channels of the
layers to store things like color.
The length of the layer stack is determined by the type and dimensions stored in the Geometry data
is stored in 3 separate layer stacks for: vertex data, corner data and face data. The
vertex data stores things like verities, blend shapes, weight maps, and vertex colors. The first
layer in a vertex stack has to be a 3 channel layer named "position" describing the base position
of the vertices. The corner stack describes data per corner or edge of the polygons. It can be used
for things like UV, normals, and adjacency. The first layer in a corner stack has to be a 1 channel
integer layer named "index" describing the vertices used to form polygons. The last value in each
polygon has a negative - 1 index to indicate the end of the polygon.
For Example:
A quad and a tri with the vertex index:
[0, 1, 2, 3] [1, 4, 2]
is stored:
[0, 1, 2, -4, 1, 4, -3]
The face stack stores values per face. the length of the face stack has to match the number of
negative values in the index layer in the corner stack. The face stack can be used to store things
like material index.
Storage:
-------
All data is stored in little endian byte order with no padding. The layout mirrors the structs
defined below with a few exceptions. All names are stored as a 8-bit unsigned integer indicating
the length of the name followed by that many characters. Termination is not stored in the file.
Text strings stored in meta data are stored the same way as names, but instead of a 8-bit unsigned
integer a 32-bit unsigned integer is used.
*/
package encoding_hxa
+24 -1
View File
@@ -116,7 +116,30 @@ assign_int :: proc(val: any, i: $T) -> bool {
case int: dst = int (i)
case uint: dst = uint (i)
case uintptr: dst = uintptr(i)
case: return false
case:
ti := type_info_of(v.id)
if _, ok := ti.variant.(runtime.Type_Info_Bit_Set); ok {
do_byte_swap := !reflect.bit_set_is_big_endian(v)
switch ti.size * 8 {
case 0: // no-op.
case 8:
x := (^u8)(v.data)
x^ = u8(i)
case 16:
x := (^u16)(v.data)
x^ = do_byte_swap ? intrinsics.byte_swap(u16(i)) : u16(i)
case 32:
x := (^u32)(v.data)
x^ = do_byte_swap ? intrinsics.byte_swap(u32(i)) : u32(i)
case 64:
x := (^u64)(v.data)
x^ = do_byte_swap ? intrinsics.byte_swap(u64(i)) : u64(i)
case:
panic("unknown bit_size size")
}
return true
}
return false
}
return true
}
+5 -4
View File
@@ -21,8 +21,9 @@ cryptographically-secure, per RFC 9562's suggestion.
- Version 6 without either a clock or node argument.
- Version 7 in all cases.
Here's an example of how to set up one:
Example:
package main
import "core:crypto"
import "core:encoding/uuid"
@@ -40,7 +41,7 @@ Here's an example of how to set up one:
For more information on the specifications, see here:
- https://www.rfc-editor.org/rfc/rfc4122.html
- https://www.rfc-editor.org/rfc/rfc9562.html
- [[ https://www.rfc-editor.org/rfc/rfc4122.html ]]
- [[ https://www.rfc-editor.org/rfc/rfc9562.html ]]
*/
package uuid
+20 -15
View File
@@ -11,7 +11,7 @@ Write a UUID in the 8-4-4-4-12 format.
This procedure performs error checking with every byte written.
If you can guarantee beforehand that your stream has enough space to hold the
UUID (32 bytes), then it is better to use `unsafe_write` instead as that will
UUID (36 bytes), then it is better to use `unsafe_write` instead as that will
be faster.
Inputs:
@@ -22,7 +22,7 @@ Returns:
- error: An `io` error, if one occurred, otherwise `nil`.
*/
write :: proc(w: io.Writer, id: Identifier) -> (error: io.Error) #no_bounds_check {
write_octet :: proc (w: io.Writer, octet: u8) -> io.Error #no_bounds_check {
write_octet :: proc(w: io.Writer, octet: u8) -> io.Error #no_bounds_check {
high_nibble := octet >> 4
low_nibble := octet & 0xF
@@ -31,15 +31,15 @@ write :: proc(w: io.Writer, id: Identifier) -> (error: io.Error) #no_bounds_chec
return nil
}
for index in 0 ..< 4 { write_octet(w, id[index]) or_return }
for index in 0 ..< 4 {write_octet(w, id[index]) or_return}
io.write_byte(w, '-') or_return
for index in 4 ..< 6 { write_octet(w, id[index]) or_return }
for index in 4 ..< 6 {write_octet(w, id[index]) or_return}
io.write_byte(w, '-') or_return
for index in 6 ..< 8 { write_octet(w, id[index]) or_return }
for index in 6 ..< 8 {write_octet(w, id[index]) or_return}
io.write_byte(w, '-') or_return
for index in 8 ..< 10 { write_octet(w, id[index]) or_return }
for index in 8 ..< 10 {write_octet(w, id[index]) or_return}
io.write_byte(w, '-') or_return
for index in 10 ..< 16 { write_octet(w, id[index]) or_return }
for index in 10 ..< 16 {write_octet(w, id[index]) or_return}
return nil
}
@@ -54,7 +54,7 @@ Inputs:
- id: The identifier to convert.
*/
unsafe_write :: proc(w: io.Writer, id: Identifier) #no_bounds_check {
write_octet :: proc (w: io.Writer, octet: u8) #no_bounds_check {
write_octet :: proc(w: io.Writer, octet: u8) #no_bounds_check {
high_nibble := octet >> 4
low_nibble := octet & 0xF
@@ -62,15 +62,15 @@ unsafe_write :: proc(w: io.Writer, id: Identifier) #no_bounds_check {
io.write_byte(w, strconv.digits[low_nibble])
}
for index in 0 ..< 4 { write_octet(w, id[index]) }
for index in 0 ..< 4 {write_octet(w, id[index])}
io.write_byte(w, '-')
for index in 4 ..< 6 { write_octet(w, id[index]) }
for index in 4 ..< 6 {write_octet(w, id[index])}
io.write_byte(w, '-')
for index in 6 ..< 8 { write_octet(w, id[index]) }
for index in 6 ..< 8 {write_octet(w, id[index])}
io.write_byte(w, '-')
for index in 8 ..< 10 { write_octet(w, id[index]) }
for index in 8 ..< 10 {write_octet(w, id[index])}
io.write_byte(w, '-')
for index in 10 ..< 16 { write_octet(w, id[index]) }
for index in 10 ..< 16 {write_octet(w, id[index])}
}
/*
@@ -106,7 +106,7 @@ Convert a UUID to a string in the 8-4-4-4-12 format.
Inputs:
- id: The identifier to convert.
- buffer: A byte buffer to store the result. Must be at least 32 bytes large.
- buffer: A byte buffer to store the result. Must be at least 36 bytes large.
- loc: The caller location for debugging purposes (default: #caller_location)
Returns:
@@ -119,7 +119,11 @@ to_string_buffer :: proc(
) -> (
str: string,
) {
assert(len(buffer) >= EXPECTED_LENGTH, "The buffer provided is not at least 32 bytes large.", loc)
assert(
len(buffer) >= EXPECTED_LENGTH,
"The buffer provided is not at least 36 bytes large.",
loc,
)
builder := strings.builder_from_bytes(buffer)
unsafe_write(strings.to_writer(&builder), id)
return strings.to_string(builder)
@@ -129,3 +133,4 @@ to_string :: proc {
to_string_allocated,
to_string_buffer,
}
+6 -7
View File
@@ -1,10 +1,11 @@
/*
Implementation of the LEB128 variable integer encoding as used by DWARF encoding and DEX files, among others.
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
Author of this Odin package: Jeroen van Rijn
Example:
package main
Example:
```odin
import "core:encoding/varint"
import "core:fmt"
@@ -22,7 +23,5 @@
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 encoding_varint
package encoding_varint
+1 -3
View File
@@ -6,8 +6,6 @@
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 encoding_varint
// In theory we should use the bigint package. In practice, varints bigger than this indicate a corrupted file.
@@ -160,4 +158,4 @@ encode_ileb128 :: proc(buf: []u8, val: i128) -> (size: int, err: Error) {
buf[size - 1] = u8(low)
}
return
}
}
+23
View File
@@ -0,0 +1,23 @@
/*
XML 1.0 / 1.1 parser
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?
For a full example, see: [[ core/encoding/xml/example; https://github.com/odin-lang/Odin/tree/master/core/encoding/xml/example ]]
*/
package encoding_xml
+5 -23
View File
@@ -1,29 +1,11 @@
/*
XML 1.0 / 1.1 parser
2021-2022 Jeroen van Rijn <nom@duclavier.com>.
available under Odin's BSD-3 license.
2021-2022 Jeroen van Rijn <nom@duclavier.com>.
available under Odin's BSD-3 license.
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.
List of contributors:
- Jeroen van Rijn: Initial implementation.
*/
package encoding_xml
// An XML 1.0 / 1.1 parser
+15 -25
View File
@@ -11,15 +11,13 @@ Command-Line Syntax:
Arguments are treated differently depending on how they're formatted.
The format is similar to the Odin binary's way of handling compiler flags.
```
type handling
------------ ------------------------
<positional> depends on struct layout
-<flag> set a bool true
-<flag:option> set flag to option
-<flag=option> set flag to option, alternative syntax
-<map>:<key>=<value> set map[key] to value
```
type handling
------------ ------------------------
<positional> depends on struct layout
-<flag> set a bool true
-<flag:option> set flag to option
-<flag=option> set flag to option, alternative syntax
-<map>:<key>=<value> set map[key] to value
Struct Tags:
@@ -40,11 +38,9 @@ Under the `args` tag, there are the following subtags:
- `indistinct`: allow the setting of distinct types by their base type.
`required` may be given a range specifier in the following formats:
```
min
<max
min<max
```
min
<max
min<max
`max` is not inclusive in this range, as noted by the less-than `<` sign, so if
you want to require 3 and only 3 arguments in a dynamic array, you would
@@ -161,21 +157,15 @@ UNIX-style:
This package also supports parsing arguments in a limited flavor of UNIX.
Odin and UNIX style are mutually exclusive, and which one to be used is chosen
at parse time.
```
--flag
--flag=argument
--flag argument
--flag argument repeating-argument
```
--flag
--flag=argument
--flag argument
--flag argument repeating-argument
`-flag` may also be substituted for `--flag`.
Do note that map flags are not currently supported in this parsing style.
Example:
A complete example is given in the `example` subdirectory.
For a complete example, see: [[ core/flags/example; https://github.com/odin-lang/Odin/blob/master/core/flags/example/example.odin ]].
*/
package flags
+1 -1
View File
@@ -1,4 +1,4 @@
//+build netbsd, openbsd
#+build netbsd, openbsd
package flags
import "base:runtime"
+2 -1
View File
@@ -1,4 +1,5 @@
//+build !netbsd !openbsd
#+build !netbsd
#+build !openbsd
package flags
import "base:runtime"
+4 -4
View File
@@ -1,4 +1,4 @@
//+private
#+private
package flags
import "base:intrinsics"
@@ -14,10 +14,10 @@ import "core:reflect"
// positionals first before adding it to a fallback field.
@(optimization_mode="favor_size")
push_positional :: #force_no_inline proc (model: ^$T, parser: ^Parser, arg: string) -> (error: Error) {
if bit_array.get(&parser.filled_pos, parser.filled_pos.max_index) {
// The max index is set, which means we're out of space.
if set, valid_index := bit_array.get(&parser.filled_pos, parser.filled_pos.length - 1); set || !valid_index {
// The index below the last one is either set or invalid, which means we're out of space.
// Add one free bit by setting the index above to false.
bit_array.set(&parser.filled_pos, 1 + parser.filled_pos.max_index, false)
bit_array.set(&parser.filled_pos, parser.filled_pos.length, false)
}
pos: int = ---
+1 -1
View File
@@ -1,4 +1,4 @@
//+private
#+private
package flags
import "core:container/bit_array"
+1 -1
View File
@@ -1,4 +1,4 @@
//+private
#+private
package flags
import "base:intrinsics"
+3 -2
View File
@@ -1,5 +1,6 @@
//+private
//+build !netbsd !openbsd
#+private
#+build !netbsd
#+build !openbsd
package flags
import "core:net"
+1 -1
View File
@@ -1,4 +1,4 @@
//+private
#+private
package flags
@require import "base:runtime"
+1 -1
View File
@@ -1,4 +1,4 @@
//+build ignore
#+build ignore
package custom_formatter_example
import "core:fmt"
import "core:io"
+1 -1
View File
@@ -1,4 +1,4 @@
//+build js
#+build js
package fmt
import "core:bufio"
+3 -3
View File
@@ -1,6 +1,6 @@
//+build !freestanding
//+build !js
//+build !orca
#+build !freestanding
#+build !js
#+build !orca
package fmt
import "base:runtime"
+2 -1
View File
@@ -1,5 +1,4 @@
/*
An implementation of Yann Collet's [xxhash Fast Hash Algorithm](https://cyan4973.github.io/xxHash/).
Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
Made available under Odin's BSD-3 license, based on the original C code.
@@ -7,6 +6,8 @@
List of contributors:
Jeroen van Rijn: Initial implementation.
*/
// An implementation of Yann Collet's [[ xxhash Fast Hash Algorithm; https://cyan4973.github.io/xxHash/ ]].
package xxhash
import "base:intrinsics"
+2 -1
View File
@@ -7,6 +7,7 @@
List of contributors:
Jeroen van Rijn: Initial implementation.
*/
package xxhash
import "core:mem"
@@ -371,4 +372,4 @@ XXH3_generate_secret :: proc(secret_buffer: []u8, custom_seed: []u8) {
mem_copy(&secret_buffer[segment_start], &segment, size_of(segment))
}
}
}
}
+1
View File
@@ -7,6 +7,7 @@
List of contributors:
Jeroen van Rijn: Initial implementation.
*/
package xxhash
import "base:intrinsics"
+1
View File
@@ -7,6 +7,7 @@
List of contributors:
Jeroen van Rijn: Initial implementation.
*/
package xxhash
import "base:intrinsics"
+10 -9
View File
@@ -7,6 +7,7 @@
List of contributors:
Jeroen van Rijn: Initial implementation.
*/
package xxhash
import "base:intrinsics"
@@ -19,15 +20,15 @@ xxh_u64 :: u64
XXH64_DEFAULT_SEED :: XXH64_hash(0)
XXH64_state :: struct {
total_len: XXH64_hash, /*!< Total length hashed. This is always 64-bit. */
v1: XXH64_hash, /*!< First accumulator lane */
v2: XXH64_hash, /*!< Second accumulator lane */
v3: XXH64_hash, /*!< Third accumulator lane */
v4: XXH64_hash, /*!< Fourth accumulator lane */
mem64: [4]XXH64_hash, /*!< Internal buffer for partial reads. Treated as unsigned char[32]. */
memsize: XXH32_hash, /*!< Amount of data in @ref mem64 */
reserved32: XXH32_hash, /*!< Reserved field, needed for padding anyways*/
reserved64: XXH64_hash, /*!< Reserved field. Do not read or write to it, it may be removed. */
total_len: XXH64_hash, /*!< Total length hashed. This is always 64-bit. */
v1: XXH64_hash, /*!< First accumulator lane */
v2: XXH64_hash, /*!< Second accumulator lane */
v3: XXH64_hash, /*!< Third accumulator lane */
v4: XXH64_hash, /*!< Fourth accumulator lane */
mem64: [4]XXH64_hash, /*!< Internal buffer for partial reads. Treated as unsigned char[32]. */
memsize: XXH32_hash, /*!< Amount of data in @ref mem64 */
reserved32: XXH32_hash, /*!< Reserved field, needed for padding anyways*/
reserved64: XXH64_hash, /*!< Reserved field. Do not read or write to it, it may be removed. */
}
XXH64_canonical :: struct {
+1 -1
View File
@@ -1,4 +1,4 @@
//+build js
#+build js
package core_image_bmp
load :: proc{load_from_bytes, load_from_context}
+1 -1
View File
@@ -1,4 +1,4 @@
//+build !js
#+build !js
package core_image_bmp
import "core:os"
+2
View File
@@ -1393,6 +1393,7 @@ expand_grayscale :: proc(img: ^Image, allocator := context.allocator) -> (ok: bo
for p in inp {
out[0].rgb = p.r // Gray component.
out[0].a = p.g // Alpha component.
out = out[1:]
}
case:
@@ -1417,6 +1418,7 @@ expand_grayscale :: proc(img: ^Image, allocator := context.allocator) -> (ok: bo
for p in inp {
out[0].rgb = p.r // Gray component.
out[0].a = p.g // Alpha component.
out = out[1:]
}
case:

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