123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344 |
- 'use strict';
- var support = require('./support');
- var compressions = require('./compressions');
- var nodeBuffer = require('./nodeBuffer');
- /**
- * Convert a string to a "binary string" : a string containing only char codes between 0 and 255.
- * @param {string} str the string to transform.
- * @return {String} the binary string.
- */
- exports.string2binary = function(str) {
- var result = "";
- for (var i = 0; i < str.length; i++) {
- result += String.fromCharCode(str.charCodeAt(i) & 0xff);
- }
- return result;
- };
- exports.arrayBuffer2Blob = function(buffer, mimeType) {
- exports.checkSupport("blob");
- mimeType = mimeType || 'application/zip';
- try {
- // Blob constructor
- return new Blob([buffer], {
- type: mimeType
- });
- }
- catch (e) {
- try {
- // deprecated, browser only, old way
- var Builder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder || window.MSBlobBuilder;
- var builder = new Builder();
- builder.append(buffer);
- return builder.getBlob(mimeType);
- }
- catch (e) {
- // well, fuck ?!
- throw new Error("Bug : can't construct the Blob.");
- }
- }
- };
- /**
- * The identity function.
- * @param {Object} input the input.
- * @return {Object} the same input.
- */
- function identity(input) {
- return input;
- }
- /**
- * Fill in an array with a string.
- * @param {String} str the string to use.
- * @param {Array|ArrayBuffer|Uint8Array|Buffer} array the array to fill in (will be mutated).
- * @return {Array|ArrayBuffer|Uint8Array|Buffer} the updated array.
- */
- function stringToArrayLike(str, array) {
- for (var i = 0; i < str.length; ++i) {
- array[i] = str.charCodeAt(i) & 0xFF;
- }
- return array;
- }
- /**
- * Transform an array-like object to a string.
- * @param {Array|ArrayBuffer|Uint8Array|Buffer} array the array to transform.
- * @return {String} the result.
- */
- function arrayLikeToString(array) {
- // Performances notes :
- // --------------------
- // String.fromCharCode.apply(null, array) is the fastest, see
- // see http://jsperf.com/converting-a-uint8array-to-a-string/2
- // but the stack is limited (and we can get huge arrays !).
- //
- // result += String.fromCharCode(array[i]); generate too many strings !
- //
- // This code is inspired by http://jsperf.com/arraybuffer-to-string-apply-performance/2
- var chunk = 65536;
- var result = [],
- len = array.length,
- type = exports.getTypeOf(array),
- k = 0,
- canUseApply = true;
- try {
- switch(type) {
- case "uint8array":
- String.fromCharCode.apply(null, new Uint8Array(0));
- break;
- case "nodebuffer":
- String.fromCharCode.apply(null, nodeBuffer(0));
- break;
- }
- } catch(e) {
- canUseApply = false;
- }
- // no apply : slow and painful algorithm
- // default browser on android 4.*
- if (!canUseApply) {
- var resultStr = "";
- for(var i = 0; i < array.length;i++) {
- resultStr += String.fromCharCode(array[i]);
- }
- return resultStr;
- }
- while (k < len && chunk > 1) {
- try {
- if (type === "array" || type === "nodebuffer") {
- result.push(String.fromCharCode.apply(null, array.slice(k, Math.min(k + chunk, len))));
- }
- else {
- result.push(String.fromCharCode.apply(null, array.subarray(k, Math.min(k + chunk, len))));
- }
- k += chunk;
- }
- catch (e) {
- chunk = Math.floor(chunk / 2);
- }
- }
- return result.join("");
- }
- exports.applyFromCharCode = arrayLikeToString;
- /**
- * Copy the data from an array-like to an other array-like.
- * @param {Array|ArrayBuffer|Uint8Array|Buffer} arrayFrom the origin array.
- * @param {Array|ArrayBuffer|Uint8Array|Buffer} arrayTo the destination array which will be mutated.
- * @return {Array|ArrayBuffer|Uint8Array|Buffer} the updated destination array.
- */
- function arrayLikeToArrayLike(arrayFrom, arrayTo) {
- for (var i = 0; i < arrayFrom.length; i++) {
- arrayTo[i] = arrayFrom[i];
- }
- return arrayTo;
- }
- // a matrix containing functions to transform everything into everything.
- var transform = {};
- // string to ?
- transform["string"] = {
- "string": identity,
- "array": function(input) {
- return stringToArrayLike(input, new Array(input.length));
- },
- "arraybuffer": function(input) {
- return transform["string"]["uint8array"](input).buffer;
- },
- "uint8array": function(input) {
- return stringToArrayLike(input, new Uint8Array(input.length));
- },
- "nodebuffer": function(input) {
- return stringToArrayLike(input, nodeBuffer(input.length));
- }
- };
- // array to ?
- transform["array"] = {
- "string": arrayLikeToString,
- "array": identity,
- "arraybuffer": function(input) {
- return (new Uint8Array(input)).buffer;
- },
- "uint8array": function(input) {
- return new Uint8Array(input);
- },
- "nodebuffer": function(input) {
- return nodeBuffer(input);
- }
- };
- // arraybuffer to ?
- transform["arraybuffer"] = {
- "string": function(input) {
- return arrayLikeToString(new Uint8Array(input));
- },
- "array": function(input) {
- return arrayLikeToArrayLike(new Uint8Array(input), new Array(input.byteLength));
- },
- "arraybuffer": identity,
- "uint8array": function(input) {
- return new Uint8Array(input);
- },
- "nodebuffer": function(input) {
- return nodeBuffer(new Uint8Array(input));
- }
- };
- // uint8array to ?
- transform["uint8array"] = {
- "string": arrayLikeToString,
- "array": function(input) {
- return arrayLikeToArrayLike(input, new Array(input.length));
- },
- "arraybuffer": function(input) {
- return input.buffer;
- },
- "uint8array": identity,
- "nodebuffer": function(input) {
- return nodeBuffer(input);
- }
- };
- // nodebuffer to ?
- transform["nodebuffer"] = {
- "string": arrayLikeToString,
- "array": function(input) {
- return arrayLikeToArrayLike(input, new Array(input.length));
- },
- "arraybuffer": function(input) {
- return transform["nodebuffer"]["uint8array"](input).buffer;
- },
- "uint8array": function(input) {
- return arrayLikeToArrayLike(input, new Uint8Array(input.length));
- },
- "nodebuffer": identity
- };
- /**
- * Transform an input into any type.
- * The supported output type are : string, array, uint8array, arraybuffer, nodebuffer.
- * If no output type is specified, the unmodified input will be returned.
- * @param {String} outputType the output type.
- * @param {String|Array|ArrayBuffer|Uint8Array|Buffer} input the input to convert.
- * @throws {Error} an Error if the browser doesn't support the requested output type.
- */
- exports.transformTo = function(outputType, input) {
- if (!input) {
- // undefined, null, etc
- // an empty string won't harm.
- input = "";
- }
- if (!outputType) {
- return input;
- }
- exports.checkSupport(outputType);
- var inputType = exports.getTypeOf(input);
- var result = transform[inputType][outputType](input);
- return result;
- };
- /**
- * Return the type of the input.
- * The type will be in a format valid for JSZip.utils.transformTo : string, array, uint8array, arraybuffer.
- * @param {Object} input the input to identify.
- * @return {String} the (lowercase) type of the input.
- */
- exports.getTypeOf = function(input) {
- if (typeof input === "string") {
- return "string";
- }
- if (Object.prototype.toString.call(input) === "[object Array]") {
- return "array";
- }
- if (support.nodebuffer && nodeBuffer.test(input)) {
- return "nodebuffer";
- }
- if (support.uint8array && input instanceof Uint8Array) {
- return "uint8array";
- }
- if (support.arraybuffer && input instanceof ArrayBuffer) {
- return "arraybuffer";
- }
- };
- /**
- * Throw an exception if the type is not supported.
- * @param {String} type the type to check.
- * @throws {Error} an Error if the browser doesn't support the requested type.
- */
- exports.checkSupport = function(type) {
- var supported = support[type.toLowerCase()];
- if (!supported) {
- throw new Error(type + " is not supported by this browser");
- }
- };
- exports.MAX_VALUE_16BITS = 65535;
- exports.MAX_VALUE_32BITS = -1; // well, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" is parsed as -1
- /**
- * Prettify a string read as binary.
- * @param {string} str the string to prettify.
- * @return {string} a pretty string.
- */
- exports.pretty = function(str) {
- var res = '',
- code, i;
- for (i = 0; i < (str || "").length; i++) {
- code = str.charCodeAt(i);
- res += '\\x' + (code < 16 ? "0" : "") + code.toString(16).toUpperCase();
- }
- return res;
- };
- /**
- * Find a compression registered in JSZip.
- * @param {string} compressionMethod the method magic to find.
- * @return {Object|null} the JSZip compression object, null if none found.
- */
- exports.findCompression = function(compressionMethod) {
- for (var method in compressions) {
- if (!compressions.hasOwnProperty(method)) {
- continue;
- }
- if (compressions[method].magic === compressionMethod) {
- return compressions[method];
- }
- }
- return null;
- };
- /**
- * Cross-window, cross-Node-context regular expression detection
- * @param {Object} object Anything
- * @return {Boolean} true if the object is a regular expression,
- * false otherwise
- */
- exports.isRegExp = function (object) {
- return Object.prototype.toString.call(object) === "[object RegExp]";
- };
- /**
- * Merge the objects passed as parameters into a new one.
- * @private
- * @param {...Object} var_args All objects to merge.
- * @return {Object} a new object with the data of the others.
- */
- exports.extend = function() {
- var result = {}, i, attr;
- for (i = 0; i < arguments.length; i++) { // arguments is not enumerable in some browsers
- for (attr in arguments[i]) {
- if (arguments[i].hasOwnProperty(attr) && typeof result[attr] === "undefined") {
- result[attr] = arguments[i][attr];
- }
- }
- }
- return result;
- };
|