135 lines
3.5 KiB
Text
135 lines
3.5 KiB
Text
Kilobyte :: 1024;
|
|
Megabyte :: 1024 * Kilobyte;
|
|
Gigabyte :: 1024 * Megabyte;
|
|
|
|
DefaultAlign :: size_of(*void);
|
|
|
|
/// MemEqual checks the equality of two pieces of memory.
|
|
///
|
|
/// Note: MemEqual will panic if size_in_bytes is negative.
|
|
MemEqual :: (p1: *void, p2: *void, size_in_bytes: int) -> bool {
|
|
if size_in_bytes < 0
|
|
{ Panic("jc: size_in_bytes cannot be negative"); }
|
|
return memcmp(p1, p2, size_in_bytes) == 0; // Provided by Preload
|
|
}
|
|
|
|
/// MemCopy copies the memory of src to dst.
|
|
///
|
|
/// Note: MemCopy will panic if size_in_bytes is negative.
|
|
MemCopy :: (dst: *void, src: *void, size_in_bytes: int) {
|
|
if size_in_bytes < 0
|
|
{ Panic("jc: size_in_bytes cannot be negative"); }
|
|
memcpy(dst, src, size_in_bytes); // Provided by Preload
|
|
}
|
|
|
|
/// MemOverwrite overwites the memory of p with value.
|
|
///
|
|
/// Note: MemOverwrite will panic if size_in_bytes is negative.
|
|
MemOverwrite :: (p: *void, size_in_bytes: int, value: u8 = 0) {
|
|
if size_in_bytes < 0
|
|
{ Panic("jc: size_in_bytes cannot be negative"); }
|
|
memset(p, value, size_in_bytes); // Provided by preload
|
|
}
|
|
|
|
/// MemZero zeroes the memory of p.
|
|
///
|
|
/// Note: MemZero will panic if size_in_bytes is negative.
|
|
MemZero :: (p: *void, size_in_bytes: int) {
|
|
MemOverwrite(p, size_in_bytes, 0);
|
|
}
|
|
|
|
/// MemZero zeroes the memory of p.
|
|
///
|
|
/// Note: MemZero will not call the initializer for aggregate types,
|
|
/// so you may want MemReset instead.
|
|
MemZero :: (p: *$T) {
|
|
MemOverwrite(p, size_of(T), 0);
|
|
}
|
|
|
|
/// MemReset resets the memory of p, as if it was just instantiated.
|
|
///
|
|
/// Note: MemReset will call the initializer for aggregate types, so you
|
|
/// may want MemZero instead.
|
|
MemReset :: (p: *$T) {
|
|
initializer :: initializer_of(T);
|
|
#if initializer {
|
|
inline initializer(p);
|
|
}
|
|
else {
|
|
inline MemZero(p);
|
|
}
|
|
}
|
|
|
|
MemAligned :: (p: *void, align: int = DefaultAlign) -> bool {
|
|
return Aligned(p.(int), align);
|
|
}
|
|
|
|
MemAlignForward :: (p: *void, align: int = DefaultAlign) -> *void {
|
|
return AlignForward(p.(int), align).(*void);
|
|
}
|
|
|
|
MemAlignBackward :: (p: *void, align: int = DefaultAlign) -> *void {
|
|
return AlignBackward(p.(int), align).(*void);
|
|
}
|
|
|
|
Aligned :: (a: int, align: int = DefaultAlign) -> bool {
|
|
return (a & (align - 1)) == 0;
|
|
}
|
|
|
|
AlignForward :: (a: int, align: int = DefaultAlign) -> int {
|
|
Assert(PowerOfTwo(align), "jc: must be a power of two");
|
|
return (a + align - 1) & ~(align - 1);
|
|
}
|
|
|
|
AlignBackward :: (a: int, align: int = DefaultAlign) -> int {
|
|
Assert(PowerOfTwo(align), "jc: must be a power of two");
|
|
return a & ~(align - 1);
|
|
}
|
|
|
|
|
|
PowerOfTwo :: (x: int) -> bool {
|
|
if x == 0 return false;
|
|
return x & (x - 1) == 0;
|
|
}
|
|
|
|
NextPowerOfTwo :: (x: int) -> int #no_aoc {
|
|
Assert(PowerOfTwo(x), "jc: must be a power of two");
|
|
|
|
// Bit twiddling hacks next power of two
|
|
x |= x >> 1;
|
|
x |= x >> 2;
|
|
x |= x >> 4;
|
|
x |= x >> 8;
|
|
x |= x >> 16;
|
|
x |= x >> 32;
|
|
|
|
return x + 1;
|
|
}
|
|
|
|
|
|
#scope_module
|
|
|
|
TrySetAllocator :: (thing: *$T) #modify {
|
|
info := T.(*Type_Info_Struct);
|
|
|
|
ok := false;
|
|
if info.type == .STRUCT
|
|
{ ok = true; }
|
|
|
|
if ok for info.members if it.name == "allocator" && it.type == Allocator.(*Type_Info) {
|
|
ok = true;
|
|
break;
|
|
}
|
|
|
|
return ok, "can only set allocator on struct with an allocator field or dynamic array";
|
|
} #expand {
|
|
if thing.allocator.proc == null {
|
|
thing.allocator = context.allocator;
|
|
}
|
|
} @jc.nodocs
|
|
|
|
TrySetAllocator :: (array: *[..]$T) #expand {
|
|
if array.allocator.proc == null {
|
|
array.allocator = context.allocator;
|
|
}
|
|
} @jc.nodocs
|