Skip to content

Commit

Permalink
Queue improvements and sdlang package
Browse files Browse the repository at this point in the history
  • Loading branch information
al1-ce committed May 9, 2023
1 parent 657c205 commit 8b49b50
Show file tree
Hide file tree
Showing 9 changed files with 405 additions and 27 deletions.
67 changes: 53 additions & 14 deletions core/sily/queue.d
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,15 @@ import std.conv: to;
struct Queue(T) {
/// First element
private Node!T* _root = null;

/// Last element
private Node!T* _end = null;
/// Length
private size_t _length = 0;
/// Length limit
private size_t _lengthLimit = -1;

/// Length of queue
@property public size_t length() { return _length; }
/// Is queue empty
@property public bool empty() { return _root == null; }
/// Returns first value without removing it from queue
Expand All @@ -18,48 +26,79 @@ struct Queue(T) {
public this(T[] vals...) {
push(vals);
}

/// opOpAssign x += y == x.push(y)
Queue!T opOpAssign(string op)( in T b ) if ( op == "+" ) {
push(b);
return this;
}

/++
Limits length of queue, default is -1 which is limitless.
If length is limited and new element is attempted to be
pushed when Queue is overfilled nothing will happen.
+/
void limitLength(size_t len) {
_lengthLimit = len;
clearUntil(_lengthLimit);
}

/// Adds vals at end of queue
public void push(T[] vals...) {
if (vals.length == 0) return;
if (_length >= _lengthLimit) return;

Node!T* last;

if (_root == null) {
if (_root == null && _length < _lengthLimit) {
_root = new Node!T(vals[0]);
last = _root;
_end = _root;
vals.popFront();
} else {
last = _root;
while(true) {
if ((*last).next == null) break;
last = (*last).next;
}
++_length;
}

foreach (val; vals) {
if (_length >= _lengthLimit) break;
Node!T* _new = new Node!T(val);
(*last).next = _new;
last = _new;
(*_end).next = _new;
_end = _new;
++_length;
}

}

/// Returns first value and removes it from queue
public T pop() {
if (_root == null) { return T.init; }
T val = (*_root).value;
--_length;
if ((*_root).next != null) {
_root = (*_root).next;
} else {
_root = null;
_end = null;
}
return val;
}

/// Removes all elements after pos (used in limitLength)
private void clearUntil(size_t pos) {
if (_root == null) return;
if (pos >= _length) return;
Node!T* _node = _root;
for (int i = 0; i < pos; ++i) {
if (i != pos - 1) {
_node = (*_node).next;
} else {
(*_node).next = null;
_end = _node;
}
}
}

/// Removes all elements from queue
public void clear() {
_root = null;
_end = null;
_length = 0;
}

public string toString() const {
Expand Down
9 changes: 9 additions & 0 deletions core/sily/vector.d
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,15 @@ struct Vector(T, size_t N) if (isNumeric!T && N > 0) {
return ret;
}

/// Ditto
R opCast(R)() const if (is(R == quat) && N == 4){
R ret;
foreach (i; 0 .. N) {
ret[i] = cast(float) data[i];
}
return ret;
}

/// Cast to matrix (column/row matrix)
R opCast(R)() const if (isMatrix!(R, N, 1)) {
R ret;
Expand Down
10 changes: 10 additions & 0 deletions dub.sdl
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,15 @@ subPackage {
importPaths "dyaml/"
}

subPackage {
name "sdlang"
dependency "sdlite" version="~>1.1.2"
dependency "taggedalgebraic" version="~>0.11.22"
targetType "library"
targetPath "lib"
sourcePaths "sdlang/"
importPaths "sdlang/"
}



7 changes: 7 additions & 0 deletions dub.selections.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"fileVersion": 1,
"versions": {
"sdlite": "1.1.2",
"taggedalgebraic": "0.11.22"
}
}
146 changes: 146 additions & 0 deletions sdlang/sily/sdlang/package.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
/++
Wrapper for SDLite.
Noticable differences between SDLang and SDLite parser:
- Line breaking is not allowed ("title \", newline, " 'value'")
+/
module sily.sdlang;

import sdl = sdlite;
import std.range;

import taggedalgebraic.taggedunion;

/++
Representation of single sdlang node
Example:
---
// Create SDLNode. SDLNode("name", SDLValue[] values, SDLAttribute[] attributes, SDLNode[] children)
SDLNode node = SDLNode("name", [SDLValue.text("values")], [], []);
// Get name
node.name;
// Get namespace
node.namespace;
// Get/Set qualified name (eq to namespace:name)
node.qualifiedName;
node.qualifiedName = "namespace:name";
// Get array of values (aka 'node 1 "b" v=2' -> returns 1 "b")
node.values;
// Get array of attributes (aka 'node 1 "b" v=2' -> returns v=2)
node.attributes;
// Get array of children
node.children;
// Gets attribute by qualified name
node.getAttribute("email")
// Gets attribute by qualified name with default value
node.getAttribute("email", SDLValue.text("[email protected]"))
---
+/
alias SDLNode = sdl.SDLNode;

/++
Value of sdlang node
Example:
---
// Create new value
SDLValue val = SDLValue.double_(22.5);
// Get value casted to int
val.value!int;
// Check type
val.kind == SDLType.text;
---
+/
alias SDLValue = sdl.SDLValue;

/++
Attribute of sdlang node (attr="val")
Example:
---
// Create new attribute
SDLAttribute attr = SDLAttribute("qualifiedName", SDLValue.text("value"));
// Get name
attr.name;
// Get namepsace
attr.namespace;
// Get/Set qualified name (namespace:name)
attr.qualifiedName;
attr.qualifiedName = "namespace:name";
// Get/Set value
attr.value;
attr.value = SDLValue.text("new value")
---
+/
alias SDLAttribute = sdl.SDLAttribute;

/++
Alias to SDLValue.Kind. Represents type of SDLValue.
Example:
---
node.values[0].kind == SDLType.float_;
---
Defined types:
---
Void null_;
string text;
immutable(ubyte)[] binary;
int int_;
long long_;
long[2] decimal;
float float_;
double double_;
bool bool_;
SysTime dateTime;
Date date;
Duration duration;
---
+/
alias SDLType = sdl.SDLValue.Kind;

/++
Parses SDL string into SDLNode[]
Example:
---
import sily.sdlang;
import std.file;
SDLNode[] arr1 = parseSDL(readText("file.sdl"));
SDLNode[] arr2 = parseSDL("name \"Direct SDLang parsing\" cool=true");
---
+/
SDLNode[] parseSDL(string input) {
SDLNode[] result;
sdl.parseSDLDocument!((n) { result ~= n; })(input, "");
return result;
}

private alias generateSDLang = sdl.generateSDLang;

/++
Writes SDL data into string
Example:
---
import sily.sdlang;
import std.file;
SDLNode[] arr1 = parseSDL(readText("file.sdl"));
string out = arr1.generateSDL();
---
+/
string generateSDL(SDLNode[] input) {
auto app = appender!string;
app.generateSDLang(input);
return app.data;
}

/// Ditto
string generateSDL(SDLNode input) {
auto app = appender!string;
app.generateSDLang(input);
return app.data;
}

/// Ditto
string generateSDL(SDLValue input) {
auto app = appender!string;
app.generateSDLang(input);
return app.data;
}

55 changes: 42 additions & 13 deletions test/queue
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,58 @@
/+ dub.sdl:
name "queuetest"
dependency "sily" path="/g/sily-dlang/"
dependency "sily-terminal" path="/g/sily-terminal/"
dependency "sily-terminal:logger" path="/g/sily-terminal/"
+/

import std.stdio: writeln;
import std.stdio;
import std.conv: to;

import sily.queue;

import sily.bashfmt;
import sily.logger;

void eq(T, S, int line = __LINE__, string file = "test.d")(T t1, S t2, string message) {
bool cond = t1 == t2;
hr('─', message.to!dstring, cond ? (cast(string) FR.reset) : (cast(string) FG.ltred),
cond ? (cast(string) FR.reset) : (cast(string) FG.ltred));
if (!cond) writeln(cast(string)(FG.dkgray), "Expected: ", cast(string)(FG.ltred));
if (!cond) {
write(t2.to!string);
}
if (!cond) writeln();
if (!cond) writeln(cast(string)(FG.dkgray), "Got: ", cast(string)(FG.ltred));
write(t1.to!string);
if (!cond) write(cast(string)(FR.fullreset));
writeln();
}


void main() {
Queue!int ique = Queue!int(1, 2, 3, 4);
writeln(ique.toString());
writeln(ique.front);
writeln(ique.pop());
ique.toString.eq("[1, 2, 3, 4]", "toString()");
ique.front.eq(1, "front");
ique.pop.eq(1, "pop");
ique.pop();
writeln(ique.pop());
writeln(ique.pop());
writeln(ique.empty);
writeln(ique.toString());
writeln(ique.pop());
ique.front.eq(3, "front");
ique.pop.eq(3, "pop");
ique.pop.eq(4, "pop");
ique.empty.eq(true, "pop");
ique.toString.eq("[]", "toString()");
ique.pop.eq(0, "pop");
ique.push(4);
writeln(ique.pop());
ique.pop.eq(4, "pop");
ique.push(4, 5, 6);
writeln(ique.toString());
ique.toString.eq("[4, 5, 6]", "toString()");
ique.length.eq(3, "length");
ique.clear();
writeln(ique.toString());
auto nque = Queue!int();
ique.toString.eq("[]", "toString()");
ique.push();
ique.toString.eq("[]", "toString()");
ique += 3;
ique.front.eq(3, "front");
ique.push(4, 5, 6, 7, 8, 9, 10);
ique.limitLength(5);
ique.toString.eq("[3, 4, 5, 6, 7]", "limitLength()");
}
Loading

0 comments on commit 8b49b50

Please sign in to comment.