Files
Mozilla/mozilla/zap/base/ArrayUtils.js
alex%croczilla.com 6ff4b5a4b4 toString() redefinition for modules breaks ("redeclaration of const toString"), probably because of #339041. Patch by Marc Petit-Huguenin <marc@8x8.com>.
git-svn-id: svn://10.0.0.236/branches/ZAP_20050610_BRANCH@212118 18797224-902f-48f8-a5cc-f745e15eee43
2006-09-21 17:46:57 +00:00

258 lines
8.0 KiB
JavaScript

/* -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 moz-jssh-buffer-globalobj: "Components.utils.importModule('gre:ArrayUtils.js', null)" -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Mozilla SIP client project.
*
* The Initial Developer of the Original Code is 8x8 Inc.
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Alex Fritze <alex@croczilla.com> (original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
Components.utils.importModule("gre:FunctionUtils.js");
EXPORTED_SYMBOLS = [ "arraymerge",
"arrayclone",
"arraysplit",
"member",
"findif",
"isarray",
"flatten",
"dflatten",
"arraysubst",
"arrayequal",
"union",
"intersection",
"difference",
"makeArrayIterator"];
// name our global object:
// function toString() { return "[ArrayUtils.js]"; }
//----------------------------------------------------------------------
// arraymerge
defun(
"Append elements from array 'src' to array 'dest', ommitting elements "+
"that are present in both 'src' and 'dest' and equal under 'eq' "+
"(default: '=='). Returns 'dest' array.",
function arraymerge(dest, src, /*[opt]*/ eq) {
if (!eq)
eq = function(a,b) {return a==b;};
for (var i=0, sl=src.length; i<sl; ++i) {
for (var j=0, dl=dest.length; j<dl; ++j) {
if (eq(src[i], dest[j])) break;
}
if (j==dl)
dest.push(src[i]);
}
return dest;
});
//----------------------------------------------------------------------
// arrayclone
defun(
"Returns a shallow copy of array 'src'.",
function arrayclone(src) {
return src.slice(0);
});
//----------------------------------------------------------------------
// arraysplit
defun(
"Destructively remove items satisfying 'predicate' from 'array'. "+
"Returns array of removed items.",
function arraysplit(predicate, array) {
var removed = [];
for (var i=array.length-1; i>=0; --i) {
if (predicate(array[i]))
removed.unshift(array.splice(i,1)[0]);
}
return removed;
});
//----------------------------------------------------------------------
// member
defun(
"Returns true if 'array' contains at least one element equal ('==') "+
"to 'element'.",
function member(element, array) {
return array.some(function(e) {return e==element;});
});
//----------------------------------------------------------------------
// findif
defun(
"Returns the first element in 'array' that satisfies 'predicate', or "+
"null if no matching element is found.",
function findif(predicate, array) {
for (var i=0, l=array.length; i<l; ++i) {
if (predicate(array[i]))
return array[i];
}
return null;
});
//----------------------------------------------------------------------
// isarray
defun(
"Check whether 'obj' is of array type. More reliable than "+
"'obj instanceof Array' which gives false negatives if the context "+
"that 'obj' was created in is different to the content that the test "+
"is performed in.",
function isarray(obj) {
// XXX ideally we would like to use 'instanceof' to test whether
// something is an array. Unfortunately, arrays might be instances
// of different 'Array' objects, depending on the context that they
// were created in. We have to use the following hack instead:
if (obj && obj.length!=null && obj.push)
return true;
return false;
});
//----------------------------------------------------------------------
// flatten
defun(
"Returns a flattened version of 'array'.",
function flatten(array) {
var l = array.length;
var retval = [];
for (var i=0; i<l; ++i) {
if (isarray(array[i])) {
array[i].forEach(function(e){retval.push(e);});
}
else
retval.push(array[i]);
}
return retval;
});
//----------------------------------------------------------------------
// dflatten
defun(
"Destructively flattens 'array': Any members of 'array' which are "+
"arrays themselves are spliced into 'array'.",
function dflatten(array) {
for (var i=array.length-1; i>=0; --i) {
if (isarray(array[i])) {
var a = array.splice(i,1)[0];
for (var k=0,l=a.length; k<l; ++k)
array.splice(i+k,0,a[k]);
}
}
return array;
});
//----------------------------------------------------------------------
// arraysubst
defun(
"Destructively substitute 'newelem' for 'oldelem' in 'array'.",
function arraysubst(newelem, oldelem, array) {
for (var i=0, l=array.length; i<l; ++i) {
if (array[i]==oldelem)
array[i]=newelem;
}
});
//----------------------------------------------------------------------
// arrayequal
defun(
"Returns true iff arrays 'arr1' and 'arr2' have the same length and "+
"their elements are equal under 'eq' (default: '==').",
function arrayequal(arr1, arr2, /*[opt]*/ eq) {
if (arr1.length!=arr2.length) return false;
if (!eq)
eq = function(a,b) {return a==b;};
for (var i=0, l=arr1.length; i<l; ++i) {
if (!eq(arr1[i],arr2[i]))
return false;
}
return true;
});
//----------------------------------------------------------------------
// union
defun(
"Returns the union of the given arrays.",
function union(arr1, arr2) {
var retval = [];
arraymerge(retval, arr1);
arraymerge(retval, arr2);
return retval;
});
//----------------------------------------------------------------------
// intersection
defun(
"Returns the intersection of the given arrays.",
function intersection(arr1, arr2) {
var retval = [];
arr1.forEach(function(item) {
if (member(item, arr2)) arraymerge(retval, [item]);});
return retval;
});
//----------------------------------------------------------------------
// difference
defun(
"Returns the set difference 'arr1'-'arr2'.",
function difference(arr1, arr2) {
var retval = [];
arr1.forEach(function(item) {
if (!member(item, arr2)) retval.push(item);});
return retval;
});
//----------------------------------------------------------------------
// makeArrayIterator
defun(
"Returns an iterator with methods getNext() and hasMore() "+
"for the given array.",
function makeArrayIterator(arr) {
var index = 0;
return {
getNext: function() { return arr[index++]; },
hasMore: function() { return index<arr.length; }
};
});