move globals.Hash to std.Hash
Add std.nas to loadpriority.xml and update related files
This commit is contained in:
parent
78e9eff433
commit
4cb8a03e4b
10 changed files with 367 additions and 270 deletions
|
@ -1,5 +1,12 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#
|
||||
# NOTE! This copyright does *not* cover user models that use these Nasal
|
||||
# services by normal function calls - this is merely considered normal use
|
||||
# of the code, and does *not* fall under the heading of "derived work."
|
||||
#-------------------------------------------------------------------------------
|
||||
# emesary.deb.nas - emesary debug helpers
|
||||
# author: Henning Stahlke
|
||||
# created: 06/2020
|
||||
#-------------------------------------------------------------------------------
|
||||
var _emesaryDebugN = props.getNode("/_debug/emesary/",1);
|
||||
var _emesaryDebugEnableN = _emesaryDebugN.getNode("enabled",1);
|
||||
|
@ -41,10 +48,11 @@ var __setup = func {
|
|||
emesary.GlobalTransmitter.NotifyAll(debugNotification);
|
||||
|
||||
#add monitoring
|
||||
var name = emesary._transmitters.getName();
|
||||
emesary._transmitters.addCallback(func (k, v) {
|
||||
emesary._transmitters.keys2props(_emesaryDebugN);
|
||||
emesary._transmitters.keys2props(_emesaryDebugN.getNode(name, 1));
|
||||
});
|
||||
emesary._transmitters.keys2props(_emesaryDebugN);
|
||||
emesary._transmitters.keys2props(_emesaryDebugN.getNode(name, 1));
|
||||
}
|
||||
|
||||
settimer(__setup,0);
|
|
@ -32,7 +32,7 @@
|
|||
var __emesaryUniqueId = 14; # 0-15 are reserved, this way the global transmitter will be 15.
|
||||
|
||||
# add registry so we can find a transmitter by name in genericEmesaryGlobalTransmitterTransmit
|
||||
var _transmitters = Hash.new("transmitters");
|
||||
var _transmitters = std.Hash.new({}, "transmitters");
|
||||
|
||||
var _registerTransmitter = func (key, t) {
|
||||
_transmitters.set(key, t);
|
||||
|
|
|
@ -188,55 +188,3 @@ settimer(func {
|
|||
if(size(file) > 4 and substr(file, -4) == ".nas")
|
||||
io.load_nasal(path ~ "/" ~ file, substr(file, 0, size(file) - 4));
|
||||
}, 0);
|
||||
|
||||
# simple hash class for developers, allows to add callback on write
|
||||
Hash = {
|
||||
class_name: "Hash",
|
||||
|
||||
new: func(name) {
|
||||
var obj = {
|
||||
parents: [me],
|
||||
name: name,
|
||||
_h: {},
|
||||
_callback: func,
|
||||
};
|
||||
return obj;
|
||||
},
|
||||
|
||||
set: func (key, value) {
|
||||
me._h[key] = value;
|
||||
me._callback(key, value);
|
||||
return me;
|
||||
},
|
||||
|
||||
get: func (key) {
|
||||
return me._h[key];
|
||||
},
|
||||
|
||||
getName: func (key) {
|
||||
return me.name;
|
||||
},
|
||||
|
||||
getKeys: func () {
|
||||
return keys(me._h);
|
||||
},
|
||||
|
||||
keys2props: func (p) {
|
||||
if (!isa(p, props.Node)) {
|
||||
p = props.getNode(p,1);
|
||||
}
|
||||
p = p.getNode(me.name,1);
|
||||
foreach (var key; keys(me._h)) {
|
||||
p.getNode(key,1);
|
||||
}
|
||||
return;
|
||||
},
|
||||
|
||||
# callback for set()
|
||||
addCallback: func (f) {
|
||||
if (isfunc(f)) {
|
||||
me._callback = f;
|
||||
}
|
||||
return me;
|
||||
},
|
||||
};
|
||||
|
|
|
@ -34,6 +34,8 @@ string.nas <- gui.nas
|
|||
io.nas <- gui.nas
|
||||
gui.nas <- multiplayer.nas
|
||||
multiplayer.nas <- view.nas
|
||||
io.nas <- std.nas
|
||||
|
||||
geo.nas <- view.nas
|
||||
view.nas <- dynamic_view.nas
|
||||
-->
|
||||
|
@ -45,6 +47,7 @@ geo.nas <- view.nas
|
|||
<file>math.nas</file>
|
||||
<file>string.nas</file>
|
||||
<file>io.nas</file>
|
||||
<file>std.nas</file>
|
||||
<file>debug.nas</file>
|
||||
<!-- stage 1 -->
|
||||
<file>modules.nas</file>
|
||||
|
|
21
Nasal/std.nas
Normal file
21
Nasal/std.nas
Normal file
|
@ -0,0 +1,21 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#
|
||||
# NOTE! This copyright does *not* cover user models that use these Nasal
|
||||
# services by normal function calls - this is merely considered normal use
|
||||
# of the code, and does *not* fall under the heading of "derived work."
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# std.nas - class loader for std lib
|
||||
# author: Henning Stahlke
|
||||
# created: 07/2020
|
||||
#-------------------------------------------------------------------------------
|
||||
var include_path = "Nasal/std/";
|
||||
var files = [
|
||||
"hash",
|
||||
"string",
|
||||
"vector",
|
||||
];
|
||||
|
||||
foreach (var file; files) {
|
||||
io.include(include_path~file~".nas");
|
||||
}
|
195
Nasal/std.nut
Normal file
195
Nasal/std.nut
Normal file
|
@ -0,0 +1,195 @@
|
|||
#-------------------------------------------------------------------------------
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#-------------------------------------------------------------------------------
|
||||
# std.nut - Nasal Unit Test for std.nas
|
||||
# author: Henning Stahlke
|
||||
# created: 06/2020
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
var setUp = func {
|
||||
};
|
||||
|
||||
var tearDown = func {
|
||||
};
|
||||
|
||||
#-- test std.Hash
|
||||
var test_hash = func {
|
||||
var hash = std.Hash.new({}, "testhash");
|
||||
unitTest.assert(isa(hash, std.Hash), "std.Hash.new");
|
||||
unitTest.assert(hash.getName() == "testhash" , "std.Hash.getName");
|
||||
|
||||
unitTest.assert(hash.set("foo", 42) == hash, "std.Hash.set");
|
||||
unitTest.assert(hash.get("foo") == 42 , "std.Hash.get");
|
||||
unitTest.assert(hash.contains("foo"), "std.Hash.contains");
|
||||
|
||||
hash.set("bar", 21);
|
||||
unitTest.assert(isvec(hash.getKeys()), "std.Hash.getKeys isvec");
|
||||
unitTest.assert(size(hash.getKeys()) == 2, "std.Hash.getKeys size");
|
||||
|
||||
unitTest.assert(hash.clear() == hash, "std.Hash.clear");
|
||||
unitTest.assert(!hash.contains("foo"), "std.Hash.contains after clear");
|
||||
unitTest.assert(size(hash.getKeys()) == 0, "std.Hash.getKeys after clear");
|
||||
|
||||
var cb_hash = {};
|
||||
unitTest.assert(hash.addCallback(func(key, val) { cb_hash[key] = val; }) == hash,
|
||||
"std.Hash.addCallback");
|
||||
hash.set("foo", 21);
|
||||
unitTest.assert(cb_hash["foo"] == 21, "std.addCallback worked");
|
||||
|
||||
hash.set("funct", func {});
|
||||
hash.set("vec", [0,1,2]);
|
||||
hash.set("hsh", {a:1, b:2});
|
||||
|
||||
var tmp = props.Node.new();
|
||||
hash.keys2props(tmp);
|
||||
unitTest.assert(isa(tmp.getNode("foo"), props.Node), "std.keys2props node ok");
|
||||
|
||||
var tmp = props.Node.new();
|
||||
hash.hash2props(tmp);
|
||||
unitTest.assert(tmp.getNode("foo").getValue() == 21, "std.hash2props ok");
|
||||
}
|
||||
|
||||
#-- test std.String
|
||||
var test_stoul = func {
|
||||
unitTest.assert(std.stoul("123") == 123, "std.stoul 123");
|
||||
unitTest.assert(std.stoul("A0", 16) == 160, "std.stoul 0xAF");
|
||||
}
|
||||
|
||||
var test_string = func {
|
||||
var x = std.String.new("FlightGear");
|
||||
unitTest.assert(isa(x, std.String), "std.String.new");
|
||||
unitTest.assert(x.compare("FlightGear"), "std.String.compare");
|
||||
|
||||
unitTest.assert(x.starts_with("Fli"), "std.String.starts_with");
|
||||
unitTest.assert(!x.starts_with("Gear"), "std.String.starts_with");
|
||||
|
||||
unitTest.assert(x.find_first_of("i") == 2, "std.String.find_first_of");
|
||||
unitTest.assert(x.find_first_of("i", 3) == -1, "std.String.find_first_of");
|
||||
unitTest.assert(x.find_first_not_of("F") == 1, "std.String.find_first_not_of");
|
||||
unitTest.assert(x.find_first_not_of("F", 2) == 2, "std.String.find_first_not_of");
|
||||
unitTest.assert(x.find_first_not_of("F", 3) == 3, "std.String.find_first_not_of");
|
||||
}
|
||||
|
||||
#-- test std.Vector
|
||||
var test_vector = func {
|
||||
var x = std.Vector.new();
|
||||
unitTest.assert(isa(x, std.Vector), "std.Vector.new()");
|
||||
unitTest.assert(x.size() == 0);
|
||||
|
||||
x = std.Vector.new(["x", "y"]);
|
||||
unitTest.assert_equal(x.vector, ["x", "y"], "std.Vector.new(['x', 'y'])");
|
||||
unitTest.assert(x.size() == 2, "std.Vector.new size 2");
|
||||
x.clear();
|
||||
unitTest.assert(isvec(x.vector) and x.size() == 0);
|
||||
|
||||
x = std.Vector.new([], "testvector");
|
||||
var cb_vector = [];
|
||||
unitTest.assert(x.getName() == "testvector" , "std.Vector.getName");
|
||||
unitTest.assert(x.addCallback(func (index, item) {
|
||||
if (index >= size(cb_vector)) append(cb_vector, item);
|
||||
else cb_vector = cb_vector[0:index]~[item]~subvec(cb_vector, index);
|
||||
}) == x, "std.Vector.addCallback");
|
||||
|
||||
# append():
|
||||
x.append("a");
|
||||
x.append("b");
|
||||
x.append("c");
|
||||
unitTest.assert_equal(x.vector, ["a", "b", "c"]);
|
||||
unitTest.assert_equal(cb_vector, ["a", "b", "c"]);
|
||||
unitTest.assert(x.size() == 3);
|
||||
|
||||
# extend():
|
||||
x.extend(["d", "e"]);
|
||||
unitTest.assert_equal(x.vector, ["a", "b", "c", "d", "e"]);
|
||||
unitTest.assert(x.size() == 5);
|
||||
|
||||
# insert():
|
||||
x.insert(2, "cc");
|
||||
unitTest.assert_equal(x.vector, ["a", "b", "cc", "c", "d", "e"]);
|
||||
unitTest.assert(x.size() == 6);
|
||||
|
||||
# pop():
|
||||
unitTest.assert(x.pop(3), "c");
|
||||
unitTest.assert_equal(x.vector, ["a", "b", "cc", "d", "e"]);
|
||||
unitTest.assert(x.size() == 5);
|
||||
|
||||
unitTest.assert(x.pop(), "e");
|
||||
unitTest.assert_equal(x.vector, ["a", "b", "cc", "d"]);
|
||||
unitTest.assert(x.size() == 4);
|
||||
|
||||
|
||||
# extend():
|
||||
x.clear();
|
||||
x.extend(["a", "b", "c", "d"]);
|
||||
unitTest.assert_equal(x.vector, ["a", "b", "c", "d"]);
|
||||
unitTest.assert(x.size() == 4);
|
||||
|
||||
# index():
|
||||
unitTest.assert(x.index("c"), 2);
|
||||
|
||||
# contains():
|
||||
unitTest.assert(x.contains("c"));
|
||||
unitTest.assert(x.contains("e") == 0);
|
||||
|
||||
# remove():
|
||||
x.remove("c");
|
||||
unitTest.assert_equal(x.vector, ["a", "b", "d"]);
|
||||
unitTest.assert(x.size() == 3);
|
||||
|
||||
# insert():
|
||||
x.insert(0, "f");
|
||||
unitTest.assert_equal(x.vector, ["f", "a", "b", "d"]);
|
||||
unitTest.assert(x.size() == 4);
|
||||
x.remove("f");
|
||||
unitTest.assert_equal(x.vector, ["a", "b", "d"]);
|
||||
|
||||
x.insert(1, "f");
|
||||
unitTest.assert_equal(x.vector, ["a", "f", "b", "d"]);
|
||||
unitTest.assert(x.size() == 4);
|
||||
x.remove("f");
|
||||
unitTest.assert_equal(x.vector, ["a", "b", "d"]);
|
||||
|
||||
x.insert(2, "f");
|
||||
unitTest.assert_equal(x.vector, ["a", "b", "f", "d"]);
|
||||
x.remove("f");
|
||||
unitTest.assert_equal(x.vector, ["a", "b", "d"]);
|
||||
|
||||
x.insert(3, "g");
|
||||
unitTest.assert_equal(x.vector, ["a", "b", "d", "g"]);
|
||||
x.remove("g");
|
||||
|
||||
x.insert(4, "g");
|
||||
unitTest.assert_equal(x.vector, ["a", "b", "d", "g"]);
|
||||
x.remove("g");
|
||||
|
||||
x.insert(-1, "h");
|
||||
unitTest.assert_equal(x.vector, ["a", "b", "h", "d"]);
|
||||
x.remove("h");
|
||||
|
||||
x.insert(-2, "h");
|
||||
unitTest.assert_equal(x.vector, ["a", "h", "b", "d"]);
|
||||
x.remove("h");
|
||||
|
||||
x.insert(-3, "h");
|
||||
unitTest.assert_equal(x.vector, ["h", "a", "b", "d"]);
|
||||
x.remove("h");
|
||||
|
||||
x.insert(-4, "h");
|
||||
unitTest.assert_equal(x.vector, ["h", "a", "b", "d"]);
|
||||
x.remove("h");
|
||||
|
||||
# pop():
|
||||
unitTest.assert(x.pop(-1) == "d");
|
||||
unitTest.assert_equal(x.vector, ["a", "b"]);
|
||||
x.append("d");
|
||||
|
||||
unitTest.assert(x.pop(-2) == "b");
|
||||
unitTest.assert_equal(x.vector, ["a", "d"]);
|
||||
x.insert(1, "b");
|
||||
|
||||
unitTest.assert(x.pop(-3) == "a");
|
||||
unitTest.assert_equal(x.vector, ["b", "d"]);
|
||||
x.insert(0, "a");
|
||||
unitTest.assert_equal(x.vector, ["a", "b", "d"]);
|
||||
}
|
||||
|
|
@ -17,39 +17,50 @@
|
|||
# services by normal function calls - this is merely considered normal use
|
||||
# of the code, and does *not* fall under the heading of "derived work."
|
||||
|
||||
|
||||
var min = func(a, b) { a < b ? a : b }
|
||||
var max = func(a, b) { a > b ? a : b }
|
||||
#load only once (via /Nasal/std.nas) not via C++ module loader
|
||||
if (ishash(globals["std"]) and ishash(std["Vector"]))
|
||||
return;
|
||||
|
||||
var Vector = {
|
||||
|
||||
new: func (vector=nil) {
|
||||
new: func (vector=nil, name="") {
|
||||
var m = {
|
||||
parents: [Vector]
|
||||
parents: [Vector],
|
||||
name: name,
|
||||
vector: [],
|
||||
_callback: func,
|
||||
};
|
||||
if (vector == nil) {
|
||||
vector = [];
|
||||
if (isvec(vector)) {
|
||||
m.vector = vector;
|
||||
}
|
||||
m.vector = vector;
|
||||
return m;
|
||||
},
|
||||
|
||||
# add callback for writes (insert() and append())
|
||||
# will be called as f(index, item), compare insert() below
|
||||
addCallback: func (f) {
|
||||
if (isfunc(f)) {
|
||||
me._callback = f;
|
||||
return me;
|
||||
}
|
||||
return nil;
|
||||
},
|
||||
|
||||
getName: func () {
|
||||
return me.name;
|
||||
},
|
||||
|
||||
size: func {
|
||||
# Return the number of items in the vector
|
||||
|
||||
return size(me.vector);
|
||||
},
|
||||
|
||||
clear: func {
|
||||
# Remove all items from the vector, resulting in an empty vector
|
||||
|
||||
me.vector = [];
|
||||
},
|
||||
|
||||
append: func (item) {
|
||||
# Append the given item at the end of the vector
|
||||
|
||||
append(me.vector, item);
|
||||
me._callback(me.size() - 1, item);
|
||||
},
|
||||
|
||||
extend: func (other_vector) {
|
||||
|
@ -73,11 +84,13 @@ var Vector = {
|
|||
# insert(3, "f") => ["a", "b", "c", "f"]
|
||||
# insert(-3, "g") => ["f", "a", "b", "c"]
|
||||
|
||||
index = min(index, me.size());
|
||||
index = math.min(index, me.size());
|
||||
if (index < 0) {
|
||||
index = max(0, me.size() + index);
|
||||
index = math.max(0, me.size() + index);
|
||||
}
|
||||
me.vector = subvec(me.vector, 0, index) ~ [item] ~ subvec(me.vector, index);
|
||||
me._callback(index, item);
|
||||
return me.vector;
|
||||
},
|
||||
|
||||
pop: func (index=nil) {
|
||||
|
@ -116,22 +129,14 @@ var Vector = {
|
|||
index: func (item) {
|
||||
# Return first index of the given item. Raises a ValueError
|
||||
# if the item is not in the vector.
|
||||
|
||||
forindex (var index; me.vector) {
|
||||
if (me.vector[index] == item) {
|
||||
return index;
|
||||
}
|
||||
};
|
||||
die("ValueError: item not in the vector");
|
||||
var i = vecindex(me.vector, item);
|
||||
if (i == nil) die("ValueError: item not in the vector");
|
||||
return i;
|
||||
},
|
||||
|
||||
contains: func (item) {
|
||||
# Return true if the vector contains the item, false otherwise
|
||||
|
||||
var err = [];
|
||||
call(Vector.index, [item], me, err);
|
||||
|
||||
return size(err) == 0;
|
||||
return vecindex(me.vector, item) != nil;
|
||||
},
|
||||
|
||||
remove: func (item) {
|
||||
|
|
|
@ -1,179 +0,0 @@
|
|||
# Unit tests helpers
|
||||
# TODO generalize (eg. move comparison operators somewhere global)
|
||||
|
||||
var eq = func(lhs, rhs)
|
||||
{
|
||||
if( typeof(lhs) != typeof(rhs) )
|
||||
return 0;
|
||||
|
||||
if( typeof(lhs) == "scalar" )
|
||||
return lhs == rhs;
|
||||
if( typeof(lhs) == "vector" )
|
||||
{
|
||||
if( size(lhs) != size(rhs) )
|
||||
return 0;
|
||||
|
||||
forindex(var i; lhs)
|
||||
{
|
||||
if( !eq(lhs[i], rhs[i]) )
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return lhs == rhs;
|
||||
}
|
||||
|
||||
var print_fail = func(msg)
|
||||
{
|
||||
var c = caller(1); # [namespace, func, file, line]
|
||||
die(c[2] ~ "(" ~ c[3] ~ "): error: " ~ msg);
|
||||
}
|
||||
|
||||
var REQUIRE_EQUAL = func(lhs, rhs)
|
||||
{
|
||||
if( !eq(lhs, rhs) )
|
||||
print_fail( "check failed [" ~ debug.string(lhs, 0)
|
||||
~ " != "
|
||||
~ debug.string(rhs, 0)
|
||||
~ "]" );
|
||||
}
|
||||
|
||||
# @param fn Function for testing
|
||||
# @param ex (Part of) the expection thrown (with die())
|
||||
var REQUIRE_THROW = func(fn, ex)
|
||||
{
|
||||
call(fn, nil, var err = []);
|
||||
|
||||
var err_msg = "exception " ~ ex ~ " expected";
|
||||
|
||||
if( size(err) )
|
||||
{
|
||||
if( err[0].starts_with(ex ~ ": ") )
|
||||
return;
|
||||
|
||||
err_msg ~= " (got '" ~ err[0] ~ "')";
|
||||
}
|
||||
|
||||
print_fail(err_msg);
|
||||
}
|
||||
|
||||
var x = std.Vector.new();
|
||||
REQUIRE_EQUAL(x.size(), 0);
|
||||
|
||||
x = std.Vector.new(["x", "y"]);
|
||||
REQUIRE_EQUAL(x.vector, ["x", "y"]);
|
||||
REQUIRE_EQUAL(x.size(), 2);
|
||||
x.clear();
|
||||
REQUIRE_EQUAL(x.vector, []);
|
||||
REQUIRE_EQUAL(x.size(), 0);
|
||||
|
||||
# append():
|
||||
x.append("a");
|
||||
x.append("b");
|
||||
x.append("c");
|
||||
REQUIRE_EQUAL(x.vector, ["a", "b", "c"]);
|
||||
REQUIRE_EQUAL(x.size(), 3);
|
||||
|
||||
# extend():
|
||||
x.extend(["d", "e"]);
|
||||
REQUIRE_EQUAL(x.vector, ["a", "b", "c", "d", "e"]);
|
||||
REQUIRE_EQUAL(x.size(), 5);
|
||||
|
||||
# insert():
|
||||
x.insert(2, "cc");
|
||||
REQUIRE_EQUAL(x.vector, ["a", "b", "cc", "c", "d", "e"]);
|
||||
REQUIRE_EQUAL(x.size(), 6);
|
||||
|
||||
# pop():
|
||||
REQUIRE_EQUAL(x.pop(3), "c");
|
||||
REQUIRE_EQUAL(x.vector, ["a", "b", "cc", "d", "e"]);
|
||||
REQUIRE_EQUAL(x.size(), 5);
|
||||
|
||||
REQUIRE_EQUAL(x.pop(), "e");
|
||||
REQUIRE_EQUAL(x.vector, ["a", "b", "cc", "d"]);
|
||||
REQUIRE_EQUAL(x.size(), 4);
|
||||
|
||||
# clear():
|
||||
x.clear();
|
||||
REQUIRE_EQUAL(x.vector, []);
|
||||
REQUIRE_EQUAL(x.size(), 0);
|
||||
|
||||
# extend():
|
||||
x.extend(["a", "b", "c", "d"]);
|
||||
REQUIRE_EQUAL(x.vector, ["a", "b", "c", "d"]);
|
||||
REQUIRE_EQUAL(x.size(), 4);
|
||||
|
||||
# index():
|
||||
REQUIRE_EQUAL(x.index("c"), 2);
|
||||
|
||||
# contains():
|
||||
REQUIRE_EQUAL(x.contains("c"), 1);
|
||||
REQUIRE_EQUAL(x.contains("e"), 0);
|
||||
|
||||
# remove():
|
||||
x.remove("c");
|
||||
REQUIRE_EQUAL(x.vector, ["a", "b", "d"]);
|
||||
REQUIRE_EQUAL(x.size(), 3);
|
||||
|
||||
# insert():
|
||||
x.insert(0, "f");
|
||||
REQUIRE_EQUAL(x.vector, ["f", "a", "b", "d"]);
|
||||
REQUIRE_EQUAL(x.size(), 4);
|
||||
x.remove("f");
|
||||
REQUIRE_EQUAL(x.vector, ["a", "b", "d"]);
|
||||
|
||||
x.insert(1, "f");
|
||||
REQUIRE_EQUAL(x.vector, ["a", "f", "b", "d"]);
|
||||
REQUIRE_EQUAL(x.size(), 4);
|
||||
x.remove("f");
|
||||
REQUIRE_EQUAL(x.vector, ["a", "b", "d"]);
|
||||
|
||||
x.insert(2, "f");
|
||||
REQUIRE_EQUAL(x.vector, ["a", "b", "f", "d"]);
|
||||
x.remove("f");
|
||||
REQUIRE_EQUAL(x.vector, ["a", "b", "d"]);
|
||||
|
||||
x.insert(3, "g");
|
||||
REQUIRE_EQUAL(x.vector, ["a", "b", "d", "g"]);
|
||||
x.remove("g");
|
||||
|
||||
x.insert(4, "g");
|
||||
REQUIRE_EQUAL(x.vector, ["a", "b", "d", "g"]);
|
||||
x.remove("g");
|
||||
|
||||
x.insert(-1, "h");
|
||||
REQUIRE_EQUAL(x.vector, ["a", "b", "h", "d"]);
|
||||
x.remove("h");
|
||||
|
||||
x.insert(-2, "h");
|
||||
REQUIRE_EQUAL(x.vector, ["a", "h", "b", "d"]);
|
||||
x.remove("h");
|
||||
|
||||
x.insert(-3, "h");
|
||||
REQUIRE_EQUAL(x.vector, ["h", "a", "b", "d"]);
|
||||
x.remove("h");
|
||||
|
||||
x.insert(-4, "h");
|
||||
REQUIRE_EQUAL(x.vector, ["h", "a", "b", "d"]);
|
||||
x.remove("h");
|
||||
|
||||
# pop():
|
||||
REQUIRE_EQUAL(x.pop(-1), "d");
|
||||
REQUIRE_EQUAL(x.vector, ["a", "b"]);
|
||||
x.append("d");
|
||||
|
||||
REQUIRE_EQUAL(x.pop(-2), "b");
|
||||
REQUIRE_EQUAL(x.vector, ["a", "d"]);
|
||||
x.insert(1, "b");
|
||||
|
||||
REQUIRE_EQUAL(x.pop(-3), "a");
|
||||
REQUIRE_EQUAL(x.vector, ["b", "d"]);
|
||||
x.insert(0, "a");
|
||||
REQUIRE_EQUAL(x.vector, ["a", "b", "d"]);
|
||||
|
||||
# Exceptions (should fail)
|
||||
REQUIRE_THROW(func x.pop(-4), "IndexError");
|
||||
REQUIRE_THROW(func x.pop(3), "IndexError");
|
||||
REQUIRE_THROW(func x.remove("e"), "ValueError");
|
86
Nasal/std/hash.nas
Normal file
86
Nasal/std/hash.nas
Normal file
|
@ -0,0 +1,86 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#
|
||||
# NOTE! This copyright does *not* cover user models that use these Nasal
|
||||
# services by normal function calls - this is merely considered normal use
|
||||
# of the code, and does *not* fall under the heading of "derived work."
|
||||
#-------------------------------------------------------------------------------
|
||||
# hash.nas - simple hash class for development, allows to add callback on write
|
||||
# author: Henning Stahlke
|
||||
# created: 07/2020
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
#load only once (via /Nasal/std.nas) not via C++ module loader
|
||||
if (ishash(globals["std"]) and ishash(std["Hash"]))
|
||||
return;
|
||||
|
||||
Hash = {
|
||||
new: func(hash=nil, name="") {
|
||||
var obj = {
|
||||
parents: [me],
|
||||
name: name,
|
||||
_h: {},
|
||||
_callback: func,
|
||||
};
|
||||
if (ishash(hash))
|
||||
obj._h = hash;
|
||||
return obj;
|
||||
},
|
||||
|
||||
set: func (key, value) {
|
||||
me._h[key] = value;
|
||||
me._callback(key, value);
|
||||
return me;
|
||||
},
|
||||
|
||||
get: func (key) {
|
||||
return me._h[key];
|
||||
},
|
||||
|
||||
clear: func() {
|
||||
me._h = {};
|
||||
return me;
|
||||
},
|
||||
|
||||
contains: func(key) {
|
||||
return contains(me._h, key);
|
||||
},
|
||||
|
||||
getName: func () {
|
||||
return me.name;
|
||||
},
|
||||
|
||||
getKeys: func () {
|
||||
return keys(me._h);
|
||||
},
|
||||
|
||||
# export keys to props p/<keys>
|
||||
# p: root property path or props.Node object
|
||||
keys2props: func (p) {
|
||||
if (!isa(p, props.Node)) {
|
||||
p = props.getNode(p, 1);
|
||||
}
|
||||
foreach (var key; keys(me._h)) {
|
||||
p.getNode(key, 1);
|
||||
}
|
||||
return me;
|
||||
},
|
||||
|
||||
# export hash to props p/<key>=<value>
|
||||
# p: root property path or props.Node object
|
||||
hash2props: func (p) {
|
||||
if (!isa(p, props.Node)) {
|
||||
p = props.getNode(p, 1);
|
||||
}
|
||||
p.setValues(me._h);
|
||||
return me;
|
||||
},
|
||||
|
||||
# callback for set()
|
||||
addCallback: func (f) {
|
||||
if (isfunc(f)) {
|
||||
me._callback = f;
|
||||
return me;
|
||||
}
|
||||
return nil;
|
||||
},
|
||||
};
|
|
@ -9,15 +9,15 @@
|
|||
#
|
||||
# Copyright (C) 2012-2013 by Thomas Geymayer
|
||||
|
||||
#load only once (via /Nasal/std.nas) not via C++ module loader
|
||||
if (ishash(globals["std"]) and ishash(std["String"]))
|
||||
return;
|
||||
|
||||
# capture global string
|
||||
var _string = string;
|
||||
|
||||
var string = {
|
||||
var String = {
|
||||
# public:
|
||||
new: func(str)
|
||||
{
|
||||
return { parents: [string], _str: str };
|
||||
return { parents: [String], _str: str };
|
||||
},
|
||||
# compare(s)
|
||||
# compare(pos, n, s)
|
||||
|
@ -56,6 +56,9 @@ var string = {
|
|||
return 0;
|
||||
return 1;
|
||||
},
|
||||
|
||||
# returns index (zero based) of first occurrence of s
|
||||
# searching from pos
|
||||
find_first_of: func(s, pos = 0)
|
||||
{
|
||||
return me._find(pos, size(me._str), s, 1);
|
||||
|
@ -101,6 +104,13 @@ var string = {
|
|||
}
|
||||
};
|
||||
|
||||
# for backward compatibility
|
||||
var string = {parents: [String]};
|
||||
string.new = func {
|
||||
logprint(LOG_ALERT, "Deprecated use of std.string, please use std.String instead.");
|
||||
return String.new(arg[0]);
|
||||
}
|
||||
|
||||
# converts a string to an unsigned integer
|
||||
var stoul = func(str, base = 10)
|
||||
{
|
||||
|
@ -109,10 +119,10 @@ var stoul = func(str, base = 10)
|
|||
{
|
||||
var c = str[pos];
|
||||
|
||||
if( _string.isdigit(c) )
|
||||
if( globals.string.isdigit(c) )
|
||||
var digval = c - `0`;
|
||||
else if( _string.isalpha(c) )
|
||||
var digval = _string.toupper(c) - `A` + 10;
|
||||
else if( globals.string.isalpha(c) )
|
||||
var digval = globals.string.toupper(c) - `A` + 10;
|
||||
else
|
||||
break;
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue