2014-10-17 23:13:37 +00:00
|
|
|
# Copyright (C) 2014 onox
|
|
|
|
#
|
|
|
|
# This program is free software: you can redistribute it and/or modify
|
|
|
|
# it under the terms of the GNU General Public License as published by
|
|
|
|
# the Free Software Foundation; either version 2 of the License, or
|
|
|
|
# (at your option) any later version.
|
|
|
|
#
|
|
|
|
# This program is distributed in the hope that it will be useful,
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
# GNU General Public License for more details.
|
|
|
|
#
|
|
|
|
# You should have received a copy of the GNU General Public License
|
|
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
2020-06-08 13:07:28 +00:00
|
|
|
#
|
|
|
|
# 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."
|
|
|
|
|
2020-07-01 12:46:47 +00:00
|
|
|
#load only once (via /Nasal/std.nas) not via C++ module loader
|
|
|
|
if (ishash(globals["std"]) and ishash(std["Vector"]))
|
|
|
|
return;
|
2014-10-17 23:13:37 +00:00
|
|
|
|
|
|
|
var Vector = {
|
|
|
|
|
2020-07-01 12:46:47 +00:00
|
|
|
new: func (vector=nil, name="") {
|
2014-10-17 23:13:37 +00:00
|
|
|
var m = {
|
2020-07-01 12:46:47 +00:00
|
|
|
parents: [Vector],
|
|
|
|
name: name,
|
|
|
|
vector: [],
|
|
|
|
_callback: func,
|
2014-10-17 23:13:37 +00:00
|
|
|
};
|
2020-07-01 12:46:47 +00:00
|
|
|
if (isvec(vector)) {
|
|
|
|
m.vector = vector;
|
2014-10-17 23:13:37 +00:00
|
|
|
}
|
|
|
|
return m;
|
|
|
|
},
|
2020-07-01 12:46:47 +00:00
|
|
|
|
|
|
|
# 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;
|
|
|
|
},
|
2014-10-17 23:13:37 +00:00
|
|
|
|
|
|
|
size: func {
|
|
|
|
return size(me.vector);
|
|
|
|
},
|
|
|
|
|
|
|
|
clear: func {
|
|
|
|
me.vector = [];
|
|
|
|
},
|
|
|
|
|
|
|
|
append: func (item) {
|
|
|
|
append(me.vector, item);
|
2020-07-01 12:46:47 +00:00
|
|
|
me._callback(me.size() - 1, item);
|
2014-10-17 23:13:37 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
extend: func (other_vector) {
|
|
|
|
# Extend the vector with another vector, appending the items of
|
|
|
|
# the other vector to this vector
|
|
|
|
|
|
|
|
me.vector = me.vector ~ other_vector;
|
|
|
|
},
|
|
|
|
|
|
|
|
insert: func (index, item) {
|
|
|
|
# Insert the given item at the given index before the old item
|
|
|
|
# at that index. Any index greater than n-1 where n is the size of
|
|
|
|
# the vector will append the given item at the end. Any index smaller
|
|
|
|
# or equal to -n will insert the item at the beginning of the vector.
|
|
|
|
#
|
|
|
|
# For example, if the vector contains ["a", "b", "c"], then the
|
|
|
|
# following operations can happen:
|
|
|
|
#
|
|
|
|
# insert(0, "d") => ["d", "a", "b", "c"]
|
|
|
|
# insert(2, "e") => ["a", "b", "e", "c"]
|
|
|
|
# insert(3, "f") => ["a", "b", "c", "f"]
|
|
|
|
# insert(-3, "g") => ["f", "a", "b", "c"]
|
|
|
|
|
2020-07-01 12:46:47 +00:00
|
|
|
index = math.min(index, me.size());
|
2014-10-17 23:13:37 +00:00
|
|
|
if (index < 0) {
|
2020-07-01 12:46:47 +00:00
|
|
|
index = math.max(0, me.size() + index);
|
2014-10-17 23:13:37 +00:00
|
|
|
}
|
|
|
|
me.vector = subvec(me.vector, 0, index) ~ [item] ~ subvec(me.vector, index);
|
2020-07-01 12:46:47 +00:00
|
|
|
me._callback(index, item);
|
|
|
|
return me.vector;
|
2014-10-17 23:13:37 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
pop: func (index=nil) {
|
|
|
|
# Remove and return the item at the given index. If index
|
|
|
|
# is not given, then it will remove and return the last item.
|
|
|
|
# A negative index represents the position from the end.
|
|
|
|
#
|
|
|
|
# For example, if the vector contains ["a", "b", "c"], then the
|
|
|
|
# following operations can happen:
|
|
|
|
#
|
|
|
|
# pop(0) => "a"
|
|
|
|
# pop(2) => "c"
|
|
|
|
# pop(-1) => "c"
|
|
|
|
# pop(-3) => "a"
|
|
|
|
#
|
|
|
|
# Thus the range is -n .. n-1 where n is the size of the vector.
|
|
|
|
# IndexError is raised if the index is out of range.
|
|
|
|
|
|
|
|
if (index != nil) {
|
|
|
|
if (index < -me.size() or index >= me.size()) {
|
|
|
|
die("IndexError: index out of range");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (index < 0) {
|
|
|
|
index = me.size() + index;
|
|
|
|
}
|
|
|
|
var item = me.vector[index];
|
|
|
|
me.vector = subvec(me.vector, 0, index) ~ subvec(me.vector, index + 1);
|
|
|
|
return item;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return pop(me.vector);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
index: func (item) {
|
|
|
|
# Return first index of the given item. Raises a ValueError
|
|
|
|
# if the item is not in the vector.
|
2020-07-01 12:46:47 +00:00
|
|
|
var i = vecindex(me.vector, item);
|
|
|
|
if (i == nil) die("ValueError: item not in the vector");
|
|
|
|
return i;
|
2014-10-17 23:13:37 +00:00
|
|
|
},
|
|
|
|
|
2014-12-23 13:40:29 +00:00
|
|
|
contains: func (item) {
|
|
|
|
# Return true if the vector contains the item, false otherwise
|
2020-07-01 12:46:47 +00:00
|
|
|
return vecindex(me.vector, item) != nil;
|
2014-12-23 13:40:29 +00:00
|
|
|
},
|
|
|
|
|
2014-10-17 23:13:37 +00:00
|
|
|
remove: func (item) {
|
|
|
|
# Remove the first occurrence of the given item. Raises a
|
|
|
|
# ValueError if the item is not present in the vector.
|
|
|
|
|
|
|
|
me.pop(me.index(item));
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|