/** ** ============================== ** O O O OOOO ** O O O O O O ** O O O O O O ** OOOO OOOO O OOO OOOO ** O O O O O O O ** O O O O O O O ** OOOO OOOO O O OOOO ** ============================== ** Dr. Stefan Bosse http://www.bsslab.de ** ** COPYRIGHT: THIS SOFTWARE, EXECUTABLE AND SOURCE CODE IS OWNED ** BY THE AUTHOR(S). ** THIS SOURCE CODE MAY NOT BE COPIED, EXTRACTED, ** MODIFIED, OR OTHERWISE USED IN A CONTEXT ** OUTSIDE OF THE SOFTWARE SYSTEM. ** ** $AUTHORS: Stefan Bosse ** $INITIAL: (C) 2006-2021 bLAB ** $CREATED: 30-3-15 by sbosse. ** $VERSION: 1.24.1 ** ** $INFO: ** ** JavaScript-OCaML Compatibility Module ** ** $ENDOFINFO */ var Io = Require('com/io'); var Path = Require('com/path'); var Sprintf = Require('com/sprintf'); /******************************* ** Some global special "values" ********************************/ /** A matching template pattern matching any value * * @type {undefined} */ global.any = undefined; /** A matching template pattern matching any value * * @type {undefined} */ global._ = undefined; /** * * @type {null} */ global.none = null; /** * * @type {null} */ global.empty = null; global.NL = '\n'; global.int = function (v) {return v|0}; global.div = function (a,b) {return a/b|0}; if (!Object.prototype.forEach) { Object.defineProperties(Object.prototype, { 'forEach': { value: function (callback) { if (this == null) { throw new TypeError('Not an object'); } var obj = this; for (var key in obj) { if (obj.hasOwnProperty(key)) { callback.call(obj, obj[key], key, obj); } } }, writable: true } }); } /** Just transfer parent prototypes to child * */ function inherit(child,parent) { for(var p in parent.prototype) { if (p == '__proto__') continue; child.prototype[p]=parent.prototype[p]; } } /** Portable class inheritance and instanceOf polyfill * */ // SomeObject.prototype.__proto__=SomeObject2.prototype; // Child class inherits prototype from parent using __proto__ function inheritPrototype(child,parent) { var __proto__=child.__proto__; child.prototype.__proto__=parent.prototype; if (!__proto__) for(var p in parent.prototype) { if (p == '__proto__') continue; child.prototype[p]=parent.prototype[p]; } } // Polyfill fir o instanceof c with inheritance check (checking __proto__) function instanceOf(obj,cla) { var p=obj.__proto__; if (obj instanceof cla) return true; while (p) { if (p === cla.prototype) return true; p=p.__proto__ } return false; } // Polyfill for __defineGetter__ / __defineSetter__ function defineGetter(cla,prop,fun) { Object.defineProperty(cla.prototype,prop,{ configurable:true, get:fun }); } function defineSetter(cla,prop,fun) { Object.defineProperty(cla.prototype,prop,{ configurable:true, set:fun }); } Object.addProperty = function (obj,name,fun) { if (obj.prototype[name]) return; obj.prototype[name]=fun; Object.defineProperty(obj.prototype, name, {enumerable: false}); }; Object.updateProperty = function (obj,name,fun) { obj.prototype[name]=fun; Object.defineProperty(obj.prototype, name, {enumerable: false}); }; Object.addProperty(Array,'contains',function (el) { return this.indexOf(el)!=-1 }); Object.addProperty(Array,'last',function () { return this[this.length-1] }); global.inherit = inherit; global.inheritPrototype = inheritPrototype; global.instanceOf = instanceOf; global.defineGetter = defineGetter; global.defineSetter = defineSetter; /** * */ var assert = function(condmsg) { if (condmsg != true) { Io.out('** Assertion failed: '+condmsg+' **'); Io.stacktrace(); throw Error(condmsg); } }; global.assert=assert; function forof(obj,f) { var _iteratorNormalCompletion = true; var _didIteratorError = false; var _iteratorError = undefined; try { for (var _iterator = obj[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { element = _step.value; f(element); } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator.return) { _iterator.return(); } } finally { if (_didIteratorError) { throw _iteratorError; } } } } global.forof=forof; /** OBJ * */ var obj = { /** Compact an object: * [{a:b},[c:d},..] -> {a:b,c:d,..} * {a:[b]} -> {a:b} * */ compact: function (o) { var a; if (obj.isArray(o)) { if (o.length==1 && obj.isObject(o[0])) return obj.compact(o[0]); else return o; } else if (obj.isObject(o)) for (a in o) { var elem=o[a]; o[a]=obj.compact(elem); } return o; }, copy: function (o) { if (o === null || typeof o !== 'object') { return o; } var temp = (o instanceof Array) ? [] : {}; for (var key in o) { temp[key] = obj.copy(o[key]); } return temp; }, equal: function (o1,o2) { if (!o1 || !o2) return false; for(var i in o1) if (o1[i]!=o2[i]) return false; for(var i in o2) if (o1[i]!=o2[i]) return false; return true; }, extend: function (o1,o2) { for(var i in o2) o1[i]=o2[i]; return o1; }, find: function(obj,fun) { var p; for(p in obj) { if (fun(obj[p],p)) return obj[p]; } }, hasProperty: function (o,p) { return o[p]!=undefined || (p in o); }, head:function(o) { for (var p in o) return p; return undefined; }, // transfer src attributes to dst recusively (no object overwrite) inherit: function (dst,src) { for(var i in src) { if (typeof dst[i] == 'object' && typeof src[i] == 'object') inherit(dst[i],src[i]); else if (typeof dst[i] == 'undefined') dst[i]=src[i]; } return dst; }, isArray:function (o) { if (o==_ || o ==null) return false; else return typeof o == "array" || (typeof o == "object" && o.constructor === Array); }, isMatrix:function (o) { if (o==_ || o ==null) return false; else return obj.isArray(o) && obj.isArray(o[0]); }, isEmpty: function (o) { for(var prop in o) { if (o[prop]!=undefined) return false; } return true; }, isError: function (o) { return o instanceof Error }, isFunction: function (o) { return typeof o == "function"; }, isObj:function (o) { return typeof o == "object"; }, isObject:function (o) { return typeof o == "object"; }, isRegex: function (o) { return o instanceof RegExp; }, isString: function (o) { return typeof o == "string" || (typeof o == "object" && o.constructor === String); }, isNumber: function (o) { return typeof o == "number" || (typeof o == "object" && o.constructor === Number); }, iter: function(obj,fun) { var p; for(p in obj) { fun(obj[p],p) } } }; /** ARRAY * */ var array = { /** Evaluate a function returning a boolean value for each member of the array and * compute the boolean conjunction. * * @param {* []} array * @param {function(*,number)} fun */ and: function(array,fun) { var res=true; var i=0; var len=array.length; for(i=0;i|string|Blob|ArrayBuffer} */ copy: function(src,dst) { var i; if (dst) { for(i in src) dst[i]=src[i]; } else return src.slice(); }, /** Create a new array with initial element values. * * @param length * @param init * @returns {Array} */ create : function(length,init) { var arr = [], i = length; while (i--) { arr[i] = init; } return arr; }, /** Create a matrix (array of array) with initial element values. * */ create_matrix : function(rows,cols,init) { var m = []; var r = []; var i,j; for (i = 0; i < rows; i++) { r=[]; for(j=0;j=0;i--) { fun(array[i],i) } }, /** Return last element of array. * */ last : function(array) { var len=array.length; if (len==0) return none; else return array[len-1]; }, length : function(array) { return array.length; }, /** * * @param {* []} array1 * @param {* []} array2 * @param {function(*,*,number)} fun * @returns {* []} */ map2: function(array1,array2,fun) { var i=0; assert((array1.length == array2.length)||('Array.map2: arrays of different lengths')); var len=array1.length; var res=[]; for(i=0;i1) { var hd = this.head(array); var tl = this.tail(array); fun_hdtl(hd,tl); } else fun_hdtl(this.head(array),[]); }, /** * * @param {* []} array * @param {Function} fun_hd1hd2 - function(hd1,hd2) * @param {Function} [fun_hdtl] - function(hd,tl) * @param {Function} [fun_empty] - function() */ match2: function(array,fun_hd1hd2,fun_hdtl,fun_empty) { if (array.length == 0 && fun_empty) fun_empty(); else if (array.length == 2) { var hd1 = this.head(array); var hd2 = this.second(array); fun_hd1hd2(hd1,hd2); } else if (array.length>1 && fun_hdtl) { var hd = this.head(array); var tl = this.tail(array); fun_hdtl(hd,tl); } else if (fun_hdtl) fun_hdtl(this.head(array),[]); }, /** Return the maximum element of an array applying * an optional mapping function. * * @param {* []} array * @param [fun] * @returns {number|undefined} */ max : function (array,fun) { var res,max,num; for(var i in array) { if (fun) num=fun(array[i]); else num=array[i]; if (max==undefined) { max=num; res=array[i] } else if (num > max) { max=num; res=array[i] } } return res; }, /** Return the minimum element of an array applying * an optional mapping function. * * @param {* []} array * @param [fun] * @returns {number|undefined} */ min : function (array,fun) { var res,min,num; for(var i in array) { if (fun) num=fun(array[i]); else num=array[i]; if (min==undefined) { min=num; res=array[i] } else if (num < min) { min=num; res=array[i] } } return res; }, /** Check for an element in the array. * * @param {(number|string|boolean) []} array * @param {number|string|boolean} element * @returns {boolean} */ member: function(array,element) { var i,exist; var len=array.length; exist=false; loop: for(i=0;i ['barney', 'fred'] */ pluck: function(collection, key) { return collection.map(function(object) { return object == null ? undefined : object[key]; }); }, /* ** Push/pop head elements (Stack behaviour) */ /** Remove and return top element of array. * * @param array * @returns {*} */ pop : function(array) { var element=array[0]; array.shift(); return element; }, print: function(array) { var i; var len=array.length; var str='['; for(i=0;i [1,2,6] * @param {* []} array * @returns {* []} */ remove: function(array,begin,end) { var i,a; if (end==undefined) end=begin+1; if (begin<0 || end >= array.length) return []; a=array.slice(0,begin); for(i=end;i use remove!!! split should return two arrays!! * * @param array * @param pos * @param [len] * @param element */ split: function(array,pos,len) { if (pos==0) return array.slice((len||1)); else { var a1=array.slice(0,pos); var a2=array.slice(pos+(len||1)); return a1.concat(a2); } }, /** Return the sum number of an array applying * an optional mapping function. * * @param {* []} array * @param [fun] * @returns {number|undefined} */ sum : function (array,fun) { var res=0; for(var i in array) { var num=0; if (fun) num=fun(array[i]); else num=array[i]; if (!obj.isNumber(num)) return undefined; res += num; } return res; }, /** Return a new array w/o the head element (or optional * w/o the first top elements). * */ tail : function(array,top) { var array2=array.slice(); array2.shift(); if (top) for(;top>1;top--) array2.shift(); return array2; }, /** Return union of two sets (== conjunction set) * * @param {* []} set1 * @param {* []} set2 * @param {function} [fun] Equality test * @returns {* []} */ union : function(set1,set2,fun) { var i,j,res = []; for (i in set1) { for (j in set2) { if (fun != undefined && fun(set1[i],set2[j])) res.push(set1[i]); else if (fun == undefined && set1[i]==set2[j]) res.push(set1[i]); } } return res; }, /** * Creates a duplicate-free version of an array */ unique: function(array) { var length = array ? array.length : 0; function baseUniq(array) { var index = -1, length = array.length, seen, result = []; seen = result; outer: while (++index < length) { var value = array[index]; var seenIndex = seen.length; while (seenIndex--) { if (seen[seenIndex] === value) { continue outer; } } result.push(value); } return result; } if (!length) { return []; } return baseUniq(array); }, /** * Creates an array excluding all provided values * without([1, 2, 1, 3], 1, 2); * // => [3] */ without: function () { var array, values=[]; for(var i in arguments) { if (i==0) array=arguments[0]; else values.push(arguments[i]); } return array.filter(function (e) { return values.indexOf(e) == -1; }); }, /** Test for zero elements {0, '', false, undefined, ..} */ zero: function (array) { for(var i in array) if (!!array[i]) return false; return true; }, }; /** STRING * */ var string = { /** Is pattern conatined in template? * */ contains: function (template,pattern) { return template.indexOf(pattern)>-1; }, copy: function(src) { var i; var dst=''; for(i=0;i>4) & 0xf).toString(16))+ ((n&0xf).toString(16)); case 4: return (((n>>12) & 0xf).toString(16)+ ((n>>8) & 0xf).toString(16)+ ((n>>4) & 0xf).toString(16)+ (n&0xf).toString(16)); case 6: return (((n>>20) & 0xf).toString(16)+ ((n>>16) & 0xf).toString(16)+ ((n>>12) & 0xf).toString(16)+ ((n>>8) & 0xf).toString(16)+ ((n>>4) & 0xf).toString(16)+ (n&0xf).toString(16)); case 8: return (((n>>28) & 0xf).toString(16)+ ((n>>24) & 0xf).toString(16)+ ((n>>20) & 0xf).toString(16)+ ((n>>16) & 0xf).toString(16)+ ((n>>12) & 0xf).toString(16)+ ((n>>8) & 0xf).toString(16)+ ((n>>4) & 0xf).toString(16)+ (n&0xf).toString(16)); default: return 'format_hex??'; } }, /** * * @param {string} str * @param {number} index * @returns {string} */ get: function (str,index) { assert((str != undefined && index < str.length && index >= 0)||('string.get ('+str.length+')')); return str.charAt(index); }, isBoolean: function (str) { return (str=='true' || str=='false') }, isNumeric: function (str) { return !isNaN(parseFloat(str)) && isFinite(str); }, isText: function (s) { var is_text=true; string.iter(s,function (ch,i) { string.match(ch,[ ['a','z',function () {}], ['A','Z',function () {}], ['0','9',function () {if (i==0) is_text=false;}], function () {is_text=false;} ]); }); return is_text; }, /** * * @param {string} str * @param {function(string,number)} fun */ iter: function(str,fun) { var i; var len=str.length; for (i = 0; i < len; i++) { var c = str.charAt(i); fun(c,i); } }, /** * * @param str * @returns {*} */ length: function(str) { if (str!=undefined) return str.length; else return 0; }, /** * * @param str * @returns {string} */ lowercase : function (str) { return str.toLowerCase(); }, /** * * @param {number} size * @param {string} init * @returns {string} */ make: function(size,init) { var i; var s=''; for(i=0;i,,..],fun] | [:string,:string,fun] | fun) [] */ match: function(str,cases) { var i,j; var cas,cex,cv; for(i in cases) { cas=cases[i]; if (obj.isArray(cas)) { switch (cas.length) { case 2: // Multi-value-case cex=cas[0]; if (!obj.isArray(cex)) { if (this.equal(str,cex)) { cas[1](); return; } } else { for(j in cex) { cv=cex[j]; if (this.equal(str,cv)) { cas[1](); return; } } } break; case 3: // Character range check try { j=pervasives.int_of_char(str); if (j>= pervasives.int_of_char(cas[0]) && j<=pervasives.int_of_char(cas[1])) { cas[2](str); return; } } catch(e) { return }; break; case 1: cas[0](str); // Default case - obsolete return; default: throw 'String.match #args'; } } else if (obj.isFunction(cas)) { // Default case cas(str); return; } } }, /** Pad a string on the left (pre-str.length) if pre>0, * right (post-str.length) if post>0, or centered (pre>0&post>0). * */ pad: function (str,pre,post,char) { var len = str.length; if (pre>0 && post==0) return string.make(len-pre,char||' ')+str; else if (post>0 && pre==0) return str+string.make(post-len,char||' '); else return string.make(len-pre/2,char||' ')+str+string.make(len-post/2,char||' '); }, /** * * @param str * @param pos * @param len * @returns {Number} */ parse_hex: function (str,pos,len) { // parse a hexadecimal number in string 'str' starting at position 'pos' with 'len' figures. return parseInt(this.sub(str,pos,len),16); }, /** Return the sub-string after a point in the source string ('.' or optional point string). * If there is no splitting point, the original string is returned. * * @param str * @param [point] * @returns {string} */ postfix: function (str,point) { var n = str.indexOf(point||'.'); if (n <= 0) return str; else return str.substr(n+1); }, /** Return the sub-string before a point in the source string ('.' or optional point string) * If there is no splitting point, the original string is returned. * * @param str * @param [point] * @returns {string} */ prefix: function (str,point) { var n = str.indexOf(point||'.'); if (n <= 0) return str; else return str.substr(0,n); }, replace_first: function (pat,repl,str) { return str.replace(pat,repl); }, replace_all: function (pat,repl,str) { return str.replace('/'+pat+'/g',repl); }, /** * * @param str * @param index * @param char * @returns {string} */ set: function (str,index,char) { assert((str != undefined && index < str.length && index >= 0)||'string.get'); return str.substr(0, index) + char + str.substr(index+1) }, /** * * @param delim * @param str * @returns {*|Array} */ split: function (delim,str) { return str.split(delim); }, startsWith : function (str,head) { return !str.indexOf(head); }, /** Return a sub-string. * * @param str * @param off * @param [len] If not give, return a sub-string from off to end * @returns {string} */ sub: function (str,off,len) { if (len) return str.substr(off,len); else return str.substr(off); }, /** Remove leading and trailing characters from string * * @param str * @param {number} pref number of head characters to remove * @param {number} post number of tail characters to remove * @returns {*} */ trim: function (str,pref,post) { if (str.length==0 || pref>str.length || post>str.length || pref < 0 || post < 0 || (pref==0 && post==0) ) return str; return str.substr(pref,str.length-pref-post); }, /** Return a string with all characters converted to uppercase letters. * * @param str * @returns {string} */ uppercase : function (str) { return str.toUpperCase(); }, /** Return a string with first character converted to uppercase letter. * * @param str * @returns {string} */ Uppercase : function (str) { var len = str.length; if (len > 1) { var head = str.substr(0,1); var tail = str.substr(1,len-1); return head.toUpperCase()+tail.toLowerCase() } if (len==1) return str.toUpperCase(); else return ''; } }; /** RANDOM * */ var rnd = Math.random; /* Antti Syk\E4ri's algorithm adapted from Wikipedia MWC ** Returns a random generator function [0.0,1.0| with seed initialization */ var seeder = function(s) { var m_w = s; var m_z = 987654321; var mask = 0xffffffff; return function() { m_z = (36969 * (m_z & 65535) + (m_z >> 16)) & mask; m_w = (18000 * (m_w & 65535) + (m_w >> 16)) & mask; var result = ((m_z << 16) + m_w) & mask; result /= 4294967296; return result + 0.5; } } var random = { float: function(max) { return rnd()*max }, int: function(max) { return Math.floor(rnd()*max+0) }, // integer interval: function(min,max) { return Math.round(min+rnd()*(max-min)) }, // float range: function(min,max) { return min+rnd()*(max-min) }, seed: function (s) { // Create a new initialized random generator rnd=seeder(s); } }; /** PRINTF * */ var printf = { /** Trim string(s). * * @param str * @param indent * @param [width] * @param {string} [tab] * @returns {string} */ align: function (str,indent,width,tab) { var lines = string.split('\n',str); var form = ''; var sp = printf.spaces(indent); var spbreak = sp; array.iter(lines,function(line){ var rest; function breakit(spbreak,str) { if (width < (str.length + spbreak.length)) { return spbreak+string.sub(str,0,width-spbreak.length)+'\n'+ breakit(spbreak,string.sub(str,width-spbreak.length,str.length-width+spbreak.length)); } else return spbreak+str+'\n'; } if (width && width < (line.length + indent)) { if (tab) { var pos = string.find(tab,line); if (pos > 0 && pos < width) spbreak=printf.spaces(pos+indent+1); else spbreak=sp; } form=form+sp+string.sub(line,0,width-indent)+'\n'; rest=string.sub(line,width-indent,line.length-width+indent); form=form+breakit(spbreak,rest); } else form=form+sp+line+'\n'; }); return form; }, /** Format a list of array elements using the (optional) mapping * function and the separator (optional, too, default is ','). * */ list: function (array,fun,sep) { var i, str=''; if (sep==undefined) sep=','; if (fun==undefined) fun=function (s) {return s;}; if (!obj.isArray(array)) array=[array]; for (i in array) { if (str==='') str=fun(array[i]); else str=str+sep+fun(array[i]); } return str; }, /** * * @param n * @returns {string} */ spaces: function (n){ return string.make(n,' '); }, /** Formatted printer (simplified) * * @param {* []} args (['%format',arg]|string) [] format=%s,%d,%f,%c,%x,%#d,%#s,.. * @returns {string} */ sprintf2: function(args) { var str=''; array.iter(args,function(fmtarg) { var len, n,fs; if (obj.isArray(fmtarg)) { if (fmtarg.length==2) { var fmt=fmtarg[0]; var arg=fmtarg[1]; var fc=''; var fn=0; string.iter(fmt,function(c) { if (c=='s' || c=='d' || c=='f' || c=='x') { fc=c; } else if (c!='%') { fn=fn*10; n=parseInt(c); if (!isNaN(n)) fn=fn+n; } }); if (fc=='s' && obj.isString(arg)) { str=str+arg; if (fn!=0) { len=arg.length; if (len 0 && path[0] == '/'); }, /** * * @param pathl * @param absolute * @returns {string} */ join: function (pathl,absolute) { var path=(absolute?'/':''); array.iter(pathl,function (name,index) { if (index>0) { path=path+'/'+name; } else { path=path+name; } }); return path; }, /** * * @param path * @returns {string} */ normalize : function (path) { return Path.normalize(path) }, /** * * @param path * @returns {*} */ path_absolute: function (path) { if (this.is_relative(path)) { var workdir = Io.workdir(); return this.path_normalize(workdir + '/' + path); } else return this.path_normalize(path); }, /** Duplicate of Path.normalize!? * * @param path * @returns {string} */ path_normalize: function (path) { var i; if (string.equal(path, '')) path = '/'; var relpath = !(string.get(path, 0) == '/'); var pathlist = path.split('/'); var pathlist2 = pathlist.filter(function (s) { return (!string.equal(s, '') && !string.equal(s, '.')) }); var pathlist3 = []; array.iter(pathlist2, function (pe) { if (!string.equal(pe, '..')) { array.push(pathlist3, pe) } else { if (pathlist3.length == 0) return ''; else pathlist3 = array.tail(pathlist3); } }); var path2 = ''; i = 0; array.iter(pathlist3, function (pe) { var sep; if (i == 0) sep = ''; else sep = '/'; path2 = pe + sep + path2; i++; }); if (relpath) return path2; else return '/' + path2; }, removeext: function (path) { return path.substr(0, path.lastIndexOf('.')); } }; /** PERVASIVES * * */ var pervasives = { assert:assert, char_of_int: function (i) {return String.fromCharCode(i)}, div: function(a,b) {return a/b|0;}, failwith: function(msg) {Io.err(msg);}, float_of_string: function(s) {var num=parseFloat(s); if (isNaN(num)) throw 'NaN'; else return num;}, int_of_char: function(c) {return c.charCodeAt()}, int_of_float: function(f) {return f|0;}, int_of_string: function(s) { var num=parseInt(s); if (isNaN(num)) throw 'NaN'; else return num; }, /** Try to find a value in a search list and return a mapping value. * * @param {*} value * @param {* []} mapping [testval,mapval] [] * @returns {*} */ map: function(value,mapping) { function eq(v1,v2) { if (v1==v2) return true; if (obj.isString(v1) && obj.isString(v2)) return string.equal(v1,v2); return false; } if (!array.empty(mapping)) { var hd=array.head(mapping); var tl=array.tail(mapping); if (eq(hd[0],value)) return hd[1]; else return pervasives.map(value,tl); } else return undefined; }, /** Apply a matcher function to a list of cases with case handler functions. * A case is matched if the matcher function returns a value/object. * * The result of the matcher function is passed as an argument ot the case handler function. * The return value of the case handler fucntion is finally returned by this match function * or undefined if there was no matching case. * * @param {function(*,*):*} matcher function(expr,pat) * @param {*} expr * @param {*[]} cases (pattern,handler function | handler function) [] * @returns {*|undefined} */ match: function (matcher,expr,cases) { var ret = undefined; array.iter_break(cases, function (match) { var quit, succ, pat, fun; if (match.length == 2) { /* ** Pattern, Function */ pat = match[0]; fun = match[1]; succ = matcher(expr, pat); if (succ) ret = fun(succ); quit = succ!=undefined; } else if (match.length == 1) { /* ** Default case, Function */ fun = match[0]; ret = fun(); quit= true; } return quit; }); return ret; }, mtime: function () {var time = new Date(); return time.getTime();}, min: function(a,b) { return (ab)?a:b}, string_of_float: function(f) {return f.toString()}, string_of_int: function(i) {return i.toString()}, string_of_int64: function(i) {return i.toString()}, time: function () {var time = new Date(); return (time.getTime()/1000)|0;} }; /** BIT * */ var bit = { get: function (v,b) {return (v >> b) && 1;}, isSet: function (v,b) {return ((v >> b) && 1)==1;}, set: function (v,b) {return v & (1 << b);} }; /** ARGS * */ var args = { /** Parse process or command line arguments (array argv). The first offset [1] arguments are ** ignored. The numarg pattern '*' consumes all remaining arguments. * * @param {string []} argv * @param {*[]} map [,,]|[] [] * @param {number} [offset] */ parse: function(argv,map,offset) { var shift=undefined, in_shift=0, shift_args=[], names, mapfun, numarg, len=argv.length; if (offset==undefined) offset=1; argv.forEach(function (val, index) { var last=index==(len-1); if(index>=offset) { if (in_shift==0) { array.check(map,function (onemap) { assert(onemap!=undefined||'map'); if (onemap.length==3) { names = onemap[0]; numarg = onemap[1]; mapfun = onemap[2]; if (!obj.isArray(names)) names=[names]; var found = array.find(names,function (name) { if (string.equal(val, name)) return name; else _; }); if (found) { if (numarg==0) mapfun(found); else { in_shift=numarg; shift_args=[]; shift=mapfun; } return true; } } else if (obj.isFunction(onemap)) { onemap(val); return true; } else if (onemap.length==1) { mapfun = onemap[0]; mapfun(val); return true; } return false; }); } else { shift_args.push(val); if (in_shift!='*') in_shift--; if (in_shift==0 && shift!=undefined) { numarg=shift_args.length; switch (numarg) { case 0: shift(val);break; case 1: shift(shift_args[0],val); break; case 2: shift(shift_args[0],shift_args[1],val); break; case 3: shift(shift_args[0],shift_args[1],shift_args[2],val); break; default: break; } shift=undefined; } else if (in_shift=='*' && last) shift(shift_args); } } }); } }; /** HASHTBL * */ var hashtbl = { add: function(hash,key,data) { hash[key]=data; }, create: function(initial) { return []; }, empty: function(hash) { for (var key in hash) return false; return true; }, find: function(hash,key) { return hash[key]; }, invalidate: function(hash,key) { hash[key]=undefined; }, iter: function(hash,fun) { for (var key in hash) { if (hash[key]!=undefined) fun(key,hash[key]); } }, mem: function(hash,key) { return hash[key] != undefined; }, remove: function(hash,key) { // TODO: check, its wrong! if (!hash.hasOwnProperty(key)) return; if (isNaN(parseInt(key)) || !(hash instanceof Array)) delete hash[key]; else hash.splice(key, 1) } }; var types = []; /** * * @param name * @returns {number} */ function register_type(name) { var typoff = 1000+types.length*1000; if (array.member(types,name)) throw('[COMP] register_type: type '+name+' exists already.'); types.push(name); return typoff; } /** * * @typedef {{v1:*, v2:*, v3:*, v4:*, v5:*, v6:*, v7:*, v8:*, v9:* }} tuple */ /** * * @typedef {{t:number, v1:*, v2:*, v3:*, v4:*, v5:*, v6:*, v7:*, v8:*, v9:* }} tagged_tuple */ module.exports = { args:args, assert: assert, array:array, bit:bit, copy:obj.copy, div:pervasives.div, filename:filename, hashtbl:hashtbl, isNodeJS: function () { return (typeof global !== "undefined" && {}.toString.call(global) == '[object global]'); }, obj:obj, pervasives:pervasives, printf:printf, random:random, string:string, isArray: obj.isArray, isString: obj.isString, isNumber: obj.isNumber, register_type:register_type, /** * * @param tag * @param [val1] * @param [val2] * @param [val3] * @returns {(tagged_tuple)} */ Tuple: function (tag,val1,val2,val3) { if(val3) return {t:tag,v1:val1,v2:val2,v3:val3}; else if (val2) return {t:tag,v1:val1,v2:val2}; else if (val1) return {t:tag,v1:val1}; else return {t:tag}; } };