Merge pull request #4191 from laytan/improve-package-doc-comments

core: improve package doc comments for the documentation generator
This commit is contained in:
gingerBill
2024-09-04 21:37:48 +01:00
committed by GitHub
66 changed files with 954 additions and 938 deletions
+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. which is an English word model.
*/ */
// package shoco is an implementation of the shoco short string compressor
package compress_shoco package compress_shoco
DEFAULT_MODEL :: Shoco_Model { 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 }, { 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 }, { 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. 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 package compress_shoco
import "base:intrinsics" import "base:intrinsics"
@@ -308,4 +308,4 @@ compress_string :: proc(input: string, model := DEFAULT_MODEL, allocator := cont
resize(&buf, length) or_return resize(&buf, length) or_return
return buf[:length], result 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)
}
+4 -4
View File
@@ -1,8 +1,8 @@
/* /*
The Bit Array can be used in several ways: 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 package test
import "core:fmt" import "core:fmt"
@@ -22,8 +22,8 @@ The Bit Array can be used in several ways:
destroy(&bits) 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 package test
import "core:fmt" import "core:fmt"
+9 -6
View File
@@ -1,22 +1,22 @@
/* /*
Package list implements an intrusive doubly-linked list. 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 { My_String :: struct {
node: list.Node, node: list.Node,
value: string, 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 { My_String :: struct {
using node: list.Node, using node: list.Node,
value: string, value: string,
} }
Here is a full example: Here is a full example.
Example:
package test package test
import "core:fmt" import "core:fmt"
@@ -42,5 +42,8 @@ Here is a full example:
value: string, value: string,
} }
Output:
Hello
World
*/ */
package container_intrusive_list package container_intrusive_list
+35 -36
View File
@@ -10,49 +10,48 @@ algorithm.
WARNING: Reusing the same key + iv to seal (encrypt) multiple messages WARNING: Reusing the same key + iv to seal (encrypt) multiple messages
results in catastrophic loss of security for most algorithms. results in catastrophic loss of security for most algorithms.
```odin Example:
package aead_example package aead_example
import "core:bytes" import "core:bytes"
import "core:crypto" import "core:crypto"
import "core:crypto/aead" import "core:crypto/aead"
main :: proc() { main :: proc() {
algo := aead.Algorithm.XCHACHA20POLY1305 algo := aead.Algorithm.XCHACHA20POLY1305
// The example added associated data, and plaintext. // The example added associated data, and plaintext.
aad_str := "Get your ass in gear boys." aad_str := "Get your ass in gear boys."
pt_str := "They're immanetizing the Eschaton." pt_str := "They're immanetizing the Eschaton."
aad := transmute([]byte)aad_str aad := transmute([]byte)aad_str
plaintext := transmute([]byte)pt_str plaintext := transmute([]byte)pt_str
pt_len := len(plaintext) pt_len := len(plaintext)
// Generate a random key for the purposes of illustration. // Generate a random key for the purposes of illustration.
key := make([]byte, aead.KEY_SIZES[algo]) key := make([]byte, aead.KEY_SIZES[algo])
defer delete(key) defer delete(key)
crypto.rand_bytes(key) crypto.rand_bytes(key)
// `ciphertext || tag`, is a common way data is transmitted, so // `ciphertext || tag`, is a common way data is transmitted, so
// demonstrate that. // demonstrate that.
buf := make([]byte, pt_len + aead.TAG_SIZES[algo]) buf := make([]byte, pt_len + aead.TAG_SIZES[algo])
defer delete(buf) defer delete(buf)
ciphertext, tag := buf[:pt_len], buf[pt_len:] ciphertext, tag := buf[:pt_len], buf[pt_len:]
// Seal the AAD + Plaintext. // Seal the AAD + Plaintext.
iv := make([]byte, aead.IV_SIZES[algo]) iv := make([]byte, aead.IV_SIZES[algo])
defer delete(iv) defer delete(iv)
crypto.rand_bytes(iv) // Random IVs are safe with XChaCha20-Poly1305. crypto.rand_bytes(iv) // Random IVs are safe with XChaCha20-Poly1305.
aead.seal(algo, ciphertext, tag, key, iv, aad, plaintext) aead.seal(algo, ciphertext, tag, key, iv, aad, plaintext)
// Open the AAD + Ciphertext. // Open the AAD + Ciphertext.
opened_pt := buf[:pt_len] opened_pt := buf[:pt_len]
if ok := aead.open(algo, opened_pt, key, iv, aad, ciphertext, tag); !ok { if ok := aead.open(algo, opened_pt, key, iv, aad, ciphertext, tag); !ok {
panic("aead example: failed to open") 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. package aes implements the AES block cipher and some common modes.
See: See:
- https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.197-upd1.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-38a.pdf ]]
- https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf - [[ https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf ]]
*/ */
package aes package aes
+2 -2
View File
@@ -2,8 +2,8 @@
package blake2b implements the BLAKE2b hash algorithm. package blake2b implements the BLAKE2b hash algorithm.
See: See:
- https://datatracker.ietf.org/doc/html/rfc7693 - [[ https://datatracker.ietf.org/doc/html/rfc7693 ]]
- https://www.blake2.net - [[ https://www.blake2.net ]]
*/ */
package blake2b package blake2b
+2 -2
View File
@@ -2,8 +2,8 @@
package blake2s implements the BLAKE2s hash algorithm. package blake2s implements the BLAKE2s hash algorithm.
See: See:
- https://datatracker.ietf.org/doc/html/rfc7693 - [[ https://datatracker.ietf.org/doc/html/rfc7693 ]]
- https://www.blake2.net/ - [[ https://www.blake2.net/ ]]
*/ */
package blake2s package blake2s
+2 -2
View File
@@ -2,8 +2,8 @@
package chacha20 implements the ChaCha20 and XChaCha20 stream ciphers. package chacha20 implements the ChaCha20 and XChaCha20 stream ciphers.
See: See:
- https://datatracker.ietf.org/doc/html/rfc8439 - [[ https://datatracker.ietf.org/doc/html/rfc8439 ]]
- https://datatracker.ietf.org/doc/draft-irtf-cfrg-xchacha/03/ - [[ https://datatracker.ietf.org/doc/draft-irtf-cfrg-xchacha/03/ ]]
*/ */
package chacha20 package chacha20
@@ -4,8 +4,8 @@ AEAD_XChaCha20_Poly1305 Authenticated Encryption with Additional Data
algorithms. algorithms.
See: See:
- https://www.rfc-editor.org/rfc/rfc8439 - [[ https://www.rfc-editor.org/rfc/rfc8439 ]]
- https://datatracker.ietf.org/doc/html/draft-arciszewski-xchacha-03 - [[ https://datatracker.ietf.org/doc/html/draft-arciszewski-xchacha-03 ]]
*/ */
package chacha20poly1305 package chacha20poly1305
+3 -3
View File
@@ -2,9 +2,9 @@
package ed25519 implements the Ed25519 EdDSA signature algorithm. package ed25519 implements the Ed25519 EdDSA signature algorithm.
See: See:
- https://datatracker.ietf.org/doc/html/rfc8032 - [[ https://datatracker.ietf.org/doc/html/rfc8032 ]]
- https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-5.pdf - [[ https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-5.pdf ]]
- https://eprint.iacr.org/2020/1244.pdf - [[ https://eprint.iacr.org/2020/1244.pdf ]]
*/ */
package ed25519 package ed25519
+28 -30
View File
@@ -17,46 +17,44 @@ accomplish common tasks.
A third optional boolean parameter controls if the file is streamed A third optional boolean parameter controls if the file is streamed
(default), or or read at once. (default), or or read at once.
```odin Example:
package hash_example package hash_example
import "core:crypto/hash" import "core:crypto/hash"
main :: proc() { main :: proc() {
input := "Feed the fire." input := "Feed the fire."
// Compute the digest, using the high level API. // Compute the digest, using the high level API.
returned_digest := hash.hash(hash.Algorithm.SHA512_256, input) returned_digest := hash.hash(hash.Algorithm.SHA512_256, input)
defer delete(returned_digest) defer delete(returned_digest)
// Variant that takes a destination buffer, instead of returning // Variant that takes a destination buffer, instead of returning
// the digest. // 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. 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) defer delete(digest)
hash.hash(hash.Algorithm.BLAKE2B, input, digest) hash.hash(hash.Algorithm.BLAKE2B, input, digest)
} }
```
A generic low level API is provided supporting the init/update/final interface A generic low level API is provided supporting the init/update/final interface
that is typical with cryptographic hash function implementations. that is typical with cryptographic hash function implementations.
```odin Example:
package hash_example package hash_example
import "core:crypto/hash" import "core:crypto/hash"
main :: proc() { main :: proc() {
input := "Let the cinders burn." input := "Let the cinders burn."
// Compute the digest, using the low level API. // Compute the digest, using the low level API.
ctx: hash.Context ctx: hash.Context
digest := make([]byte, hash.DIGEST_SIZES[hash.Algorithm.SHA3_512]) digest := make([]byte, hash.DIGEST_SIZES[hash.Algorithm.SHA3_512])
defer delete(digest) defer delete(digest)
hash.init(&ctx, hash.Algorithm.SHA3_512) hash.init(&ctx, hash.Algorithm.SHA3_512)
hash.update(&ctx, transmute([]byte)input) hash.update(&ctx, transmute([]byte)input)
hash.final(&ctx, digest) hash.final(&ctx, digest)
} }
```
*/ */
package crypto_hash package crypto_hash
+1 -1
View File
@@ -2,7 +2,7 @@
package hkdf implements the HKDF HMAC-based Extract-and-Expand Key package hkdf implements the HKDF HMAC-based Extract-and-Expand Key
Derivation Function. Derivation Function.
See: https://www.rfc-editor.org/rfc/rfc5869 See: [[ https://www.rfc-editor.org/rfc/rfc5869 ]]
*/ */
package hkdf package hkdf
+1 -1
View File
@@ -2,7 +2,7 @@
package hmac implements the HMAC MAC algorithm. package hmac implements the HMAC MAC algorithm.
See: 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 package hmac
+1 -1
View File
@@ -2,7 +2,7 @@
package kmac implements the KMAC MAC algorithm. package kmac implements the KMAC MAC algorithm.
See: 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 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. used for interoperating with legacy applications.
See: See:
- https://eprint.iacr.org/2005/075 - [[ https://eprint.iacr.org/2005/075 ]]
- https://datatracker.ietf.org/doc/html/rfc1321 - [[ https://datatracker.ietf.org/doc/html/rfc1321 ]]
*/ */
package md5 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. used for interoperating with legacy applications.
See: See:
- https://eprint.iacr.org/2017/190 - [[ https://eprint.iacr.org/2017/190 ]]
- https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf - [[ https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf ]]
- https://datatracker.ietf.org/doc/html/rfc3174 - [[ https://datatracker.ietf.org/doc/html/rfc3174 ]]
*/ */
package sha1 package sha1
+1 -1
View File
@@ -1,7 +1,7 @@
/* /*
package pbkdf2 implements the PBKDF2 password-based key derivation function. 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 package pbkdf2
+1 -1
View File
@@ -2,7 +2,7 @@
package poly1305 implements the Poly1305 one-time MAC algorithm. package poly1305 implements the Poly1305 one-time MAC algorithm.
See: See:
- https://datatracker.ietf.org/doc/html/rfc8439 - [[ https://datatracker.ietf.org/doc/html/rfc8439 ]]
*/ */
package poly1305 package poly1305
+1 -1
View File
@@ -2,7 +2,7 @@
package ristretto255 implement the ristretto255 prime-order group. package ristretto255 implement the ristretto255 prime-order group.
See: See:
- https://www.rfc-editor.org/rfc/rfc9496 - [[ https://www.rfc-editor.org/rfc/rfc9496 ]]
*/ */
package ristretto255 package ristretto255
+2 -2
View File
@@ -2,8 +2,8 @@
package sha2 implements the SHA2 hash algorithm family. package sha2 implements the SHA2 hash algorithm family.
See: See:
- https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf - [[ https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf ]]
- https://datatracker.ietf.org/doc/html/rfc3874 - [[ https://datatracker.ietf.org/doc/html/rfc3874 ]]
*/ */
package sha2 package sha2
+1 -1
View File
@@ -6,7 +6,7 @@ pre-standardization Keccak algorithm is required, it can be found in
crypto/legacy/keccak. crypto/legacy/keccak.
See: See:
- https://nvlpubs.nist.gov/nistpubs/fips/nist.fips.202.pdf - [[ https://nvlpubs.nist.gov/nistpubs/fips/nist.fips.202.pdf ]]
*/ */
package sha3 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. The SHA3 hash algorithm can be found in the crypto/sha3.
See: See:
- https://nvlpubs.nist.gov/nistpubs/fips/nist.fips.202.pdf - [[ 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/specialpublications/nist.sp.800-185.pdf ]]
*/ */
package shake 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 package siphash
/* /*
@@ -6,10 +15,6 @@ package siphash
List of contributors: List of contributors:
zhibog: Initial implementation. 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"
+1 -1
View File
@@ -2,7 +2,7 @@
package sm3 implements the SM3 hash algorithm. package sm3 implements the SM3 hash algorithm.
See: 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 package sm3
+1 -1
View File
@@ -2,7 +2,7 @@
package tuplehash implements the TupleHash and TupleHashXOF algorithms. package tuplehash implements the TupleHash and TupleHashXOF algorithms.
See: 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 package tuplehash
+1 -1
View File
@@ -3,7 +3,7 @@ package x25519 implements the X25519 (aka curve25519) Elliptic-Curve
Diffie-Hellman key exchange protocol. Diffie-Hellman key exchange protocol.
See: See:
- https://www.rfc-editor.org/rfc/rfc7748 - [[ https://www.rfc-editor.org/rfc/rfc7748 ]]
*/ */
package x25519 package x25519
+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. 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. 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 For a full example, see: [[ core/dynlib/example; https://github.com/odin-lang/Odin/tree/master/core/dynlib/example ]]
by defining a symbol table struct.
*/ */
package dynlib package dynlib
+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) 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: For more information, see:
1. https://en.wikipedia.org/wiki/ANSI_escape_code - [[ https://en.wikipedia.org/wiki/ANSI_escape_code ]]
2. https://www.vt100.net/docs/vt102-ug/chapter5.html - [[ https://www.vt100.net/docs/vt102-ug/chapter5.html ]]
3. https://invisible-island.net/xterm/ctlseqs/ctlseqs.html - [[ https://invisible-island.net/xterm/ctlseqs/ctlseqs.html ]]
*/ */
package ansi package ansi
+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
-90
View File
@@ -1,90 +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)
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)
}
}
}
+2 -2
View File
@@ -1,5 +1,5 @@
// package csv reads and writes comma-separated values (CSV) files. // 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 package encoding_csv
import "core:bufio" import "core:bufio"
@@ -484,4 +484,4 @@ _read_record :: proc(r: ^Reader, dst: ^[dynamic]string, allocator := context.all
r.fields_per_record = len(dst) r.fields_per_record = len(dst)
} }
return dst[:], err return dst[:], err
} }
+13 -12
View File
@@ -2,22 +2,23 @@
Package endian implements a simple translation between bytes and numbers with Package endian implements a simple translation between bytes and numbers with
specific endian encodings. specific endian encodings.
buf: [100]u8 Example:
put_u16(buf[:], .Little, 16) or_return 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: // You may ask yourself, why isn't `byte_order` platform Endianness by default, so we can write:
put_u16(buf[:], 16) or_return 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 // 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. // 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: // 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 file_order := .Little if buf[0] == 0 else .Big
field := get_u16(buf[1:], file_order) or_return 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, // 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. // 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 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>. Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
Made available under Odin's BSD-3 license. 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: List of contributors:
Jeroen van Rijn: Initial implementation. 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/utf8"
import "core:unicode" import "core:unicode"
import "core:strings" import "core:strings"
@@ -353,4 +355,4 @@ _handle_xml_special :: proc(t: ^Tokenizer, builder: ^strings.Builder, options: X
} }
return false, .None return false, .None
} }
+89 -83
View File
@@ -1,83 +1,89 @@
// Implementation of the HxA 3D asset format /*
// HxA is a interchangeable graphics asset format. Implementation of the HxA 3D asset format
// Designed by Eskil Steenberg. @quelsolaar / eskil 'at' obsession 'dot' se / www.quelsolaar.com 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
// Author of this Odin package: Ginger Bill
// Following comment is copied from the original C-implementation
// --------- 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 - Does the world need another Graphics file format?
// scratch, or don't have some basic features needed in modern computer graphics. Unfortunately, Yes. All existing formats are either too large and complicated to be implemented from
// -Who is this format for? scratch, or don't have some basic features needed in modern computer graphics.
// 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 - Who is this format for?
// wants to build custom graphics pipelines. Given how easy it is to parse and write, it For people who want a capable open Graphics format that can be implemented from scratch in
// should be easy to write utilities that process assets to preform tasks like: generating a few hours. It is ideal for graphics researchers, game developers or other people who
// normals, light-maps, tangent spaces, Error detection, GPU optimization, LOD generation, wants to build custom graphics pipelines. Given how easy it is to parse and write, it
// and UV mapping. should be easy to write utilities that process assets to preform tasks like: generating
// -Why store images in the format when there are so many good image formats already? normals, light-maps, tangent spaces, Error detection, GPU optimization, LOD generation,
// Yes there are, but only for 2D RGB/RGBA images. A lot of computer graphics rendering rely and UV mapping.
// 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 - Why store images in the format when there are so many good image formats already?
// file paths, and this often creates issues when the assets are moved. By including the Yes there are, but only for 2D RGB/RGBA images. A lot of computer graphics rendering rely
// texture data in the files directly the assets become self contained. on 1D, 3D, cube, multilayer, multi channel, floating point bitmap buffers. There almost no
// -Why doesn't the format support <insert whatever>? formats for this kind of data. Also 3D files that reference separate image files rely on
// Because the entire point is to make a format that can be implemented. Features like NURBSs, file paths, and this often creates issues when the assets are moved. By including the
// Construction history, or BSP trees would make the format too large to serve its purpose. texture data in the files directly the assets become self contained.
// 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. - Why doesn't the format support <insert whatever>?
// Because the entire point is to make a format that can be implemented. Features like NURBSs,
// Structure: 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
// HxA is designed to be extremely simple to parse, and is therefore based around conventions. It has for most uses. Adding HxA support should be something anyone can do in a days work.
// 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 Structure:
// 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 HxA is designed to be extremely simple to parse, and is therefore based around conventions. It has
// to store data axillary data. Anyone who wants to store data not covered by a convention can submit a few basic structures, and depending on how they are used they mean different things. This means
// a convention to extend the format. There should never be a convention for storing the same data in that you can implement a tool that loads the entire file, modifies the parts it cares about and
// two differed ways. leaves the rest intact. It is also possible to write a tool that makes all data in the file
// The data is story in a number of nodes that are stored in an array. Each node stores an array of editable without the need to understand its use. It is also possible for anyone to use the format
// meta data. Meta data can describe anything you want, and a lot of conventions will use meta data to store data axillary data. Anyone who wants to store data not covered by a convention can submit
// to store additional information, for things like transforms, lights, shaders and animation. a convention to extend the format. There should never be a convention for storing the same data in
// Data for Vertices, Corners, Faces, and Pixels are stored in named layer stacks. Each stack consists two differed ways.
// 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 The data is story in a number of nodes that are stored in an array. Each node stores an array of
// store data of a different type. 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.
// HaX stores 3 kinds of nodes Data for Vertices, Corners, Faces, and Pixels are stored in named layer stacks. Each stack consists
// - Pixel data. of a number of named layers. All layers in the stack have the same number of elements. Each layer
// - Polygon geometry data. describes one property of the primitive. Each layer can have multiple channels and each layer can
// - Meta data only. store data of a different type.
//
// Pixel Nodes stores pixels in a layer stack. A layer may store things like Albedo, Roughness, HaX stores 3 kinds of nodes
// Reflectance, Light maps, Masks, Normal maps, and Displacement. Layers use the channels of the - Pixel data.
// layers to store things like color. The length of the layer stack is determined by the type and - Polygon geometry data.
// dimensions stored in the - Meta data only.
//
// Geometry data is stored in 3 separate layer stacks for: vertex data, corner data and face data. The Pixel Nodes stores pixels in a layer stack. A layer may store things like Albedo, Roughness,
// vertex data stores things like verities, blend shapes, weight maps, and vertex colors. The first Reflectance, Light maps, Masks, Normal maps, and Displacement. Layers use the channels of the
// layer in a vertex stack has to be a 3 channel layer named "position" describing the base position layers to store things like color.
// of the vertices. The corner stack describes data per corner or edge of the polygons. It can be used The length of the layer stack is determined by the type and dimensions stored in the Geometry data
// for things like UV, normals, and adjacency. The first layer in a corner stack has to be a 1 channel is stored in 3 separate layer stacks for: vertex data, corner data and face data. The
// integer layer named "index" describing the vertices used to form polygons. The last value in each vertex data stores things like verities, blend shapes, weight maps, and vertex colors. The first
// polygon has a negative - 1 index to indicate the end of the polygon. 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
// Example: for things like UV, normals, and adjacency. The first layer in a corner stack has to be a 1 channel
// A quad and a tri with the vertex index: integer layer named "index" describing the vertices used to form polygons. The last value in each
// [0, 1, 2, 3] [1, 4, 2] polygon has a negative - 1 index to indicate the end of the polygon.
// is stored:
// [0, 1, 2, -4, 1, 4, -3] For Example:
// The face stack stores values per face. the length of the face stack has to match the number of A quad and a tri with the vertex index:
// negative values in the index layer in the corner stack. The face stack can be used to store things [0, 1, 2, 3] [1, 4, 2]
// like material index. is stored:
// [0, 1, 2, -4, 1, 4, -3]
// Storage
// ------- The face stack stores values per face. the length of the face stack has to match the number of
// All data is stored in little endian byte order with no padding. The layout mirrors the structs negative values in the index layer in the corner stack. The face stack can be used to store things
// defined below with a few exceptions. All names are stored as a 8-bit unsigned integer indicating like material index.
// 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 Storage:
// integer a 32-bit unsigned integer is used. -------
package encoding_hxa 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
+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 6 without either a clock or node argument.
- Version 7 in all cases. - Version 7 in all cases.
Here's an example of how to set up one: Example:
package main
import "core:crypto" import "core:crypto"
import "core:encoding/uuid" 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: For more information on the specifications, see here:
- https://www.rfc-editor.org/rfc/rfc4122.html - [[ https://www.rfc-editor.org/rfc/rfc4122.html ]]
- https://www.rfc-editor.org/rfc/rfc9562.html - [[ https://www.rfc-editor.org/rfc/rfc9562.html ]]
*/ */
package uuid package uuid
+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:encoding/varint"
import "core:fmt" import "core:fmt"
@@ -22,7 +23,5 @@
assert(decoded_val == value && decode_size == encode_size && decode_err == .None) 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") 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. 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 package encoding_varint
// In theory we should use the bigint package. In practice, varints bigger than this indicate a corrupted file. // 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) buf[size - 1] = u8(low)
} }
return 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>. List of contributors:
available under Odin's BSD-3 license. - Jeroen van Rijn: Initial implementation.
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 encoding_xml package encoding_xml
// An XML 1.0 / 1.1 parser // 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. Arguments are treated differently depending on how they're formatted.
The format is similar to the Odin binary's way of handling compiler flags. The format is similar to the Odin binary's way of handling compiler flags.
``` type handling
type handling ------------ ------------------------
------------ ------------------------ <positional> depends on struct layout
<positional> depends on struct layout -<flag> set a bool true
-<flag> set a bool true -<flag:option> set flag to option
-<flag:option> set flag to option -<flag=option> set flag to option, alternative syntax
-<flag=option> set flag to option, alternative syntax -<map>:<key>=<value> set map[key] to value
-<map>:<key>=<value> set map[key] to value
```
Struct Tags: 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. - `indistinct`: allow the setting of distinct types by their base type.
`required` may be given a range specifier in the following formats: `required` may be given a range specifier in the following formats:
``` min
min <max
<max min<max
min<max
```
`max` is not inclusive in this range, as noted by the less-than `<` sign, so if `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 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. 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 Odin and UNIX style are mutually exclusive, and which one to be used is chosen
at parse time. at parse time.
--flag
``` --flag=argument
--flag --flag argument
--flag=argument --flag argument repeating-argument
--flag argument
--flag argument repeating-argument
```
`-flag` may also be substituted for `--flag`. `-flag` may also be substituted for `--flag`.
Do note that map flags are not currently supported in this parsing style. Do note that map flags are not currently supported in this parsing style.
For a complete example, see: [[ core/flags/example; https://github.com/odin-lang/Odin/blob/master/core/flags/example/example.odin ]].
Example:
A complete example is given in the `example` subdirectory.
*/ */
package flags package flags
+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>. Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
Made available under Odin's BSD-3 license, based on the original C code. Made available under Odin's BSD-3 license, based on the original C code.
@@ -7,6 +6,8 @@
List of contributors: List of contributors:
Jeroen van Rijn: Initial implementation. Jeroen van Rijn: Initial implementation.
*/ */
// An implementation of Yann Collet's [[ xxhash Fast Hash Algorithm; https://cyan4973.github.io/xxHash/ ]].
package xxhash package xxhash
import "base:intrinsics" import "base:intrinsics"
+2 -1
View File
@@ -7,6 +7,7 @@
List of contributors: List of contributors:
Jeroen van Rijn: Initial implementation. Jeroen van Rijn: Initial implementation.
*/ */
package xxhash package xxhash
import "core:mem" 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)) mem_copy(&secret_buffer[segment_start], &segment, size_of(segment))
} }
} }
} }
+1
View File
@@ -7,6 +7,7 @@
List of contributors: List of contributors:
Jeroen van Rijn: Initial implementation. Jeroen van Rijn: Initial implementation.
*/ */
package xxhash package xxhash
import "base:intrinsics" import "base:intrinsics"
+1
View File
@@ -7,6 +7,7 @@
List of contributors: List of contributors:
Jeroen van Rijn: Initial implementation. Jeroen van Rijn: Initial implementation.
*/ */
package xxhash package xxhash
import "base:intrinsics" import "base:intrinsics"
+1
View File
@@ -7,6 +7,7 @@
List of contributors: List of contributors:
Jeroen van Rijn: Initial implementation. Jeroen van Rijn: Initial implementation.
*/ */
package xxhash package xxhash
import "base:intrinsics" import "base:intrinsics"
+348
View File
@@ -0,0 +1,348 @@
/*
package png implements a PNG image reader
The PNG specification is at [[ https://www.w3.org/TR/PNG/ ]].
Example:
package main
import "core:image"
// import "core:image/png"
import "core:bytes"
import "core:fmt"
// For PPM writer
import "core:mem"
import "core:os"
main :: proc() {
track := mem.Tracking_Allocator{}
mem.tracking_allocator_init(&track, context.allocator)
context.allocator = mem.tracking_allocator(&track)
demo()
if len(track.allocation_map) > 0 {
fmt.println("Leaks:")
for _, v in track.allocation_map {
fmt.printf("\t%v\n\n", v)
}
}
}
demo :: proc() {
file: string
options := image.Options{.return_metadata}
err: image.Error
img: ^image.Image
file = "../../../misc/logo-slim.png"
img, err = load(file, options)
defer destroy(img)
if err != nil {
fmt.printf("Trying to read PNG file %v returned %v\n", file, err)
} else {
fmt.printf("Image: %vx%vx%v, %v-bit.\n", img.width, img.height, img.channels, img.depth)
if v, ok := img.metadata.(^image.PNG_Info); ok {
// Handle ancillary chunks as you wish.
// We provide helper functions for a few types.
for c in v.chunks {
#partial switch c.header.type {
case .tIME:
if t, t_ok := core_time(c); t_ok {
fmt.printf("[tIME]: %v\n", t)
}
case .gAMA:
if gama, gama_ok := gamma(c); gama_ok {
fmt.printf("[gAMA]: %v\n", gama)
}
case .pHYs:
if phys, phys_ok := phys(c); phys_ok {
if phys.unit == .Meter {
xm := f32(img.width) / f32(phys.ppu_x)
ym := f32(img.height) / f32(phys.ppu_y)
dpi_x, dpi_y := phys_to_dpi(phys)
fmt.printf("[pHYs] Image resolution is %v x %v pixels per meter.\n", phys.ppu_x, phys.ppu_y)
fmt.printf("[pHYs] Image resolution is %v x %v DPI.\n", dpi_x, dpi_y)
fmt.printf("[pHYs] Image dimensions are %v x %v meters.\n", xm, ym)
} else {
fmt.printf("[pHYs] x: %v, y: %v pixels per unknown unit.\n", phys.ppu_x, phys.ppu_y)
}
}
case .iTXt, .zTXt, .tEXt:
res, ok_text := text(c)
if ok_text {
if c.header.type == .iTXt {
fmt.printf("[iTXt] %v (%v:%v): %v\n", res.keyword, res.language, res.keyword_localized, res.text)
} else {
fmt.printf("[tEXt/zTXt] %v: %v\n", res.keyword, res.text)
}
}
defer text_destroy(res)
case .bKGD:
fmt.printf("[bKGD] %v\n", img.background)
case .eXIf:
if res, ok_exif := exif(c); ok_exif {
/*
Other than checking the signature and byte order, we don't handle Exif data.
If you wish to interpret it, pass it to an Exif parser.
*/
fmt.printf("[eXIf] %v\n", res)
}
case .PLTE:
if plte, plte_ok := plte(c); plte_ok {
fmt.printf("[PLTE] %v\n", plte)
} else {
fmt.printf("[PLTE] Error\n")
}
case .hIST:
if res, ok_hist := hist(c); ok_hist {
fmt.printf("[hIST] %v\n", res)
}
case .cHRM:
if res, ok_chrm := chrm(c); ok_chrm {
fmt.printf("[cHRM] %v\n", res)
}
case .sPLT:
res, ok_splt := splt(c)
if ok_splt {
fmt.printf("[sPLT] %v\n", res)
}
splt_destroy(res)
case .sBIT:
if res, ok_sbit := sbit(c); ok_sbit {
fmt.printf("[sBIT] %v\n", res)
}
case .iCCP:
res, ok_iccp := iccp(c)
if ok_iccp {
fmt.printf("[iCCP] %v\n", res)
}
iccp_destroy(res)
case .sRGB:
if res, ok_srgb := srgb(c); ok_srgb {
fmt.printf("[sRGB] Rendering intent: %v\n", res)
}
case:
type := c.header.type
name := chunk_type_to_name(&type)
fmt.printf("[%v]: %v\n", name, c.data)
}
}
}
}
fmt.printf("Done parsing metadata.\n")
if err == nil && .do_not_decompress_image not_in options && .info not_in options {
if ok := write_image_as_ppm("out.ppm", img); ok {
fmt.println("Saved decoded image.")
} else {
fmt.println("Error saving out.ppm.")
fmt.println(img)
}
}
}
// Crappy PPM writer used during testing. Don't use in production.
write_image_as_ppm :: proc(filename: string, image: ^image.Image) -> (success: bool) {
_bg :: proc(bg: Maybe([3]u16), x, y: int, high := true) -> (res: [3]u16) {
if v, ok := bg.?; ok {
res = v
} else {
if high {
l := u16(30 * 256 + 30)
if (x & 4 == 0) ~ (y & 4 == 0) {
res = [3]u16{l, 0, l}
} else {
res = [3]u16{l >> 1, 0, l >> 1}
}
} else {
if (x & 4 == 0) ~ (y & 4 == 0) {
res = [3]u16{30, 30, 30}
} else {
res = [3]u16{15, 15, 15}
}
}
}
return
}
// profiler.timed_proc();
using image
using os
flags: int = O_WRONLY|O_CREATE|O_TRUNC
img := image
// PBM 16-bit images are big endian
when ODIN_ENDIAN == .Little {
if img.depth == 16 {
// The pixel components are in Big Endian. Let's byteswap back.
input := mem.slice_data_cast([]u16, img.pixels.buf[:])
output := mem.slice_data_cast([]u16be, img.pixels.buf[:])
#no_bounds_check for v, i in input {
output[i] = u16be(v)
}
}
}
pix := bytes.buffer_to_bytes(&img.pixels)
if len(pix) == 0 || len(pix) < image.width * image.height * int(image.channels) {
return false
}
mode: int = 0
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, err := open(filename, flags, mode)
if err != nil {
return false
}
defer close(fd)
write_string(fd,
fmt.tprintf("P6\n%v %v\n%v\n", width, height, uint(1 << uint(depth) - 1)),
)
if channels == 3 {
// We don't handle transparency here...
write_ptr(fd, raw_data(pix), len(pix))
} else {
bpp := depth == 16 ? 2 : 1
bytes_needed := width * height * 3 * bpp
op := bytes.Buffer{}
bytes.buffer_init_allocator(&op, bytes_needed, bytes_needed)
defer bytes.buffer_destroy(&op)
if channels == 1 {
if depth == 16 {
assert(len(pix) == width * height * 2)
p16 := mem.slice_data_cast([]u16, pix)
o16 := mem.slice_data_cast([]u16, op.buf[:])
#no_bounds_check for len(p16) != 0 {
r := u16(p16[0])
o16[0] = r
o16[1] = r
o16[2] = r
p16 = p16[1:]
o16 = o16[3:]
}
} else {
o := 0
for i := 0; i < len(pix); i += 1 {
r := pix[i]
op.buf[o ] = r
op.buf[o+1] = r
op.buf[o+2] = r
o += 3
}
}
write_ptr(fd, raw_data(op.buf), len(op.buf))
} else if channels == 2 {
if depth == 16 {
p16 := mem.slice_data_cast([]u16, pix)
o16 := mem.slice_data_cast([]u16, op.buf[:])
bgcol := img.background
#no_bounds_check for len(p16) != 0 {
r := f64(u16(p16[0]))
bg: f64
if bgcol != nil {
v := bgcol.([3]u16)[0]
bg = f64(v)
}
a := f64(u16(p16[1])) / 65535.0
l := (a * r) + (1 - a) * bg
o16[0] = u16(l)
o16[1] = u16(l)
o16[2] = u16(l)
p16 = p16[2:]
o16 = o16[3:]
}
} else {
o := 0
for i := 0; i < len(pix); i += 2 {
r := pix[i]; a := pix[i+1]; a1 := f32(a) / 255.0
c := u8(f32(r) * a1)
op.buf[o ] = c
op.buf[o+1] = c
op.buf[o+2] = c
o += 3
}
}
write_ptr(fd, raw_data(op.buf), len(op.buf))
} else if channels == 4 {
if depth == 16 {
p16 := mem.slice_data_cast([]u16be, pix)
o16 := mem.slice_data_cast([]u16be, op.buf[:])
#no_bounds_check for len(p16) != 0 {
bg := _bg(img.background, 0, 0)
r := f32(p16[0])
g := f32(p16[1])
b := f32(p16[2])
a := f32(p16[3]) / 65535.0
lr := (a * r) + (1 - a) * f32(bg[0])
lg := (a * g) + (1 - a) * f32(bg[1])
lb := (a * b) + (1 - a) * f32(bg[2])
o16[0] = u16be(lr)
o16[1] = u16be(lg)
o16[2] = u16be(lb)
p16 = p16[4:]
o16 = o16[3:]
}
} else {
o := 0
for i := 0; i < len(pix); i += 4 {
x := (i / 4) % width
y := i / width / 4
_b := _bg(img.background, x, y, false)
bgcol := [3]u8{u8(_b[0]), u8(_b[1]), u8(_b[2])}
r := f32(pix[i])
g := f32(pix[i+1])
b := f32(pix[i+2])
a := f32(pix[i+3]) / 255.0
lr := u8(f32(r) * a + (1 - a) * f32(bgcol[0]))
lg := u8(f32(g) * a + (1 - a) * f32(bgcol[1]))
lb := u8(f32(b) * a + (1 - a) * f32(bgcol[2]))
op.buf[o ] = lr
op.buf[o+1] = lg
op.buf[o+2] = lb
o += 3
}
}
write_ptr(fd, raw_data(op.buf), len(op.buf))
} else {
return false
}
}
return true
}
*/
package png
-351
View File
@@ -1,351 +0,0 @@
/*
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.
An example of how to use `load`.
*/
//+build ignore
package png
import "core:image"
// import "core:image/png"
import "core:bytes"
import "core:fmt"
// For PPM writer
import "core:mem"
import "core:os"
main :: proc() {
track := mem.Tracking_Allocator{}
mem.tracking_allocator_init(&track, context.allocator)
context.allocator = mem.tracking_allocator(&track)
demo()
if len(track.allocation_map) > 0 {
fmt.println("Leaks:")
for _, v in track.allocation_map {
fmt.printf("\t%v\n\n", v)
}
}
}
demo :: proc() {
file: string
options := image.Options{.return_metadata}
err: image.Error
img: ^image.Image
file = "../../../misc/logo-slim.png"
img, err = load(file, options)
defer destroy(img)
if err != nil {
fmt.printf("Trying to read PNG file %v returned %v\n", file, err)
} else {
fmt.printf("Image: %vx%vx%v, %v-bit.\n", img.width, img.height, img.channels, img.depth)
if v, ok := img.metadata.(^image.PNG_Info); ok {
// Handle ancillary chunks as you wish.
// We provide helper functions for a few types.
for c in v.chunks {
#partial switch c.header.type {
case .tIME:
if t, t_ok := core_time(c); t_ok {
fmt.printf("[tIME]: %v\n", t)
}
case .gAMA:
if gama, gama_ok := gamma(c); gama_ok {
fmt.printf("[gAMA]: %v\n", gama)
}
case .pHYs:
if phys, phys_ok := phys(c); phys_ok {
if phys.unit == .Meter {
xm := f32(img.width) / f32(phys.ppu_x)
ym := f32(img.height) / f32(phys.ppu_y)
dpi_x, dpi_y := phys_to_dpi(phys)
fmt.printf("[pHYs] Image resolution is %v x %v pixels per meter.\n", phys.ppu_x, phys.ppu_y)
fmt.printf("[pHYs] Image resolution is %v x %v DPI.\n", dpi_x, dpi_y)
fmt.printf("[pHYs] Image dimensions are %v x %v meters.\n", xm, ym)
} else {
fmt.printf("[pHYs] x: %v, y: %v pixels per unknown unit.\n", phys.ppu_x, phys.ppu_y)
}
}
case .iTXt, .zTXt, .tEXt:
res, ok_text := text(c)
if ok_text {
if c.header.type == .iTXt {
fmt.printf("[iTXt] %v (%v:%v): %v\n", res.keyword, res.language, res.keyword_localized, res.text)
} else {
fmt.printf("[tEXt/zTXt] %v: %v\n", res.keyword, res.text)
}
}
defer text_destroy(res)
case .bKGD:
fmt.printf("[bKGD] %v\n", img.background)
case .eXIf:
if res, ok_exif := exif(c); ok_exif {
/*
Other than checking the signature and byte order, we don't handle Exif data.
If you wish to interpret it, pass it to an Exif parser.
*/
fmt.printf("[eXIf] %v\n", res)
}
case .PLTE:
if plte, plte_ok := plte(c); plte_ok {
fmt.printf("[PLTE] %v\n", plte)
} else {
fmt.printf("[PLTE] Error\n")
}
case .hIST:
if res, ok_hist := hist(c); ok_hist {
fmt.printf("[hIST] %v\n", res)
}
case .cHRM:
if res, ok_chrm := chrm(c); ok_chrm {
fmt.printf("[cHRM] %v\n", res)
}
case .sPLT:
res, ok_splt := splt(c)
if ok_splt {
fmt.printf("[sPLT] %v\n", res)
}
splt_destroy(res)
case .sBIT:
if res, ok_sbit := sbit(c); ok_sbit {
fmt.printf("[sBIT] %v\n", res)
}
case .iCCP:
res, ok_iccp := iccp(c)
if ok_iccp {
fmt.printf("[iCCP] %v\n", res)
}
iccp_destroy(res)
case .sRGB:
if res, ok_srgb := srgb(c); ok_srgb {
fmt.printf("[sRGB] Rendering intent: %v\n", res)
}
case:
type := c.header.type
name := chunk_type_to_name(&type)
fmt.printf("[%v]: %v\n", name, c.data)
}
}
}
}
fmt.printf("Done parsing metadata.\n")
if err == nil && .do_not_decompress_image not_in options && .info not_in options {
if ok := write_image_as_ppm("out.ppm", img); ok {
fmt.println("Saved decoded image.")
} else {
fmt.println("Error saving out.ppm.")
fmt.println(img)
}
}
}
// Crappy PPM writer used during testing. Don't use in production.
write_image_as_ppm :: proc(filename: string, image: ^image.Image) -> (success: bool) {
_bg :: proc(bg: Maybe([3]u16), x, y: int, high := true) -> (res: [3]u16) {
if v, ok := bg.?; ok {
res = v
} else {
if high {
l := u16(30 * 256 + 30)
if (x & 4 == 0) ~ (y & 4 == 0) {
res = [3]u16{l, 0, l}
} else {
res = [3]u16{l >> 1, 0, l >> 1}
}
} else {
if (x & 4 == 0) ~ (y & 4 == 0) {
res = [3]u16{30, 30, 30}
} else {
res = [3]u16{15, 15, 15}
}
}
}
return
}
// profiler.timed_proc();
using image
using os
flags: int = O_WRONLY|O_CREATE|O_TRUNC
img := image
// PBM 16-bit images are big endian
when ODIN_ENDIAN == .Little {
if img.depth == 16 {
// The pixel components are in Big Endian. Let's byteswap back.
input := mem.slice_data_cast([]u16, img.pixels.buf[:])
output := mem.slice_data_cast([]u16be, img.pixels.buf[:])
#no_bounds_check for v, i in input {
output[i] = u16be(v)
}
}
}
pix := bytes.buffer_to_bytes(&img.pixels)
if len(pix) == 0 || len(pix) < image.width * image.height * int(image.channels) {
return false
}
mode: int = 0
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, err := open(filename, flags, mode)
if err != nil {
return false
}
defer close(fd)
write_string(fd,
fmt.tprintf("P6\n%v %v\n%v\n", width, height, uint(1 << uint(depth) - 1)),
)
if channels == 3 {
// We don't handle transparency here...
write_ptr(fd, raw_data(pix), len(pix))
} else {
bpp := depth == 16 ? 2 : 1
bytes_needed := width * height * 3 * bpp
op := bytes.Buffer{}
bytes.buffer_init_allocator(&op, bytes_needed, bytes_needed)
defer bytes.buffer_destroy(&op)
if channels == 1 {
if depth == 16 {
assert(len(pix) == width * height * 2)
p16 := mem.slice_data_cast([]u16, pix)
o16 := mem.slice_data_cast([]u16, op.buf[:])
#no_bounds_check for len(p16) != 0 {
r := u16(p16[0])
o16[0] = r
o16[1] = r
o16[2] = r
p16 = p16[1:]
o16 = o16[3:]
}
} else {
o := 0
for i := 0; i < len(pix); i += 1 {
r := pix[i]
op.buf[o ] = r
op.buf[o+1] = r
op.buf[o+2] = r
o += 3
}
}
write_ptr(fd, raw_data(op.buf), len(op.buf))
} else if channels == 2 {
if depth == 16 {
p16 := mem.slice_data_cast([]u16, pix)
o16 := mem.slice_data_cast([]u16, op.buf[:])
bgcol := img.background
#no_bounds_check for len(p16) != 0 {
r := f64(u16(p16[0]))
bg: f64
if bgcol != nil {
v := bgcol.([3]u16)[0]
bg = f64(v)
}
a := f64(u16(p16[1])) / 65535.0
l := (a * r) + (1 - a) * bg
o16[0] = u16(l)
o16[1] = u16(l)
o16[2] = u16(l)
p16 = p16[2:]
o16 = o16[3:]
}
} else {
o := 0
for i := 0; i < len(pix); i += 2 {
r := pix[i]; a := pix[i+1]; a1 := f32(a) / 255.0
c := u8(f32(r) * a1)
op.buf[o ] = c
op.buf[o+1] = c
op.buf[o+2] = c
o += 3
}
}
write_ptr(fd, raw_data(op.buf), len(op.buf))
} else if channels == 4 {
if depth == 16 {
p16 := mem.slice_data_cast([]u16be, pix)
o16 := mem.slice_data_cast([]u16be, op.buf[:])
#no_bounds_check for len(p16) != 0 {
bg := _bg(img.background, 0, 0)
r := f32(p16[0])
g := f32(p16[1])
b := f32(p16[2])
a := f32(p16[3]) / 65535.0
lr := (a * r) + (1 - a) * f32(bg[0])
lg := (a * g) + (1 - a) * f32(bg[1])
lb := (a * b) + (1 - a) * f32(bg[2])
o16[0] = u16be(lr)
o16[1] = u16be(lg)
o16[2] = u16be(lb)
p16 = p16[4:]
o16 = o16[3:]
}
} else {
o := 0
for i := 0; i < len(pix); i += 4 {
x := (i / 4) % width
y := i / width / 4
_b := _bg(img.background, x, y, false)
bgcol := [3]u8{u8(_b[0]), u8(_b[1]), u8(_b[2])}
r := f32(pix[i])
g := f32(pix[i+1])
b := f32(pix[i+2])
a := f32(pix[i+3]) / 255.0
lr := u8(f32(r) * a + (1 - a) * f32(bgcol[0]))
lg := u8(f32(g) * a + (1 - a) * f32(bgcol[1]))
lb := u8(f32(b) * a + (1 - a) * f32(bgcol[2]))
op.buf[o ] = lr
op.buf[o+1] = lg
op.buf[o+2] = lb
o += 3
}
}
write_ptr(fd, raw_data(op.buf), len(op.buf))
} else {
return false
}
}
return true
}
+1
View File
@@ -8,6 +8,7 @@
These are a few useful utility functions to work with PNG images. These are a few useful utility functions to work with PNG images.
*/ */
package png package png
import "core:image" import "core:image"
+1 -4
View File
@@ -8,9 +8,6 @@
*/ */
// package png implements a PNG image reader
//
// The PNG specification is at https://www.w3.org/TR/PNG/.
//+vet !using-stmt //+vet !using-stmt
package png package png
@@ -1619,4 +1616,4 @@ defilter :: proc(img: ^Image, filter_bytes: ^bytes.Buffer, header: ^image.PNG_IH
@(init, private) @(init, private)
_register :: proc() { _register :: proc() {
image.register(.PNG, load_from_bytes, destroy) image.register(.PNG, load_from_bytes, destroy)
} }
+1 -1
View File
@@ -9,7 +9,7 @@
// package qoi implements a QOI image reader // package qoi implements a QOI image reader
// //
// The QOI specification is at https://qoiformat.org. // The QOI specification is at [[ https://qoiformat.org ]].
package qoi package qoi
import "core:image" import "core:image"
+3 -3
View File
@@ -1,8 +1,8 @@
/* /*
OpenSimplex2 noise implementation. OpenSimplex2 noise implementation.
Ported from https://github.com/KdotJPG/OpenSimplex2. Ported from [[ https://github.com/KdotJPG/OpenSimplex2 }].
Copyright 2022 Yuki2 (https://github.com/NoahR02) Copyright 2022 Yuki2 [[ https://github.com/NoahR02 ]]
*/ */
package math_noise package math_noise
@@ -177,4 +177,4 @@ noise_4d_fallback :: proc(seed: i64, coord: Vec4) -> (value: f32) {
// Get points for A4 lattice // Get points for A4 lattice
skew := f64(SKEW_4D) * (coord.x + coord.y + coord.z + coord.w) skew := f64(SKEW_4D) * (coord.x + coord.y + coord.z + coord.w)
return _internal_noise_4d_unskewed_base(seed, coord + skew) return _internal_noise_4d_unskewed_base(seed, coord + skew)
} }
+25 -27
View File
@@ -13,36 +13,34 @@
*/ */
/* /*
Package net implements cross-platform Berkeley Sockets, DNS resolution and associated procedures. Package net implements cross-platform Berkeley Sockets, DNS resolution and associated procedures.
For other protocols and their features, see subdirectories of this package. For other protocols and their features, see subdirectories of this package.
Features: Features:
- Supports Windows, Linux and OSX. - Supports Windows, Linux and OSX.
- Opening and closing of TCP and UDP sockets. - Opening and closing of TCP and UDP sockets.
- Sending to and receiving from these sockets. - Sending to and receiving from these sockets.
- DNS name lookup, using either the OS or our own resolver. - DNS name lookup, using either the OS or our own resolver.
Planned: Planned:
- Nonblocking IO - Nonblocking IO
- `Connection` struct - `Connection` struct; A "fat socket" struct that remembers how you opened it, etc, instead of just being a handle.
A "fat socket" struct that remembers how you opened it, etc, instead of just being a handle. - IP Range structs, CIDR/class ranges, netmask calculator and associated helper procedures.
- IP Range structs, CIDR/class ranges, netmask calculator and associated helper procedures. - Use `context.temp_allocator` instead of stack-based arenas?
- Use `context.temp_allocator` instead of stack-based arenas? And check it's the default temp allocator or can give us 4 MiB worth of memory
And check it's the default temp allocator or can give us 4 MiB worth of memory without punting to the main allocator by comparing their addresses in an @(init) procedure.
without punting to the main allocator by comparing their addresses in an @(init) procedure. Panic if this assumption is not met.
Panic if this assumption is not met. - Document assumptions about libc usage (or avoidance thereof) for each platform.
- Document assumptions about libc usage (or avoidance thereof) for each platform. Assumptions:
For performance reasons this package relies on the `context.temp_allocator` in some places.
Assumptions: You can replace the default `context.temp_allocator` with your own as long as it meets
- For performance reasons this package relies on the `context.temp_allocator` in some places. this requirement: A minimum of 4 MiB of scratch space that's expected not to be freed.
You can replace the default `context.temp_allocator` with your own as long as it meets If this expectation is not met, the package's @(init) procedure will attempt to detect
this requirement: A minimum of 4 MiB of scratch space that's expected not to be freed. this and panic to avoid temp allocations prematurely overwriting data and garbling results,
or worse. This means that should you replace the temp allocator with an insufficient one,
If this expectation is not met, the package's @(init) procedure will attempt to detect we'll do our best to loudly complain the first time you try it.
this and panic to avoid temp allocations prematurely overwriting data and garbling results,
or worse. This means that should you replace the temp allocator with an insufficient one,
we'll do our best to loudly complain the first time you try it.
*/ */
package net package net
+3
View File
@@ -1,4 +1,7 @@
/* /*
Example:
package main
import "base:runtime" import "base:runtime"
import "core:prof/spall" import "core:prof/spall"
import "core:sync" import "core:sync"
+3 -3
View File
@@ -7,8 +7,8 @@ synchronize threads' access to shared memory.
To limit or control the threads' access to shared memory typically the To limit or control the threads' access to shared memory typically the
following approaches are used: following approaches are used:
* Locks - Locks
* Lock-free - Lock-free
When using locks, sections of the code that access shared memory (also known as When using locks, sections of the code that access shared memory (also known as
**critical sections**) are guarded by locks, allowing limited access to threads **critical sections**) are guarded by locks, allowing limited access to threads
@@ -18,4 +18,4 @@ In lock-free programming the data itself is organized in such a way that threads
don't intervene much. It can be done via segmenting the data between threads, don't intervene much. It can be done via segmenting the data between threads,
and/or by using atomic operations. and/or by using atomic operations.
*/ */
package sync package sync
+8 -1
View File
@@ -2,6 +2,12 @@
Copyright 2022 Jeroen van Rijn <nom@duclavier.com>. Copyright 2022 Jeroen van Rijn <nom@duclavier.com>.
Made available under Odin's BSD-3 license. Made available under Odin's BSD-3 license.
List of contributors:
Jeroen van Rijn: Initial implementation.
Laytan: ARM and RISC-V CPU feature detection.
*/
/*
Package `core:sys/info` gathers system information on: Package `core:sys/info` gathers system information on:
Windows, Linux, macOS, FreeBSD & OpenBSD. Windows, Linux, macOS, FreeBSD & OpenBSD.
@@ -11,9 +17,10 @@ and CPU information.
On Windows, GPUs will also be enumerated using the registry. On Windows, GPUs will also be enumerated using the registry.
CPU feature flags can be tested against `cpu_features`, where applicable, e.g. CPU feature flags can be tested against `cpu_features`, where applicable, e.g.
`if .aes in si.aes { ... }` `if .aes in info.cpu_features.? { ... }`
Example: Example:
package main
import "core:fmt" import "core:fmt"
import si "core:sys/info" import si "core:sys/info"
+1
View File
@@ -1,4 +1,5 @@
// Bit Manipulation Intrinsics // Bit Manipulation Intrinsics
package sys_llvm package sys_llvm
/* /*
+1
View File
@@ -1,4 +1,5 @@
// Code Generator Intrinsics // Code Generator Intrinsics
package sys_llvm package sys_llvm
@(default_calling_convention="none") @(default_calling_convention="none")
+1
View File
@@ -1,4 +1,5 @@
// Standard C Library Intrinsics // Standard C Library Intrinsics
package sys_llvm package sys_llvm
@(default_calling_convention="none") @(default_calling_convention="none")
+1 -1
View File
@@ -112,7 +112,7 @@ foreign lib {
Return configuration-defined string values. Return configuration-defined string values.
Its use and purpose are similar to sysconf(), but it is used where string values rather than numeric values are returned. Its use and purpose are similar to sysconf(), but it is used where string values rather than numeric values are returned.
Returns: 0 (setting errno) if `name` is invalid, need `buf` `len` if buf is `nil`, amount of bytes added to buf otherwise Returns: 0 (setting errno) if `name` is invalid, need `buf` of `len` bytes if `buf` is `nil`, amount of bytes added to buf otherwise
[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/confstr.html ]] [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/confstr.html ]]
*/ */
+4 -5
View File
@@ -1,10 +1,9 @@
package text_edit
/* /*
Based off the articles by rxi: Based off the articles by rxi:
* https://rxi.github.io/textbox_behaviour.html - [[ https://rxi.github.io/textbox_behaviour.html ]]
* https://rxi.github.io/a_simple_undo_system.html - [[ https://rxi.github.io/a_simple_undo_system.html ]]
*/ */
package text_edit
import "base:runtime" import "base:runtime"
import "core:time" import "core:time"
+10 -19
View File
@@ -1,8 +1,8 @@
/* /*
The package `table` implements plain-text/markdown/HTML/custom rendering of tables. The package `table` implements plain-text/markdown/HTML/custom rendering of tables.
**Custom rendering example:** **Custom rendering.**
Example:
package main package main
import "core:io" import "core:io"
@@ -24,13 +24,12 @@ The package `table` implements plain-text/markdown/HTML/custom rendering of tabl
} }
} }
This outputs: Output:
A_LONG_ENUM = 54, // A comment about A_LONG_ENUM A_LONG_ENUM = 54, // A comment about A_LONG_ENUM
AN_EVEN_LONGER_ENUM = 1, // A comment about AN_EVEN_LONGER_ENUM AN_EVEN_LONGER_ENUM = 1, // A comment about AN_EVEN_LONGER_ENUM
**Plain-text rendering example:** **Plain-text rendering.**
Example:
package main package main
import "core:fmt" import "core:fmt"
@@ -81,8 +80,7 @@ This outputs:
table.write_markdown_table(stdout, tbl) table.write_markdown_table(stdout, tbl)
} }
This outputs: Output:
+-----------------------------------------------+ +-----------------------------------------------+
| This is a table caption and it is very long | | This is a table caption and it is very long |
+------------------+-----------------+----------+ +------------------+-----------------+----------+
@@ -93,16 +91,12 @@ This outputs:
| a | bbb | c | | a | bbb | c |
+------------------+-----------------+----------+ +------------------+-----------------+----------+
and
| AAAAAAAAA | B | C | | AAAAAAAAA | B | C |
|:-----------------|:---------------:|---------:| |:-----------------|:---------------:|---------:|
| 123 | foo | | | 123 | foo | |
| 000000005 | 6.283185 | | | 000000005 | 6.283185 | |
| a | bbb | c | | a | bbb | c |
respectively.
Additionally, if you want to set the alignment and values in-line while Additionally, if you want to set the alignment and values in-line while
constructing a table, you can use `aligned_row_of_values` or constructing a table, you can use `aligned_row_of_values` or
@@ -116,8 +110,7 @@ constructing a table, you can use `aligned_row_of_values` or
If you only need to build a table once but display it potentially many times, If you only need to build a table once but display it potentially many times,
it may be more efficient to cache the results of your write into a string. it may be more efficient to cache the results of your write into a string.
Here's an example of how you can do that: Example:
package main package main
import "core:fmt" import "core:fmt"
@@ -191,8 +184,7 @@ This package makes use of the `grapheme_count` procedure from the
implementation for counting graphemes and calculating visual width of a Unicode implementation for counting graphemes and calculating visual width of a Unicode
grapheme cluster in monospace cells. grapheme cluster in monospace cells.
Here is a full example of how well-supported Unicode is with this package: Example:
package main package main
import "core:fmt" import "core:fmt"
@@ -237,7 +229,7 @@ Here is a full example of how well-supported Unicode is with this package:
scripts(stdout) scripts(stdout)
} }
This will print out: Output:
+----------------------------------------------------------------------------------------------------------------------------+ +----------------------------------------------------------------------------------------------------------------------------+
| Tést Suite | | Tést Suite |
@@ -271,8 +263,7 @@ If you'd prefer to change the borders used by the plain-text table printing,
there is the `write_decorated_table` procedure that allows you to change the there is the `write_decorated_table` procedure that allows you to change the
corners and dividers. corners and dividers.
Here is a complete example: Example:
package main package main
import "core:fmt" import "core:fmt"