# 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 . # # 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." #load only once (via /Nasal/std.nas) not via C++ module loader if (ishash(globals["std"]) and ishash(std["Vector"])) return; var min = func(a, b) { a < b ? a : b } var max = func(a, b) { a > b ? a : b } var Vector = { new: func (vector=nil, name="") { var m = { parents: [Vector], name: name, vector: [], _callback: func, }; if (isvec(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 size(me.vector); }, clear: func { me.vector = []; }, append: func (item) { append(me.vector, item); me._callback(me.size() - 1, item); }, 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"] index = math.min(index, me.size()); if (index < 0) { 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) { # 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. 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 return vecindex(me.vector, item) != nil; }, 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)); } };