This commit is contained in:
Christoffer Lerno
2023-02-24 10:49:01 +01:00
parent a7ce0f95e6
commit 2f255ac5c3
4 changed files with 272 additions and 5 deletions

View File

@@ -74,14 +74,14 @@ fn void*! SimpleHeapAllocator._realloc(SimpleHeapAllocator* this, void* old_poin
return new;
}
fn void*! SimpleHeapAllocator._calloc(SimpleHeapAllocator* this, usz bytes) @private
fn void*! SimpleHeapAllocator._calloc(SimpleHeapAllocator* this, usz bytes) @local
{
void* data = this._alloc(bytes)?;
mem::clear(data, bytes, DEFAULT_MEM_ALIGNMENT);
return data;
}
fn void*! SimpleHeapAllocator._alloc(SimpleHeapAllocator* this, usz bytes) @private
fn void*! SimpleHeapAllocator._alloc(SimpleHeapAllocator* this, usz bytes) @local
{
usz aligned_bytes = mem::aligned_offset(bytes, DEFAULT_MEM_ALIGNMENT);
if (!this.free_list)
@@ -130,7 +130,7 @@ fn void*! SimpleHeapAllocator._alloc(SimpleHeapAllocator* this, usz bytes) @priv
return this.alloc(aligned_bytes);
}
fn void! SimpleHeapAllocator.add_block(SimpleHeapAllocator* this, usz aligned_bytes) @private
fn void! SimpleHeapAllocator.add_block(SimpleHeapAllocator* this, usz aligned_bytes) @local
{
assert(mem::aligned_offset(aligned_bytes, DEFAULT_MEM_ALIGNMENT) == aligned_bytes);
char[] result = this.alloc_fn(aligned_bytes + Header.sizeof)?;
@@ -141,7 +141,7 @@ fn void! SimpleHeapAllocator.add_block(SimpleHeapAllocator* this, usz aligned_by
}
fn void SimpleHeapAllocator._free(SimpleHeapAllocator* this, void* ptr) @private
fn void SimpleHeapAllocator._free(SimpleHeapAllocator* this, void* ptr) @local
{
// Empty ptr -> do nothing.
if (!ptr) return;

View File

@@ -6,7 +6,7 @@ typedef DynStr = VarString;
typedef DynString = VarString;
typedef DString = VarString;
typedef VString = VarString;
typedef Text = VarString;
const usz MIN_CAPACITY = 16;

237
lib/std/hash/sha1.c3 Normal file
View File

@@ -0,0 +1,237 @@
// Copyright (c) 2021 Christoffer Lerno. All rights reserved.
// Use of this source code is governed by the MIT license
// a copy of which can be found in the LICENSE_STDLIB file.
//
// Implementation was off Steve Reid's SHA-1 C implementation
module std::hash::sha1;
import std::bits;
struct Sha1
{
uint[5] state;
uint[2] count;
char[64] buffer;
}
fn void Sha1.init(Sha1* this)
{
// SHA1 initialization constants
*this = {
.state = {
0x67452301,
0xEFCDAB89,
0x98BADCFE,
0x10325476,
0xC3D2E1F0
}
};
}
/**
* @param [&inout] this
* @param [in] data
* @require data.len <= uint.max
**/
fn void Sha1.update(Sha1* this, char[] data)
{
uint j = this.count[0];
uint len = data.len;
if ((this.count[0] += len << 3) < j) this.count[1]++;
this.count[1] += len >> 29;
j = (j >> 3) & 63;
uint i;
if (j + len > 63)
{
i = 64 - j;
this.buffer[j..] = data[:i];
sha1_transform(&this.state, &this.buffer);
for (; i + 63 < len; i += 64)
{
sha1_transform(&this.state, &data[i]);
}
j = 0;
}
this.buffer[j:len - i] = data[i..];
}
fn char[20] Sha1.final(Sha1* this)
{
char[8] finalcount;
for (uint i = 0; i < 8; i++)
{
finalcount[i] = (char)((this.count[(i >= 4 ? 0 : 1)] >> ((3 - (i & 3)) * 8)) & 0xFF);
}
this.update(char[] { 0o200 });
while ((this.count[0] & 504) != 448)
{
this.update(char[] { 0 });
}
this.update(&finalcount);
char[20] digest;
for (uint i = 0; i < 20; i++)
{
digest[i] = (char)((this.state[i >> 2] >> ((3 - (i & 3)) * 8)) & 0xFF);
}
// Clear mem
mem::clear(this, Sha1.sizeof);
finalcount = {};
return digest;
}
union Long16 @local
{
char[64] c;
uint[16] l;
}
macro @blk(&block, i) @local
{
return (block.l[i & 15] = (block.l[(i + 13) & 15] ^ block.l[(i + 8) & 15]
^ block.l[(i + 2) & 15] ^ block.l[i & 15]).rotl(1));
}
macro @blk0(&block, i) @local
{
$if (env::BIG_ENDIAN):
return block.l[i];
$else:
return block.l[i] = (block.l[i].rotl(24) & 0xFF00FF00)
| (block.l[i].rotl(8) & 0x00FF00FF);
$endif;
}
macro @r0(&block, v, &w, x, y, &z, i) @local
{
z += ((w & (x ^ y)) ^ y) + @blk0(block, i) + 0x5A827999 + v.rotl(5);
w = w.rotl(30);
}
macro @r1(&block, v, &w, x, y, &z, i) @local
{
z += ((w & (x ^ y)) ^ y) + @blk(block, i) + 0x5A827999 + v.rotl(5);
w = w.rotl(30);
}
macro @r2(&block, v, &w, x, y, &z, i) @local
{
z += (w ^ x ^ y) + @blk(block, i) + 0x6ED9EBA1 + v.rotl(5);
w = w.rotl(30);
}
macro @r3(&block, v, &w, x, y, &z, i) @local
{
z += (((w | x) &y) | (w & x)) + @blk(block, i) + 0x8F1BBCDC + v.rotl(5);
w = w.rotl(30);
}
macro @r4(&block, v, &w, x, y, &z, i) @local
{
z += (w ^ x ^ y) + @blk(block, i) + 0xCA62C1D6 + v.rotl(5);
w = w.rotl(30);
}
/**
* @param [&inout] state
* @param [&in] buffer
**/
fn void sha1_transform(uint* state, char* buffer) @local
{
Long16 block;
block.c[..] = buffer[:64];
uint a = state[0];
uint b = state[1];
uint c = state[2];
uint d = state[3];
uint e = state[4];
@r0(block, a, b, c, d, e, 0);
@r0(block, e, a, b, c, d, 1);
@r0(block, d, e, a, b, c, 2);
@r0(block, c, d, e, a, b, 3);
@r0(block, b, c, d, e, a, 4);
@r0(block, a, b, c, d, e, 5);
@r0(block, e, a, b, c, d, 6);
@r0(block, d, e, a, b, c, 7);
@r0(block, c, d, e, a, b, 8);
@r0(block, b, c, d, e, a, 9);
@r0(block, a, b, c, d, e, 10);
@r0(block, e, a, b, c, d, 11);
@r0(block, d, e, a, b, c, 12);
@r0(block, c, d, e, a, b, 13);
@r0(block, b, c, d, e, a, 14);
@r0(block, a, b, c, d, e, 15);
@r1(block, e, a, b, c, d, 16);
@r1(block, d, e, a, b, c, 17);
@r1(block, c, d, e, a, b, 18);
@r1(block, b, c, d, e, a, 19);
@r2(block, a, b, c, d, e, 20);
@r2(block, e, a, b, c, d, 21);
@r2(block, d, e, a, b, c, 22);
@r2(block, c, d, e, a, b, 23);
@r2(block, b, c, d, e, a, 24);
@r2(block, a, b, c, d, e, 25);
@r2(block, e, a, b, c, d, 26);
@r2(block, d, e, a, b, c, 27);
@r2(block, c, d, e, a, b, 28);
@r2(block, b, c, d, e, a, 29);
@r2(block, a, b, c, d, e, 30);
@r2(block, e, a, b, c, d, 31);
@r2(block, d, e, a, b, c, 32);
@r2(block, c, d, e, a, b, 33);
@r2(block, b, c, d, e, a, 34);
@r2(block, a, b, c, d, e, 35);
@r2(block, e, a, b, c, d, 36);
@r2(block, d, e, a, b, c, 37);
@r2(block, c, d, e, a, b, 38);
@r2(block, b, c, d, e, a, 39);
@r3(block, a, b, c, d, e, 40);
@r3(block, e, a, b, c, d, 41);
@r3(block, d, e, a, b, c, 42);
@r3(block, c, d, e, a, b, 43);
@r3(block, b, c, d, e, a, 44);
@r3(block, a, b, c, d, e, 45);
@r3(block, e, a, b, c, d, 46);
@r3(block, d, e, a, b, c, 47);
@r3(block, c, d, e, a, b, 48);
@r3(block, b, c, d, e, a, 49);
@r3(block, a, b, c, d, e, 50);
@r3(block, e, a, b, c, d, 51);
@r3(block, d, e, a, b, c, 52);
@r3(block, c, d, e, a, b, 53);
@r3(block, b, c, d, e, a, 54);
@r3(block, a, b, c, d, e, 55);
@r3(block, e, a, b, c, d, 56);
@r3(block, d, e, a, b, c, 57);
@r3(block, c, d, e, a, b, 58);
@r3(block, b, c, d, e, a, 59);
@r4(block, a, b, c, d, e, 60);
@r4(block, e, a, b, c, d, 61);
@r4(block, d, e, a, b, c, 62);
@r4(block, c, d, e, a, b, 63);
@r4(block, b, c, d, e, a, 64);
@r4(block, a, b, c, d, e, 65);
@r4(block, e, a, b, c, d, 66);
@r4(block, d, e, a, b, c, 67);
@r4(block, c, d, e, a, b, 68);
@r4(block, b, c, d, e, a, 69);
@r4(block, a, b, c, d, e, 70);
@r4(block, e, a, b, c, d, 71);
@r4(block, d, e, a, b, c, 72);
@r4(block, c, d, e, a, b, 73);
@r4(block, b, c, d, e, a, 74);
@r4(block, a, b, c, d, e, 75);
@r4(block, e, a, b, c, d, 76);
@r4(block, d, e, a, b, c, 77);
@r4(block, c, d, e, a, b, 78);
@r4(block, b, c, d, e, a, 79);
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
state[4] += e;
a = b = c = d = e = 0;
buffer[:64] = 0;
}

View File

@@ -0,0 +1,30 @@
module std::hash::sha1_test @test;
import std::hash::sha1;
fn void test_sha1_abc()
{
Sha1 sha;
sha.init();
sha.update("abc");
assert(sha.final() == x"A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D");
}
fn void test_sha1_longer()
{
Sha1 sha;
sha.init();
sha.update("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq");
assert(sha.final() == x"84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1");
}
fn void test_sha1_million_a()
{
Sha1 sha;
sha.init();
const int COUNT = 1_000_000;
for (int i = 0; i < COUNT / 10; i++)
{
sha.update("aaaaaaaaaa");
}
assert(sha.final() == x"34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F");
}