PageSourceSearch

https://igpex.com/public/js/php.js

js igpex.com collected 2026-10-07 21:20:46 UTC 132,819 bytes, 3,875 lines download raw bytes

vendor: 4,711 bytes, lines 1-131
1//-----------------------------------------------------------------
2//-----------------------------------------------------------------
3function md5 (str) {
4    // Calculate the md5 hash of a string  
5    // 
6    // version: 1109.2015
7    // discuss at: http://phpjs.org/functions/md5
8    // +   original by: Webtoolkit.info (http://www.webtoolkit.info/)
9    // + namespaced by: Michael White (http://getsprink.com)
10    // +    tweaked by: Jack
11    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
12    // +      input by: Brett Zamir (http://brett-zamir.me)
13    // +   bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
14    // -    depends on: utf8_encode
15    // *     example 1: md5('Kevin van Zonneveld');
16    // *     returns 1: '6e658d4bfcb59cc13f96c14450ac40b9'
17    var xl;
18 
19    var rotateLeft = function (lValue, iShiftBits) {
20        return (lValue << iShiftBits) | (lValue >>> (32 - iShiftBits));
21    };
22 
23    var addUnsigned = function (lX, lY) {
24        var lX4, lY4, lX8, lY8, lResult;
25        lX8 = (lX & 0x80000000);
26        lY8 = (lY & 0x80000000);
27        lX4 = (lX & 0x40000000);
28        lY4 = (lY & 0x40000000);
29        lResult = (lX & 0x3FFFFFFF) + (lY & 0x3FFFFFFF);
30        if (lX4 & lY4) {
31            return (lResult ^ 0x80000000 ^ lX8 ^ lY8);
32        }
33        if (lX4 | lY4) {
34            if (lResult & 0x40000000) {
35                return (lResult ^ 0xC0000000 ^ lX8 ^ lY8);
36            } else {
37                return (lResult ^ 0x40000000 ^ lX8 ^ lY8);
38            }
39        } else {
40            return (lResult ^ lX8 ^ lY8);
41        }
42    };
43 
44    var _F = function (x, y, z) {
45        return (x & y) | ((~x) & z);
46    };
47    var _G = function (x, y, z) {
48        return (x & z) | (y & (~z));
49    };
50    var _H = function (x, y, z) {
51        return (x ^ y ^ z);
52    };
53    var _I = function (x, y, z) {
54        return (y ^ (x | (~z)));
55    };
56 
57    var _FF = function (a, b, c, d, x, s, ac) {
58        a = addUnsigned(a, addUnsigned(addUnsigned(_F(b, c, d), x), ac));
59        return addUnsigned(rotateLeft(a, s), b);
60    };
61 
62    var _GG = function (a, b, c, d, x, s, ac) {
63        a = addUnsigned(a, addUnsigned(addUnsigned(_G(b, c, d), x), ac));
64        return addUnsigned(rotateLeft(a, s), b);
65    };
66 
67    var _HH = function (a, b, c, d, x, s, ac) {
68        a = addUnsigned(a, addUnsigned(addUnsigned(_H(b, c, d), x), ac));
69        return addUnsigned(rotateLeft(a, s), b);
70    };
71 
72    var _II = function (a, b, c, d, x, s, ac) {
73        a = addUnsigned(a, addUnsigned(addUnsigned(_I(b, c, d), x), ac));
74        return addUnsigned(rotateLeft(a, s), b);
75    };
76 
77    var convertToWordArray = function (str) {
78        var lWordCount;
79        var lMessageLength = str.length;
80        var lNumberOfWords_temp1 = lMessageLength + 8;
81        var lNumberOfWords_temp2 = (lNumberOfWords_temp1 - (lNumberOfWords_temp1 % 64)) / 64;
82        var lNumberOfWords = (lNumberOfWords_temp2 + 1) * 16;
83        var lWordArray = new Array(lNumberOfWords - 1);
84        var lBytePosition = 0;
85        var lByteCount = 0;
86        while (lByteCount < lMessageLength) {
87            lWordCount = (lByteCount - (lByteCount % 4)) / 4;
88            lBytePosition = (lByteCount % 4) * 8;
89            lWordArray[lWordCount] = (lWordArray[lWordCount] | (str.charCodeAt(lByteCount) << lBytePosition));
90            lByteCount++;
91        }
92        lWordCount = (lByteCount - (lByteCount % 4)) / 4;
93        lBytePosition = (lByteCount % 4) * 8;
94        lWordArray[lWordCount] = lWordArray[lWordCount] | (0x80 << lBytePosition);
95        lWordArray[lNumberOfWords - 2] = lMessageLength << 3;
96        lWordArray[lNumberOfWords - 1] = lMessageLength >>> 29;
97        return lWordArray;
98    };
99 
100    var wordToHex = function (lValue) {
101        var wordToHexValue = "",
102            wordToHexValue_temp = "",
103            lByte, lCount;
104        for (lCount = 0; lCount <= 3; lCount++) {
105            lByte = (lValue >>> (lCount * 8)) & 255;
106            wordToHexValue_temp = "0" + lByte.toString(16);
107            wordToHexValue = wordToHexValue + wordToHexValue_temp.substr(wordToHexValue_temp.length - 2, 2);
108        }
109        return wordToHexValue;
110    };
111 
112    var x = [],
113        k, AA, BB, CC, DD, a, b, c, d, S11 = 7,
114        S12 = 12,
115        S13 = 17,
116        S14 = 22,
117        S21 = 5,
118        S22 = 9,
119        S23 = 14,
120        S24 = 20,
121        S31 = 4,
122        S32 = 11,
123        S33 = 16,
124        S34 = 23,
125        S41 = 6,
126        S42 = 10,
127        S43 = 15,
128        S44 = 21;
129 
130    str = this.utf8_encode(str);
131    x = convertToWordArray(str);
132    a = 0x67452301;
133    b = 0xEFCDAB89;
134    c = 0x98BADCFE;
135    d = 0x10325476;
136 
137    xl = x.length;
138    for (k = 0; k < xl; k += 16) {
139        AA = a;
140        BB = b;
141        CC = c;
142        DD = d;
143        a = _FF(a, b, c, d, x[k + 0], S11, 0xD76AA478);
144        d = _FF(d, a, b, c, x[k + 1], S12, 0xE8C7B756);
145        c = _FF(c, d, a, b, x[k + 2], S13, 0x242070DB);
146        b = _FF(b, c, d, a, x[k + 3], S14, 0xC1BDCEEE);
147        a = _FF(a, b, c, d, x[k + 4], S11, 0xF57C0FAF);
148        d = _FF(d, a, b, c, x[k + 5], S12, 0x4787C62A);
149        c = _FF(c, d, a, b, x[k + 6], S13, 0xA8304613);
150        b = _FF(b, c, d, a, x[k + 7], S14, 0xFD469501);
151        a = _FF(a, b, c, d, x[k + 8], S11, 0x698098D8);
152        d = _FF(d, a, b, c, x[k + 9], S12, 0x8B44F7AF);
153        c = _FF(c, d, a, b, x[k + 10], S13, 0xFFFF5BB1);
154        b = _FF(b, c, d, a, x[k + 11], S14, 0x895CD7BE);
155        a = _FF(a, b, c, d, x[k + 12], S11, 0x6B901122);
156        d = _FF(d, a, b, c, x[k + 13], S12, 0xFD987193);
157        c = _FF(c, d, a, b, x[k + 14], S13, 0xA679438E);
158        b = _FF(b, c, d, a, x[k + 15], S14, 0x49B40821);
159        a = _GG(a, b, c, d, x[k + 1], S21, 0xF61E2562);
160        d = _GG(d, a, b, c, x[k + 6], S22, 0xC040B340);
161        c = _GG(c, d, a, b, x[k + 11], S23, 0x265E5A51);
162        b = _GG(b, c, d, a, x[k + 0], S24, 0xE9B6C7AA);
163        a = _GG(a, b, c, d, x[k + 5], S21, 0xD62F105D);
164        d = _GG(d, a, b, c, x[k + 10], S22, 0x2441453);
165        c = _GG(c, d, a, b, x[k + 15], S23, 0xD8A1E681);
166        b = _GG(b, c, d, a, x[k + 4], S24, 0xE7D3FBC8);
167        a = _GG(a, b, c, d, x[k + 9], S21, 0x21E1CDE6);
168        d = _GG(d, a, b, c, x[k + 14], S22, 0xC33707D6);
169        c = _GG(c, d, a, b, x[k + 3], S23, 0xF4D50D87);
170        b = _GG(b, c, d, a, x[k + 8], S24, 0x455A14ED);
171        a = _GG(a, b, c, d, x[k + 13], S21, 0xA9E3E905);
172        d = _GG(d, a, b, c, x[k + 2], S22, 0xFCEFA3F8);
173        c = _GG(c, d, a, b, x[k + 7], S23, 0x676F02D9);
174        b = _GG(b, c, d, a, x[k + 12], S24, 0x8D2A4C8A);
175        a = _HH(a, b, c, d, x[k + 5], S31, 0xFFFA3942);
176        d = _HH(d, a, b, c, x[k + 8], S32, 0x8771F681);
177        c = _HH(c, d, a, b, x[k + 11], S33, 0x6D9D6122);
178        b = _HH(b, c, d, a, x[k + 14], S34, 0xFDE5380C);
179        a = _HH(a, b, c, d, x[k + 1], S31, 0xA4BEEA44);
180        d = _HH(d, a, b, c, x[k + 4], S32, 0x4BDECFA9);
181        c = _HH(c, d, a, b, x[k + 7], S33, 0xF6BB4B60);
182        b = _HH(b, c, d, a, x[k + 10], S34, 0xBEBFBC70);
183        a = _HH(a, b, c, d, x[k + 13], S31, 0x289B7EC6);
184        d = _HH(d, a, b, c, x[k + 0], S32, 0xEAA127FA);
185        c = _HH(c, d, a, b, x[k + 3], S33, 0xD4EF3085);
186        b = _HH(b, c, d, a, x[k + 6], S34, 0x4881D05);
187        a = _HH(a, b, c, d, x[k + 9], S31, 0xD9D4D039);
188        d = _HH(d, a, b, c, x[k + 12], S32, 0xE6DB99E5);
189        c = _HH(c, d, a, b, x[k + 15], S33, 0x1FA27CF8);
190        b = _HH(b, c, d, a, x[k + 2], S34, 0xC4AC5665);
191        a = _II(a, b, c, d, x[k + 0], S41, 0xF4292244);
192        d = _II(d, a, b, c, x[k + 7], S42, 0x432AFF97);
193        c = _II(c, d, a, b, x[k + 14], S43, 0xAB9423A7);
194        b = _II(b, c, d, a, x[k + 5], S44, 0xFC93A039);
195        a = _II(a, b, c, d, x[k + 12], S41, 0x655B59C3);
196        d = _II(d, a, b, c, x[k + 3], S42, 0x8F0CCC92);
197        c = _II(c, d, a, b, x[k + 10], S43, 0xFFEFF47D);
198        b = _II(b, c, d, a, x[k + 1], S44, 0x85845DD1);
199        a = _II(a, b, c, d, x[k + 8], S41, 0x6FA87E4F);
200        d = _II(d, a, b, c, x[k + 15], S42, 0xFE2CE6E0);
201        c = _II(c, d, a, b, x[k + 6], S43, 0xA3014314);
202        b = _II(b, c, d, a, x[k + 13], S44, 0x4E0811A1);
203        a = _II(a, b, c, d, x[k + 4], S41, 0xF7537E82);
204        d = _II(d, a, b, c, x[k + 11], S42, 0xBD3AF235);
205        c = _II(c, d, a, b, x[k + 2], S43, 0x2AD7D2BB);
206        b = _II(b, c, d, a, x[k + 9], S44, 0xEB86D391);
207        a = addUnsigned(a, AA);
208        b = addUnsigned(b, BB);
209        c = addUnsigned(c, CC);
210        d = addUnsigned(d, DD);
211    }
212 
213    var temp = wordToHex(a) + wordToHex(b) + wordToHex(c) + wordToHex(d);
214 
215    return temp.toLowerCase();
216}
217//-----------------------------------------------------------------
218//-----------------------------------------------------------------
219function uniqid (prefix, more_entropy) {
220    // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
221    // +    revised by: Kankrelune (http://www.webfaktory.info/)
222    // %        note 1: Uses an internal counter (in php_js global) to avoid collision
223    // *     example 1: uniqid();
224    // *     returns 1: 'a30285b160c14'
225    // *     example 2: uniqid('foo');
226    // *     returns 2: 'fooa30285b1cd361'
227    // *     example 3: uniqid('bar', true);
228    // *     returns 3: 'bara20285b23dfd1.31879087'
229    if (typeof prefix == 'undefined') {
230        prefix = "";
231    }
232 
233    var retId;
234    var formatSeed = function (seed, reqWidth) {
235        seed = parseInt(seed, 10).toString(16); // to hex str
236        if (reqWidth < seed.length) { // so long we split
237            return seed.slice(seed.length - reqWidth);
238        }
239        if (reqWidth > seed.length) { // so short we pad
240            return Array(1 + (reqWidth - seed.length)).join('0') + seed;
241        }
242        return seed;
243    };
244 
245    // BEGIN REDUNDANT
246    if (!this.php_js) {
247        this.php_js = {};
248    }
249    // END REDUNDANT
250    if (!this.php_js.uniqidSeed) { // init seed with big random int
251        this.php_js.uniqidSeed = Math.floor(Math.random() * 0x75bcd15);
252    }
253    this.php_js.uniqidSeed++;
254 
255    retId = prefix; // start with prefix, add current milliseconds hex string
256    retId += formatSeed(parseInt(new Date().getTime() / 1000, 10), 8);
257    retId += formatSeed(this.php_js.uniqidSeed, 5); // add seed hex string
258    if (more_entropy) {
259        // for more entropy we add a float lower to 10
260        retId += (Math.random() * 10).toFixed(8).toString();
261    }
262 
263    return retId;
264}
265
266/*
267
268字串->陣列 by 分隔符號
269
270*/
271function explode(delimiter, data_array){
272	var exploded = data_array.split(delimiter);
273	
274	//the delimiter was not found if the second array returns undefined
275	if(exploded[1]===undefined){
276		// alert("delimiter " + delimiter + " was not found");
277		//you can return false here
278		return false;
279	}
280	else{
281		// alert(exploded);
282		return exploded;
283		//you can return true or return the exploded value here
284	}
285	
286}
287/*
288
289陣列->字串 by 分隔符號
290
291*/
292
293function implode(glue, pieces) {
294    var i = '',
295        retVal = '',
296        tGlue = '';
297    if (arguments.length === 1) {
298        pieces = glue;
299        glue = '';
300    }
301    if (typeof(pieces) === 'object') {
302        if (Object.prototype.toString.call(pieces) === '[object Array]') {
303            return pieces.join(glue);
304        } 
305        for (i in pieces) {
306            retVal += tGlue + pieces[i];
307            tGlue = glue;
308        }
309        return retVal;
310    }
311    return pieces;
312}
313
314
315
316
317/*
318浮點數
319*/
320
321//浮點數相加
322function bcadd(left_operand, right_operand, scale) {
323  //  discuss at: http://phpjs.org/functions/bcadd/
324  // original by: lmeyrick (https://sourceforge.net/projects/bcmath-js/)
325  //  depends on: _phpjs_shared_bc
326  //   example 1: bcadd(1, 2);
327  //   returns 1: 3
328  //        todo: implement these testcases
329
330  var libbcmath = this._phpjs_shared_bc();
331
332  var first, second, result;
333
334  if (typeof scale === 'undefined') {
335    scale = libbcmath.scale;
336  }
337  scale = ((scale < 0) ? 0 : scale);
338
339  // create objects
340  first = libbcmath.bc_init_num();
341  second = libbcmath.bc_init_num();
342  result = libbcmath.bc_init_num();
343
344  first = libbcmath.php_str2num(left_operand.toString());
345  second = libbcmath.php_str2num(right_operand.toString());
346
347  result = libbcmath.bc_add(first, second, scale);
348
349  if (result.n_scale > scale) {
350    result.n_scale = scale;
351  }
352
353  return result.toString();
354}
355//浮點數相減
356function bcsub(left_operand, right_operand, scale) {
357  //  discuss at: http://phpjs.org/functions/bcsub/
358  // original by: lmeyrick (https://sourceforge.net/projects/bcmath-js/)
359  //  depends on: _phpjs_shared_bc
360  //   example 1: bcsub(1, 2);
361  //   returns 1: -1
362  //        todo: implement these testcases
363
364  var libbcmath = this._phpjs_shared_bc();
365
366  var first, second, result;
367
368  if (typeof scale === 'undefined') {
369    scale = libbcmath.scale;
370  }
371  scale = ((scale < 0) ? 0 : scale);
372
373  // create objects
374  first = libbcmath.bc_init_num();
375  second = libbcmath.bc_init_num();
376  result = libbcmath.bc_init_num();
377
378  first = libbcmath.php_str2num(left_operand.toString());
379  second = libbcmath.php_str2num(right_operand.toString());
380
381  result = libbcmath.bc_sub(first, second, scale);
382
383  if (result.n_scale > scale) {
384    result.n_scale = scale;
385  }
386
387  return result.toString();
388}
389
390//浮點數相乘
391function bcmul(left_operand, right_operand, scale) {
392  //  discuss at: http://phpjs.org/functions/bcmul/
393  // original by: lmeyrick (https://sourceforge.net/projects/bcmath-js/)
394  //  depends on: _phpjs_shared_bc
395  //   example 1: bcmul(1, 2);
396  //   returns 1: 3
397  //        todo: implement these testcases
398
vendor: 4,437 bytes, lines 399-551
399  var libbcmath = this._phpjs_shared_bc();
400
401  var first, second, result;
402
403  if (typeof scale === 'undefined') {
404    scale = libbcmath.scale;
405  }
406  scale = ((scale < 0) ? 0 : scale);
407
408  // create objects
409  first = libbcmath.bc_init_num();
410  second = libbcmath.bc_init_num();
411  result = libbcmath.bc_init_num();
412
413  first = libbcmath.php_str2num(left_operand.toString());
414  second = libbcmath.php_str2num(right_operand.toString());
415
416  result = libbcmath.bc_multiply(first, second, scale);
417
418  if (result.n_scale > scale) {
419    result.n_scale = scale;
420  }
421  return result.toString();
422}
423
424/*
425浮點數相除
426*/
427function bcdiv(left_operand, right_operand, scale) {
428  //  discuss at: http://phpjs.org/functions/bcdiv/
429  // original by: lmeyrick (https://sourceforge.net/projects/bcmath-js/)
430  //  depends on: _phpjs_shared_bc
431  //   example 1: bcdiv(1, 2);
432  //   returns 1: 3
433  //        todo: implement these testcases
434
435  var libbcmath = this._phpjs_shared_bc();
436
437  var first, second, result;
438
439  if (typeof scale === 'undefined') {
440    scale = libbcmath.scale;
441  }
442  scale = ((scale < 0) ? 0 : scale);
443
444  // create objects
445  first = libbcmath.bc_init_num();
446  second = libbcmath.bc_init_num();
447  result = libbcmath.bc_init_num();
448
449  first = libbcmath.php_str2num(left_operand.toString());
450  second = libbcmath.php_str2num(right_operand.toString());
451
452  result = libbcmath.bc_divide(first, second, scale);
453  if (result === -1) {
454    // error
455    // throw new Error(11, '(BC) Division by zero');
456  }
457  if (result.n_scale > scale) {
458    result.n_scale = scale;
459  }
460  return result.toString();
461}
462
463/*
464
465
466*/
467function bccomp(left_operand, right_operand, scale) {
468  //  discuss at: http://phpjs.org/functions/bccomp/
469  // original by: lmeyrick (https://sourceforge.net/projects/bcmath-js/)
470  //  depends on: _phpjs_shared_bc
471  //   example 1: bccomp(1, 2);
472  //   returns 1: 3
473  //        todo: implement these testcases
474
475  var libbcmath = this._phpjs_shared_bc();
476
477  var first, second; //bc_num
478  if (typeof scale === 'undefined') {
479    scale = libbcmath.scale;
480  }
481  scale = ((scale < 0) ? 0 : scale);
482
483  first = libbcmath.bc_init_num();
484  second = libbcmath.bc_init_num();
485
486  first = libbcmath.bc_str2num(left_operand.toString(), scale); // note bc_ not php_str2num
487  second = libbcmath.bc_str2num(right_operand.toString(), scale); // note bc_ not php_str2num
488  return libbcmath.bc_compare(first, second, scale);
489}
490
491function bcround(val, precision) {
492  //  discuss at: http://phpjs.org/functions/bcround/
493  // original by: lmeyrick (https://sourceforge.net/projects/bcmath-js/)
494  //  depends on: _phpjs_shared_bc
495  //   example 1: bcround(1, 2);
496  //   returns 1: 3
497  //        todo: implement these testcases
498
499  var libbcmath = this._phpjs_shared_bc();
500
501  var temp, result, digit;
502  var right_operand;
503
504  // create number
505  temp = libbcmath.bc_init_num();
506  temp = libbcmath.php_str2num(val.toString());
507
508  // check if any rounding needs
509  if (precision >= temp.n_scale) {
510    // nothing to round, just add the zeros.
511    while (temp.n_scale < precision) {
512      temp.n_value[temp.n_len + temp.n_scale] = 0;
513      temp.n_scale++;
514    }
515    return temp.toString();
516  }
517
518  // get the digit we are checking (1 after the precision)
519  // loop through digits after the precision marker
520  digit = temp.n_value[temp.n_len + precision];
521
522  right_operand = libbcmath.bc_init_num();
523  right_operand = libbcmath.bc_new_num(1, precision);
524
525  if (digit >= 5) {
526    //round away from zero by adding 1 (or -1) at the "precision".. ie 1.44999 @ 3dp = (1.44999 + 0.001).toString().substr(0,5)
527    right_operand.n_value[right_operand.n_len + right_operand.n_scale - 1] = 1;
528    if (temp.n_sign == libbcmath.MINUS) {
529      // round down
530      right_operand.n_sign = libbcmath.MINUS;
531    }
532    result = libbcmath.bc_add(temp, right_operand, precision);
533  } else {
534    // leave-as-is.. just truncate it.
535    result = temp;
536  }
537
538  if (result.n_scale > precision) {
539    result.n_scale = precision;
540  }
541  return result.toString();
542}
543
544function bcscale(scale) {
545  //  discuss at: http://phpjs.org/functions/bcscale/
546  // original by: lmeyrick (https://sourceforge.net/projects/bcmath-js/)this.
547  //  depends on: _phpjs_shared_bc
548  //   example 1: bcscale(1);
549  //   returns 1: 3
550  //        todo: implement these testcases
551
552  var libbcmath = this._phpjs_shared_bc();
553
554  scale = parseInt(scale, 10);
555  if (isNaN(scale)) {
556    return false;
557  }
558  if (scale < 0) {
559    return false;
560  }
561  libbcmath.scale = scale;
562  return true;
563}
564
565/*
566
567判斷值
568
569*/
570function isset() {
571    // !No description available for isset. @php.js developers: Please update the function summary text file.
572    // 
573    // version: 1103.1210
574    // discuss at: http://phpjs.org/functions/isset
575    // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
576    // +   improved by: FremyCompany
577    // +   improved by: Onno Marsman
578    // +   improved by: Rafał Kukawski
579    // *     example 1: isset( undefined, true);
580    // *     returns 1: false
581    // *     example 2: isset( 'Kevin van Zonneveld' );
582    // *     returns 2: true
583    var a = arguments,
584        l = a.length,
585        i = 0,
586        undef;
587 
588    if (l === 0) {
589        throw new Error('Empty isset');
590    }
591 
592    while (i !== l) {
593        if (a[i] === undef || a[i] === null) {
594            return false;
595        }
596        i++;
597    }
598    return true;
599}
600
601
602function empty(mixed_var) {
603  //  discuss at: http://phpjs.org/functions/empty/
604  // original by: Philippe Baumann
605  //    input by: Onno Marsman
606  //    input by: LH
607  //    input by: Stoyan Kyosev (http://www.svest.org/)
608  // bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
609  // improved by: Onno Marsman
610  // improved by: Francesco
611  // improved by: Marc Jansen
612  // improved by: Rafal Kukawski
613  //   example 1: empty(null);
614  //   returns 1: true
615  //   example 2: empty(undefined);
616  //   returns 2: true
617  //   example 3: empty([]);
618  //   returns 3: true
619  //   example 4: empty({});
620  //   returns 4: true
621  //   example 5: empty({'aFunc' : function () { alert('humpty'); } });
622  //   returns 5: false
623
624  var undef, key, i, len;
625  var emptyValues = [undef, null, false, 0, '', '0'];
626
627  for (i = 0, len = emptyValues.length; i < len; i++) {
628    if (mixed_var === emptyValues[i]) {
629      return true;
630    }
631  }
632
633  if (typeof mixed_var === 'object') {
634    for (key in mixed_var) {
635      // TODO: should we check for own properties only?
636      //if (mixed_var.hasOwnProperty(key)) {
637      return false;
638      //}
639    }
640    return true;
641  }
642
643  return false;
644}
645function key_exits(string,arr)
646{
647if(arr.hasOwnProperty(string)) {
648return true;	
649}	
650return false;	
651}
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689//-----------------------------------------------------------------
690//-----------------------------------------------------------------
691//-----------------------------------------------------------------
692//-----------------------------------------------------------------
693//-----------------------------------------------------------------
694//-----------------------------------------------------------------
695//-----------------------------------------------------------------
696//-----------------------------------------------------------------
697//-----------------------------------------------------------------
698//-----------------------------------------------------------------
699//-----------------------------------------------------------------
700//-----------------------------------------------------------------
701//-----------------------------------------------------------------
702function _phpjs_shared_bc() {
703  // From: http://phpjs.org/functions
704  // +   original by: lmeyrick (https://sourceforge.net/projects/bcmath-js/)
705  // +   improved by: Brett Zamir (http://brett-zamir.me)
706  // *     example 1: _phpjs_shared_bc();
707  // *     returns 1: {}
708  /**
709   * BC Math Library for Javascript
710   * Ported from the PHP5 bcmath extension source code,
711   * which uses the libbcmath package...
712   *    Copyright (C) 1991, 1992, 1993, 1994, 1997 Free Software Foundation, Inc.
713   *    Copyright (C) 2000 Philip A. Nelson
714   *     The Free Software Foundation, Inc.
715   *     59 Temple Place, Suite 330
716   *     Boston, MA 02111-1307 USA.
717   *      e-mail:  [email protected]
718   *     us-mail:  Philip A. Nelson
719   *               Computer Science Department, 9062
720   *               Western Washington University
721   *               Bellingham, WA 98226-9062
722   *
723   * bcmath-js homepage:
724   *
725   * This code is covered under the LGPL licence, and can be used however you want :)
726   * Be kind and share any decent code changes.
727   */
728
729  /**
730   * Binary Calculator (BC) Arbitrary Precision Mathematics Lib v0.10  (LGPL)
731   * Copy of libbcmath included in PHP5 src
732   *
733   * Note: this is just the shared library file and does not include the php-style functions.
734   *       use bcmath{-min}.js for functions like bcadd, bcsub etc.
735   *
736   * Feel free to use how-ever you want, just email any bug-fixes/improvements to the sourceforge project:
737   *
738   *
739   * Ported from the PHP5 bcmath extension source code,
740   * which uses the libbcmath package...
741   *    Copyright (C) 1991, 1992, 1993, 1994, 1997 Free Software Foundation, Inc.
742   *    Copyright (C) 2000 Philip A. Nelson
743   *     The Free Software Foundation, Inc.
744   *     59 Temple Place, Suite 330
745   *     Boston, MA 02111-1307 USA.
746   *      e-mail:  [email protected]
747   *     us-mail:  Philip A. Nelson
748   *               Computer Science Department, 9062
749   *               Western Washington University
750   *               Bellingham, WA 98226-9062
751   */
752
753  var libbcmath = {
754    PLUS: '+',
755    MINUS: '-',
756    BASE: 10,
757    // must be 10 (for now)
758    scale: 0,
759    // default scale
760    /**
761     * Basic number structure
762     */
763    bc_num: function() {
764      this.n_sign = null; // sign
765      this.n_len = null; /* (int) The number of digits before the decimal point. */
766      this.n_scale = null; /* (int) The number of digits after the decimal point. */
767      //this.n_refs = null; /* (int) The number of pointers to this number. */
768      //this.n_text = null; /* ?? Linked list for available list. */
769      this.n_value = null; /* array as value, where 1.23 = [1,2,3] */
770      this.toString = function() {
771        var r, tmp;
772        tmp = this.n_value.join('');
773
774        // add minus sign (if applicable) then add the integer part
775        r = ((this.n_sign == libbcmath.PLUS) ? '' : this.n_sign) + tmp.substr(0, this.n_len);
776
777        // if decimal places, add a . and the decimal part
778        if (this.n_scale > 0) {
779          r += '.' + tmp.substr(this.n_len, this.n_scale);
780        }
781        return r;
782      };
783    },
784
785    /**
786     * Base add function
787     *
788     //  Here is the full add routine that takes care of negative numbers.
789     //  N1 is added to N2 and the result placed into RESULT.  SCALE_MIN
790     //  is the minimum scale for the result.
791     *
792     * @param {bc_num} n1
793     * @param {bc_num} n2
794     * @param {int} scale_min
795     * @return bc_num
796     */
797    bc_add: function(n1, n2, scale_min) {
798      var sum, cmp_res, res_scale;
799
800      if (n1.n_sign === n2.n_sign) {
801        sum = libbcmath._bc_do_add(n1, n2, scale_min);
802        sum.n_sign = n1.n_sign;
803      } else { /* subtraction must be done. */
804        cmp_res = libbcmath._bc_do_compare(n1, n2, false, false); /* Compare magnitudes. */
805        switch (cmp_res) {
806          case -1:
807            /* n1 is less than n2, subtract n1 from n2. */
808            sum = libbcmath._bc_do_sub(n2, n1, scale_min);
809            sum.n_sign = n2.n_sign;
810            break;
811
812          case 0:
813            /* They are equal! return zero with the correct scale! */
814            res_scale = libbcmath.MAX(scale_min, libbcmath.MAX(n1.n_scale, n2.n_scale));
815            sum = libbcmath.bc_new_num(1, res_scale);
816            libbcmath.memset(sum.n_value, 0, 0, res_scale + 1);
817            break;
818
819          case 1:
820            /* n2 is less than n1, subtract n2 from n1. */
821            sum = libbcmath._bc_do_sub(n1, n2, scale_min);
822            sum.n_sign = n1.n_sign;
823        }
824      }
825      return sum;
826    },
827
828    /**
829     * This is the "user callable" routine to compare numbers N1 and N2.
830     * @param {bc_num} n1
831     * @param {bc_num} n2
832     * @return int -1, 0, 1  (n1 < n2, ==, n1 > n2)
833     */
834    bc_compare: function(n1, n2) {
835      return libbcmath._bc_do_compare(n1, n2, true, false);
836    },
837
838    _one_mult: function(num, n_ptr, size, digit, result, r_ptr) {
839      var carry, value; // int
840      var nptr, rptr; // int pointers
841      if (digit === 0) {
842        libbcmath.memset(result, 0, 0, size); //memset (result, 0, size);
843      } else {
844        if (digit == 1) {
845          libbcmath.memcpy(result, r_ptr, num, n_ptr, size); //memcpy (result, num, size);
846        } else { /*  Initialize */
847          nptr = n_ptr + size - 1; //nptr = (unsigned char *) (num+size-1);
848          rptr = r_ptr + size - 1; //rptr = (unsigned char *) (result+size-1);
849          carry = 0;
850
851          while (size-- > 0) {
852            value = num[nptr--] * digit + carry; //value = *nptr-- * digit + carry;
853            //result[rptr--] = libbcmath.cint(value % libbcmath.BASE); // @CHECK cint //*rptr-- = value % BASE;
854            result[rptr--] = value % libbcmath.BASE; // @CHECK cint //*rptr-- = value % BASE;
855            //carry = libbcmath.cint(value / libbcmath.BASE);   // @CHECK cint //carry = value / BASE;
856            carry = Math.floor(value / libbcmath.BASE); // @CHECK cint //carry = value / BASE;
857          }
858
859          if (carry !== 0) {
860            result[rptr] = carry;
861          }
862        }
863      }
864    },
865
866    bc_divide: function(n1, n2, scale) {
867      var quot; // bc_num return
868      var qval; // bc_num
869      var num1, num2; // string
870      var ptr1, ptr2, n2ptr, qptr; // int pointers
871      var scale1, val; // int
872      var len1, len2, scale2, qdigits, extra, count; // int
873      var qdig, qguess, borrow, carry; // int
874      var mval; // string
875      var zero; // char
876      var norm; // int
877      var ptrs; // return object from one_mul
878      /* Test for divide by zero. (return failure) */
879      if (libbcmath.bc_is_zero(n2)) {
880        return -1;
881      }
882
883      /* Test for zero divide by anything (return zero) */
884      if (libbcmath.bc_is_zero(n1)) {
885        return libbcmath.bc_new_num(1, scale);
886      }
887
888      /* Test for n1 equals n2 (return 1 as n1 nor n2 are zero)
889  if (libbcmath.bc_compare(n1, n2, libbcmath.MAX(n1.n_scale, n2.n_scale)) === 0) {
890    quot=libbcmath.bc_new_num(1, scale);
891    quot.n_value[0] = 1;
892    return quot;
893  }
894  */
895
896      /* Test for divide by 1.  If it is we must truncate. */
897      // todo: check where scale > 0 too.. can't see why not (ie bc_is_zero - add bc_is_one function)
898      if (n2.n_scale === 0) {
899        if (n2.n_len === 1 && n2.n_value[0] === 1) {
900          qval = libbcmath.bc_new_num(n1.n_len, scale); //qval = bc_new_num (n1->n_len, scale);
901          qval.n_sign = (n1.n_sign == n2.n_sign ? libbcmath.PLUS : libbcmath.MINUS);
902          libbcmath.memset(qval.n_value, n1.n_len, 0, scale); //memset (&qval->n_value[n1->n_len],0,scale);
903          libbcmath.memcpy(qval.n_value, 0, n1.n_value, 0, n1.n_len + libbcmath.MIN(n1.n_scale, scale)); //memcpy (qval->n_value, n1->n_value, n1->n_len + MIN(n1->n_scale,scale));
904          // can we return here? not in c src, but can't see why-not.
905          // return qval;
906        }
907      }
908
909      /* Set up the divide.  Move the decimal point on n1 by n2's scale.
910   Remember, zeros on the end of num2 are wasted effort for dividing. */
911      scale2 = n2.n_scale; //scale2 = n2->n_scale;
912      n2ptr = n2.n_len + scale2 - 1; //n2ptr = (unsigned char *) n2.n_value+n2.n_len+scale2-1;
913      while ((scale2 > 0) && (n2.n_value[n2ptr--] === 0)) {
914        scale2--;
915      }
916
917      len1 = n1.n_len + scale2;
918      scale1 = n1.n_scale - scale2;
919      if (scale1 < scale) {
920        extra = scale - scale1;
921      } else {
922        extra = 0;
923      }
924
925      num1 = libbcmath.safe_emalloc(1, n1.n_len + n1.n_scale, extra + 2); //num1 = (unsigned char *) safe_emalloc (1, n1.n_len+n1.n_scale, extra+2);
926      if (num1 === null) {
927        libbcmath.bc_out_of_memory();
928      }
929      libbcmath.memset(num1, 0, 0, n1.n_len + n1.n_scale + extra + 2); //memset (num1, 0, n1->n_len+n1->n_scale+extra+2);
930      libbcmath.memcpy(num1, 1, n1.n_value, 0, n1.n_len + n1.n_scale); //memcpy (num1+1, n1.n_value, n1.n_len+n1.n_scale);
931      len2 = n2.n_len + scale2; // len2 = n2->n_len + scale2;
932      num2 = libbcmath.safe_emalloc(1, len2, 1); //num2 = (unsigned char *) safe_emalloc (1, len2, 1);
933      if (num2 === null) {
934        libbcmath.bc_out_of_memory();
935      }
936      libbcmath.memcpy(num2, 0, n2.n_value, 0, len2); //memcpy (num2, n2.n_value, len2);
937      num2[len2] = 0; // *(num2+len2) = 0;
938      n2ptr = 0; //n2ptr = num2;
939      while (num2[n2ptr] === 0) { // while (*n2ptr == 0)
940        n2ptr++;
941        len2--;
942      }
943
944      /* Calculate the number of quotient digits. */
945      if (len2 > len1 + scale) {
946        qdigits = scale + 1;
947        zero = true;
948      } else {
949        zero = false;
950        if (len2 > len1) {
951          qdigits = scale + 1; /* One for the zero integer part. */
952        } else {
953          qdigits = len1 - len2 + scale + 1;
954        }
955      }
956
957      /* Allocate and zero the storage for the quotient. */
958      qval = libbcmath.bc_new_num(qdigits - scale, scale); //qval = bc_new_num (qdigits-scale,scale);
959      libbcmath.memset(qval.n_value, 0, 0, qdigits); //memset (qval->n_value, 0, qdigits);
960      /* Allocate storage for the temporary storage mval. */
961      mval = libbcmath.safe_emalloc(1, len2, 1); //mval = (unsigned char *) safe_emalloc (1, len2, 1);
962      if (mval === null) {
963        libbcmath.bc_out_of_memory();
964      }
965
966      /* Now for the full divide algorithm. */
967      if (!zero) { /* Normalize */
968        //norm = libbcmath.cint(10 / (libbcmath.cint(n2.n_value[n2ptr]) + 1)); //norm =  10 / ((int)*n2ptr + 1);
969        norm = Math.floor(10 / (n2.n_value[n2ptr] + 1)); //norm =  10 / ((int)*n2ptr + 1);
970        if (norm != 1) {
971          libbcmath._one_mult(num1, 0, len1 + scale1 + extra + 1, norm, num1, 0); //libbcmath._one_mult(num1, len1+scale1+extra+1, norm, num1);
972          libbcmath._one_mult(n2.n_value, n2ptr, len2, norm, n2.n_value, n2ptr); //libbcmath._one_mult(n2ptr, len2, norm, n2ptr);
973          // @CHECK Is the pointer affected by the call? if so, maybe need to adjust points on return?
974        }
975
976        /* Initialize divide loop. */
977        qdig = 0;
978        if (len2 > len1) {
979          qptr = len2 - len1; //qptr = (unsigned char *) qval.n_value+len2-len1;
980        } else {
981          qptr = 0; //qptr = (unsigned char *) qval.n_value;
982        }
983
984        /* Loop */
985        while (qdig <= len1 + scale - len2) { /* Calculate the quotient digit guess. */
986          if (n2.n_value[n2ptr] == num1[qdig]) {
987            qguess = 9;
988          } else {
989            qguess = Math.floor((num1[qdig] * 10 + num1[qdig + 1]) / n2.n_value[n2ptr]);
990          } /* Test qguess. */
991
992          if (n2.n_value[n2ptr + 1] * qguess > (num1[qdig] * 10 + num1[qdig + 1] - n2.n_value[n2ptr] * qguess) * 10 + num1[qdig + 2]) { //if (n2ptr[1]*qguess > (num1[qdig]*10 + num1[qdig+1] - *n2ptr*qguess)*10 + num1[qdig+2]) {
993            qguess--; /* And again. */
994            if (n2.n_value[n2ptr + 1] * qguess > (num1[qdig] * 10 + num1[qdig + 1] - n2.n_value[n2ptr] * qguess) * 10 + num1[qdig + 2]) { //if (n2ptr[1]*qguess > (num1[qdig]*10 + num1[qdig+1] - *n2ptr*qguess)*10 + num1[qdig+2])
995              qguess--;
996            }
997          }
998
999          /* Multiply and subtract. */
1000          borrow = 0;
1001          if (qguess !== 0) {
1002            mval[0] = 0; //*mval = 0; // @CHECK is this to fix ptr2 < 0?
1003            libbcmath._one_mult(n2.n_value, n2ptr, len2, qguess, mval, 1); //_one_mult (n2ptr, len2, qguess, mval+1); // @CHECK
1004            ptr1 = qdig + len2; //(unsigned char *) num1+qdig+len2;
1005            ptr2 = len2; //(unsigned char *) mval+len2;
1006            // @CHECK: Does a negative pointer return null?
1007            //         ptr2 can be < 0 here as ptr1 = len2, thus count < len2+1 will always fail ?
1008            for (count = 0; count < len2 + 1; count++) {
1009              if (ptr2 < 0) {
1010                //val = libbcmath.cint(num1[ptr1]) - 0 - borrow;    //val = (int) *ptr1 - (int) *ptr2-- - borrow;
1011                val = num1[ptr1] - 0 - borrow; //val = (int) *ptr1 - (int) *ptr2-- - borrow;
1012              } else {
1013                //val = libbcmath.cint(num1[ptr1]) - libbcmath.cint(mval[ptr2--]) - borrow;    //val = (int) *ptr1 - (int) *ptr2-- - borrow;
1014                val = num1[ptr1] - mval[ptr2--] - borrow; //val = (int) *ptr1 - (int) *ptr2-- - borrow;
1015              }
1016              if (val < 0) {
1017                val += 10;
1018                borrow = 1;
1019              } else {
1020                borrow = 0;
1021              }
1022              num1[ptr1--] = val;
1023            }
1024          }
1025
1026          /* Test for negative result. */
1027          if (borrow == 1) {
1028            qguess--;
1029            ptr1 = qdig + len2; //(unsigned char *) num1+qdig+len2;
1030            ptr2 = len2 - 1; //(unsigned char *) n2ptr+len2-1;
1031            carry = 0;
1032            for (count = 0; count < len2; count++) {
1033              if (ptr2 < 0) {
1034                //val = libbcmath.cint(num1[ptr1]) + 0 + carry; //val = (int) *ptr1 + (int) *ptr2-- + carry;
1035                val = num1[ptr1] + 0 + carry; //val = (int) *ptr1 + (int) *ptr2-- + carry;
1036              } else {
1037                //val = libbcmath.cint(num1[ptr1]) + libbcmath.cint(n2.n_value[ptr2--]) + carry; //val = (int) *ptr1 + (int) *ptr2-- + carry;
1038                val = num1[ptr1] + n2.n_value[ptr2--] + carry; //val = (int) *ptr1 + (int) *ptr2-- + carry;
1039              }
1040              if (val > 9) {
1041                val -= 10;
1042                carry = 1;
1043              } else {
1044                carry = 0;
1045              }
1046              num1[ptr1--] = val; //*ptr1-- = val;
1047            }
1048            if (carry == 1) {
1049              //num1[ptr1] = libbcmath.cint((num1[ptr1] + 1) % 10);  // *ptr1 = (*ptr1 + 1) % 10; // @CHECK
1050              num1[ptr1] = (num1[ptr1] + 1) % 10; // *ptr1 = (*ptr1 + 1) % 10; // @CHECK
1051            }
1052          }
1053
1054          /* We now know the quotient digit. */
1055          qval.n_value[qptr++] = qguess; //*qptr++ =  qguess;
1056          qdig++;
1057        }
1058      }
1059
1060      /* Clean up and return the number. */
1061      qval.n_sign = (n1.n_sign == n2.n_sign ? libbcmath.PLUS : libbcmath.MINUS);
1062      if (libbcmath.bc_is_zero(qval)) {
1063        qval.n_sign = libbcmath.PLUS;
1064      }
1065      libbcmath._bc_rm_leading_zeros(qval);
1066
1067      return qval;
1068
1069      //return 0;    /* Everything is OK. */
1070    },
1071
1072
1073
1074    MUL_BASE_DIGITS: 80,
1075    MUL_SMALL_DIGITS: (this.MUL_BASE_DIGITS / 4),
1076    //#define MUL_SMALL_DIGITS mul_base_digits/4
1077
1078    /* The multiply routine.  N2 times N1 is put int PROD with the scale of
1079   the result being MIN(N2 scale+N1 scale, MAX (SCALE, N2 scale, N1 scale)).
1080   */
1081    /**
1082     * @param n1 bc_num
1083     * @param n2 bc_num
1084     * @param scale [int] optional
1085     */
1086    bc_multiply: function(n1, n2, scale) {
1087      var pval; // bc_num
1088      var len1, len2; // int
1089      var full_scale, prod_scale; // int
1090      // Initialize things.
1091      len1 = n1.n_len + n1.n_scale;
1092      len2 = n2.n_len + n2.n_scale;
1093      full_scale = n1.n_scale + n2.n_scale;
1094      prod_scale = libbcmath.MIN(full_scale, libbcmath.MAX(scale, libbcmath.MAX(n1.n_scale, n2.
1094n_scale)));
1095
1096      //pval = libbcmath.bc_init_num(); // allow pass by ref
1097      // Do the multiply
1098      pval = libbcmath._bc_rec_mul(n1, len1, n2, len2, full_scale);
1099
1100      // Assign to prod and clean up the number.
1101      pval.n_sign = (n1.n_sign == n2.n_sign ? libbcmath.PLUS : libbcmath.MINUS);
1102      //pval.n_value = pval.n_ptr; // @FIX
1103      pval.n_len = len2 + len1 + 1 - full_scale;
1104      pval.n_scale = prod_scale;
1105      libbcmath._bc_rm_leading_zeros(pval);
1106      if (libbcmath.bc_is_zero(pval)) {
1107        pval.n_sign = libbcmath.PLUS;
1108      }
1109      //bc_free_num (prod);
1110      return pval;
1111    },
1112
1113    new_sub_num: function(length, scale, value) {
1114      var temp = new libbcmath.bc_num();
1115      temp.n_sign = libbcmath.PLUS;
1116      temp.n_len = length;
1117      temp.n_scale = scale;
1118      temp.n_value = value;
1119      return temp;
1120    },
1121
1122    _bc_simp_mul: function(n1, n1len, n2, n2len, full_scale) {
1123      var prod; // bc_num
1124      var n1ptr, n2ptr, pvptr; // char *n1ptr, *n2ptr, *pvptr;
1125      var n1end, n2end; //char *n1end, *n2end;        /* To the end of n1 and n2. */
1126      var indx, sum, prodlen; //int indx, sum, prodlen;
1127      prodlen = n1len + n2len + 1;
1128
1129      prod = libbcmath.bc_new_num(prodlen, 0);
1130
1131      n1end = n1len - 1; //(char *) (n1->n_value + n1len - 1);
1132      n2end = n2len - 1; //(char *) (n2->n_value + n2len - 1);
1133      pvptr = prodlen - 1; //(char *) ((*prod)->n_value + prodlen - 1);
1134      sum = 0;
1135
1136      // Here is the loop...
1137      for (indx = 0; indx < prodlen - 1; indx++) {
1138        n1ptr = n1end - libbcmath.MAX(0, indx - n2len + 1); //(char *) (n1end - MAX(0, indx-n2len+1));
1139        n2ptr = n2end - libbcmath.MIN(indx, n2len - 1); //(char *) (n2end - MIN(indx, n2len-1));
1140        while ((n1ptr >= 0) && (n2ptr <= n2end)) {
1141          sum += n1.n_value[n1ptr--] * n2.n_value[n2ptr++]; //sum += *n1ptr-- * *n2ptr++;
1142        }
1143        prod.n_value[pvptr--] = Math.floor(sum % libbcmath.BASE); //*pvptr-- = sum % BASE;
1144        sum = Math.floor(sum / libbcmath.BASE); //sum = sum / BASE;
1145      }
1146      prod.n_value[pvptr] = sum; //*pvptr = sum;
1147      return prod;
1148    },
1149
1150
1151    /* A special adder/subtractor for the recursive divide and conquer
1152       multiply algorithm.  Note: if sub is called, accum must
1153       be larger that what is being subtracted.  Also, accum and val
1154       must have n_scale = 0.  (e.g. they must look like integers. *) */
1155    _bc_shift_addsub: function(accum, val, shift, sub) {
1156      var accp, valp; //signed char *accp, *valp;
1157      var count, carry; //int  count, carry;
1158      count = val.n_len;
1159      if (val.n_value[0] === 0) {
1160        count--;
1161      }
1162
1163      //assert (accum->n_len+accum->n_scale >= shift+count);
1164      if (accum.n_len + accum.n_scale < shift + count) {
1165        throw new Error('len + scale < shift + count'); // ?? I think that's what assert does :)
1166      }
1167
1168
1169      // Set up pointers and others
1170      accp = accum.n_len + accum.n_scale - shift - 1; // (signed char *)(accum->n_value + accum->n_len + accum->n_scale - shift - 1);
1171      valp = val.n_len = 1; //(signed char *)(val->n_value + val->n_len - 1);
1172      carry = 0;
1173      if (sub) {
1174        // Subtraction, carry is really borrow.
1175        while (count--) {
1176          accum.n_value[accp] -= val.n_value[valp--] + carry; //*accp -= *valp-- + carry;
1177          if (accum.n_value[accp] < 0) { //if (*accp < 0)
1178            carry = 1;
1179            accum.n_value[accp--] += libbcmath.BASE; //*accp-- += BASE;
1180          } else {
1181            carry = 0;
1182            accp--;
1183          }
1184        }
1185        while (carry) {
1186          accum.n_value[accp] -= carry; //*accp -= carry;
1187          if (accum.n_value[accp] < 0) { //if (*accp < 0)
1188            accum.n_value[accp--] += libbcmath.BASE; //    *accp-- += BASE;
1189          } else {
1190            carry = 0;
1191          }
1192        }
1193      } else {
1194        // Addition
1195        while (count--) {
1196          accum.n_value[accp] += val.n_value[valp--] + carry; //*accp += *valp-- + carry;
1197          if (accum.n_value[accp] > (libbcmath.BASE - 1)) { //if (*accp >
1197 (BASE-1))
1198            carry = 1;
1199            accum.n_value[accp--] -= libbcmath.BASE; //*accp-- -= BASE;
1200          } else {
1201            carry = 0;
1202            accp--;
1203          }
1204        }
1205        while (carry) {
1206          accum.n_value[accp] += carry; //*accp += carry;
1207          if (accum.n_value[accp] > (libbcmath.BASE - 1)) { //if (*accp > (BASE-1))
1208            accum.n_value[accp--] -= libbcmath.BASE; //*accp-- -= BASE;
1209          } else {
1210            carry = 0;
1211          }
1212        }
1213      }
1214      return true; // accum is the pass-by-reference return
1215    },
1216
1217    /* Recursive divide and conquer multiply algorithm.
1218       original by
1219       Let u = u0 + u1*(b^n)
1220       Let v = v0 + v1*(b^n)
1221       Then uv = (B^2n+B^n)*u1*v1 + B^n*(u1-u0)*(v0-v1) + (B^n+1)*u0*v0
1222
1223       B is the base of storage, number of digits in u1,u0 close to equal.
1224    */
1225    _bc_rec_mul: function(u, ulen, v, vlen, full_scale) {
1226      var prod; // @return
1227      var u0, u1, v0, v1; //bc_num
1228      var u0len, v0len; //int
1229      var m1, m2, m3, d1, d2; //bc_num
1230      var n, prodlen, m1zero; // int
1231      var d1len, d2len; // int
1232      // Base case?
1233      if ((ulen + vlen) < libbcmath.MUL_BASE_DIGITS || ulen < libbcmath.MUL_SMALL_DIGITS || vlen < libbcmath.MUL_SMALL_DIGITS) {
1234        return libbcmath._bc_simp_mul(u, ulen, v, vlen, full_scale);
1235      }
1236
1237      // Calculate n -- the u and v split point in digits.
1238      n = Math.floor((libbcmath.MAX(ulen, vlen) + 1) / 2);
1239
1240      // Split u and v.
1241      if (ulen < n) {
1242        u1 = libbcmath.bc_init_num(); //u1 = bc_copy_num (BCG(_zero_));
1243        u0 = libbcmath.new_sub_num(ulen, 0, u.n_value);
1244      } else {
1245        u1 = libbcmath.new_sub_num(ulen - n, 0, u.n_value);
1246        u0 = libbcmath.new_sub_num(n, 0, u.n_value + ulen - n);
1247      }
1248      if (vlen < n) {
1249        v1 = libbcmath.bc_init_num(); //bc_copy_num (BCG(_zero_));
1250        v0 = libbcmath.new_sub_num(vlen, 0, v.n_value);
1251      } else {
1252        v1 = libbcmath.new_sub_num(vlen - n, 0, v.n_value);
1253        v0 = libbcmath.new_sub_num(n, 0, v.n_value + vlen - n);
1254      }
1255      libbcmath._bc_rm_leading_zeros(u1);
1256      libbcmath._bc_rm_leading_zeros(u0);
1257      u0len = u0.n_len;
1258      libbcmath._bc_rm_leading_zeros(v1);
1259      libbcmath._bc_rm_leading_zeros(v0);
1260      v0len = v0.n_len;
1261
1262      m1zero = libbcmath.bc_is_zero(u1) || libbcmath.bc_is_zero(v1);
1263
1264      // Calculate sub results ...
1265      d1 = libbcmath.bc_init_num(); // needed?
1266      d2 = libbcmath.bc_init_num(); // needed?
1267      d1 = libbcmath.bc_sub(u1, u0, 0);
1268      d1len = d1.n_len;
1269
1270      d2 = libbcmath.bc_sub(v0, v1, 0);
1271      d2len = d2.n_len;
1272
1273      // Do recursive multiplies and shifted adds.
1274      if (m1zero) {
1275        m1 = libbcmath.bc_init_num(); //bc_copy_num (BCG(_zero_));
1276      } else {
1277        //m1 = libbcmath.bc_init_num(); //allow pass-by-ref
1278        m1 = libbcmath._bc_rec_mul(u1, u1.n_len, v1, v1.n_len, 0);
1279      }
1280      if (libbcmath.bc_is_zero(d1) || libbcmath.bc_is_zero(d2)) {
1281        m2 = libbcmath.bc_init_num(); //bc_copy_num (BCG(_zero_));
1282      } else {
1283        //m2 = libbcmath.bc_init_num(); //allow pass-by-ref
1284        m2 = libbcmath._bc_rec_mul(d1, d1len, d2, d2len, 0);
1285      }
1286
1287      if (libbcmath.bc_is_zero(u0) || libbcmath.bc_is_zero(v0)) {
1288        m3 = libbcmath.bc_init_num(); //bc_copy_num (BCG(_zero_));
1289      } else {
1290        //m3 = libbcmath.bc_init_num(); //allow pass-by-ref
1291        m3 = libbcmath._bc_rec_mul(u0, u0.n_len, v0, v0.n_len, 0);
1292      }
1293
1294      // Initialize product
1295      prodlen = ulen + vlen + 1;
1296      prod = libbcmath.bc_new_num(prodlen, 0);
1297
1298      if (!m1zero) {
1299        libbcmath._bc_shift_addsub(prod, m1, 2 * n, 0);
1300        libbcmath._bc_shift_addsub(prod, m1, n, 0);
1301      }
1302      libbcmath._bc_shift_addsub(prod, m3, n, 0);
1303      libbcmath._bc_shift_addsub(prod, m3, 0, 0);
1304      libbcmath._bc_shift_addsub(prod, m2, n, d1.n_sign != d2.n_sign);
1305
1306      return prod;
1307      // Now clean up!
1308      //bc_free_num (&u1);
1309      //bc_free_num (&u0);
1310      //bc_free_num (&v1);
1311      //bc_free_num (&m1);
1312      //bc_free_num (&v0);
1313      //bc_free_num (&m2);
1314      //bc_free_num (&m3);
1315      //bc_free_num (&d1);
1316      //bc_free_num (&d2);
1317    },
1318
1319
1320    /**
1321     *
1322     * @param {bc_num} n1
1323     * @param {bc_num} n2
1324     * @param {boolean} use_sign
1325     * @param {boolean} ignore_last
1326     * @return -1, 0, 1 (see bc_compare)
1327     */
1328    _bc_do_compare: function(n1, n2, use_sign, ignore_last) {
1329      var n1ptr, n2ptr; // int
1330      var count; // int
1331      /* First, compare signs. */
1332      if (use_sign && (n1.n_sign != n2.n_sign)) {
1333        if (n1.n_sign == libbcmath.PLUS) {
1334          return (1); /* Positive N1 > Negative N2 */
1335        } else {
1336          return (-1); /* Negative N1 < Positive N1 */
1337        }
1338      }
1339
1340      /* Now compare the magnitude. */
1341      if (n1.n_len != n2.n_len) {
1342        if (n1.n_len > n2.n_len) { /* Magnitude of n1 > n2. */
1343          if (!use_sign || (n1.n_sign == libbcmath.PLUS)) {
1344            return (1);
1345          } else {
1346            return (-1);
1347          }
1348        } else { /* Magnitude of n1 < n2. */
1349          if (!use_sign || (n1.n_sign == libbcmath.PLUS)) {
1350            return (-1);
1351          } else {
1352            return (1);
1353          }
1354        }
1355      }
1356
1357      /* If we get here, they have the same number of integer digits.
1358     check the integer part and the equal length part of the fraction. */
1359      count = n1.n_len + Math.min(n1.n_scale, n2.n_scale);
1360      n1ptr = 0;
1361      n2ptr = 0;
1362
1363      while ((count > 0) && (n1.n_value[n1ptr] == n2.n_value[n2ptr])) {
1364        n1ptr++;
1365        n2ptr++;
1366        count--;
1367      }
1368
1369      if (ignore_last && (count == 1) && (n1.n_scale == n2.n_scale)) {
1370        return (0);
1371      }
1372
1373      if (count !== 0) {
1374        if (n1.n_value[n1ptr] > n2.n_value[n2ptr]) { /* Magnitude of n1 > n2. */
1375          if (!use_sign || n1.n_sign == libbcmath.PLUS) {
1376            return (1);
1377          } else {
1378            return (-1);
1379          }
1380        } else { /* Magnitude of n1 < n2. */
1381          if (!use_sign || n1.n_sign == libbcmath.PLUS) {
1382            return (-1);
1383          } else {
1384            return (1);
1385          }
1386        }
1387      }
1388
1389      /* They are equal up to the last part of the equal part of the fraction. */
1390      if (n1.n_scale != n2.n_scale) {
1391        if (n1.n_scale > n2.n_scale) {
1392          for (count = (n1.n_scale - n2.n_scale); count > 0; count--) {
1393            if (n1.n_value[n1ptr++] !== 0) { /* Magnitude of n1 > n2. */
1394              if (!use_sign || n1.n_sign == libbcmath.PLUS) {
1395                return (1);
1396              } else {
1397                return (-1);
1398              }
1399            }
1400          }
1401        } else {
1402          for (count = (n2.n_scale - n1.n_scale); count > 0; count--) {
1403            if (n2.n_value[n2ptr++] !== 0) { /* Magnitude of n1 < n2. */
1404              if (!use_sign || n1.n_sign == libbcmath.PLUS) {
1405                return (-1);
1406              } else {
1407                return (1);
1408              }
1409            }
1410          }
1411        }
1412      }
1413
1414      /* They must be equal! */
1415      return (0);
1416    },
1417
1418
1419
1420    /* Here is the full subtract routine that takes care of negative numbers.
1421   N2 is subtracted from N1 and the result placed in RESULT.  SCALE_MIN
1422   is the minimum scale for the result. */
1423    bc_sub: function(n1, n2, scale_min) {
1424      var diff; // bc_num
1425      var cmp_res, res_scale; //int
1426      if (n1.n_sign != n2.n_sign) {
1427        diff = libbcmath._bc_do_add(n1, n2, scale_min);
1428        diff.n_sign = n1.n_sign;
1429      } else { /* subtraction must be done. */
1430        /* Compare magnitudes. */
1431        cmp_res = libbcmath._bc_do_compare(n1, n2, false, false);
1432        switch (cmp_res) {
1433          case -1:
1434            /* n1 is less than n2, subtract n1 from n2. */
1435            diff = libbcmath._bc_do_sub(n2, n1, scale_min);
1436            diff.n_sign = (n2.n_sign == libbcmath.PLUS ? libbcmath.MINUS : libbcmath.PLUS);
1437            break;
1438          case 0:
1439            /* They are equal! return zero! */
1440            res_scale = libbcmath.MAX(scale_min, libbcmath.MAX(n1.n_scale, n2.n_scale));
1441            diff = libbcmath.bc_new_num(1, res_scale);
1442            libbcmath.memset(diff.n_value, 0, 0, res_scale + 1);
1443            break;
1444          case 1:
1445            /* n2 is less than n1, subtract n2 from n1. */
1446            diff = libbcmath._bc_do_sub(n1, n2, scale_min);
1447            diff.n_sign = n1.n_sign;
1448            break;
1449        }
1450      }
1451
1452      /* Clean up and return. */
1453      //bc_free_num (result);
1454      //*result = diff;
1455      return diff;
1456    },
1457
1458
1459    _bc_do_add: function(n1, n2, scale_min) {
1460      var sum; // bc_num
1461      var sum_scale, sum_digits; // int
1462      var n1ptr, n2ptr, sumptr; // int
1463      var carry, n1bytes, n2bytes; // int
1464      var tmp; // int
1465
1466      // Prepare sum.
1467      sum_scale = libbcmath.MAX(n1.n_scale, n2.n_scale);
1468      sum_digits = libbcmath.MAX(n1.n_len, n2.n_len) + 1;
1469      sum = libbcmath.bc_new_num(sum_digits, libbcmath.MAX(sum_scale, scale_min));
1470
1471
1472      /* Not needed?
1473    if (scale_min > sum_scale) {
1474      sumptr = (char *) (sum->n_value + sum_scale + sum_digits);
1475      for (count = scale_min - sum_scale; count > 0; count--) {
1476        *sumptr++ = 0;
1477      }
1478    }
1479    */
1480
1481      // Start with the fraction part.  Initialize the pointers.
1482      n1bytes = n1.n_scale;
1483      n2bytes = n2.n_scale;
1484      n1ptr = (n1.n_len + n1bytes - 1);
1485      n2ptr = (n2.n_len + n2bytes - 1);
1486      sumptr = (sum_scale + sum_digits - 1);
1487
1488      // Add the fraction part.  First copy the longer fraction (ie when adding 1.2345 to 1 we know .2345 is correct already) .
1489      if (n1bytes != n2bytes) {
1490        if (n1bytes > n2bytes) {
1491          // n1 has more dp then n2
1492          while (n1bytes > n2bytes) {
1493            sum.n_value[sumptr--] = n1.n_value[n1ptr--];
1494            // *sumptr-- = *n1ptr--;
1495            n1bytes--;
1496          }
1497        } else {
1498          // n2 has more dp then n1
1499          while (n2bytes > n1bytes) {
1500            sum.n_value[sumptr--] = n2.n_value[n2ptr--];
1501            // *sumptr-- = *n2ptr--;
1502            n2bytes--;
1503          }
1504        }
1505      }
1506
1507      // Now add the remaining fraction part and equal size integer parts.
1508      n1bytes += n1.n_len;
1509      n2bytes += n2.n_len;
1510      carry = 0;
1511      while ((n1bytes > 0) && (n2bytes > 0)) {
1512
1513        // add the two numbers together
1514        tmp = n1.n_value[n1ptr--] + n2.n_value[n2ptr--] + carry;
1515        // *sumptr = *n1ptr-- + *n2ptr-- + carry;
1516        // check if they are >= 10 (impossible to be more then 18)
1517        if (tmp >= libbcmath.BASE) {
1518          carry = 1;
1519          tmp -= libbcmath.BASE; // yep, subtract 10, add a carry
1520        } else {
1521          carry = 0;
1522        }
1523        sum.n_value[sumptr] = tmp;
1524        sumptr--;
1525        n1bytes--;
1526        n2bytes--;
1527      }
1528
1529      // Now add carry the [rest of the] longer integer part.
1530      if (n1bytes === 0) {
1531        // n2 is a bigger number then n1
1532        while (n2bytes-- > 0) {
1533          tmp = n2.n_value[n2ptr--] + carry;
1534          // *sumptr = *n2ptr-- + carry;
1535          if (tmp >= libbcmath.BASE) {
1536            carry = 1;
1537            tmp -= libbcmath.BASE;
1538          } else {
1539            carry = 0;
1540          }
1541          sum.n_value[sumptr--] = tmp;
1542        }
1543      } else {
1544        // n1 is bigger then n2..
1545        while (n1bytes-- > 0) {
1546          tmp = n1.n_value[n1ptr--] + carry;
1547          // *sumptr = *n1ptr-- + carry;
1548          if (tmp >= libbcmath.BASE) {
1549            carry = 1;
1550            tmp -= libbcmath.BASE;
1551          } else {
1552            carry = 0;
1553          }
1554          sum.n_value[sumptr--] = tmp;
1555        }
1556      }
1557
1558      // Set final carry.
1559      if (carry == 1) {
1560        sum.n_value[sumptr] += 1;
1561        // *sumptr += 1;
1562      }
1563
1564      // Adjust sum and return.
1565      libbcmath._bc_rm_leading_zeros(sum);
1566      return sum;
1567    },
1568
1569    /**
1570     * Perform a subtraction
1571     *
1572     // Perform subtraction: N2 is subtracted from N1 and the value is
1573     //  returned.  The signs of N1 and N2 are ignored.  Also, N1 is
1574     //  assumed to be larger than N2.  SCALE_MIN is the minimum scale
1575     //  of the result.
1576     *
1577     * Basic school maths says to subtract 2 numbers..
1578     * 1. make them the same length, the decimal places, and the integer part
1579     * 2. start from the right and subtract the two numbers from each other
1580     * 3. if the sum of the 2 numbers < 0, carry -1 to the next set and add 10 (ie 18 > carry 1 becomes 8). thus 0.9 + 0.9 = 1.8
1581     *
1582     * @param {bc_num} n1
1583     * @param {bc_num} n2
1584     * @param {int} scale_min
1585     * @return bc_num
1586     */
1587    _bc_do_sub: function(n1, n2, scale_min) {
1588      var diff; //bc_num
1589      var diff_scale, diff_len; // int
1590      var min_scale, min_len; // int
1591      var n1ptr, n2ptr, diffptr; // int
1592      var borrow, count, val; // int
1593      // Allocate temporary storage.
1594      diff_len = libbcmath.MAX(n1.n_len, n2.n_len);
1595      diff_scale = libbcmath.MAX(n1.n_scale, n2.n_scale);
1596      min_len = libbcmath.MIN(n1.n_len, n2.n_len);
1597      min_scale = libbcmath.MIN(n1.n_scale, n2.n_scale);
1598      diff = libbcmath.bc_new_num(diff_len, libbcmath.MAX(diff_scale, scale_min));
1599
1600      /* Not needed?
1601    // Zero extra digits made by scale_min.
1602    if (scale_min > diff_scale) {
1603      diffptr = (char *) (diff->n_value + diff_len + diff_scale);
1604      for (count = scale_min - diff_scale; count > 0; count--) {
1605        *diffptr++ = 0;
1606      }
1607    }
1608    */
1609
1610      // Initialize the subtract.
1611      n1ptr = (n1.n_len + n1.n_scale - 1);
1612      n2ptr = (n2.n_len + n2.n_scale - 1);
1613      diffptr = (diff_len + diff_scale - 1);
1614
1615      // Subtract the numbers.
1616      borrow = 0;
1617
1618      // Take care of the longer scaled number.
1619      if (n1.n_scale != min_scale) {
1620        // n1 has the longer scale
1621        for (count = n1.n_scale - min_scale; count > 0; count--) {
1622          diff.n_value[diffptr--] = n1.n_value[n1ptr--];
1623          // *diffptr-- = *n1ptr--;
1624        }
1625      } else {
1626        // n2 has the longer scale
1627        for (count = n2.n_scale - min_scale; count > 0; count--) {
1628          val = 0 - n2.n_value[n2ptr--] - borrow;
1629          //val = - *n2ptr-- - borrow;
1630          if (val < 0) {
1631            val += libbcmath.BASE;
1632            borrow = 1;
1633          } else {
1634            borrow = 0;
1635          }
1636          diff.n_value[diffptr--] = val;
1637          //*diffptr-- = val;
1638        }
1639      }
1640
1641      // Now do the equal length scale and integer parts.
1642      for (count = 0; count < min_len + min_scale; count++) {
1643        val = n1.n_value[n1ptr--] - n2.n_value[n2ptr--] - borrow;
1644        //val = *n1ptr-- - *n2ptr-- - borrow;
1645        if (val < 0) {
1646          val += libbcmath.BASE;
1647          borrow = 1;
1648        } else {
1649          borrow = 0;
1650        }
1651        diff.n_value[diffptr--] = val;
1652        //*diffptr-- = val;
1653      }
1654
1655      // If n1 has more digits then n2, we now do that subtract.
1656      if (diff_len != min_len) {
1657        for (count = diff_len - min_len; count > 0; count--) {
1658          val = n1.n_value[n1ptr--] - borrow;
1659          // val = *n1ptr-- - borrow;
1660          if (val < 0) {
1661            val += libbcmath.BASE;
1662            borrow = 1;
1663          } else {
1664            borrow = 0;
1665          }
1666          diff.n_value[diffptr--] = val;
1667        }
1668      }
1669
1670      // Clean up and return.
1671      libbcmath._bc_rm_leading_zeros(diff);
1672      return diff;
1673    },
1674
1675    /**
1676     *
1677     * @param {int} length
1678     * @param {int} scale
1679     * @return bc_num
1680     */
1681    bc_new_num: function(length, scale) {
1682      var temp; // bc_num
1683      temp = new libbcmath.bc_num();
1684      temp.n_sign = libbcmath.PLUS;
1685      temp.n_len = length;
1686      temp.n_scale = scale;
1687      temp.n_value = libbcmath.safe_emalloc(1, length + scale, 0);
1688      libbcmath.memset(temp.n_value, 0, 0, length + scale);
1689      return temp;
1690    },
1691
1692    safe_emalloc: function(size, len, extra) {
1693      return Array((size * len) + extra);
1694    },
1695
1696    /**
1697     * Create a new number
1698     */
1699    bc_init_num: function() {
1700      return new libbcmath.bc_new_num(1, 0);
1701
1702    },
1703
1704    _bc_rm_leading_zeros: function(num) { /* We can move n_value to point to the first non zero digit! */
1705      while ((num.n_value[0] === 0) && (num.n_len > 1)) {
1706        num.n_value.shift();
1707        num.n_len--;
1708      }
1709    },
1710
1711    /**
1712     * Convert to bc_num detecting scale
1713     */
1714    php_str2num: function(str) {
1715      var p;
1716      p = str.indexOf('.');
1717      if (p == -1) {
1718        return libbcmath.bc_str2num(str, 0);
1719      } else {
1720        return libbcmath.bc_str2num(str, (str.length - p));
1721      }
1722
1723    },
1724
1725    CH_VAL: function(c) {
1726      return c - '0'; //??
1727    },
1728
1729    BCD_CHAR: function(d) {
1730      return d + '0'; // ??
1731    },
1732
1733    isdigit: function(c) {
1734      return (isNaN(parseInt(c, 10)) ? false : true);
1735    },
1736
1737    bc_str2num: function(str_in, scale) {
1738      var str, num, ptr, digits, strscale, zero_int, nptr;
1739      // remove any non-expected characters
1740      /* Check for valid number and count digits. */
1741
1742      str = str_in.split(''); // convert to array
1743      ptr = 0; // str
1744      digits = 0;
1745      strscale = 0;
1746      zero_int = false;
1747      if ((str[ptr] === '+') || (str[ptr] === '-')) {
1748        ptr++; /* Sign */
1749      }
1750      while (str[ptr] === '0') {
1751        ptr++; /* Skip leading zeros. */
1752      }
1753      //while (libbcmath.isdigit(str[ptr])) {
1754      while ((str[ptr]) % 1 === 0) { //libbcmath.isdigit(str[ptr])) {
1755        ptr++;
1756        digits++; /* digits */
1757      }
1758
1759      if (str[ptr] === '.') {
1760        ptr++; /* decimal point */
1761      }
1762      //while (libbcmath.isdigit(str[ptr])) {
1763      while ((str[ptr]) % 1 === 0) { //libbcmath.isdigit(str[ptr])) {
1764        ptr++;
1765        strscale++; /* digits */
1766      }
1767
1768      if ((str[ptr]) || (digits + strscale === 0)) {
1769        // invalid number, return 0
1770        return libbcmath.bc_init_num();
1771        //*num = bc_copy_num (BCG(_zero_));
1772      }
1773
1774      /* Adjust numbers and allocate storage and initialize fields. */
1775      strscale = libbcmath.MIN(strscale, scale);
1776      if (digits === 0) {
1777        zero_int = true;
1778        digits = 1;
1779      }
1780
1781      num = libbcmath.bc_new_num(digits, strscale);
1782
1783      /* Build the whole number. */
1784      ptr = 0; // str
1785      if (str[ptr] === '-') {
1786        num.n_sign = libbcmath.MINUS;
1787        //(*num)->n_sign = MINUS;
1788        ptr++;
1789      } else {
1790        num.n_sign = libbcmath.PLUS;
1791        //(*num)->n_sign = PLUS;
1792        if (str[ptr] === '+') {
1793          ptr++;
1794        }
1795      }
1796      while (str[ptr] === '0') {
1797        ptr++; /* Skip leading zeros. */
1798      }
1799
1800      nptr = 0; //(*num)->n_value;
1801      if (zero_int) {
1802        num.n_value[nptr++] = 0;
1803        digits = 0;
1804      }
1805      for (; digits > 0; digits--) {
1806        num.n_value[nptr++] = libbcmath.CH_VAL(str[ptr++]);
1807        //*nptr++ = CH_VAL(*ptr++);
1808      }
1809
1810      /* Build the fractional part. */
1811      if (strscale > 0) {
1812        ptr++; /* skip the decimal point! */
1813        for (; strscale > 0; strscale--) {
1814          num.n_value[nptr++] = libbcmath.CH_VAL(str[ptr++]);
1815        }
1816      }
1817
1818      return num;
1819    },
1820
1821    cint: function(v) {
1822      if (typeof v === 'undefined') {
1823        v = 0;
1824      }
1825      var x = parseInt(v, 10);
1826      if (isNaN(x)) {
1827        x = 0;
1828      }
1829      return x;
1830    },
1831
1832    /**
1833     * Basic min function
1834     * @param {int} a
1835     * @param {int} b
1836     */
1837    MIN: function(a, b) {
1838      return ((a > b) ? b : a);
1839    },
1840
1841    /**
1842     * Basic max function
1843     * @param {int} a
1844     * @param {int} b
1845     */
1846    MAX: function(a, b) {
1847      return ((a > b) ? a : b);
1848    },
1849
1850    /**
1851     * Basic odd function
1852     * @param {int} a
1853     */
1854    ODD: function(a) {
1855      return (a & 1);
1856    },
1857
1858    /**
1859     * replicate c function
1860     * @param {array} r     return (by reference)
1861     * @param {int} ptr
1862     * @param {string} chr    char to fill
1863     * @param {int} len       length to fill
1864     */
1865    memset: function(r, ptr, chr, len) {
1866      var i;
1867      for (i = 0; i < len; i++) {
1868        r[ptr + i] = chr;
1869      }
1870    },
1871
1872    /**
1873     * Replacement c function
1874     * Obviously can't work like c does, so we've added an "offset" param so you could do memcpy(dest+1, src, len) as memcpy(dest, 1, src, len)
1875     * Also only works on arrays
1876     */
1877    memcpy: function(dest, ptr, src, srcptr, len) {
1878      var i;
1879      for (i = 0; i < len; i++) {
1880        dest[ptr + i] = src[srcptr + i];
1881      }
1882      return true;
1883    },
1884
1885
1886    /**
1887     * Determine if the number specified is zero or not
1888     * @param {bc_num} num    number to check
1889     * @return boolean      true when zero, false when not zero.
1890     */
1891    bc_is_zero: function(num) {
1892      var count; // int
1893      var nptr; // int
1894      /* Quick check. */
1895      //if (num == BCG(_zero_)) return TRUE;
1896      /* Initialize */
1897      count = num.n_len + num.n_scale;
1898      nptr = 0; //num->n_value;
1899      /* The check */
1900      while ((count > 0) && (num.n_value[nptr++] === 0)) {
1901        count--;
1902      }
1903
1904      if (count !== 0) {
1905        return false;
1906      } else {
1907        return true;
1908      }
1909    },
1910
1911    bc_out_of_memory: function() {
1912      throw new Error('(BC) Out of memory');
1913    }
1914  };
1915  return libbcmath;
1916}
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929function strtotime(text, now) {
1930  //  discuss at: http://phpjs.org/functions/strtotime/
1931  //     version: 1109.2016
1932  // original by: Caio Ariede (http://caioariede.com)
1933  // improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
1934  // improved by: Caio Ariede (http://caioariede.com)
1935  // improved by: A. Matías Quezada (http://amatiasq.com)
1936  // improved by: preuter
1937  // improved by: Brett Zamir (http://brett-zamir.me)
1938  // improved by: Mirko Faber
1939  //    input by: David
1940  // bugfixed by: Wagner B. Soares
1941  // bugfixed by: Artur Tchernychev
1942  //        note: Examples all have a fixed timestamp to prevent tests to fail because of variable time(zones)
1943  //   example 1: strtotime('+1 day', 1129633200);
1944  //   returns 1: 1129719600
1945  //   example 2: strtotime('+1 week 2 days 4 hours 2 seconds', 1129633200);
1946  //   returns 2: 1130425202
1947  //   example 3: strtotime('last month', 1129633200);
1948  //   returns 3: 1127041200
1949  //   example 4: strtotime('2009-05-04 08:30:00 GMT');
1950  //   returns 4: 1241425800
1951
1952  var parsed, match, today, year, date, days, ranges, len, times, regex, i, fail = false;
1953
1954  if (!text) {
1955    return fail;
1956  }
1957
1958  // Unecessary spaces
1959  text = text.replace(/^\s+|\s+$/g, '')
1960    .replace(/\s{2,}/g, ' ')
1961    .replace(/[\t\r\n]/g, '')
1962    .toLowerCase();
1963
1964  // in contrast to php, js Date.parse function interprets:
1965  // dates given as yyyy-mm-dd as in timezone: UTC,
1966  // dates with "." or "-" as MDY instead of DMY
1967  // dates with two-digit years differently
1968  // etc...etc...
1969  // ...therefore we manually parse lots of common date formats
1970  match = text.match(
1971    /^(\d{1,4})([\-\.\/\:])(\d{1,2})([\-\.\/\:])(\d{1,4})(?:\s(\d{1,2}):(\d{2})?:?(\d{2})?)?(?:\s([A-Z]+)?)?$/);
1972
1973  if (match && match[2] === match[4]) {
1974    if (match[1] > 1901) {
1975      switch (match[2]) {
1976        case '-':
1977          { // YYYY-M-D
1978            if (match[3] > 12 || match[5] > 31) {
1979              return fail;
1980            }
1981
1982            return new Date(match[1], parseInt(match[3], 10) - 1, match[5],
1983              match[6] || 0, match[7] || 0, match[8] || 0, match[9] || 0) / 1000;
1984          }
1985        case '.':
1986          { // YYYY.M.D is not parsed by strtotime()
1987            return fail;
1988          }
1989        case '/':
1990          { // YYYY/M/D
1991            if (match[3] > 12 || match[5] > 31) {
1992              return fail;
1993            }
1994
1995            return new Date(match[1], parseInt(match[3], 10) - 1, match[5],
1996              match[6] || 0, match[7] || 0, match[8] || 0, match[9] || 0) / 1000;
1997          }
1998      }
1999    } else if (match[5] > 1901) {
2000      switch (match[2]) {
2001        case '-':
2002          { // D-M-YYYY
2003            if (match[3] > 12 || match[1] > 31) {
2004              return fail;
2005            }
2006
2007            return new Date(match[5], parseInt(match[3], 10) - 1, match[1],
2008              match[6] || 0, match[7] || 0, match[8] || 0, match[9] || 0) / 1000;
2009          }
2010        case '.':
2011          { // D.M.YYYY
2012            if (match[3] > 12 || match[1] > 31) {
2013              return fail;
2014            }
2015
2016            return new Date(match[5], parseInt(match[3], 10) - 1, match[1],
2017              match[6] || 0, match[7] || 0, match[8] || 0, match[9] || 0) / 1000;
2018          }
2019        case '/':
2020          { // M/D/YYYY
2021            if (match[1] > 12 || match[3] > 31) {
2022              return fail;
2023            }
2024
2025            return new Date(match[5], parseInt(match[1], 10) - 1, match[3],
2026              match[6] || 0, match[7] || 0, match[8] || 0, match[9] || 0) / 1000;
2027          }
2028      }
2029    } else {
2030      switch (match[2]) {
2031        case '-':
2032          { // YY-M-D
2033            if (match[3] > 12 || match[5] > 31 || (match[1] < 70 && match[1] > 38)) {
2034              return fail;
2035            }
2036
2037            year = match[1] >= 0 && match[1] <= 38 ? +match[1] + 2000 : match[1];
2038            return new Date(year, parseInt(match[3], 10) - 1, match[5],
2039              match[6] || 0, match[7] || 0, match[8] || 0, match[9] || 0) / 1000;
2040          }
2041        case '.':
2042          { // D.M.YY or H.MM.SS
2043            if (match[5] >= 70) { // D.M.YY
2044              if (match[3] > 12 || match[1] > 31) {
2045                return fail;
2046              }
2047
2048              return new Date(match[5], parseInt(match[3], 10) - 1, match[1],
2049                match[6] || 0, match[7] || 0, match[8] || 0, match[9] || 0) / 1000;
2050            }
2051            if (match[5] < 60 && !match[6]) { // H.MM.SS
2052              if (match[1] > 23 || match[3] > 59) {
2053                return fail;
2054              }
2055
2056              today = new Date();
2057              return new Date(today.getFullYear(), today.getMonth(), today.getDate(),
2058                match[1] || 0, match[3] || 0, match[5] || 0, match[9] || 0) / 1000;
2059            }
2060
2061            return fail; // invalid format, cannot be parsed
2062          }
2063        case '/':
2064          { // M/D/YY
2065            if (match[1] > 12 || match[3] > 31 || (match[5] < 70 && match[5] > 38)) {
2066              return fail;
2067            }
2068
2069            year = match[5] >= 0 && match[5] <= 38 ? +match[5] + 2000 : match[5];
2070            return new Date(year, parseInt(match[1], 10) - 1, match[3],
2071              match[6] || 0, match[7] || 0, match[8] || 0, match[9] || 0) / 1000;
2072          }
2073        case ':':
2074          { // HH:MM:SS
2075            if (match[1] > 23 || match[3] > 59 || match[5] > 59) {
2076              return fail;
2077            }
2078
2079            today = new Date();
2080            return new Date(today.getFullYear(), today.getMonth(), today.getDate(),
2081              match[1] || 0, match[3] || 0, match[5] || 0) / 1000;
2082          }
2083      }
2084    }
2085  }
2086
2087  // other formats and "now" should be parsed by Date.parse()
2088  if (text === 'now') {
2089    return now === null || isNaN(now) ? new Date()
2090      .getTime() / 1000 | 0 : now | 0;
2091  }
2092  if (!isNaN(parsed = Date.parse(text))) {
2093    return parsed / 1000 | 0;
2094  }
2095
2096  date = now ? new Date(now * 1000) : new Date();
2097  days = {
2098    'sun': 0,
2099    'mon': 1,
2100    'tue': 2,
2101    'wed': 3,
2102    'thu': 4,
vendor: 26,424 bytes, lines 2103-2849
2103    'fri': 5,
2104    'sat': 6
2105  };
2106  ranges = {
2107    'yea': 'FullYear',
2108    'mon': 'Month',
2109    'day': 'Date',
2110    'hou': 'Hours',
2111    'min': 'Minutes',
2112    'sec': 'Seconds'
2113  };
2114
2115  function lastNext(type, range, modifier) {
2116    var diff, day = days[range];
2117
2118    if (typeof day !== 'undefined') {
2119      diff = day - date.getDay();
2120
2121      if (diff === 0) {
2122        diff = 7 * modifier;
2123      } else if (diff > 0 && type === 'last') {
2124        diff -= 7;
2125      } else if (diff < 0 && type === 'next') {
2126        diff += 7;
2127      }
2128
2129      date.setDate(date.getDate() + diff);
2130    }
2131  }
2132
2133  function process(val) {
2134    var splt = val.split(' '), // Todo: Reconcile this with regex using \s, taking into account browser issues with split and regexes
2135      type = splt[0],
2136      range = splt[1].substring(0, 3),
2137      typeIsNumber = /\d+/.test(type),
2138      ago = splt[2] === 'ago',
2139      num = (type === 'last' ? -1 : 1) * (ago ? -1 : 1);
2140
2141    if (typeIsNumber) {
2142      num *= parseInt(type, 10);
2143    }
2144
2145    if (ranges.hasOwnProperty(range) && !splt[1].match(/^mon(day|\.)?$/i)) {
2146      return date['set' + ranges[range]](date['get' + ranges[range]]() + num);
2147    }
2148
2149    if (range === 'wee') {
2150      return date.setDate(date.getDate() + (num * 7));
2151    }
2152
2153    if (type === 'next' || type === 'last') {
2154      lastNext(type, range, num);
2155    } else if (!typeIsNumber) {
2156      return false;
2157    }
2158
2159    return true;
2160  }
2161
2162  times = '(years?|months?|weeks?|days?|hours?|minutes?|min|seconds?|sec' +
2163    '|sunday|sun\\.?|monday|mon\\.?|tuesday|tue\\.?|wednesday|wed\\.?' +
2164    '|thursday|thu\\.?|friday|fri\\.?|saturday|sat\\.?)';
2165  regex = '([+-]?\\d+\\s' + times + '|' + '(last|next)\\s' + times + ')(\\sago)?';
2166
2167  match = text.match(new RegExp(regex, 'gi'));
2168  if (!match) {
2169    return fail;
2170  }
2171
2172  for (i = 0, len = match.length; i < len; i++) {
2173    if (!process(match[i])) {
2174      return fail;
2175    }
2176  }
2177
2178  // ECMAScript 5 only
2179  // if (!match.every(process))
2180  //    return false;
2181
2182  return (date.getTime() / 1000);
2183}
2184
2185function time() {
2186  //  discuss at: http://phpjs.org/functions/time/
2187  // original by: GeekFG (http://geekfg.blogspot.com)
2188  // improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
2189  // improved by: metjay
2190  // improved by: HKM
2191  //   example 1: timeStamp = time();
2192  //   example 1: timeStamp > 1000000000 && timeStamp < 2000000000
2193  //   returns 1: true
2194
2195  return Math.floor(new Date()
2196    .getTime() / 1000);
2197}
2198
2199function checkdate(m, d, y) {
2200  //  discuss at: http://phpjs.org/functions/checkdate/
2201  // original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
2202  // improved by: Pyerre
2203  // improved by: Theriault
2204  //   example 1: checkdate(12, 31, 2000);
2205  //   returns 1: true
2206  //   example 2: checkdate(2, 29, 2001);
2207  //   returns 2: false
2208  //   example 3: checkdate(3, 31, 2008);
2209  //   returns 3: true
2210  //   example 4: checkdate(1, 390, 2000);
2211  //   returns 4: false
2212
2213  return m > 0 && m < 13 && y > 0 && y < 32768 && d > 0 && d <= (new Date(y, m, 0))
2214    .getDate();
2215}
2216
2217function microtime(get_as_float) {
2218  //  discuss at: http://phpjs.org/functions/microtime/
2219  // original by: Paulo Freitas
2220  //   example 1: timeStamp = microtime(true);
2221  //   example 1: timeStamp > 1000000000 && timeStamp < 2000000000
2222  //   returns 1: true
2223
2224  var now = new Date()
2225    .getTime() / 1000;
2226  var s = parseInt(now, 10);
2227
2228  return (get_as_float) ? now : (Math.round((now - s) * 1000) / 1000) + ' ' + s;
2229}
2230
2231function date_parse(date) {
2232  //  discuss at: http://phpjs.org/functions/date_parse/
2233  // original by: Brett Zamir (http://brett-zamir.me)
2234  //  depends on: strtotime
2235  //   example 1: date_parse('2006-12-12 10:00:00.5');
2236  //   returns 1: {year : 2006, month: 12, day: 12, hour: 10, minute: 0, second: 0, fraction: 0.5, warning_count: 0, warnings: [], error_count: 0, errors: [], is_localtime: false}
2237
2238  // BEGIN REDUNDANT
2239  this.php_js = this.php_js || {};
2240  // END REDUNDANT
2241
2242  var ts,
2243    warningsOffset = this.php_js.warnings ? this.php_js.warnings.length : null,
2244    errorsOffset = this.php_js.errors ? this.php_js.errors.length : null;
2245
2246  try {
2247    this.php_js.date_parse_state = true; // Allow strtotime to return a decimal (which it normally does not)
2248    ts = this.strtotime(date);
2249    this.php_js.date_parse_state = false;
2250  } finally {
2251    if (!ts) {
2252      return false;
2253    }
2254  }
2255
2256  var dt = new Date(ts * 1000);
2257
2258  var retObj = { // Grab any new warnings or errors added (not implemented yet in strtotime()); throwing warnings, notices, or errors could also be easily monitored by using 'watch' on this.php_js.latestWarning, etc. and/or calling any defined error handlers
2259    warning_count: warningsOffset !== null ? this.php_js.warnings.slice(warningsOffset)
2260      .length : 0,
2261    warnings: warningsOffset !== null ? this.php_js.warnings.slice(warningsOffset) : [],
2262    error_count: errorsOffset !== null ? this.php_js.errors.slice(errorsOffset)
2263      .length : 0,
2264    errors: errorsOffset !== null ? this.php_js.errors.slice(errorsOffset) : []
2265  };
2266  retObj.year = dt.getFullYear();
2267  retObj.month = dt.getMonth() + 1;
2268  retObj.day = dt.getDate();
2269  retObj.hour = dt.getHours();
2270  retObj.minute = dt.getMinutes();
2271  retObj.second = dt.getSeconds();
2272  retObj.fraction = parseFloat('0.' + dt.getMilliseconds());
2273  retObj.is_localtime = dt.getTimezoneOffset() !== 0;
2274
2275  return retObj;
2276}
2277
2278function mktime() {
2279  //  discuss at: http://phpjs.org/functions/mktime/
2280  // original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
2281  // improved by: baris ozdil
2282  // improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
2283  // improved by: FGFEmperor
2284  // improved by: Brett Zamir (http://brett-zamir.me)
2285  //    input by: gabriel paderni
2286  //    input by: Yannoo
2287  //    input by: jakes
2288  //    input by: 3D-GRAF
2289  //    input by: Chris
2290  // bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
2291  // bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
2292  // bugfixed by: Marc Palau
2293  // bugfixed by: Brett Zamir (http://brett-zamir.me)
2294  //  revised by: Theriault
2295  //        note: The return values of the following examples are
2296  //        note: received only if your system's timezone is UTC.
2297  //   example 1: mktime(14, 10, 2, 2, 1, 2008);
2298  //   returns 1: 1201875002
2299  //   example 2: mktime(0, 0, 0, 0, 1, 2008);
2300  //   returns 2: 1196467200
2301  //   example 3: make = mktime();
2302  //   example 3: td = new Date();
2303  //   example 3: real = Math.floor(td.getTime() / 1000);
2304  //   example 3: diff = (real - make);
2305  //   example 3: diff < 5
2306  //   returns 3: true
2307  //   example 4: mktime(0, 0, 0, 13, 1, 1997)
2308  //   returns 4: 883612800
2309  //   example 5: mktime(0, 0, 0, 1, 1, 1998)
2310  //   returns 5: 883612800
2311  //   example 6: mktime(0, 0, 0, 1, 1, 98)
2312  //   returns 6: 883612800
2313  //   example 7: mktime(23, 59, 59, 13, 0, 2010)
2314  //   returns 7: 1293839999
2315  //   example 8: mktime(0, 0, -1, 1, 1, 1970)
2316  //   returns 8: -1
2317
2318  var d = new Date(),
2319    r = arguments,
2320    i = 0,
2321    e = ['Hours', 'Minutes', 'Seconds', 'Month', 'Date', 'FullYear'];
2322
2323  for (i = 0; i < e.length; i++) {
2324    if (typeof r[i] === 'undefined') {
2325      r[i] = d['get' + e[i]]();
2326      r[i] += (i === 3); // +1 to fix JS months.
2327    } else {
2328      r[i] = parseInt(r[i], 10);
2329      if (isNaN(r[i])) {
2330        return false;
2331      }
2332    }
2333  }
2334
2335  // Map years 0-69 to 2000-2069 and years 70-100 to 1970-2000.
2336  r[5] += (r[5] >= 0 ? (r[5] <= 69 ? 2e3 : (r[5] <= 100 ? 1900 : 0)) : 0);
2337
2338  // Set year, month (-1 to fix JS months), and date.
2339  // !This must come before the call to setHours!
2340  d.setFullYear(r[5], r[3] - 1, r[4]);
2341
2342  // Set hours, minutes, and seconds.
2343  d.setHours(r[0], r[1], r[2]);
2344
2345  // Divide milliseconds by 1000 to return seconds and drop decimal.
2346  // Add 1 second if negative or it'll be off from PHP by 1 second.
2347  return (d.getTime() / 1e3 >> 0) - (d.getTime() < 0);
2348}
2349
2350
2351function date(format, timestamp) {
2352  //  discuss at: http://phpjs.org/functions/date/
2353  // original by: Carlos R. L. Rodrigues (http://www.jsfromhell.com)
2354  // original by: gettimeofday
2355  //    parts by: Peter-Paul Koch (http://www.quirksmode.org/js/beat.html)
2356  // improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
2357  // improved by: MeEtc (http://yass.meetcweb.com)
2358  // improved by: Brad Touesnard
2359  // improved by: Tim Wiel
2360  // improved by: Bryan Elliott
2361  // improved by: David Randall
2362  // improved by: Theriault
2363  // improved by: Theriault
2364  // improved by: Brett Zamir (http://brett-zamir.me)
2365  // improved by: Theriault
2366  // improved by: Thomas Beaucourt (http://www.webapp.fr)
2367  // improved by: JT
2368  // improved by: Theriault
2369  // improved by: Rafał Kukawski (http://blog.kukawski.pl)
2370  // improved by: Theriault
2371  //    input by: Brett Zamir (http://brett-zamir.me)
2372  //    input by: majak
2373  //    input by: Alex
2374  //    input by: Martin
2375  //    input by: Alex Wilson
2376  //    input by: Haravikk
2377  // bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
2378  // bugfixed by: majak
2379  // bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
2380  // bugfixed by: Brett Zamir (http://brett-zamir.me)
2381  // bugfixed by: omid (http://phpjs.org/functions/380:380#comment_137122)
2382  // bugfixed by: Chris (http://www.devotis.nl/)
2383  //        note: Uses global: php_js to store the default timezone
2384  //        note: Although the function potentially allows timezone info (see notes), it currently does not set
2385  //        note: per a timezone specified by date_default_timezone_set(). Implementers might use
2386  //        note: this.php_js.currentTimezoneOffset and this.php_js.currentTimezoneDST set by that function
2387  //        note: in order to adjust the dates in this function (or our other date functions!) accordingly
2388  //   example 1: date('H:m:s \\m \\i\\s \\m\\o\\n\\t\\h', 1062402400);
2389  //   returns 1: '09:09:40 m is month'
2390  //   example 2: date('F j, Y, g:i a', 1062462400);
2391  //   returns 2: 'September 2, 2003, 2:26 am'
2392  //   example 3: date('Y W o', 1062462400);
2393  //   returns 3: '2003 36 2003'
2394  //   example 4: x = date('Y m d', (new Date()).getTime()/1000);
2395  //   example 4: (x+'').length == 10 // 2009 01 09
2396  //   returns 4: true
2397  //   example 5: date('W', 1104534000);
2398  //   returns 5: '53'
2399  //   example 6: date('B t', 1104534000);
2400  //   returns 6: '999 31'
2401  //   example 7: date('W U', 1293750000.82); // 2010-12-31
2402  //   returns 7: '52 1293750000'
2403  //   example 8: date('W', 1293836400); // 2011-01-01
2404  //   returns 8: '52'
2405  //   example 9: date('W Y-m-d', 1293974054); // 2011-01-02
2406  //   returns 9: '52 2011-01-02'
2407
2408  var that = this;
2409  var jsdate, f;
2410  // Keep this here (works, but for code commented-out below for file size reasons)
2411  // var tal= [];
2412  var txt_words = [
2413    'Sun', 'Mon', 'Tues', 'Wednes', 'Thurs', 'Fri', 'Satur',
2414    'January', 'February', 'March', 'April', 'May', 'June',
2415    'July', 'August', 'September', 'October', 'November', 'December'
2416  ];
2417  // trailing backslash -> (dropped)
2418  // a backslash followed by any character (including backslash) -> the character
2419  // empty string -> empty string
2420  var formatChr = /\\?(.?)/gi;
2421  var formatChrCb = function(t, s) {
2422    return f[t] ? f[t]() : s;
2423  };
2424  var _pad = function(n, c) {
2425    n = String(n);
2426    while (n.length < c) {
2427      n = '0' + n;
2428    }
2429    return n;
2430  };
2431  f = {
2432    // Day
2433    d: function() { // Day of month w/leading 0; 01..31
2434      return _pad(f.j(), 2);
2435    },
2436    D: function() { // Shorthand day name; Mon...Sun
2437      return f.l()
2438        .slice(0, 3);
2439    },
2440    j: function() { // Day of month; 1..31
2441      return jsdate.getDate();
2442    },
2443    l: function() { // Full day name; Monday...Sunday
2444      return txt_words[f.w()] + 'day';
2445    },
2446    N: function() { // ISO-8601 day of week; 1[Mon]..7[Sun]
2447      return f.w() || 7;
2448    },
2449    S: function() { // Ordinal suffix for day of month; st, nd, rd, th
2450      var j = f.j();
2451      var i = j % 10;
2452      if (i <= 3 && parseInt((j % 100) / 10, 10) == 1) {
2453        i = 0;
2454      }
2455      return ['st', 'nd', 'rd'][i - 1] || 'th';
2456    },
2457    w: function() { // Day of week; 0[Sun]..6[Sat]
2458      return jsdate.getDay();
2459    },
2460    z: function() { // Day of year; 0..365
2461      var a = new Date(f.Y(), f.n() - 1, f.j());
2462      var b = new Date(f.Y(), 0, 1);
2463      return Math.round((a - b) / 864e5);
2464    },
2465
2466    // Week
2467    W: function() { // ISO-8601 week number
2468      var a = new Date(f.Y(), f.n() - 1, f.j() - f.N() + 3);
2469      var b = new Date(a.getFullYear(), 0, 4);
2470      return _pad(1 + Math.round((a - b) / 864e5 / 7), 2);
2471    },
2472
2473    // Month
2474    F: function() { // Full month name; January...December
2475      return txt_words[6 + f.n()];
2476    },
2477    m: function() { // Month w/leading 0; 01...12
2478      return _pad(f.n(), 2);
2479    },
2480    M: function() { // Shorthand month name; Jan...Dec
2481      return f.F()
2482        .slice(0, 3);
2483    },
2484    n: function() { // Month; 1...12
2485      return jsdate.getMonth() + 1;
2486    },
2487    t: function() { // Days in month; 28...31
2488      return (new Date(f.Y(), f.n(), 0))
2489        .getDate();
2490    },
2491
2492    // Year
2493    L: function() { // Is leap year?; 0 or 1
2494      var j = f.Y();
2495      return j % 4 === 0 & j % 100 !== 0 | j % 400 === 0;
2496    },
2497    o: function() { // ISO-8601 year
2498      var n = f.n();
2499      var W = f.W();
2500      var Y = f.Y();
2501      return Y + (n === 12 && W < 9 ? 1 : n === 1 && W > 9 ? -1 : 0);
2502    },
2503    Y: function() { // Full year; e.g. 1980...2010
2504      return jsdate.getFullYear();
2505    },
2506    y: function() { // Last two digits of year; 00...99
2507      return f.Y()
2508        .toString()
2509        .slice(-2);
2510    },
2511
2512    // Time
2513    a: function() { // am or pm
2514      return jsdate.getHours() > 11 ? 'pm' : 'am';
2515    },
2516    A: function() { // AM or PM
2517      return f.a()
2518        .toUpperCase();
2519    },
2520    B: function() { // Swatch Internet time; 000..999
2521      var H = jsdate.getUTCHours() * 36e2;
2522      // Hours
2523      var i = jsdate.getUTCMinutes() * 60;
2524      // Minutes
2525      var s = jsdate.getUTCSeconds(); // Seconds
2526      return _pad(Math.floor((H + i + s + 36e2) / 86.4) % 1e3, 3);
2527    },
2528    g: function() { // 12-Hours; 1..12
2529      return f.G() % 12 || 12;
2530    },
2531    G: function() { // 24-Hours; 0..23
2532      return jsdate.getHours();
2533    },
2534    h: function() { // 12-Hours w/leading 0; 01..12
2535      return _pad(f.g(), 2);
2536    },
2537    H: function() { // 24-Hours w/leading 0; 00..23
2538      return _pad(f.G(), 2);
2539    },
2540    i: function() { // Minutes w/leading 0; 00..59
2541      return _pad(jsdate.getMinutes(), 2);
2542    },
2543    s: function() { // Seconds w/leading 0; 00..59
2544      return _pad(jsdate.getSeconds(), 2);
2545    },
2546    u: function() { // Microseconds; 000000-999000
2547      return _pad(jsdate.getMilliseconds() * 1000, 6);
2548    },
2549
2550    // Timezone
2551    e: function() { // Timezone identifier; e.g. Atlantic/Azores, ...
2552      // The following works, but requires inclusion of the very large
2553      // timezone_abbreviations_list() function.
2554      /*              return that.date_default_timezone_get();
2555       */
2556      throw 'Not supported (see source code of date() for timezone on how to add support)';
2557    },
2558    I: function() { // DST observed?; 0 or 1
2559      // Compares Jan 1 minus Jan 1 UTC to Jul 1 minus Jul 1 UTC.
2560      // If they are not equal, then DST is observed.
2561      var a = new Date(f.Y(), 0);
2562      // Jan 1
2563      var c = Date.UTC(f.Y(), 0);
2564      // Jan 1 UTC
2565      var b = new Date(f.Y(), 6);
2566      // Jul 1
2567      var d = Date.UTC(f.Y(), 6); // Jul 1 UTC
2568      return ((a - c) !== (b - d)) ? 1 : 0;
2569    },
2570    O: function() { // Difference to GMT in hour format; e.g. +0200
2571      var tzo = jsdate.getTimezoneOffset();
2572      var a = Math.abs(tzo);
2573      return (tzo > 0 ? '-' : '+') + _pad(Math.floor(a / 60) * 100 + a % 60, 4);
2574    },
2575    P: function() { // Difference to GMT w/colon; e.g. +02:00
2576      var O = f.O();
2577      return (O.substr(0, 3) + ':' + O.substr(3, 2));
2578    },
2579    T: function() { // Timezone abbreviation; e.g. EST, MDT, ...
2580      // The following works, but requires inclusion of the very
2581      // large timezone_abbreviations_list() function.
2582      /*              var abbr, i, os, _default;
2583      if (!tal.length) {
2584        tal = that.timezone_abbreviations_list();
2585      }
2586      if (that.php_js && that.php_js.default_timezone) {
2587        _default = that.php_js.default_timezone;
2588        for (abbr in tal) {
2589          for (i = 0; i < tal[abbr].length; i++) {
2590            if (tal[abbr][i].timezone_id === _default) {
2591              return abbr.toUpperCase();
2592            }
2593          }
2594        }
2595      }
2596      for (abbr in tal) {
2597        for (i = 0; i < tal[abbr].length; i++) {
2598          os = -jsdate.getTimezoneOffset() * 60;
2599          if (tal[abbr][i].offset === os) {
2600            return abbr.toUpperCase();
2601          }
2602        }
2603      }
2604      */
2605      return 'UTC';
2606    },
2607    Z: function() { // Timezone offset in seconds (-43200...50400)
2608      return -jsdate.getTimezoneOffset() * 60;
2609    },
2610
2611    // Full Date/Time
2612    c: function() { // ISO-8601 date.
2613      return 'Y-m-d\\TH:i:sP'.replace(formatChr, formatChrCb);
2614    },
2615    r: function() { // RFC 2822
2616      return 'D, d M Y H:i:s O'.replace(formatChr, formatChrCb);
2617    },
2618    U: function() { // Seconds since UNIX epoch
2619      return jsdate / 1000 | 0;
2620    }
2621  };
2622  this.date = function(format, timestamp) {
2623    that = this;
2624    jsdate = (timestamp === undefined ? new Date() : // Not provided
2625      (timestamp instanceof Date) ? new Date(timestamp) : // JS Date()
2626      new Date(timestamp * 1000) // UNIX timestamp (auto-convert to int)
2627    );
2628    return format.replace(formatChr, formatChrCb);
2629  };
2630  return this.date(format, timestamp);
2631}
2632
2633function intval(mixed_var, base) {
2634  //  discuss at: http://phpjs.org/functions/intval/
2635  // original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
2636  // improved by: stensi
2637  // bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
2638  // bugfixed by: Brett Zamir (http://brett-zamir.me)
2639  // bugfixed by: Rafał Kukawski (http://kukawski.pl)
2640  //    input by: Matteo
2641  //   example 1: intval('Kevin van Zonneveld');
2642  //   returns 1: 0
2643  //   example 2: intval(4.2);
2644  //   returns 2: 4
2645  //   example 3: intval(42, 8);
2646  //   returns 3: 42
2647  //   example 4: intval('09');
2648  //   returns 4: 9
2649  //   example 5: intval('1e', 16);
2650  //   returns 5: 30
2651
2652  var tmp;
2653
2654  var type = typeof mixed_var;
2655
2656  if (type === 'boolean') {
2657    return +mixed_var;
2658  } else if (type === 'string') {
2659    tmp = parseInt(mixed_var, base || 10);
2660    return (isNaN(tmp) || !isFinite(tmp)) ? 0 : tmp;
2661  } else if (type === 'number' && isFinite(mixed_var)) {
2662    return mixed_var | 0;
2663  } else {
2664    return 0;
2665  }
2666}
2667
2668
2669function strip_tags(input, allowed) {
2670  //  discuss at: http://phpjs.org/functions/strip_tags/
2671  // original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
2672  // improved by: Luke Godfrey
2673  // improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
2674  //    input by: Pul
2675  //    input by: Alex
2676  //    input by: Marc Palau
2677  //    input by: Brett Zamir (http://brett-zamir.me)
2678  //    input by: Bobby Drake
2679  //    input by: Evertjan Garretsen
2680  // bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
2681  // bugfixed by: Onno Marsman
2682  // bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
2683  // bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
2684  // bugfixed by: Eric Nagel
2685  // bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
2686  // bugfixed by: Tomasz Wesolowski
2687  //  revised by: Rafał Kukawski (http://blog.kukawski.pl/)
2688  //   example 1: strip_tags('<p>Kevin</p> <br /><b>van</b> <i>Zonneveld</i>', '<i><b>');
2689  //   returns 1: 'Kevin <b>van</b> <i>Zonneveld</i>'
2690  //   example 2: strip_tags('<p>Kevin <img src="someimage.png" onmouseover="someFunction()">van <i>Zonneveld</i></p>', '<p>');
2691  //   returns 2: '<p>Kevin van Zonneveld</p>'
2692  //   example 3: strip_tags("<a href='http://kevin.vanzonneveld.net'>Kevin van Zonneveld</a>", "<a>");
2693  //   returns 3: "<a href='http://kevin.vanzonneveld.net'>Kevin van Zonneveld</a>"
2694  //   example 4: strip_tags('1 < 5 5 > 1');
2695  //   returns 4: '1 < 5 5 > 1'
2696  //   example 5: strip_tags('1 <br/> 1');
2697  //   returns 5: '1  1'
2698  //   example 6: strip_tags('1 <br/> 1', '<br>');
2699  //   returns 6: '1 <br/> 1'
2700  //   example 7: strip_tags('1 <br/> 1', '<br><br/>');
2701  //   returns 7: '1 <br/> 1'
2702
2703  allowed = (((allowed || '') + '')
2704    .toLowerCase()
2705    .match(/<[a-z][a-z0-9]*>/g) || [])
2706    .join(''); // making sure the allowed arg is a string containing only tags in lowercase (<a><b><c>)
2707  var tags = /<\/?([a-z][a-z0-9]*)\b[^>]*>/gi,
2708    commentsAndPhpTags = /<!--[\s\S]*?-->|<\?(?:php)?[\s\S]*?\?>/gi;
2709  return input.replace(commentsAndPhpTags, '')
2710    .replace(tags, function($0, $1) {
2711      return allowed.indexOf('<' + $1.toLowerCase() + '>') > -1 ? $0 : '';
2712    });
2713}
2714
2715
2716function substr(str, start, len) {
2717  //  discuss at: http://phpjs.org/functions/substr/
2718  //     version: 909.322
2719  // original by: Martijn Wieringa
2720  // bugfixed by: T.Wild
2721  // improved by: Onno Marsman
2722  // improved by: Brett Zamir (http://brett-zamir.me)
2723  //  revised by: Theriault
2724  //        note: Handles rare Unicode characters if 'unicode.semantics' ini (PHP6) is set to 'on'
2725  //   example 1: substr('abcdef', 0, -1);
2726  //   returns 1: 'abcde'
2727  //   example 2: substr(2, 0, -6);
2728  //   returns 2: false
2729  //   example 3: ini_set('unicode.semantics',  'on');
2730  //   example 3: substr('a\uD801\uDC00', 0, -1);
2731  //   returns 3: 'a'
2732  //   example 4: ini_set('unicode.semantics',  'on');
2733  //   example 4: substr('a\uD801\uDC00', 0, 2);
2734  //   returns 4: 'a\uD801\uDC00'
2735  //   example 5: ini_set('unicode.semantics',  'on');
2736  //   example 5: substr('a\uD801\uDC00', -1, 1);
2737  //   returns 5: '\uD801\uDC00'
2738  //   example 6: ini_set('unicode.semantics',  'on');
2739  //   example 6: substr('a\uD801\uDC00z\uD801\uDC00', -3, 2);
2740  //   returns 6: '\uD801\uDC00z'
2741  //   example 7: ini_set('unicode.semantics',  'on');
2742  //   example 7: substr('a\uD801\uDC00z\uD801\uDC00', -3, -1)
2743  //   returns 7: '\uD801\uDC00z'
2744
2745  var i = 0,
2746    allBMP = true,
2747    es = 0,
2748    el = 0,
2749    se = 0,
2750    ret = '';
2751  str += '';
2752  var end = str.length;
2753
2754  // BEGIN REDUNDANT
2755  this.php_js = this.php_js || {};
2756  this.php_js.ini = this.php_js.ini || {};
2757  // END REDUNDANT
2758  switch ((this.php_js.ini['unicode.semantics'] && this.php_js.ini['unicode.semantics'].local_value.toLowerCase())) {
2759    case 'on':
2760      // Full-blown Unicode including non-Basic-Multilingual-Plane characters
2761      // strlen()
2762      for (i = 0; i < str.length; i++) {
2763        if (/[\uD800-\uDBFF]/.test(str.charAt(i)) && /[\uDC00-\uDFFF]/.test(str.charAt(i + 1))) {
2764          allBMP = false;
2765          break;
2766        }
2767      }
2768
2769      if (!allBMP) {
2770        if (start < 0) {
2771          for (i = end - 1, es = (start += end); i >= es; i--) {
2772            if (/[\uDC00-\uDFFF]/.test(str.charAt(i)) && /[\uD800-\uDBFF]/.test(str.charAt(i - 1))) {
2773              start--;
2774              es--;
2775            }
2776          }
2777        } else {
2778          var surrogatePairs = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g;
2779          while ((surrogatePairs.exec(str)) != null) {
2780            var li = surrogatePairs.lastIndex;
2781            if (li - 2 < start) {
2782              start++;
2783            } else {
2784              break;
2785            }
2786          }
2787        }
2788
2789        if (start >= end || start < 0) {
2790          return false;
2791        }
2792        if (len < 0) {
2793          for (i = end - 1, el = (end += len); i >= el; i--) {
2794            if (/[\uDC00-\uDFFF]/.test(str.charAt(i)) && /[\uD800-\uDBFF]/.test(str.charAt(i - 1))) {
2795              end--;
2796              el--;
2797            }
2798          }
2799          if (start > end) {
2800            return false;
2801          }
2802          return str.slice(start, end);
2803        } else {
2804          se = start + len;
2805          for (i = start; i < se; i++) {
2806            ret += str.charAt(i);
2807            if (/[\uD800-\uDBFF]/.test(str.charAt(i)) && /[\uDC00-\uDFFF]/.test(str.charAt(i + 1))) {
2808              se++; // Go one further, since one of the "characters" is part of a surrogate pair
2809            }
2810          }
2811          return ret;
2812        }
2813        break;
2814      }
2815      // Fall-through
2816    case 'off':
2817      // assumes there are no non-BMP characters;
2818      //    if there may be such characters, then it is best to turn it on (critical in true XHTML/XML)
2819    default:
2820      if (start < 0) {
2821        start += end;
2822      }
2823      end = typeof len === 'undefined' ? end : (len < 0 ? len + end : len + start);
2824      // PHP returns false if start does not fall within the string.
2825      // PHP returns false if the calculated end comes before the calculated start.
2826      // PHP returns an empty string if start and end are the same.
2827      // Otherwise, PHP returns the portion of the string from start to end.
2828      return start >= str.length || start < 0 || start > end ? !1 : str.slice(start, end);
2829  }
2830  return undefined; // Please Netbeans
2831}
2832
2833function base64_decode(data) {
2834  //  discuss at: http://phpjs.org/functions/base64_decode/
2835  // original by: Tyler Akins (http://rumkin.com)
2836  // improved by: Thunder.m
2837  // improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
2838  // improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
2839  //    input by: Aman Gupta
2840  //    input by: Brett Zamir (http://brett-zamir.me)
2841  // bugfixed by: Onno Marsman
2842  // bugfixed by: Pellentesque Malesuada
2843  // bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
2844  //   example 1: base64_decode('S2V2aW4gdmFuIFpvbm5ldmVsZA==');
2845  //   returns 1: 'Kevin van Zonneveld'
2846  //   example 2: base64_decode('YQ===');
2847  //   returns 2: 'a'
2848
2849  var b64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
2849+/=';
2850  var o1, o2, o3, h1, h2, h3, h4, bits, i = 0,
2851    ac = 0,
2852    dec = '',
2853    tmp_arr = [];
2854
2855  if (!data) {
2856    return data;
2857  }
2858
2859  data += '';
2860
2861  do { // unpack four hexets into three octets using index points in b64
2862    h1 = b64.indexOf(data.charAt(i++));
2863    h2 = b64.indexOf(data.charAt(i++));
2864    h3 = b64.indexOf(data.charAt(i++));
2865    h4 = b64.indexOf(data.charAt(i++));
2866
2867    bits = h1 << 18 | h2 << 12 | h3 << 6 | h4;
2868
2869    o1 = bits >> 16 & 0xff;
2870    o2 = bits >> 8 & 0xff;
2871    o3 = bits & 0xff;
2872
2873    if (h3 == 64) {
2874      tmp_arr[ac++] = String.fromCharCode(o1);
2875    } else if (h4 == 64) {
2876      tmp_arr[ac++] = String.fromCharCode(o1, o2);
2877    } else {
2878      tmp_arr[ac++] = String.fromCharCode(o1, o2, o3);
2879    }
2880  } while (i < data.length);
2881
2882  dec = tmp_arr.join('');
2883
2884  return dec.replace(/\0+$/, '');
2885}
2886
2887function base64_encode(data) {
2888  //  discuss at: http://phpjs.org/functions/base64_encode/
2889  // original by: Tyler Akins (http://rumkin.com)
2890  // improved by: Bayron Guevara
2891  // improved by: Thunder.m
2892  // improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
2893  // improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
2894  // improved by: Rafał Kukawski (http://kukawski.pl)
2895  // bugfixed by: Pellentesque Malesuada
2896  //   example 1: base64_encode('Kevin van Zonneveld');
2897  //   returns 1: 'S2V2aW4gdmFuIFpvbm5ldmVsZA=='
2898  //   example 2: base64_encode('a');
2899  //   returns 2: 'YQ=='
2900
2901  var b64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
2902  var o1, o2, o3, h1, h2, h3, h4, bits, i = 0,
2903    ac = 0,
2904    enc = '',
2905    tmp_arr = [];
2906
2907  if (!data) {
2908    return data;
2909  }
2910
2911  do { // pack three octets into four hexets
2912    o1 = data.charCodeAt(i++);
2913    o2 = data.charCodeAt(i++);
2914    o3 = data.charCodeAt(i++);
2915
2916    bits = o1 << 16 | o2 << 8 | o3;
2917
2918    h1 = bits >> 18 & 0x3f;
2919    h2 = bits >> 12 & 0x3f;
2920    h3 = bits >> 6 & 0x3f;
2921    h4 = bits & 0x3f;
2922
2923    // use hexets to index into b64, and append result to encoded string
2924    tmp_arr[ac++] = b64.charAt(h1) + b64.charAt(h2) + b64.charAt(h3) + b64.charAt(h4);
2925  } while (i < data.length);
2926
2927  enc = tmp_arr.join('');
2928
2929  var r = data.length % 3;
2930
2931  return (r ? enc.slice(0, r - 3) : enc) + '==='.slice(r || 3);
2932}
2933
2934function array_push(inputArr) {
2935  //  discuss at: http://phpjs.org/functions/array_push/
2936  // original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
2937  // improved by: Brett Zamir (http://brett-zamir.me)
2938  //        note: Note also that IE retains information about property position even
2939  //        note: after being supposedly deleted, so if you delete properties and then
2940  //        note: add back properties with the same keys (including numeric) that had
2941  //        note: been deleted, the order will be as before; thus, this function is not
2942  //        note: really recommended with associative arrays (objects) in IE environments
2943  //   example 1: array_push(['kevin','van'], 'zonneveld');
2944  //   returns 1: 3
2945
2946  var i = 0,
2947    pr = '',
2948    argv = arguments,
2949    argc = argv.length,
2950    allDigits = /^\d$/,
2951    size = 0,
2952    highestIdx = 0,
2953    len = 0;
2954  if (inputArr.hasOwnProperty('length')) {
2955    for (i = 1; i < argc; i++) {
2956      inputArr[inputArr.length] = argv[i];
2957    }
2958    return inputArr.length;
2959  }
2960
2961  // Associative (object)
2962  for (pr in inputArr) {
2963    if (inputArr.hasOwnProperty(pr)) {
2964      ++len;
2965      if (pr.search(allDigits) !== -1) {
2966        size = parseInt(pr, 10);
2967        highestIdx = size > highestIdx ? size : highestIdx;
2968      }
2969    }
2970  }
2971  for (i = 1; i < argc; i++) {
2972    inputArr[++highestIdx] = argv[i];
2973  }
2974  return len + i - 1;
2975}
2976
2977function array_pop(inputArr) {
2978  //  discuss at: http://phpjs.org/functions/array_pop/
2979  // original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
2980  // improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
2981  //    input by: Brett Zamir (http://brett-zamir.me)
2982  //    input by: Theriault
2983  // bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
2984  // bugfixed by: Brett Zamir (http://brett-zamir.me)
2985  //        note: While IE (and other browsers) support iterating an object's
2986  //        note: own properties in order, if one attempts to add back properties
2987  //        note: in IE, they may end up in their former position due to their position
2988  //        note: being retained. So use of this function with "associative arrays"
2989  //        note: (objects) may lead to unexpected behavior in an IE environment if
2990  //        note: you add back properties with the same keys that you removed
2991  //   example 1: array_pop([0,1,2]);
2992  //   returns 1: 2
2993  //   example 2: data = {firstName: 'Kevin', surName: 'van Zonneveld'};
2994  //   example 2: lastElem = array_pop(data);
2995  //   example 2: $result = data
2996  //   returns 2: {firstName: 'Kevin'}
2997
2998  var key = '',
2999    lastKey = '';
3000
3001  if (inputArr.hasOwnProperty('length')) {
3002    // Indexed
3003    if (!inputArr.length) {
3004      // Done popping, are we?
3005      return null;
3006    }
3007    return inputArr.pop();
vendor: 11,744 bytes, lines 3008-3344
3008  } else {
3009    // Associative
3010    for (key in inputArr) {
3011      if (inputArr.hasOwnProperty(key)) {
3012        lastKey = key;
3013      }
3014    }
3015    if (lastKey) {
3016      var tmp = inputArr[lastKey];
3017      delete(inputArr[lastKey]);
3018      return tmp;
3019    } else {
3020      return null;
3021    }
3022  }
3023}
3024
3025function array_shift(inputArr) {
3026  //  discuss at: http://phpjs.org/functions/array_shift/
3027  // original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
3028  // improved by: Martijn Wieringa
3029  //        note: Currently does not handle objects
3030  //   example 1: array_shift(['Kevin', 'van', 'Zonneveld']);
3031  //   returns 1: 'Kevin'
3032
3033  var props = false,
3034    shift = undefined,
3035    pr = '',
3036    allDigits = /^\d$/,
3037    int_ct = -1,
3038    _checkToUpIndices = function(arr, ct, key) {
3039      // Deal with situation, e.g., if encounter index 4 and try to set it to 0, but 0 exists later in loop (need to
3040      // increment all subsequent (skipping current key, since we need its value below) until find unused)
3041      if (arr[ct] !== undefined) {
3042        var tmp = ct;
3043        ct += 1;
3044        if (ct === key) {
3045          ct += 1;
3046        }
3047        ct = _checkToUpIndices(arr, ct, key);
3048        arr[ct] = arr[tmp];
3049        delete arr[tmp];
3050      }
3051      return ct;
3052    };
3053
3054  if (inputArr.length === 0) {
3055    return null;
3056  }
3057  if (inputArr.length > 0) {
3058    return inputArr.shift();
3059  }
3060
3061  /*
3062  UNFINISHED FOR HANDLING OBJECTS
3063  for (pr in inputArr) {
3064    if (inputArr.hasOwnProperty(pr)) {
3065      props = true;
3066      shift = inputArr[pr];
3067      delete inputArr[pr];
3068      break;
3069    }
3070  }
3071  for (pr in inputArr) {
3072    if (inputArr.hasOwnProperty(pr)) {
3073      if (pr.search(allDigits) !== -1) {
3074        int_ct += 1;
3075        if (parseInt(pr, 10) === int_ct) { // Key is already numbered ok, so don't need to change key for value
3076          continue;
3077        }
3078        _checkToUpIndices(inputArr, int_ct, pr);
3079        arr[int_ct] = arr[pr];
3080        delete arr[pr];
3081      }
3082    }
3083  }
3084  if (!props) {
3085    return null;
3086  }
3087  return shift;
3088  */
3089}
3090
3091function str_replace(search, replace, subject, count) {
3092  //  discuss at: http://phpjs.org/functions/str_replace/
3093  // original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
3094  // improved by: Gabriel Paderni
3095  // improved by: Philip Peterson
3096  // improved by: Simon Willison (http://simonwillison.net)
3097  // improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
3098  // improved by: Onno Marsman
3099  // improved by: Brett Zamir (http://brett-zamir.me)
3100  //  revised by: Jonas Raoni Soares Silva (http://www.jsfromhell.com)
3101  // bugfixed by: Anton Ongson
3102  // bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
3103  // bugfixed by: Oleg Eremeev
3104  //    input by: Onno Marsman
3105  //    input by: Brett Zamir (http://brett-zamir.me)
3106  //    input by: Oleg Eremeev
3107  //        note: The count parameter must be passed as a string in order
3108  //        note: to find a global variable in which the result will be given
3109  //   example 1: str_replace(' ', '.', 'Kevin van Zonneveld');
3110  //   returns 1: 'Kevin.van.Zonneveld'
3111  //   example 2: str_replace(['{name}', 'l'], ['hello', 'm'], '{name}, lars');
3112  //   returns 2: 'hemmo, mars'
3113
3114  var i = 0,
3115    j = 0,
3116    temp = '',
3117    repl = '',
3118    sl = 0,
3119    fl = 0,
3120    f = [].concat(search),
3121    r = [].concat(replace),
3122    s = subject,
3123    ra = Object.prototype.toString.call(r) === '[object Array]',
3124    sa = Object.prototype.toString.call(s) === '[object Array]';
3125  s = [].concat(s);
3126  if (count) {
3127    this.window[count] = 0;
3128  }
3129
3130  for (i = 0, sl = s.length; i < sl; i++) {
3131    if (s[i] === '') {
3132      continue;
3133    }
3134    for (j = 0, fl = f.length; j < fl; j++) {
3135      temp = s[i] + '';
3136      repl = ra ? (r[j] !== undefined ? r[j] : '') : r[0];
3137      s[i] = (temp)
3138        .split(f[j])
3139        .join(repl);
3140      if (count && s[i] !== temp) {
3141        this.window[count] += (temp.length - s[i].length) / f[j].length;
3142      }
3143    }
3144  }
3145  return sa ? s : s[0];
3146}
3147
3148function strlen(string) {
3149  //  discuss at: http://phpjs.org/functions/strlen/
3150  // original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
3151  // improved by: Sakimori
3152  // improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
3153  //    input by: Kirk Strobeck
3154  // bugfixed by: Onno Marsman
3155  //  revised by: Brett Zamir (http://brett-zamir.me)
3156  //        note: May look like overkill, but in order to be truly faithful to handling all Unicode
3157  //        note: characters and to this function in PHP which does not count the number of bytes
3158  //        note: but counts the number of characters, something like this is really necessary.
3159  //   example 1: strlen('Kevin van Zonneveld');
3160  //   returns 1: 19
3161  //   example 2: ini_set('unicode.semantics', 'on');
3162  //   example 2: strlen('A\ud87e\udc04Z');
3163  //   returns 2: 3
3164
3165  var str = string + '';
3166  var i = 0,
3167    chr = '',
3168    lgth = 0;
3169
3170  if (!this.php_js || !this.php_js.ini || !this.php_js.ini['unicode.semantics'] || this.php_js.ini[
3171    'unicode.semantics'].local_value.toLowerCase() !== 'on') {
3172    return string.length;
3173  }
3174
3175  var getWholeChar = function(str, i) {
3176    var code = str.charCodeAt(i);
3177    var next = '',
3178      prev = '';
3179    if (0xD800 <= code && code <= 0xDBFF) { // High surrogate (could change last hex to 0xDB7F to treat high private surrogates as single characters)
3180      if (str.length <= (i + 1)) {
3181        throw 'High surrogate without following low surrogate';
3182      }
3183      next = str.charCodeAt(i + 1);
3184      if (0xDC00 > next || next > 0xDFFF) {
3185        throw 'High surrogate without following low surrogate';
3186      }
3187      return str.charAt(i) + str.charAt(i + 1);
3188    } else if (0xDC00 <= code && code <= 0xDFFF) { // Low surrogate
3189      if (i === 0) {
3190        throw 'Low surrogate without preceding high surrogate';
3191      }
3192      prev = str.charCodeAt(i - 1);
3193      if (0xD800 > prev || prev > 0xDBFF) { //(could change last hex to 0xDB7F to treat high private surrogates as single characters)
3194        throw 'Low surrogate without preceding high surrogate';
3195      }
3196      return false; // We can pass over low surrogates now as the second component in a pair which we have already processed
3197    }
3198    return str.charAt(i);
3199  };
3200
3201  for (i = 0, lgth = 0; i < str.length; i++) {
3202    if ((chr = getWholeChar(str, i)) === false) {
3203      continue;
3204    } // Adapt this line at the top of any loop, passing in the whole string and the current iteration and returning a variable to represent the individual character; purpose is to treat the first part of a surrogate pair as the whole character and then ignore the second part
3205    lgth++;
3206  }
3207  return lgth;
3208}
3209
3210function strpos(haystack, needle, offset) {
3211  //  discuss at: http://phpjs.org/functions/strpos/
3212  // original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
3213  // improved by: Onno Marsman
3214  // improved by: Brett Zamir (http://brett-zamir.me)
3215  // bugfixed by: Daniel Esteban
3216  //   example 1: strpos('Kevin van Zonneveld', 'e', 5);
3217  //   returns 1: 14
3218
3219  var i = (haystack + '')
3220    .indexOf(needle, (offset || 0));
3221  return i === -1 ? false : i;
3222}
3223
3224function substr(str, start, len) {
3225  //  discuss at: http://phpjs.org/functions/substr/
3226  //     version: 909.322
3227  // original by: Martijn Wieringa
3228  // bugfixed by: T.Wild
3229  // improved by: Onno Marsman
3230  // improved by: Brett Zamir (http://brett-zamir.me)
3231  //  revised by: Theriault
3232  //        note: Handles rare Unicode characters if 'unicode.semantics' ini (PHP6) is set to 'on'
3233  //   example 1: substr('abcdef', 0, -1);
3234  //   returns 1: 'abcde'
3235  //   example 2: substr(2, 0, -6);
3236  //   returns 2: false
3237  //   example 3: ini_set('unicode.semantics',  'on');
3238  //   example 3: substr('a\uD801\uDC00', 0, -1);
3239  //   returns 3: 'a'
3240  //   example 4: ini_set('unicode.semantics',  'on');
3241  //   example 4: substr('a\uD801\uDC00', 0, 2);
3242  //   returns 4: 'a\uD801\uDC00'
3243  //   example 5: ini_set('unicode.semantics',  'on');
3244  //   example 5: substr('a\uD801\uDC00', -1, 1);
3245  //   returns 5: '\uD801\uDC00'
3246  //   example 6: ini_set('unicode.semantics',  'on');
3247  //   example 6: substr('a\uD801\uDC00z\uD801\uDC00', -3, 2);
3248  //   returns 6: '\uD801\uDC00z'
3249  //   example 7: ini_set('unicode.semantics',  'on');
3250  //   example 7: substr('a\uD801\uDC00z\uD801\uDC00', -3, -1)
3251  //   returns 7: '\uD801\uDC00z'
3252
3253  var i = 0,
3254    allBMP = true,
3255    es = 0,
3256    el = 0,
3257    se = 0,
3258    ret = '';
3259  str += '';
3260  var end = str.length;
3261
3262  // BEGIN REDUNDANT
3263  this.php_js = this.php_js || {};
3264  this.php_js.ini = this.php_js.ini || {};
3265  // END REDUNDANT
3266  switch ((this.php_js.ini['unicode.semantics'] && this.php_js.ini['unicode.semantics'].local_value.toLowerCase())) {
3267    case 'on':
3268      // Full-blown Unicode including non-Basic-Multilingual-Plane characters
3269      // strlen()
3270      for (i = 0; i < str.length; i++) {
3271        if (/[\uD800-\uDBFF]/.test(str.charAt(i)) && /[\uDC00-\uDFFF]/.test(str.charAt(i + 1))) {
3272          allBMP = false;
3273          break;
3274        }
3275      }
3276
3277      if (!allBMP) {
3278        if (start < 0) {
3279          for (i = end - 1, es = (start += end); i >= es; i--) {
3280            if (/[\uDC00-\uDFFF]/.test(str.charAt(i)) && /[\uD800-\uDBFF]/.test(str.charAt(i - 1))) {
3281              start--;
3282              es--;
3283            }
3284          }
3285        } else {
3286          var surrogatePairs = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g;
3287          while ((surrogatePairs.exec(str)) != null) {
3288            var li = surrogatePairs.lastIndex;
3289            if (li - 2 < start) {
3290              start++;
3291            } else {
3292              break;
3293            }
3294          }
3295        }
3296
3297        if (start >= end || start < 0) {
3298          return false;
3299        }
3300        if (len < 0) {
3301          for (i = end - 1, el = (end += len); i >= el; i--) {
3302            if (/[\uDC00-\uDFFF]/.test(str.charAt(i)) && /[\uD800-\uDBFF]/.test(str.charAt(i - 1))) {
3303              end--;
3304              el--;
3305            }
3306          }
3307          if (start > end) {
3308            return false;
3309          }
3310          return str.slice(start, end);
3311        } else {
3312          se = start + len;
3313          for (i = start; i < se; i++) {
3314            ret += str.charAt(i);
3315            if (/[\uD800-\uDBFF]/.test(str.charAt(i)) && /[\uDC00-\uDFFF]/.test(str.charAt(i + 1))) {
3316              se++; // Go one further, since one of the "characters" is part of a surrogate pair
3317            }
3318          }
3319          return ret;
3320        }
3321        break;
3322      }
3323      // Fall-through
3324    case 'off':
3325      // assumes there are no non-BMP characters;
3326      //    if there may be such characters, then it is best to turn it on (critical in true XHTML/XML)
3327    default:
3328      if (start < 0) {
3329        start += end;
3330      }
3331      end = typeof len === 'undefined' ? end : (len < 0 ? len + end : len + start);
3332      // PHP returns false if start does not fall within the string.
3333      // PHP returns false if the calculated end comes before the calculated start.
3334      // PHP returns an empty string if start and end are the same.
3335      // Otherwise, PHP returns the portion of the string from start to end.
3336      return start >= str.length || start < 0 || start > end ? !1 : str.slice(start, end);
3337  }
3338  return undefined; // Please Netbeans
3339}
3340
3341function basename(path, suffix) {
3342  //  discuss at: http://phpjs.org/functions/basename/
3343  // original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
3344  // improved by: Ash Searle (http://hexmen.com/blog/)
3345  // improved by: Lincoln Ramsay
3346  // improved by: djmix
3347  // improved by: Dmitry Gorelenkov
3348  //   example 1: basename('/www/site/home.htm', '.htm');
3349  //   returns 1: 'home'
3350  //   example 2: basename('ecra.php?p=1');
3351  //   returns 2: 'ecra.php?p=1'
3352  //   example 3: basename('/some/path/');
3353  //   returns 3: 'path'
3354  //   example 4: basename('/some/path_ext.ext/','.ext');
3355  //   returns 4: 'path_ext'
3356
3357  var b = path;
3358  var lastChar = b.charAt(b.length - 1);
3359
3360  if (lastChar === '/' || lastChar === '\\') {
3361    b = b.slice(0, -1);
3362  }
3363
3364  b = b.replace(/^.*[\/\\]/g, '');
3365
3366  if (typeof suffix === 'string' && b.substr(b.length - suffix.length) == suffix) {
3367    b = b.substr(0, b.length - suffix.length);
3368  }
3369
3370  return b;
3371}
3372
3373function dirname(path) {
3374  //  discuss at: http://phpjs.org/functions/dirname/
3375  //        http: //kevin.vanzonneveld.net
3376  // original by: Ozh
3377  // improved by: XoraX (http://www.xorax.info)
3378  //   example 1: dirname('/etc/passwd');
3379  //   returns 1: '/etc'
3380  //   example 2: dirname('c:/Temp/x');
3381  //   returns 2: 'c:/Temp'
3382  //   example 3: dirname('/dir/test/');
3383  //   returns 3: '/dir'
3384
3385  return path.replace(/\\/g, '/')
3386    .replace(/\/[^\/]*\/?$/, '');
3387}
3388
3389function realpath(path) {
3390  //  discuss at: http://phpjs.org/functions/realpath/
3391  // original by: mk.keck
3392  // improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
3393  //        note: Returned path is an url like e.g. 'http://yourhost.tld/path/'
3394  //   example 1: realpath('../.././_supporters/pj_test_supportfile_1.htm');
3395  //   returns 1: 'file:/home/kevin/workspace/_supporters/pj_test_supportfile_1.htm'
3396
3397  var p = 0,
3398    arr = []; /* Save the root, if not given */
3399  var r = this.window.location.href; /* Avoid input failures */
3400  path = (path + '')
3401    .replace('\\', '/'); /* Check if there's a port in path (like 'http://') */
3402  if (path.indexOf('://') !== -1) {
3403    p = 1;
3404  } /* Ok, there's not a port in path, so let's take the root */
3405  if (!p) {
3406    path = r.substring(0, r.lastIndexOf('/') + 1) + path;
3407  } /* Explode the given path into it's parts */
3408  arr = path.split('/'); /* The path is an array now */
3409  path = []; /* Foreach part make a check */
3410  for (var k in arr) { /* This is'nt really interesting */
3411    if (arr[k] == '.') {
3412      continue;
3413    } /* This reduces the realpath */
3414    if (arr[k] == '..') {
3415      /* But only if there more than 3 parts in the path-array.
3416       * The first three parts are for the uri */
3417      if (path.length > 3) {
3418        path.pop();
3419      }
3420    } /* This adds parts to the realpath */
3421    else {
3422      /* But only if the part is not empty or the uri
3423       * (the first three parts ar needed) was not
3424       * saved */
3425      if ((path.length < 2) || (arr[k] !== '')) {
3426        path.push(arr[k]);
3427      }
3428    }
3429  } /* Returns the absloute path as a string */
3430  return path.join('/');
3431}
3432
3433function htmlspecialchars_decode(string, quote_style) {
3434  //       discuss at: http://phpjs.org/functions/htmlspecialchars_decode/
3435  //      original by: Mirek Slugen
3436  //      improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
3437  //      bugfixed by: Mateusz "loonquawl" Zalega
3438  //      bugfixed by: Onno Marsman
3439  //      bugfixed by: Brett Zamir (http://brett-zamir.me)
3440  //      bugfixed by: Brett Zamir (http://brett-zamir.me)
3441  //         input by: ReverseSyntax
3442  //         input by: Slawomir Kaniecki
3443  //         input by: Scott Cariss
3444  //         input by: Francois
3445  //         input by: Ratheous
3446  //         input by: Mailfaker (http://www.weedem.fr/)
3447  //       revised by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
3448  // reimplemented by: Brett Zamir (http://brett-zamir.me)
3449  //        example 1: htmlspecialchars_decode("<p>this -&gt; &quot;</p>", 'ENT_NOQUOTES');
3450  //        returns 1: '<p>this -> &quot;</p>'
3451  //        example 2: htmlspecialchars_decode("&amp;quot;");
3452  //        returns 2: '&quot;'
3453
3454  var optTemp = 0,
3455    i = 0,
3456    noquotes = false;
3457  if (typeof quote_style === 'undefined') {
3458    quote_style = 2;
3459  }
3460if(typeof string=='undefined') {return false;}
3461  string = string.toString();
3462  string =string.replace(/&lt;/g, '<').replace(/&gt;/g, '>');
3463  var OPTS = {
3464    'ENT_NOQUOTES'          : 0,
3465    'ENT_HTML_QUOTE_SINGLE' : 1,
3466    'ENT_HTML_QUOTE_DOUBLE' : 2,
3467    'ENT_COMPAT'            : 2,
3468    'ENT_QUOTES'            : 3,
3469    'ENT_IGNORE'            : 4
3470  };
3471  if (quote_style === 0) {
3472    noquotes = true;
3473  }
3474  if (typeof quote_style !== 'number') {
vendor: 9,103 bytes, lines 3475-3731
3475    // Allow for a single string or an array of string flags
3476    quote_style = [].concat(quote_style);
3477    for (i = 0; i < quote_style.length; i++) {
3478      // Resolve string input to bitwise e.g. 'PATHINFO_EXTENSION' becomes 4
3479      if (OPTS[quote_style[i]] === 0) {
3480        noquotes = true;
3481      } else if (OPTS[quote_style[i]]) {
3482        optTemp = optTemp | OPTS[quote_style[i]];
3483      }
3484    }
3485    quote_style = optTemp;
3486  }
3487  if (quote_style & OPTS.ENT_HTML_QUOTE_SINGLE) {
3488    string = string.replace(/&#0*39;/g, "'"); // PHP doesn't currently escape if more than one 0, but it should
3489    // string = string.replace(/&apos;|&#x0*27;/g, "'"); // This would also be useful here, but not a part of PHP
3490  }
3491  if (!noquotes) {
3492    string = string.replace(/&quot;/g, '"');
3493  }
3494  // Put this in last place to avoid escape being double-decoded
3495  string = string.replace(/&amp;/g, '&');
3496
3497  return string;
3498}
3499
3500function round(value, precision, mode) {
3501  //  discuss at: http://phpjs.org/functions/round/
3502  // original by: Philip Peterson
3503  //  revised by: Onno Marsman
3504  //  revised by: T.Wild
3505  //  revised by: Rafał Kukawski (http://blog.kukawski.pl/)
3506  //    input by: Greenseed
3507  //    input by: meo
3508  //    input by: William
3509  //    input by: Josep Sanz (http://www.ws3.es/)
3510  // bugfixed by: Brett Zamir (http://brett-zamir.me)
3511  //        note: Great work. Ideas for improvement:
3512  //        note: - code more compliant with developer guidelines
3513  //        note: - for implementing PHP constant arguments look at
3514  //        note: the pathinfo() function, it offers the greatest
3515  //        note: flexibility & compatibility possible
3516  //   example 1: round(1241757, -3);
3517  //   returns 1: 1242000
3518  //   example 2: round(3.6);
3519  //   returns 2: 4
3520  //   example 3: round(2.835, 2);
3521  //   returns 3: 2.84
3522  //   example 4: round(1.1749999999999, 2);
3523  //   returns 4: 1.17
3524  //   example 5: round(58551.799999999996, 2);
3525  //   returns 5: 58551.8
3526
3527  var m, f, isHalf, sgn; // helper variables
3528  // making sure precision is integer
3529  precision |= 0;
3530  m = Math.pow(10, precision);
3531  value *= m;
3532  // sign of the number
3533  sgn = (value > 0) | -(value < 0);
3534  isHalf = value % 1 === 0.5 * sgn;
3535  f = Math.floor(value);
3536
3537  if (isHalf) {
3538    switch (mode) {
3539    case 'PHP_ROUND_HALF_DOWN':
3540      // rounds .5 toward zero
3541      value = f + (sgn < 0);
3542      break;
3543    case 'PHP_ROUND_HALF_EVEN':
3544      // rouds .5 towards the next even integer
3545      value = f + (f % 2 * sgn);
3546      break;
3547    case 'PHP_ROUND_HALF_ODD':
3548      // rounds .5 towards the next odd integer
3549      value = f + !(f % 2);
3550      break;
3551    default:
3552      // rounds .5 away from zero
3553      value = f + (sgn > 0);
3554    }
3555  }
3556
3557  return (isHalf ? value : Math.round(value)) / m;
3558}
3559
3560function json_encode(mixed_val) {
3561  //       discuss at: http://phpjs.org/functions/json_encode/
3562  //      original by: Public Domain (http://www.json.org/json2.js)
3563  // reimplemented by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
3564  //      improved by: Michael White
3565  //         input by: felix
3566  //      bugfixed by: Brett Zamir (http://brett-zamir.me)
3567  //        example 1: json_encode('Kevin');
3568  //        returns 1: '"Kevin"'
3569
3570  /*
3571    http://www.JSON.org/json2.js
3572    2008-11-19
3573    Public Domain.
3574    NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
3575    See http://www.JSON.org/js.html
3576  */
3577  var retVal, json = this.window.JSON;
3578  try {
3579    if (typeof json === 'object' && typeof json.stringify === 'function') {
3580      retVal = json.stringify(mixed_val); // Errors will not be caught here if our own equivalent to resource
3581      //  (an instance of PHPJS_Resource) is used
3582      if (retVal === undefined) {
3583        throw new SyntaxError('json_encode');
3584      }
3585      return retVal;
3586    }
3587
3588    var value = mixed_val;
3589
3590    var quote = function(string) {
3591      var escapable =
3592        /[\\\"\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
3593      var meta = { // table of character substitutions
3594        '\b': '\\b',
3595        '\t': '\\t',
3596        '\n': '\\n',
3597        '\f': '\\f',
3598        '\r': '\\r',
3599        '"': '\\"',
3600        '\\': '\\\\'
3601      };
3602
3603      escapable.lastIndex = 0;
3604      return escapable.test(string) ? '"' + string.replace(escapable, function(a) {
3605        var c = meta[a];
3606        return typeof c === 'string' ? c : '\\u' + ('0000' + a.charCodeAt(0)
3607          .toString(16))
3608          .slice(-4);
3609      }) + '"' : '"' + string + '"';
3610    };
3611
3612    var str = function(key, holder) {
3613      var gap = '';
3614      var indent = '    ';
3615      var i = 0; // The loop counter.
3616      var k = ''; // The member key.
3617      var v = ''; // The member value.
3618      var length = 0;
3619      var mind = gap;
3620      var partial = [];
3621      var value = holder[key];
3622
3623      // If the value has a toJSON method, call it to obtain a replacement value.
3624      if (value && typeof value === 'object' && typeof value.toJSON === 'function') {
3625        value = value.toJSON(key);
3626      }
3627
3628      // What happens next depends on the value's type.
3629      switch (typeof value) {
3630        case 'string':
3631          return quote(value);
3632
3633        case 'number':
3634          // JSON numbers must be finite. Encode non-finite numbers as null.
3635          return isFinite(value) ? String(value) : 'null';
3636
3637        case 'boolean':
3638        case 'null':
3639          // If the value is a boolean or null, convert it to a string. Note:
3640          // typeof null does not produce 'null'. The case is included here in
3641          // the remote chance that this gets fixed someday.
3642          return String(value);
3643
3644        case 'object':
3645          // If the type is 'object', we might be dealing with an object or an array or
3646          // null.
3647          // Due to a specification blunder in ECMAScript, typeof null is 'object',
3648          // so watch out for that case.
3649          if (!value) {
3650            return 'null';
3651          }
3652          if ((this.PHPJS_Resource && value instanceof this.PHPJS_Resource) || (window.PHPJS_Resource &&
3653            value instanceof window.PHPJS_Resource)) {
3654            throw new SyntaxError('json_encode');
3655          }
3656
3657          // Make an array to hold the partial results of stringifying this object value.
3658          gap += indent;
3659          partial = [];
3660
3661          // Is the value an array?
3662          if (Object.prototype.toString.apply(value) === '[object Array]') {
3663            // The value is an array. Stringify every element. Use null as a placeholder
3664            // for non-JSON values.
3665            length = value.length;
3666            for (i = 0; i < length; i += 1) {
3667              partial[i] = str(i, value) || 'null';
3668            }
3669
3670            // Join all of the elements together, separated with commas, and wrap them in
3671            // brackets.
3672            v = partial.length === 0 ? '[]' : gap ? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind +
3673              ']' : '[' + partial.join(',') + ']';
3674            gap = mind;
3675            return v;
3676          }
3677
3678          // Iterate through all of the keys in the object.
3679          for (k in value) {
3680            if (Object.hasOwnProperty.call(value, k)) {
3681              v = str(k, value);
3682              if (v) {
3683                partial.push(quote(k) + (gap ? ': ' : ':') + v);
3684              }
3685            }
3686          }
3687
3688          // Join all of the member texts together, separated with commas,
3689          // and wrap them in braces.
3690          v = partial.length === 0 ? '{}' : gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' :
3691            '{' + partial.join(',') + '}';
3692          gap = mind;
3693          return v;
3694        case 'undefined':
3695          // Fall-through
3696        case 'function':
3697          // Fall-through
3698        default:
3699          throw new SyntaxError('json_encode');
3700      }
3701    };
3702
3703    // Make a fake root object containing our value under the key of ''.
3704    // Return the result of stringifying the value.
3705    return str('', {
3706      '': value
3707    });
3708
3709  } catch (err) { // Todo: ensure error handling above throws a SyntaxError in all cases where it could
3710    // (i.e., when the JSON global is not available and there is an error)
3711    if (!(err instanceof SyntaxError)) {
3712      throw new Error('Unexpected error type in json_encode()');
3713    }
3714    this.php_js = this.php_js || {};
3715    this.php_js.last_error_json = 4; // usable by json_last_error()
3716    return null;
3717  }
3718}
3719
3720function json_decode(str_json) {
3721  //       discuss at: http://phpjs.org/functions/json_decode/
3722  //      original by: Public Domain (http://www.json.org/json2.js)
3723  // reimplemented by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
3724  //      improved by: T.J. Leahy
3725  //      improved by: Michael White
3726  //        example 1: json_decode('[ 1 ]');
3727  //        returns 1: [1]
3728
3729  /*
3730    http://www.JSON.org/json2.js
3731    2008-11-19
3732    Public Domain.
3733    NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
3734    See http://www.JSON.org/js.html
3735  */
3736
3737  var json = this.window.JSON;
3738  if (typeof json === 'object' && typeof json.parse === 'function') {
3739    try {
3740      return json.parse(str_json);
3741    } catch (err) {
3742      if (!(err instanceof SyntaxError)) {
3743        throw new Error('Unexpected error type in json_decode()');
3744      }
3745      this.php_js = this.php_js || {};
3746      this.php_js.last_error_json = 4; // usable by json_last_error()
3747      return null;
3748    }
3749  }
3750
3751  var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
3752  var j;
3753  var text = str_json;
3754
3755  // Parsing happens in four stages. In the first stage, we replace certain
3756  // Unicode characters with escape sequences. JavaScript handles many characters
3757  // incorrectly, either silently deleting them, or treating them as line endings.
3758  cx.lastIndex = 0;
3759  if (cx.test(text)) {
3760    text = text.replace(cx, function(a) {
3761      return '\\u' + ('0000' + a.charCodeAt(0)
3762        .toString(16))
3763        .slice(-4);
3764    });
3765  }
3766
3767  // In the second stage, we run the text against regular expressions that look
3768  // for non-JSON patterns. We are especially concerned with '()' and 'new'
3769  // because they can cause invocation, and '=' because it can cause mutation.
3770  // But just to be safe, we want to reject all unexpected forms.
3771  // We split the second stage into 4 regexp operations in order to work around
3772  // crippling inefficiencies in IE's and Safari's regexp engines. First we
3773  // replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
3774  // replace all simple value tokens with ']' characters. Third, we delete all
3775  // open brackets that follow a colon or comma or that begin the text. Finally,
3776  // we look to see that the remaining characters are only whitespace or ']' or
3777  // ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
3778  if ((/^[\],:{}\s]*$/)
3779    .test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
3780      .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
3781      .replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
3782
3783    // In the third stage we use the eval function to compile the text into a
3784    // JavaScript structure. The '{' operator is subject to a syntactic ambiguity
3785    // in JavaScript: it can begin a block or an object literal. We wrap the text
3786    // in parens to eliminate the ambiguity.
3787    j = eval('(' + text + ')');
3788
3789    return j;
3790  }
3791
3792  this.php_js = this.php_js || {};
3793  this.php_js.last_error_json = 4; // usable by json_last_error()
3794  return null;
3795}
3796
3797function array_search(needle, haystack, argStrict) {
3798  //  discuss at: http://phpjs.org/functions/array_search/
3799  // original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
3800  //    input by: Brett Zamir (http://brett-zamir.me)
3801  // bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
3802  //  depends on: array
3803  //        test: skip
3804  //   example 1: array_search('zonneveld', {firstname: 'kevin', middle: 'van', surname: 'zonneveld'});
3805  //   returns 1: 'surname'
3806  //   example 2: ini_set('phpjs.return_phpjs_arrays', 'on');
3807  //   example 2: var ordered_arr = array({3:'value'}, {2:'value'}, {'a':'value'}, {'b':'value'});
3808  //   example 2: var key = array_search(/val/g, ordered_arr); // or var key = ordered_arr.search(/val/g);
3809  //   returns 2: '3'
3810
3811  var strict = !! argStrict,
3812    key = '';
3813
3814  if (haystack && typeof haystack === 'object' && haystack.change_key_case) { // Duck-type check for our own array()-created PHPJS_Array
3815    return haystack.search(needle, argStrict);
3816  }
3817  if (typeof needle === 'object' && needle.exec) { // Duck-type for RegExp
3818    if (!strict) { // Let's consider case sensitive searches as 
3818strict
3819      var flags = 'i' + (needle.global ? 'g' : '') +
3820        (needle.multiline ? 'm' : '') +
3821        (needle.sticky ? 'y' : ''); // sticky is FF only
3822      needle = new RegExp(needle.source, flags);
3823    }
3824    for (key in haystack) {
3825      if (needle.test(haystack[key])) {
3826        return key;
3827      }
3828    }
3829    return false;
3830  }
3831
3832  for (key in haystack) {
3833    if ((strict && haystack[key] === needle) || (!strict && haystack[key] == needle)) {
3834      return key;
3835    }
3836  }
3837
3838  return false;
3839}
3840
3841function array_filter (arr, func) {
3842  //  discuss at: http://phpjs.org/functions/array_filter/
3843  // original by: Brett Zamir (http://brett-zamir.me)
3844  //    input by: max4ever
3845  // improved by: Brett Zamir (http://brett-zamir.me)
3846  //        note: Takes a function as an argument, not a function's name
3847  //   example 1: var odd = function (num) {return (num & 1);};
3848  //   example 1: array_filter({"a": 1, "b": 2, "c": 3, "d": 4, "e": 5}, odd);
3849  //   returns 1: {"a": 1, "c": 3, "e": 5}
3850  //   example 2: var even = function (num) {return (!(num & 1));}
3851  //   example 2: array_filter([6, 7, 8, 9, 10, 11, 12], even);
3852  //   returns 2: {0: 6, 2: 8, 4: 10, 6: 12}
3853  //   example 3: array_filter({"a": 1, "b": false, "c": -1, "d": 0, "e": null, "f":'', "g":undefined});
3854  //   returns 3: {"a":1, "c":-1};
3855
3856  var retObj = {},
3857    k
3858
3859  func = func || function (v) {
3860    return v
3861  }
3862
3863  // Fix: Issue #73
3864  if (Object.prototype.toString.call(arr) === '[object Array]') {
3865    retObj = []
3866  }
3867
3868  for (k in arr) {
3869    if (func(arr[k])) {
3870      retObj[k] = arr[k]
3871    }
3872  }
3873
3874  return retObj
3875}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.