summaryrefslogtreecommitdiff
path: root/node_modules/locutus/php/misc/pack.js
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/locutus/php/misc/pack.js')
-rw-r--r--node_modules/locutus/php/misc/pack.js379
1 files changed, 379 insertions, 0 deletions
diff --git a/node_modules/locutus/php/misc/pack.js b/node_modules/locutus/php/misc/pack.js
new file mode 100644
index 0000000..ec7d6b5
--- /dev/null
+++ b/node_modules/locutus/php/misc/pack.js
@@ -0,0 +1,379 @@
+'use strict';
+
+module.exports = function pack(format) {
+ // discuss at: http://locutus.io/php/pack/
+ // original by: Tim de Koning (http://www.kingsquare.nl)
+ // parts by: Jonas Raoni Soares Silva (http://www.jsfromhell.com)
+ // bugfixed by: Tim de Koning (http://www.kingsquare.nl)
+ // note 1: Float encoding by: Jonas Raoni Soares Silva
+ // note 1: Home: http://www.kingsquare.nl/blog/12-12-2009/13507444
+ // note 1: Feedback: phpjs-pack@kingsquare.nl
+ // note 1: "machine dependent byte order and size" aren't
+ // note 1: applicable for JavaScript; pack works as on a 32bit,
+ // note 1: little endian machine.
+ // example 1: pack('nvc*', 0x1234, 0x5678, 65, 66)
+ // returns 1: '\u00124xVAB'
+ // example 2: pack('H4', '2345')
+ // returns 2: '#E'
+ // example 3: pack('H*', 'D5')
+ // returns 3: 'Õ'
+ // example 4: pack('d', -100.876)
+ // returns 4: "\u0000\u0000\u0000\u0000\u00008YÀ"
+ // test: skip-1
+
+ var formatPointer = 0;
+ var argumentPointer = 1;
+ var result = '';
+ var argument = '';
+ var i = 0;
+ var r = [];
+ var instruction, quantifier, word, precisionBits, exponentBits, extraNullCount;
+
+ // vars used by float encoding
+ var bias;
+ var minExp;
+ var maxExp;
+ var minUnnormExp;
+ var status;
+ var exp;
+ var len;
+ var bin;
+ var signal;
+ var n;
+ var intPart;
+ var floatPart;
+ var lastBit;
+ var rounded;
+ var j;
+ var k;
+ var tmpResult;
+
+ while (formatPointer < format.length) {
+ instruction = format.charAt(formatPointer);
+ quantifier = '';
+ formatPointer++;
+ while (formatPointer < format.length && format.charAt(formatPointer).match(/[\d*]/) !== null) {
+ quantifier += format.charAt(formatPointer);
+ formatPointer++;
+ }
+ if (quantifier === '') {
+ quantifier = '1';
+ }
+
+ // Now pack variables: 'quantifier' times 'instruction'
+ switch (instruction) {
+ case 'a':
+ case 'A':
+ // NUL-padded string
+ // SPACE-padded string
+ if (typeof arguments[argumentPointer] === 'undefined') {
+ throw new Error('Warning: pack() Type ' + instruction + ': not enough arguments');
+ } else {
+ argument = String(arguments[argumentPointer]);
+ }
+ if (quantifier === '*') {
+ quantifier = argument.length;
+ }
+ for (i = 0; i < quantifier; i++) {
+ if (typeof argument[i] === 'undefined') {
+ if (instruction === 'a') {
+ result += String.fromCharCode(0);
+ } else {
+ result += ' ';
+ }
+ } else {
+ result += argument[i];
+ }
+ }
+ argumentPointer++;
+ break;
+ case 'h':
+ case 'H':
+ // Hex string, low nibble first
+ // Hex string, high nibble first
+ if (typeof arguments[argumentPointer] === 'undefined') {
+ throw new Error('Warning: pack() Type ' + instruction + ': not enough arguments');
+ } else {
+ argument = arguments[argumentPointer];
+ }
+ if (quantifier === '*') {
+ quantifier = argument.length;
+ }
+ if (quantifier > argument.length) {
+ var msg = 'Warning: pack() Type ' + instruction + ': not enough characters in string';
+ throw new Error(msg);
+ }
+
+ for (i = 0; i < quantifier; i += 2) {
+ // Always get per 2 bytes...
+ word = argument[i];
+ if (i + 1 >= quantifier || typeof argument[i + 1] === 'undefined') {
+ word += '0';
+ } else {
+ word += argument[i + 1];
+ }
+ // The fastest way to reverse?
+ if (instruction === 'h') {
+ word = word[1] + word[0];
+ }
+ result += String.fromCharCode(parseInt(word, 16));
+ }
+ argumentPointer++;
+ break;
+
+ case 'c':
+ case 'C':
+ // signed char
+ // unsigned char
+ // c and C is the same in pack
+ if (quantifier === '*') {
+ quantifier = arguments.length - argumentPointer;
+ }
+ if (quantifier > arguments.length - argumentPointer) {
+ throw new Error('Warning: pack() Type ' + instruction + ': too few arguments');
+ }
+
+ for (i = 0; i < quantifier; i++) {
+ result += String.fromCharCode(arguments[argumentPointer]);
+ argumentPointer++;
+ }
+ break;
+
+ case 's':
+ case 'S':
+ case 'v':
+ // signed short (always 16 bit, machine byte order)
+ // unsigned short (always 16 bit, machine byte order)
+ // s and S is the same in pack
+ if (quantifier === '*') {
+ quantifier = arguments.length - argumentPointer;
+ }
+ if (quantifier > arguments.length - argumentPointer) {
+ throw new Error('Warning: pack() Type ' + instruction + ': too few arguments');
+ }
+
+ for (i = 0; i < quantifier; i++) {
+ result += String.fromCharCode(arguments[argumentPointer] & 0xFF);
+ result += String.fromCharCode(arguments[argumentPointer] >> 8 & 0xFF);
+ argumentPointer++;
+ }
+ break;
+
+ case 'n':
+ // unsigned short (always 16 bit, big endian byte order)
+ if (quantifier === '*') {
+ quantifier = arguments.length - argumentPointer;
+ }
+ if (quantifier > arguments.length - argumentPointer) {
+ throw new Error('Warning: pack() Type ' + instruction + ': too few arguments');
+ }
+
+ for (i = 0; i < quantifier; i++) {
+ result += String.fromCharCode(arguments[argumentPointer] >> 8 & 0xFF);
+ result += String.fromCharCode(arguments[argumentPointer] & 0xFF);
+ argumentPointer++;
+ }
+ break;
+
+ case 'i':
+ case 'I':
+ case 'l':
+ case 'L':
+ case 'V':
+ // signed integer (machine dependent size and byte order)
+ // unsigned integer (machine dependent size and byte order)
+ // signed long (always 32 bit, machine byte order)
+ // unsigned long (always 32 bit, machine byte order)
+ // unsigned long (always 32 bit, little endian byte order)
+ if (quantifier === '*') {
+ quantifier = arguments.length - argumentPointer;
+ }
+ if (quantifier > arguments.length - argumentPointer) {
+ throw new Error('Warning: pack() Type ' + instruction + ': too few arguments');
+ }
+
+ for (i = 0; i < quantifier; i++) {
+ result += String.fromCharCode(arguments[argumentPointer] & 0xFF);
+ result += String.fromCharCode(arguments[argumentPointer] >> 8 & 0xFF);
+ result += String.fromCharCode(arguments[argumentPointer] >> 16 & 0xFF);
+ result += String.fromCharCode(arguments[argumentPointer] >> 24 & 0xFF);
+ argumentPointer++;
+ }
+
+ break;
+ case 'N':
+ // unsigned long (always 32 bit, big endian byte order)
+ if (quantifier === '*') {
+ quantifier = arguments.length - argumentPointer;
+ }
+ if (quantifier > arguments.length - argumentPointer) {
+ throw new Error('Warning: pack() Type ' + instruction + ': too few arguments');
+ }
+
+ for (i = 0; i < quantifier; i++) {
+ result += String.fromCharCode(arguments[argumentPointer] >> 24 & 0xFF);
+ result += String.fromCharCode(arguments[argumentPointer] >> 16 & 0xFF);
+ result += String.fromCharCode(arguments[argumentPointer] >> 8 & 0xFF);
+ result += String.fromCharCode(arguments[argumentPointer] & 0xFF);
+ argumentPointer++;
+ }
+ break;
+
+ case 'f':
+ case 'd':
+ // float (machine dependent size and representation)
+ // double (machine dependent size and representation)
+ // version based on IEEE754
+ precisionBits = 23;
+ exponentBits = 8;
+ if (instruction === 'd') {
+ precisionBits = 52;
+ exponentBits = 11;
+ }
+
+ if (quantifier === '*') {
+ quantifier = arguments.length - argumentPointer;
+ }
+ if (quantifier > arguments.length - argumentPointer) {
+ throw new Error('Warning: pack() Type ' + instruction + ': too few arguments');
+ }
+ for (i = 0; i < quantifier; i++) {
+ argument = arguments[argumentPointer];
+ bias = Math.pow(2, exponentBits - 1) - 1;
+ minExp = -bias + 1;
+ maxExp = bias;
+ minUnnormExp = minExp - precisionBits;
+ status = isNaN(n = parseFloat(argument)) || n === -Infinity || n === +Infinity ? n : 0;
+ exp = 0;
+ len = 2 * bias + 1 + precisionBits + 3;
+ bin = new Array(len);
+ signal = (n = status !== 0 ? 0 : n) < 0;
+ n = Math.abs(n);
+ intPart = Math.floor(n);
+ floatPart = n - intPart;
+
+ for (k = len; k;) {
+ bin[--k] = 0;
+ }
+ for (k = bias + 2; intPart && k;) {
+ bin[--k] = intPart % 2;
+ intPart = Math.floor(intPart / 2);
+ }
+ for (k = bias + 1; floatPart > 0 && k; --floatPart) {
+ bin[++k] = ((floatPart *= 2) >= 1) - 0;
+ }
+ for (k = -1; ++k < len && !bin[k];) {}
+
+ // @todo: Make this more readable:
+ var key = (lastBit = precisionBits - 1 + (k = (exp = bias + 1 - k) >= minExp && exp <= maxExp ? k + 1 : bias + 1 - (exp = minExp - 1))) + 1;
+
+ if (bin[key]) {
+ if (!(rounded = bin[lastBit])) {
+ for (j = lastBit + 2; !rounded && j < len; rounded = bin[j++]) {}
+ }
+ for (j = lastBit + 1; rounded && --j >= 0; (bin[j] = !bin[j] - 0) && (rounded = 0)) {}
+ }
+
+ for (k = k - 2 < 0 ? -1 : k - 3; ++k < len && !bin[k];) {}
+
+ if ((exp = bias + 1 - k) >= minExp && exp <= maxExp) {
+ ++k;
+ } else {
+ if (exp < minExp) {
+ if (exp !== bias + 1 - len && exp < minUnnormExp) {
+ // "encodeFloat::float underflow"
+ }
+ k = bias + 1 - (exp = minExp - 1);
+ }
+ }
+
+ if (intPart || status !== 0) {
+ exp = maxExp + 1;
+ k = bias + 2;
+ if (status === -Infinity) {
+ signal = 1;
+ } else if (isNaN(status)) {
+ bin[k] = 1;
+ }
+ }
+
+ n = Math.abs(exp + bias);
+ tmpResult = '';
+
+ for (j = exponentBits + 1; --j;) {
+ tmpResult = n % 2 + tmpResult;
+ n = n >>= 1;
+ }
+
+ n = 0;
+ j = 0;
+ k = (tmpResult = (signal ? '1' : '0') + tmpResult + bin.slice(k, k + precisionBits).join('')).length;
+ r = [];
+
+ for (; k;) {
+ n += (1 << j) * tmpResult.charAt(--k);
+ if (j === 7) {
+ r[r.length] = String.fromCharCode(n);
+ n = 0;
+ }
+ j = (j + 1) % 8;
+ }
+
+ r[r.length] = n ? String.fromCharCode(n) : '';
+ result += r.join('');
+ argumentPointer++;
+ }
+ break;
+
+ case 'x':
+ // NUL byte
+ if (quantifier === '*') {
+ throw new Error('Warning: pack(): Type x: \'*\' ignored');
+ }
+ for (i = 0; i < quantifier; i++) {
+ result += String.fromCharCode(0);
+ }
+ break;
+
+ case 'X':
+ // Back up one byte
+ if (quantifier === '*') {
+ throw new Error('Warning: pack(): Type X: \'*\' ignored');
+ }
+ for (i = 0; i < quantifier; i++) {
+ if (result.length === 0) {
+ throw new Error('Warning: pack(): Type X:' + ' outside of string');
+ } else {
+ result = result.substring(0, result.length - 1);
+ }
+ }
+ break;
+
+ case '@':
+ // NUL-fill to absolute position
+ if (quantifier === '*') {
+ throw new Error('Warning: pack(): Type X: \'*\' ignored');
+ }
+ if (quantifier > result.length) {
+ extraNullCount = quantifier - result.length;
+ for (i = 0; i < extraNullCount; i++) {
+ result += String.fromCharCode(0);
+ }
+ }
+ if (quantifier < result.length) {
+ result = result.substring(0, quantifier);
+ }
+ break;
+
+ default:
+ throw new Error('Warning: pack() Type ' + instruction + ': unknown format code');
+ }
+ }
+ if (argumentPointer < arguments.length) {
+ var msg2 = 'Warning: pack(): ' + (arguments.length - argumentPointer) + ' arguments unused';
+ throw new Error(msg2);
+ }
+
+ return result;
+};
+//# sourceMappingURL=pack.js.map \ No newline at end of file