add doubly linked list, used linked list for platform inputs, add tests for linked lists + memcpy
This commit is contained in:
parent
6a757dd36b
commit
cdfe9cb660
2
assets.d
2
assets.d
@ -212,7 +212,7 @@ OpenAssetPack()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline): void
|
pragma(inline) void
|
||||||
CheckAssetPack()
|
CheckAssetPack()
|
||||||
{
|
{
|
||||||
if (!Asset_Pack_Opened)
|
if (!Asset_Pack_Opened)
|
||||||
|
|||||||
54
math.d
54
math.d
@ -678,7 +678,7 @@ Mat4MulASM(Mat4 l, Mat4 r)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline): Mat4
|
pragma(inline) Mat4
|
||||||
Mat4Identity()
|
Mat4Identity()
|
||||||
{
|
{
|
||||||
return Mat4(
|
return Mat4(
|
||||||
@ -689,7 +689,7 @@ Mat4Identity()
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline): void
|
pragma(inline) void
|
||||||
Mat4Identity(Mat4* mat)
|
Mat4Identity(Mat4* mat)
|
||||||
{
|
{
|
||||||
MatZero(mat);
|
MatZero(mat);
|
||||||
@ -700,7 +700,7 @@ Mat4Identity(Mat4* mat)
|
|||||||
(*mat)[3, 3] = 1.0;
|
(*mat)[3, 3] = 1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline): Mat3
|
pragma(inline) Mat3
|
||||||
Mat3Identity()
|
Mat3Identity()
|
||||||
{
|
{
|
||||||
return Mat3(
|
return Mat3(
|
||||||
@ -710,7 +710,7 @@ Mat3Identity()
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline): Mat2
|
pragma(inline) Mat2
|
||||||
Mat2Identity()
|
Mat2Identity()
|
||||||
{
|
{
|
||||||
return Mat2(
|
return Mat2(
|
||||||
@ -719,7 +719,7 @@ Mat2Identity()
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline): Quat
|
pragma(inline) Quat
|
||||||
QuatFromAxis(f32 angle, Vec3 axis)
|
QuatFromAxis(f32 angle, Vec3 axis)
|
||||||
{
|
{
|
||||||
Quat q;
|
Quat q;
|
||||||
@ -727,39 +727,39 @@ QuatFromAxis(f32 angle, Vec3 axis)
|
|||||||
return q;
|
return q;
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline): f32
|
pragma(inline) f32
|
||||||
Dot(Vec2* l, Vec2* r)
|
Dot(Vec2* l, Vec2* r)
|
||||||
{
|
{
|
||||||
return l.x * r.x + l.y * r.y;
|
return l.x * r.x + l.y * r.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline): f32
|
pragma(inline) f32
|
||||||
Dot(Vec3* l, Vec3* r)
|
Dot(Vec3* l, Vec3* r)
|
||||||
{
|
{
|
||||||
return l.x * r.x + l.y * r.y + l.z * r.z;
|
return l.x * r.x + l.y * r.y + l.z * r.z;
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline): f32
|
pragma(inline) f32
|
||||||
Dot(Vec4* l, Vec4* r)
|
Dot(Vec4* l, Vec4* r)
|
||||||
{
|
{
|
||||||
// TODO: SIMD this
|
// TODO: SIMD this
|
||||||
return l.x * r.x + l.y * r.y + l.z * r.z + l.w * r.w;
|
return l.x * r.x + l.y * r.y + l.z * r.z + l.w * r.w;
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline): f32
|
pragma(inline) f32
|
||||||
Norm(Vec3* v)
|
Norm(Vec3* v)
|
||||||
{
|
{
|
||||||
return sqrtf(Dot(v, v));
|
return sqrtf(Dot(v, v));
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline): f32
|
pragma(inline) f32
|
||||||
Norm(Vec4* v)
|
Norm(Vec4* v)
|
||||||
{
|
{
|
||||||
// TODO: SIMD this
|
// TODO: SIMD this
|
||||||
return sqrtf(Dot(v, v));
|
return sqrtf(Dot(v, v));
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline): void
|
pragma(inline) void
|
||||||
Normalize(T)(T* vec) if (is(T: Vec2) || is(T: Vec3) || is(T: Vec4))
|
Normalize(T)(T* vec) if (is(T: Vec2) || is(T: Vec3) || is(T: Vec4))
|
||||||
{
|
{
|
||||||
f32 length = Norm(vec);
|
f32 length = Norm(vec);
|
||||||
@ -774,14 +774,14 @@ Normalize(T)(T* vec) if (is(T: Vec2) || is(T: Vec3) || is(T: Vec4))
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline): T
|
pragma(inline) T
|
||||||
Normalize(T)(T vec) if (is(T: Vec2) || is(T: Vec3) || is(T: Vec4))
|
Normalize(T)(T vec) if (is(T: Vec2) || is(T: Vec3) || is(T: Vec4))
|
||||||
{
|
{
|
||||||
Normalize(&vec);
|
Normalize(&vec);
|
||||||
return vec;
|
return vec;
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline): Quat
|
pragma(inline) Quat
|
||||||
Normalize(Quat q)
|
Normalize(Quat q)
|
||||||
{
|
{
|
||||||
f32 dot = Norm(&q.vec);
|
f32 dot = Norm(&q.vec);
|
||||||
@ -796,7 +796,7 @@ Normalize(Quat q)
|
|||||||
return q;
|
return q;
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline): Mat4
|
pragma(inline) Mat4
|
||||||
Perspective(f32 fov, f32 aspect, f32 near, f32 far)
|
Perspective(f32 fov, f32 aspect, f32 near, f32 far)
|
||||||
{
|
{
|
||||||
Mat4 res;
|
Mat4 res;
|
||||||
@ -822,7 +822,7 @@ Ortho(f32 left, f32 bottom, f32 right, f32 top, f32 near, f32 far)
|
|||||||
return mat;
|
return mat;
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline): Vec3
|
pragma(inline) Vec3
|
||||||
Rotate(Quat q, Vec3 vec)
|
Rotate(Quat q, Vec3 vec)
|
||||||
{
|
{
|
||||||
Quat p = Normalize(q);
|
Quat p = Normalize(q);
|
||||||
@ -840,7 +840,7 @@ Rotate(Quat q, Vec3 vec)
|
|||||||
return v1 + v2;
|
return v1 + v2;
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline): Mat4
|
pragma(inline) Mat4
|
||||||
LookAt(Vec3 eye, Vec3 center, Vec3 up)
|
LookAt(Vec3 eye, Vec3 center, Vec3 up)
|
||||||
{
|
{
|
||||||
Mat4 result;
|
Mat4 result;
|
||||||
@ -849,13 +849,13 @@ LookAt(Vec3 eye, Vec3 center, Vec3 up)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline): Mat4
|
pragma(inline) Mat4
|
||||||
Look(Vec3 eye, Vec3 dir, Vec3 up)
|
Look(Vec3 eye, Vec3 dir, Vec3 up)
|
||||||
{
|
{
|
||||||
return LookAt(eye, eye + dir, up);
|
return LookAt(eye, eye + dir, up);
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline): Vec3
|
pragma(inline) Vec3
|
||||||
Cross(Vec3 a, Vec3 b)
|
Cross(Vec3 a, Vec3 b)
|
||||||
{
|
{
|
||||||
Vec3 c;
|
Vec3 c;
|
||||||
@ -863,7 +863,7 @@ Cross(Vec3 a, Vec3 b)
|
|||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline): Vec3
|
pragma(inline) Vec3
|
||||||
CrossN(Vec3 a, Vec3 b)
|
CrossN(Vec3 a, Vec3 b)
|
||||||
{
|
{
|
||||||
Vec3 c;
|
Vec3 c;
|
||||||
@ -872,20 +872,20 @@ CrossN(Vec3 a, Vec3 b)
|
|||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline): void
|
pragma(inline) void
|
||||||
CrossN(Vec3 a, Vec3 b, Vec3* dst)
|
CrossN(Vec3 a, Vec3 b, Vec3* dst)
|
||||||
{
|
{
|
||||||
Cross(a, b, dst);
|
Cross(a, b, dst);
|
||||||
glm_vec3_normalize(dst.v.ptr);
|
glm_vec3_normalize(dst.v.ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline): void
|
pragma(inline) void
|
||||||
Cross(Vec3 a, Vec3 b, Vec3* dst)
|
Cross(Vec3 a, Vec3 b, Vec3* dst)
|
||||||
{
|
{
|
||||||
glm_vec3_cross(a.v.ptr, b.v.ptr, dst.v.ptr);
|
glm_vec3_cross(a.v.ptr, b.v.ptr, dst.v.ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline): void
|
pragma(inline) void
|
||||||
MatZero(Mat4* mat)
|
MatZero(Mat4* mat)
|
||||||
{
|
{
|
||||||
auto v = &mat.vec;
|
auto v = &mat.vec;
|
||||||
@ -900,13 +900,13 @@ MatZero(Mat4* mat)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline): void
|
pragma(inline) void
|
||||||
Translate(Mat4* mat, Vec3 vec)
|
Translate(Mat4* mat, Vec3 vec)
|
||||||
{
|
{
|
||||||
glm_translate(mat.glm_mat.ptr, vec.v.ptr);
|
glm_translate(mat.glm_mat.ptr, vec.v.ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline): Mat4
|
pragma(inline) Mat4
|
||||||
Inverse(Mat4 mat)
|
Inverse(Mat4 mat)
|
||||||
{
|
{
|
||||||
Mat4 res;
|
Mat4 res;
|
||||||
@ -915,19 +915,19 @@ Inverse(Mat4 mat)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline): f32
|
pragma(inline) f32
|
||||||
Mix(f32 x, f32 y, f32 a)
|
Mix(f32 x, f32 y, f32 a)
|
||||||
{
|
{
|
||||||
return x * (1 - a) + y * a;
|
return x * (1 - a) + y * a;
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline): f32
|
pragma(inline) f32
|
||||||
InverseLerp(f32 v, f32 min, f32 max)
|
InverseLerp(f32 v, f32 min, f32 max)
|
||||||
{
|
{
|
||||||
return (v - min) / (max - min);
|
return (v - min) / (max - min);
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline): f32
|
pragma(inline) f32
|
||||||
Remap(f32 v, f32 in_min, f32 in_max, f32 out_min, f32 out_max)
|
Remap(f32 v, f32 in_min, f32 in_max, f32 out_min, f32 out_max)
|
||||||
{
|
{
|
||||||
f32 t = InverseLerp(v, in_min, in_max);
|
f32 t = InverseLerp(v, in_min, in_max);
|
||||||
|
|||||||
77
platform.d
77
platform.d
@ -1,10 +1,13 @@
|
|||||||
module dlib.platform;
|
module dlib.platform;
|
||||||
|
|
||||||
import dlib.aliases;
|
import dlib.aliases;
|
||||||
|
import dlib.alloc : Reset;
|
||||||
import dlib.alloc;
|
import dlib.alloc;
|
||||||
import dlib.util;
|
import dlib.util;
|
||||||
|
|
||||||
import includes;
|
import includes;
|
||||||
|
|
||||||
|
import std.typecons;
|
||||||
import std.stdio;
|
import std.stdio;
|
||||||
import core.memory;
|
import core.memory;
|
||||||
import core.thread.osthread;
|
import core.thread.osthread;
|
||||||
@ -73,8 +76,38 @@ struct InputEvent
|
|||||||
|
|
||||||
struct Inputs
|
struct Inputs
|
||||||
{
|
{
|
||||||
InputEvent[10] events;
|
DLList!(InputEvent) list;
|
||||||
u32 count;
|
Arena arena;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Reset(Inputs* inputs)
|
||||||
|
{
|
||||||
|
inputs.list.first = inputs.list.last;
|
||||||
|
Reset(&inputs.arena);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Push(Inputs* inputs, Input input, bool pressed)
|
||||||
|
{
|
||||||
|
DNode!(InputEvent)* node = Alloc!(DNode!(InputEvent))(&inputs.arena);
|
||||||
|
node.value.key = input;
|
||||||
|
node.value.pressed = pressed;
|
||||||
|
|
||||||
|
PushFront(&inputs.list, node, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Push(Inputs* inputs, i32 rel_x, i32 rel_y, u16 x, u16 y)
|
||||||
|
{
|
||||||
|
DNode!(InputEvent)* node = Alloc!(DNode!(InputEvent))(&inputs.arena);
|
||||||
|
node.value.key = Input.MouseMotion;
|
||||||
|
node.value.rel_x = rel_x;
|
||||||
|
node.value.rel_y = rel_y;
|
||||||
|
node.value.x = x;
|
||||||
|
node.value.y = y;
|
||||||
|
|
||||||
|
PushFront(&inputs.list, node, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct PlatformWindow
|
struct PlatformWindow
|
||||||
@ -116,6 +149,9 @@ CreateWindow(string name, u16 width, u16 height)
|
|||||||
PlatformWindow window = {
|
PlatformWindow window = {
|
||||||
w: width,
|
w: width,
|
||||||
h: height,
|
h: height,
|
||||||
|
inputs: {
|
||||||
|
arena: CreateArena(MB(1)),
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
assert(width > 0 && height > 0, "CreateWindow error: width and height must be above 0");
|
assert(width > 0 && height > 0, "CreateWindow error: width and height must be above 0");
|
||||||
@ -309,12 +345,12 @@ FlushEvents(PlatformWindow* window)
|
|||||||
void
|
void
|
||||||
HandleEvents(PlatformWindow* window)
|
HandleEvents(PlatformWindow* window)
|
||||||
{
|
{
|
||||||
window.inputs.count = 0;
|
|
||||||
|
|
||||||
xcb_generic_event_t* e;
|
xcb_generic_event_t* e;
|
||||||
|
|
||||||
bool ignore_mouse_events = false;
|
bool ignore_mouse_events = false;
|
||||||
|
|
||||||
|
Inputs* inputs = &window.inputs;
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
e = xcb_poll_for_event(window.conn);
|
e = xcb_poll_for_event(window.conn);
|
||||||
@ -339,12 +375,6 @@ HandleEvents(PlatformWindow* window)
|
|||||||
case XCB_KEY_RELEASE:
|
case XCB_KEY_RELEASE:
|
||||||
case XCB_KEY_PRESS:
|
case XCB_KEY_PRESS:
|
||||||
{
|
{
|
||||||
// TODO: definitely definitely need to rework this whole thing
|
|
||||||
if (window.inputs.count == window.inputs.events.length)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
xcb_key_press_event_t* keyboard_event = cast(xcb_key_press_event_t*)e;
|
xcb_key_press_event_t* keyboard_event = cast(xcb_key_press_event_t*)e;
|
||||||
|
|
||||||
bool pressed = e.response_type == XCB_KEY_PRESS;
|
bool pressed = e.response_type == XCB_KEY_PRESS;
|
||||||
@ -354,25 +384,12 @@ HandleEvents(PlatformWindow* window)
|
|||||||
|
|
||||||
if (input != KBI.None)
|
if (input != KBI.None)
|
||||||
{
|
{
|
||||||
window.inputs.events[window.inputs.count].key = input;
|
Push(inputs, input, pressed);
|
||||||
window.inputs.events[window.inputs.count].pressed = pressed;
|
|
||||||
window.inputs.count += 1;
|
|
||||||
|
|
||||||
if (input == KBI.F2)
|
|
||||||
{
|
|
||||||
LockCursor(window);
|
|
||||||
}
|
|
||||||
else if (input == KBI.F3)
|
|
||||||
{
|
|
||||||
UnlockCursor(window);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case XCB_BUTTON_PRESS:
|
case XCB_BUTTON_PRESS:
|
||||||
case XCB_BUTTON_RELEASE:
|
case XCB_BUTTON_RELEASE:
|
||||||
{
|
{
|
||||||
if (window.inputs.count == window.inputs.events.length) continue;
|
|
||||||
|
|
||||||
xcb_button_press_event_t* mouse_event = cast(xcb_button_press_event_t*)e;
|
xcb_button_press_event_t* mouse_event = cast(xcb_button_press_event_t*)e;
|
||||||
bool pressed = e.response_type == XCB_BUTTON_PRESS;
|
bool pressed = e.response_type == XCB_BUTTON_PRESS;
|
||||||
Input input = Input.None;
|
Input input = Input.None;
|
||||||
@ -387,15 +404,12 @@ HandleEvents(PlatformWindow* window)
|
|||||||
|
|
||||||
if (input != Input.None)
|
if (input != Input.None)
|
||||||
{
|
{
|
||||||
window.inputs.events[window.inputs.count].key = input;
|
Push(inputs, input, pressed);
|
||||||
window.inputs.events[window.inputs.count].pressed = pressed;
|
|
||||||
window.inputs.count += 1;
|
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case XCB_MOTION_NOTIFY:
|
case XCB_MOTION_NOTIFY:
|
||||||
{
|
{
|
||||||
if (ignore_mouse_events) continue;
|
if (ignore_mouse_events) continue;
|
||||||
if (window.inputs.count == window.inputs.events.length) continue;
|
|
||||||
|
|
||||||
xcb_motion_notify_event_t* move_event = cast(xcb_motion_notify_event_t*)e;
|
xcb_motion_notify_event_t* move_event = cast(xcb_motion_notify_event_t*)e;
|
||||||
|
|
||||||
@ -412,12 +426,7 @@ HandleEvents(PlatformWindow* window)
|
|||||||
|
|
||||||
if (x > 0 || y > 0)
|
if (x > 0 || y > 0)
|
||||||
{
|
{
|
||||||
window.inputs.events[window.inputs.count].key = Input.MouseMotion;
|
Push(inputs, window.mouse_prev_x-x, window.mouse_prev_y-y, x, y);
|
||||||
window.inputs.events[window.inputs.count].x = move_event.event_x;
|
|
||||||
window.inputs.events[window.inputs.count].y = move_event.event_y;
|
|
||||||
window.inputs.events[window.inputs.count].rel_x = window.mouse_prev_x - x;
|
|
||||||
window.inputs.events[window.inputs.count].rel_y = window.mouse_prev_y - y;
|
|
||||||
window.inputs.count += 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
window.mouse_prev_x = x;
|
window.mouse_prev_x = x;
|
||||||
|
|||||||
375
util.d
375
util.d
@ -56,7 +56,7 @@ GB(u64 v)
|
|||||||
return MB(v) * 1024;
|
return MB(v) * 1024;
|
||||||
};
|
};
|
||||||
|
|
||||||
pragma(inline): void
|
pragma(inline) void
|
||||||
ConvertColor(Vec4 *dst, u32 src)
|
ConvertColor(Vec4 *dst, u32 src)
|
||||||
{
|
{
|
||||||
if (src == 0)
|
if (src == 0)
|
||||||
@ -70,7 +70,7 @@ ConvertColor(Vec4 *dst, u32 src)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline): void
|
pragma(inline) void
|
||||||
Convert(Vec4* dst, u32 src)
|
Convert(Vec4* dst, u32 src)
|
||||||
{
|
{
|
||||||
dst.r = cast(f32)((src >> 0) & 0xFF) / 255.0;
|
dst.r = cast(f32)((src >> 0) & 0xFF) / 255.0;
|
||||||
@ -85,6 +85,123 @@ BitEq(u64 l, u64 r)
|
|||||||
return (l & r) == r;
|
return (l & r) == r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct DNode(T)
|
||||||
|
{
|
||||||
|
DNode!(T)* next;
|
||||||
|
DNode!(T)* prev;
|
||||||
|
T value;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct DLList(T)
|
||||||
|
{
|
||||||
|
DNode!(T)* first;
|
||||||
|
DNode!(T)* last;
|
||||||
|
}
|
||||||
|
|
||||||
|
pragma(inline) bool
|
||||||
|
CheckNil(T)(DNode!(T)* nil, DNode!(T)* node)
|
||||||
|
{
|
||||||
|
return node == null || node == nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ConcatInPlace(T)(DLList!(T)* list, DLList!(T)* to_concat)
|
||||||
|
{
|
||||||
|
if (to_concat.first)
|
||||||
|
{
|
||||||
|
if (list.first)
|
||||||
|
{
|
||||||
|
list.last.next = to_concat.first;
|
||||||
|
list.last = to_concat.last;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
list.first = to_concat.first;
|
||||||
|
list.last = to_concat.last;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(to_concat, 0, DLList!(T).sizeof);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DNode!(T)*
|
||||||
|
Pop(T)(DLList!(T)* list, DNode!(T)* nil)
|
||||||
|
{
|
||||||
|
DNode!(T)* node = list.first;
|
||||||
|
|
||||||
|
if (list.first == list.last)
|
||||||
|
{
|
||||||
|
list.first = list.last = nil;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
list.first = list.first.next;
|
||||||
|
list.first.prev = nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Remove(T)(DLList!(T)* list, DNode!(T)* node, DNode!(T)* nil)
|
||||||
|
{
|
||||||
|
if (list.first == list.last)
|
||||||
|
{
|
||||||
|
list.first = list.last = nil;
|
||||||
|
}
|
||||||
|
else if (list.first == node)
|
||||||
|
{
|
||||||
|
list.first = node.next;
|
||||||
|
list.first.prev = nil;
|
||||||
|
}
|
||||||
|
else if (list.last == node)
|
||||||
|
{
|
||||||
|
node.prev.next = nil;
|
||||||
|
list.last = node.prev;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
node.next.prev = node.prev;
|
||||||
|
node.prev.next = node.next;
|
||||||
|
}
|
||||||
|
|
||||||
|
node.prev = node.next = nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PushFront(T)(DLList!(T)* list, DNode!(T)* node, DNode!(T)* nil)
|
||||||
|
{
|
||||||
|
if (CheckNil(nil, list.first))
|
||||||
|
{
|
||||||
|
list.first = list.last = node;
|
||||||
|
node.prev = node.next = nil;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
node.next = list.first;
|
||||||
|
node.prev = nil;
|
||||||
|
list.first.prev = node;
|
||||||
|
list.first = node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Push(T)(DLList!(T)* list, DNode!(T)* node, DNode!(T)* nil)
|
||||||
|
{
|
||||||
|
if (CheckNil(nil, list.first))
|
||||||
|
{
|
||||||
|
list.first = list.last = node;
|
||||||
|
node.prev = node.next = nil;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
list.last.next = node;
|
||||||
|
node.prev = list.last;
|
||||||
|
list.last = node;
|
||||||
|
node.next = nil;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct Node(T)
|
struct Node(T)
|
||||||
{
|
{
|
||||||
Node!(T)* next;
|
Node!(T)* next;
|
||||||
@ -97,13 +214,13 @@ struct SLList(T)
|
|||||||
Node!(T)* last;
|
Node!(T)* last;
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline): bool
|
pragma(inline) bool
|
||||||
CheckNil(T)(Node!(T)* nil, Node!(T)* node)
|
CheckNil(T)(Node!(T)* nil, Node!(T)* node)
|
||||||
{
|
{
|
||||||
return node == null || node == nil;
|
return node == null || node == nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline): void
|
void
|
||||||
ConcatInPlace(T)(SLList!(T)* list, SLList!(T)* to_concat)
|
ConcatInPlace(T)(SLList!(T)* list, SLList!(T)* to_concat)
|
||||||
{
|
{
|
||||||
if (to_concat.first)
|
if (to_concat.first)
|
||||||
@ -123,7 +240,7 @@ ConcatInPlace(T)(SLList!(T)* list, SLList!(T)* to_concat)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline): Node!(T)*
|
pragma(inline) Node!(T)*
|
||||||
Pop(T)(SLList!(T)*list, Node!(T)* nil)
|
Pop(T)(SLList!(T)*list, Node!(T)* nil)
|
||||||
{
|
{
|
||||||
Node!(T)* node = list.first;
|
Node!(T)* node = list.first;
|
||||||
@ -140,11 +257,9 @@ Pop(T)(SLList!(T)*list, Node!(T)* nil)
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline): void
|
pragma(inline) void
|
||||||
Remove(T)(SLList!(T)* list, Node!(T)* node, Node!(T)* prev, Node!(T)* nil)
|
Remove(T)(SLList!(T)* list, Node!(T)* node, Node!(T)* prev, Node!(T)* nil)
|
||||||
{
|
{
|
||||||
node.next = nil;
|
|
||||||
|
|
||||||
if (list.first == list.last)
|
if (list.first == list.last)
|
||||||
{
|
{
|
||||||
list.first = list.last = nil;
|
list.first = list.last = nil;
|
||||||
@ -162,9 +277,11 @@ Remove(T)(SLList!(T)*list, Node!(T)* node, Node!(T)* prev, Node!(T)* nil)
|
|||||||
{
|
{
|
||||||
prev.next = node.next;
|
prev.next = node.next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
node.next = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline): void
|
pragma(inline) void
|
||||||
PushFront(T)(SLList!(T)* list, Node!(T)* node, Node!(T)* nil)
|
PushFront(T)(SLList!(T)* list, Node!(T)* node, Node!(T)* nil)
|
||||||
{
|
{
|
||||||
if (CheckNil(nil, list.first))
|
if (CheckNil(nil, list.first))
|
||||||
@ -179,7 +296,7 @@ PushFront(T)(SLList!(T)*list, Node!(T)* node, Node!(T)* nil)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline): void
|
pragma(inline) void
|
||||||
Push(T)(SLList!(T)* list, Node!(T)* node, Node!(T)* nil)
|
Push(T)(SLList!(T)* list, Node!(T)* node, Node!(T)* nil)
|
||||||
{
|
{
|
||||||
if (CheckNil(nil, list.first))
|
if (CheckNil(nil, list.first))
|
||||||
@ -266,7 +383,7 @@ CreateHashTable(K, V)(u64 size)
|
|||||||
return table;
|
return table;
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline): void
|
pragma(inline) void
|
||||||
Clear(K, V)(HashTable!(K, V)* ht)
|
Clear(K, V)(HashTable!(K, V)* ht)
|
||||||
{
|
{
|
||||||
table.count = 0;
|
table.count = 0;
|
||||||
@ -276,7 +393,7 @@ Clear(K, V)(HashTable!(K, V)* ht)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline): Node!(KVPair!(K, V))*
|
pragma(inline) Node!(KVPair!(K, V))*
|
||||||
Push(K, V)(HashTable!(K, V)* ht, K key, V value)
|
Push(K, V)(HashTable!(K, V)* ht, K key, V value)
|
||||||
{
|
{
|
||||||
alias P = KVPair!(K, V);
|
alias P = KVPair!(K, V);
|
||||||
@ -304,7 +421,7 @@ Push(K, V)(HashTable!(K, V)* ht, K key, V value)
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline): KVPair!(K, V)*
|
pragma(inline) KVPair!(K, V)*
|
||||||
Search(K, V)(HashTable!(K, V)* ht, K key)
|
Search(K, V)(HashTable!(K, V)* ht, K key)
|
||||||
{
|
{
|
||||||
KVPair!(K, V)* result = null;
|
KVPair!(K, V)* result = null;
|
||||||
@ -322,7 +439,7 @@ Search(K, V)(HashTable!(K, V)* ht, K key)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline): SLList!(KVPair!(K, V))*
|
pragma(inline) SLList!(KVPair!(K, V))*
|
||||||
GetList(K, V)(HashTable!(K, V)* ht, K key)
|
GetList(K, V)(HashTable!(K, V)* ht, K key)
|
||||||
{
|
{
|
||||||
u64 hash = Hash(&key);
|
u64 hash = Hash(&key);
|
||||||
@ -330,7 +447,7 @@ GetList(K, V)(HashTable!(K, V)* ht, K key)
|
|||||||
return ht.lists.ptr + index;
|
return ht.lists.ptr + index;
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline): Result!(V)
|
pragma(inline) Result!(V)
|
||||||
Delete(K, V)(HashTable!(K, V)* ht, K key)
|
Delete(K, V)(HashTable!(K, V)* ht, K key)
|
||||||
{
|
{
|
||||||
Result!(V) result = { ok: false };
|
Result!(V) result = { ok: false };
|
||||||
@ -359,25 +476,25 @@ Delete(K, V)(HashTable!(K, V)* ht, K key)
|
|||||||
|
|
||||||
const u64 HASH_SEED = 5995;
|
const u64 HASH_SEED = 5995;
|
||||||
|
|
||||||
pragma(inline): u64
|
pragma(inline) u64
|
||||||
Hash(T)(T[] value)
|
Hash(T)(T[] value)
|
||||||
{
|
{
|
||||||
return xxh3_64bits_withSeed(value.ptr, (T.sizeof * value.length) / u8.sizeof, HASH_SEED);
|
return xxh3_64bits_withSeed(value.ptr, (T.sizeof * value.length) / u8.sizeof, HASH_SEED);
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline): u64
|
pragma(inline) u64
|
||||||
Hash(T)(T* value)
|
Hash(T)(T* value)
|
||||||
{
|
{
|
||||||
return xxh3_64bits_withSeed(value, T.sizeof / u8.sizeof, HASH_SEED);
|
return xxh3_64bits_withSeed(value, T.sizeof / u8.sizeof, HASH_SEED);
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline): u64
|
pragma(inline) u64
|
||||||
Hash(string str)
|
Hash(string str)
|
||||||
{
|
{
|
||||||
return xxh3_64bits_withSeed(str.ptr, str.length, HASH_SEED);
|
return xxh3_64bits_withSeed(str.ptr, str.length, HASH_SEED);
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline): u64
|
pragma(inline) u64
|
||||||
RDTSC()
|
RDTSC()
|
||||||
{
|
{
|
||||||
union u64_split
|
union u64_split
|
||||||
@ -404,7 +521,7 @@ RDTSC()
|
|||||||
return val.full;
|
return val.full;
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline): u64
|
pragma(inline) u64
|
||||||
OSTimeFreq()
|
OSTimeFreq()
|
||||||
{
|
{
|
||||||
version (linux)
|
version (linux)
|
||||||
@ -415,7 +532,7 @@ OSTimeFreq()
|
|||||||
return freq;
|
return freq;
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline): u64
|
pragma(inline) u64
|
||||||
OSTime()
|
OSTime()
|
||||||
{
|
{
|
||||||
version(linux)
|
version(linux)
|
||||||
@ -474,7 +591,7 @@ CreateTimer(u64 fps)
|
|||||||
return timer;
|
return timer;
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline): bool
|
pragma(inline) bool
|
||||||
CheckTimer(IntervalTimer* t)
|
CheckTimer(IntervalTimer* t)
|
||||||
{
|
{
|
||||||
bool result = false;
|
bool result = false;
|
||||||
@ -529,7 +646,7 @@ CreateTimer()
|
|||||||
return timer;
|
return timer;
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline): f32
|
pragma(inline) f32
|
||||||
DeltaTime(Timer* t)
|
DeltaTime(Timer* t)
|
||||||
{
|
{
|
||||||
u64 time = RDTSC();
|
u64 time = RDTSC();
|
||||||
@ -576,7 +693,7 @@ MemCpy(void* dst_p, void* src_p, u64 length)
|
|||||||
u64 remaining = length;
|
u64 remaining = length;
|
||||||
if (remaining >= 64)
|
if (remaining >= 64)
|
||||||
{
|
{
|
||||||
for(u64 i = 0; i < length; i += 64)
|
for(u64 i = 0; i + 64 < length; i += 64)
|
||||||
{
|
{
|
||||||
asm
|
asm
|
||||||
{
|
{
|
||||||
@ -602,7 +719,7 @@ MemCpy(void* dst_p, void* src_p, u64 length)
|
|||||||
|
|
||||||
if (remaining >= 32)
|
if (remaining >= 32)
|
||||||
{
|
{
|
||||||
for(u64 i = remaining; i < length; i += 32)
|
for(u64 i = length - remaining; i + 32 < length; i += 32)
|
||||||
{
|
{
|
||||||
asm
|
asm
|
||||||
{
|
{
|
||||||
@ -622,9 +739,9 @@ MemCpy(void* dst_p, void* src_p, u64 length)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(u64 i = remaining; i < length; i += 1)
|
if (remaining > 0)
|
||||||
{
|
{
|
||||||
dst[i] = src[i];
|
dst[length-remaining .. length] = src[length-remaining .. length];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -634,3 +751,207 @@ Embed(string file_name)
|
|||||||
import std.file;
|
import std.file;
|
||||||
return cast(u8[])read(file_name);
|
return cast(u8[])read(file_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unittest
|
||||||
|
{
|
||||||
|
{ // Singly Linked List
|
||||||
|
SLList!(u32) list;
|
||||||
|
Node!(u32)[5] nodes;
|
||||||
|
foreach(u32 i, n; nodes)
|
||||||
|
{
|
||||||
|
nodes[i].value = i;
|
||||||
|
Push(&list, &nodes[i], null);
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 count = 0;
|
||||||
|
u32[3] res1 = [0, 2, 4];
|
||||||
|
|
||||||
|
Remove(&list, &nodes[1], &nodes[0], null);
|
||||||
|
Remove(&list, &nodes[3], &nodes[2], null);
|
||||||
|
|
||||||
|
Node!(u32)* n = list.first;
|
||||||
|
|
||||||
|
assert(list.first != null && list.last != null);
|
||||||
|
assert(n != null);
|
||||||
|
assert(n.next != null);
|
||||||
|
|
||||||
|
void TestSLList(SLList!(u32)* list, u32[] result)
|
||||||
|
{
|
||||||
|
Node!(u32)* n = list.first;
|
||||||
|
foreach(i, v; result)
|
||||||
|
{
|
||||||
|
assert(n != null);
|
||||||
|
assert(v == n.value);
|
||||||
|
|
||||||
|
if (i == result.length-1)
|
||||||
|
{
|
||||||
|
assert(n.next == null);
|
||||||
|
assert(n == list.last);
|
||||||
|
}
|
||||||
|
|
||||||
|
n = n.next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TestSLList(&list, res1);
|
||||||
|
|
||||||
|
count = 0;
|
||||||
|
u32[5] res2 = [3, 0, 2, 4, 1];
|
||||||
|
|
||||||
|
PushFront(&list, &nodes[3], null);
|
||||||
|
Push(&list, &nodes[1], null);
|
||||||
|
|
||||||
|
TestSLList(&list, res2);
|
||||||
|
|
||||||
|
count = 0;
|
||||||
|
|
||||||
|
Remove(&list, &nodes[3], null, null);
|
||||||
|
Remove(&list, &nodes[1], &nodes[4], null);
|
||||||
|
|
||||||
|
TestSLList(&list, res1);
|
||||||
|
}
|
||||||
|
|
||||||
|
{ // Doubly Linked List
|
||||||
|
void TestDLList(DLList!(u32)* list, u32[] result)
|
||||||
|
{
|
||||||
|
DNode!(u32)* n = list.first;
|
||||||
|
foreach(i, v; result)
|
||||||
|
{
|
||||||
|
assert(n != null);
|
||||||
|
assert(v == n.value);
|
||||||
|
|
||||||
|
if (i > 0)
|
||||||
|
{
|
||||||
|
assert(n.prev != null);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == result.length-1)
|
||||||
|
{
|
||||||
|
assert(n.next == null);
|
||||||
|
assert(n == list.last);
|
||||||
|
}
|
||||||
|
|
||||||
|
n = n.next;
|
||||||
|
}
|
||||||
|
|
||||||
|
n = list.last;
|
||||||
|
foreach_reverse(i, v; result)
|
||||||
|
{
|
||||||
|
assert(n != null);
|
||||||
|
assert(v == n.value);
|
||||||
|
|
||||||
|
if (i == result.length-1)
|
||||||
|
{
|
||||||
|
assert(n.next == null);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == 0)
|
||||||
|
{
|
||||||
|
assert(n.prev == null);
|
||||||
|
assert(n == list.first);
|
||||||
|
}
|
||||||
|
|
||||||
|
n = n.prev;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DLList!(u32) list;
|
||||||
|
DNode!(u32)[5] nodes;
|
||||||
|
foreach(u32 i, n; nodes)
|
||||||
|
{
|
||||||
|
nodes[i].value = i;
|
||||||
|
Push(&list, &nodes[i], null);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(list.first != null && list.last != null);
|
||||||
|
|
||||||
|
TestDLList(&list, [0, 1, 2, 3, 4]);
|
||||||
|
|
||||||
|
u32 count = 0;
|
||||||
|
u32[3] res1 = [0, 2, 4];
|
||||||
|
|
||||||
|
Remove(&list, &nodes[1], null);
|
||||||
|
Remove(&list, &nodes[3], null);
|
||||||
|
|
||||||
|
TestDLList(&list, res1);
|
||||||
|
|
||||||
|
count = 0;
|
||||||
|
u32[5] res2 = [3, 0, 2, 4, 1];
|
||||||
|
|
||||||
|
PushFront(&list, &nodes[3], null);
|
||||||
|
Push(&list, &nodes[1], null);
|
||||||
|
|
||||||
|
TestDLList(&list, res2);
|
||||||
|
|
||||||
|
Remove(&list, &nodes[3], null);
|
||||||
|
Remove(&list, &nodes[1], null);
|
||||||
|
|
||||||
|
TestDLList(&list, res1);
|
||||||
|
}
|
||||||
|
|
||||||
|
{ // MemCpy
|
||||||
|
import std.conv;
|
||||||
|
|
||||||
|
u8[777] bytes;
|
||||||
|
u8[777] test_bytes;
|
||||||
|
|
||||||
|
bytes[0 .. 123] = 123;
|
||||||
|
bytes[123 .. 333] = 133;
|
||||||
|
bytes[333 .. 655] = 155;
|
||||||
|
bytes[655 .. $] = 199;
|
||||||
|
|
||||||
|
test_bytes[0 .. $] = bytes[0 .. $];
|
||||||
|
|
||||||
|
assert(test_bytes == bytes);
|
||||||
|
|
||||||
|
test_bytes[0 .. $] = 0;
|
||||||
|
|
||||||
|
MemCpy(test_bytes.ptr, bytes.ptr, 777);
|
||||||
|
|
||||||
|
assert(test_bytes == bytes);
|
||||||
|
|
||||||
|
test_bytes[0 .. $] = 0;
|
||||||
|
|
||||||
|
MemCpy(test_bytes.ptr+100, bytes.ptr, 32);
|
||||||
|
|
||||||
|
u32 count = 0;
|
||||||
|
foreach(i, v; test_bytes[100 .. 132])
|
||||||
|
{
|
||||||
|
if (v != bytes[count])
|
||||||
|
{
|
||||||
|
Logf("Failed %d %d %d", i, v, bytes[count]);
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
count += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(test_bytes[100 .. 132] == bytes[0 .. 32]);
|
||||||
|
|
||||||
|
test_bytes[0 .. $] = 0;
|
||||||
|
|
||||||
|
MemCpy(test_bytes.ptr, bytes.ptr, 33);
|
||||||
|
|
||||||
|
assert(test_bytes[0 .. 33] == bytes[0 .. 33]);
|
||||||
|
|
||||||
|
test_bytes[0 .. $] = 0;
|
||||||
|
|
||||||
|
MemCpy(test_bytes.ptr, bytes.ptr, 65);
|
||||||
|
|
||||||
|
assert(test_bytes[0 .. 65] == bytes[0 .. 65]);
|
||||||
|
|
||||||
|
test_bytes[0 .. $] = 0;
|
||||||
|
|
||||||
|
MemCpy(test_bytes.ptr, bytes.ptr, 96);
|
||||||
|
|
||||||
|
foreach(i, v; test_bytes[0 .. 96])
|
||||||
|
{
|
||||||
|
if (v != bytes[i])
|
||||||
|
{
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(test_bytes[0 .. 96] == bytes[0 .. 96]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user