1"use strict"; 2 3var Buffer = require("safer-buffer").Buffer; 4 5var bomHandling = require("./bom-handling"), 6 iconv = module.exports; 7 8// All codecs and aliases are kept here, keyed by encoding name/alias. 9// They are lazy loaded in `iconv.getCodec` from `encodings/index.js`. 10iconv.encodings = null; 11 12// Characters emitted in case of error. 13iconv.defaultCharUnicode = '�'; 14iconv.defaultCharSingleByte = '?'; 15 16// Public API. 17iconv.encode = function encode(str, encoding, options) { 18 str = "" + (str || ""); // Ensure string. 19 20 var encoder = iconv.getEncoder(encoding, options); 21 22 var res = encoder.write(str); 23 var trail = encoder.end(); 24 25 return (trail && trail.length > 0) ? Buffer.concat([res, trail]) : res; 26} 27 28iconv.decode = function decode(buf, encoding, options) { 29 if (typeof buf === 'string') { 30 if (!iconv.skipDecodeWarning) { 31 console.error('Iconv-lite warning: decode()-ing strings is deprecated. Refer to https://github.com/ashtuchkin/iconv-lite/wiki/Use-Buffers-when-decoding'); 32 iconv.skipDecodeWarning = true; 33 } 34 35 buf = Buffer.from("" + (buf || ""), "binary"); // Ensure buffer. 36 } 37 38 var decoder = iconv.getDecoder(encoding, options); 39 40 var res = decoder.write(buf); 41 var trail = decoder.end(); 42 43 return trail ? (res + trail) : res; 44} 45 46iconv.encodingExists = function encodingExists(enc) { 47 try { 48 iconv.getCodec(enc); 49 return true; 50 } catch (e) { 51 return false; 52 } 53} 54 55// Legacy aliases to convert functions 56iconv.toEncoding = iconv.encode; 57iconv.fromEncoding = iconv.decode; 58 59// Search for a codec in iconv.encodings. Cache codec data in iconv._codecDataCache. 60iconv._codecDataCache = {}; 61iconv.getCodec = function getCodec(encoding) { 62 if (!iconv.encodings) 63 iconv.encodings = require("../encodings"); // Lazy load all encoding definitions. 64 65 // Canonicalize encoding name: strip all non-alphanumeric chars and appended year. 66 var enc = iconv._canonicalizeEncoding(encoding); 67 68 // Traverse iconv.encodings to find actual codec. 69 var codecOptions = {}; 70 while (true) { 71 var codec = iconv._codecDataCache[enc]; 72 if (codec) 73 return codec; 74 75 var codecDef = iconv.encodings[enc]; 76 77 switch (typeof codecDef) { 78 case "string": // Direct alias to other encoding. 79 enc = codecDef; 80 break; 81 82 case "object": // Alias with options. Can be layered. 83 for (var key in codecDef) 84 codecOptions[key] = codecDef[key]; 85 86 if (!codecOptions.encodingName) 87 codecOptions.encodingName = enc; 88 89 enc = codecDef.type; 90 break; 91 92 case "function": // Codec itself. 93 if (!codecOptions.encodingName) 94 codecOptions.encodingName = enc; 95 96 // The codec function must load all tables and return object with .encoder and .decoder methods. 97 // It'll be called only once (for each different options object). 98 codec = new codecDef(codecOptions, iconv); 99 100 iconv._codecDataCache[codecOptions.encodingName] = codec; // Save it to be reused later. 101 return codec; 102 103 default: 104 throw new Error("Encoding not recognized: '" + encoding + "' (searched as: '"+enc+"')"); 105 } 106 } 107} 108 109iconv._canonicalizeEncoding = function(encoding) { 110 // Canonicalize encoding name: strip all non-alphanumeric chars and appended year. 111 return (''+encoding).toLowerCase().replace(/:\d{4}$|[^0-9a-z]/g, ""); 112} 113 114iconv.getEncoder = function getEncoder(encoding, options) { 115 var codec = iconv.getCodec(encoding), 116 encoder = new codec.encoder(options, codec); 117 118 if (codec.bomAware && options && options.addBOM) 119 encoder = new bomHandling.PrependBOM(encoder, options); 120 121 return encoder; 122} 123 124iconv.getDecoder = function getDecoder(encoding, options) { 125 var codec = iconv.getCodec(encoding), 126 decoder = new codec.decoder(options, codec); 127 128 if (codec.bomAware && !(options && options.stripBOM === false)) 129 decoder = new bomHandling.StripBOM(decoder, options); 130 131 return decoder; 132} 133 134// Streaming API 135// NOTE: Streaming API naturally depends on 'stream' module from Node.js. Unfortunately in browser environments this module can add 136// up to 100Kb to the output bundle. To avoid unnecessary code bloat, we don't enable Streaming API in browser by default. 137// If you would like to enable it explicitly, please add the following code to your app: 138// > iconv.enableStreamingAPI(require('stream')); 139iconv.enableStreamingAPI = function enableStreamingAPI(stream_module) { 140 if (iconv.supportsStreams) 141 return; 142 143 // Dependency-inject stream module to create IconvLite stream classes. 144 var streams = require("./streams")(stream_module); 145 146 // Not public API yet, but expose the stream classes. 147 iconv.IconvLiteEncoderStream = streams.IconvLiteEncoderStream; 148 iconv.IconvLiteDecoderStream = streams.IconvLiteDecoderStream; 149 150 // Streaming API. 151 iconv.encodeStream = function encodeStream(encoding, options) { 152 return new iconv.IconvLiteEncoderStream(iconv.getEncoder(encoding, options), options); 153 } 154 155 iconv.decodeStream = function decodeStream(encoding, options) { 156 return new iconv.IconvLiteDecoderStream(iconv.getDecoder(encoding, options), options); 157 } 158 159 iconv.supportsStreams = true; 160} 161 162// Enable Streaming API automatically if 'stream' module is available and non-empty (the majority of environments). 163var stream_module; 164try { 165 stream_module = require("stream"); 166} catch (e) {} 167 168if (stream_module && stream_module.Transform) { 169 iconv.enableStreamingAPI(stream_module); 170 171} else { 172 // In rare cases where 'stream' module is not available by default, throw a helpful exception. 173 iconv.encodeStream = iconv.decodeStream = function() { 174 throw new Error("iconv-lite Streaming API is not enabled. Use iconv.enableStreamingAPI(require('stream')); to enable it."); 175 }; 176} 177 178if ("Ā" != "\u0100") { 179 console.error("iconv-lite warning: js files use non-utf8 encoding. See https://github.com/ashtuchkin/iconv-lite/wiki/Javascript-source-file-encodings for more info."); 180} 181