cputils.js 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524
  1. /* cputils.js (C) 2013-2014 SheetJS -- http://sheetjs.com */
  2. /*jshint newcap: false */
  3. (function(root, factory){
  4. "use strict";
  5. if(typeof cptable === "undefined") {
  6. if(typeof require !== "undefined"){
  7. var cpt = require('./cpt' + 'able');
  8. if (typeof module !== 'undefined' && module.exports) module.exports = factory(cpt);
  9. else root.cptable = factory(cpt);
  10. } else throw new Error("cptable not found");
  11. } else cptable = factory(cptable);
  12. }(this, function(cpt){
  13. "use strict";
  14. var magic = {
  15. "1200":"utf16le",
  16. "1201":"utf16be",
  17. "12000":"utf32le",
  18. "12001":"utf32be",
  19. "16969":"utf64le",
  20. "20127":"ascii",
  21. "65000":"utf7",
  22. "65001":"utf8"
  23. };
  24. var sbcs_cache = [874,1250,1251,1252,1253,1254,1255,1256,10000];
  25. var dbcs_cache = [932,936,949,950];
  26. var magic_cache = [65001];
  27. var magic_decode = {};
  28. var magic_encode = {};
  29. var cpecache = {};
  30. var cpdcache = {};
  31. var sfcc = function sfcc(x) { return String.fromCharCode(x); };
  32. var cca = function cca(x){ return x.charCodeAt(0); };
  33. var has_buf = (typeof Buffer !== 'undefined');
  34. if(has_buf) {
  35. var mdl = 1024, mdb = new Buffer(mdl);
  36. var make_EE = function make_EE(E){
  37. var EE = new Buffer(65536);
  38. for(var i = 0; i < 65536;++i) EE[i] = 0;
  39. var keys = Object.keys(E), len = keys.length;
  40. for(var ee = 0, e = keys[ee]; ee < len; ++ee) {
  41. if(!(e = keys[ee])) continue;
  42. EE[e.charCodeAt(0)] = E[e];
  43. }
  44. return EE;
  45. };
  46. var sbcs_encode = function make_sbcs_encode(cp) {
  47. var EE = make_EE(cpt[cp].enc);
  48. return function sbcs_e(data, ofmt) {
  49. var len = data.length;
  50. var out, i, j, D, w;
  51. if(typeof data === 'string') {
  52. out = Buffer(len);
  53. for(i = 0; i < len; ++i) out[i] = EE[data.charCodeAt(i)];
  54. } else if(Buffer.isBuffer(data)) {
  55. out = Buffer(2*len);
  56. j = 0;
  57. for(i = 0; i < len; ++i) {
  58. D = data[i];
  59. if(D < 128) out[j++] = EE[D];
  60. else if(D < 224) { out[j++] = EE[((D&31)<<6)+(data[i+1]&63)]; ++i; }
  61. else if(D < 240) { out[j++] = EE[((D&15)<<12)+((data[i+1]&63)<<6)+(data[i+2]&63)]; i+=2; }
  62. else {
  63. w = ((D&7)<<18)+((data[i+1]&63)<<12)+((data[i+2]&63)<<6)+(data[i+3]&63); i+=3;
  64. if(w < 65536) out[j++] = EE[w];
  65. else { w -= 65536; out[j++] = EE[0xD800 + ((w>>10)&1023)]; out[j++] = EE[0xDC00 + (w&1023)]; }
  66. }
  67. }
  68. out.length = j;
  69. out = out.slice(0,j);
  70. } else {
  71. out = Buffer(len);
  72. for(i = 0; i < len; ++i) out[i] = EE[data[i].charCodeAt(0)];
  73. }
  74. if(ofmt === undefined || ofmt === 'buf') return out;
  75. if(ofmt !== 'arr') return out.toString('binary');
  76. return [].slice.call(out);
  77. };
  78. };
  79. var sbcs_decode = function make_sbcs_decode(cp) {
  80. var D = cpt[cp].dec;
  81. var DD = new Buffer(131072), d=0, c;
  82. for(d=0;d<D.length;++d) {
  83. if(!(c=D[d])) continue;
  84. var w = c.charCodeAt(0);
  85. DD[2*d] = w&255; DD[2*d+1] = w>>8;
  86. }
  87. return function sbcs_d(data) {
  88. var len = data.length, i=0, j;
  89. if(2 * len > mdl) { mdl = 2 * len; mdb = new Buffer(mdl); }
  90. if(Buffer.isBuffer(data)) {
  91. for(i = 0; i < len; i++) {
  92. j = 2*data[i];
  93. mdb[2*i] = DD[j]; mdb[2*i+1] = DD[j+1];
  94. }
  95. } else if(typeof data === "string") {
  96. for(i = 0; i < len; i++) {
  97. j = 2*data.charCodeAt(i);
  98. mdb[2*i] = DD[j]; mdb[2*i+1] = DD[j+1];
  99. }
  100. } else {
  101. for(i = 0; i < len; i++) {
  102. j = 2*data[i];
  103. mdb[2*i] = DD[j]; mdb[2*i+1] = DD[j+1];
  104. }
  105. }
  106. mdb.length = 2 * len;
  107. return mdb.toString('ucs2');
  108. };
  109. };
  110. var dbcs_encode = function make_dbcs_encode(cp) {
  111. var E = cpt[cp].enc;
  112. var EE = new Buffer(131072);
  113. for(var i = 0; i < 131072; ++i) EE[i] = 0;
  114. var keys = Object.keys(E);
  115. for(var ee = 0, e = keys[ee]; ee < keys.length; ++ee) {
  116. if(!(e = keys[ee])) continue;
  117. var f = e.charCodeAt(0);
  118. EE[2*f] = E[e] & 255; EE[2*f+1] = E[e]>>8;
  119. }
  120. return function dbcs_e(data, ofmt) {
  121. var len = data.length, out = new Buffer(2*len), i, j, jj, k, D;
  122. if(typeof data === 'string') {
  123. for(i = k = 0; i < len; ++i) {
  124. j = data.charCodeAt(i)*2;
  125. out[k++] = EE[j+1] || EE[j]; if(EE[j+1] > 0) out[k++] = EE[j];
  126. }
  127. out.length = k;
  128. out = out.slice(0,k);
  129. } else if(Buffer.isBuffer(data)) {
  130. for(i = k = 0; i < len; ++i) {
  131. D = data[i];
  132. if(D < 128) j = D;
  133. else if(D < 224) { j = ((D&31)<<6)+(data[i+1]&63); ++i; }
  134. else if(D < 240) { j = ((D&15)<<12)+((data[i+1]&63)<<6)+(data[i+2]&63); i+=2; }
  135. else { j = ((D&7)<<18)+((data[i+1]&63)<<12)+((data[i+2]&63)<<6)+(data[i+3]&63); i+=3; }
  136. if(j<65536) { j*=2; out[k++] = EE[j+1] || EE[j]; if(EE[j+1] > 0) out[k++] = EE[j]; }
  137. else { jj = j-65536;
  138. j=2*(0xD800 + ((jj>>10)&1023)); out[k++] = EE[j+1] || EE[j]; if(EE[j+1] > 0) out[k++] = EE[j];
  139. j=2*(0xDC00 + (jj&1023)); out[k++] = EE[j+1] || EE[j]; if(EE[j+1] > 0) out[k++] = EE[j];
  140. }
  141. }
  142. out.length = k;
  143. out = out.slice(0,k);
  144. } else {
  145. for(i = k = 0; i < len; i++) {
  146. j = data[i].charCodeAt(0)*2;
  147. out[k++] = EE[j+1] || EE[j]; if(EE[j+1] > 0) out[k++] = EE[j];
  148. }
  149. }
  150. if(ofmt === undefined || ofmt === 'buf') return out;
  151. if(ofmt !== 'arr') return out.toString('binary');
  152. return [].slice.call(out);
  153. };
  154. };
  155. var dbcs_decode = function make_dbcs_decode(cp) {
  156. var D = cpt[cp].dec;
  157. var DD = new Buffer(131072), d=0, c, w=0, j=0, i=0;
  158. for(i = 0; i < 65536; ++i) { DD[2*i] = 0xFF; DD[2*i+1] = 0xFD;}
  159. for(d = 0; d < D.length; ++d) {
  160. if(!(c=D[d])) continue;
  161. w = c.charCodeAt(0);
  162. j = 2*d;
  163. DD[j] = w&255; DD[j+1] = w>>8;
  164. }
  165. return function dbcs_d(data) {
  166. var len = data.length, out = new Buffer(2*len), i, j, k=0;
  167. if(Buffer.isBuffer(data)) {
  168. for(i = 0; i < len; i++) {
  169. j = 2*data[i];
  170. if(DD[j]===0xFF && DD[j+1]===0xFD) { j=2*((data[i]<<8)+data[i+1]); ++i; }
  171. out[k++] = DD[j]; out[k++] = DD[j+1];
  172. }
  173. } else if(typeof data === "string") {
  174. for(i = 0; i < len; i++) {
  175. j = 2*data.charCodeAt(i);
  176. if(DD[j]===0xFF && DD[j+1]===0xFD) { j=2*((data.charCodeAt(i)<<8)+data.charCodeAt(i+1)); ++i; }
  177. out[k++] = DD[j]; out[k++] = DD[j+1];
  178. }
  179. } else {
  180. for(i = 0; i < len; i++) {
  181. j = 2*data[i];
  182. if(DD[j]===0xFF && DD[j+1]===0xFD) { j=2*((data[i]<<8)+data[i+1]); ++i; }
  183. out[k++] = DD[j]; out[k++] = DD[j+1];
  184. }
  185. }
  186. out.length = k;
  187. return out.toString('ucs2');
  188. };
  189. };
  190. magic_decode[65001] = function utf8_d(data) {
  191. var len = data.length, w = 0, ww = 0;
  192. if(4 * len > mdl) { mdl = 4 * len; mdb = new Buffer(mdl); }
  193. mdb.length = 0;
  194. var i = 0;
  195. if(len >= 3 && data[0] == 0xEF) if(data[1] == 0xBB && data[2] == 0xBF) i = 3;
  196. for(var j = 1, k = 0, D = 0; i < len; i+=j) {
  197. j = 1; D = data[i];
  198. if(D < 128) w = D;
  199. else if(D < 224) { w=(D&31)*64+(data[i+1]&63); j=2; }
  200. else if(D < 240) { w=((D&15)<<12)+(data[i+1]&63)*64+(data[i+2]&63); j=3; }
  201. else { w=(D&7)*262144+((data[i+1]&63)<<12)+(data[i+2]&63)*64+(data[i+3]&63); j=4; }
  202. if(w < 65536) { mdb[k++] = w&255; mdb[k++] = w>>8; }
  203. else {
  204. w -= 65536; ww = 0xD800 + ((w>>10)&1023); w = 0xDC00 + (w&1023);
  205. mdb[k++] = ww&255; mdb[k++] = ww>>>8; mdb[k++] = w&255; mdb[k++] = (w>>>8)&255;
  206. }
  207. }
  208. mdb.length = k;
  209. return mdb.toString('ucs2');
  210. };
  211. magic_encode[65001] = function utf8_e(data, ofmt) {
  212. var len = data.length, w = 0, ww = 0, j = 0;
  213. var direct = typeof data === "string";
  214. if(4 * len > mdl) { mdl = 4 * len; mdb = new Buffer(mdl); }
  215. for(var i = 0; i < len; ++i) {
  216. w = direct ? data.charCodeAt(i) : data[i].charCodeAt(0);
  217. if(w <= 0x007F) mdb[j++] = w;
  218. else if(w <= 0x07FF) {
  219. mdb[j++] = 192 + (w >> 6);
  220. mdb[j++] = 128 + (w&63);
  221. } else if(w >= 0xD800 && w <= 0xDFFF) {
  222. w -= 0xD800; ++i;
  223. ww = (direct ? data.charCodeAt(i) : data[i].charCodeAt(0)) - 0xDC00 + (w << 10);
  224. mdb[j++] = 240 + ((ww>>>18) & 0x07);
  225. mdb[j++] = 144 + ((ww>>>12) & 0x3F);
  226. mdb[j++] = 128 + ((ww>>>6) & 0x3F);
  227. mdb[j++] = 128 + (ww & 0x3F);
  228. } else {
  229. mdb[j++] = 224 + (w >> 12);
  230. mdb[j++] = 128 + ((w >> 6)&63);
  231. mdb[j++] = 128 + (w&63);
  232. }
  233. }
  234. mdb.length = j;
  235. if(ofmt === undefined || ofmt === 'buf') return mdb;
  236. if(ofmt !== 'arr') return mdb.toString('binary');
  237. return [].slice.call(mdb);
  238. };
  239. }
  240. var encache = function encache() {
  241. if(has_buf) {
  242. if(cpdcache[sbcs_cache[0]]) return;
  243. var i, s;
  244. for(i = 0; i < sbcs_cache.length; ++i) {
  245. s = sbcs_cache[i];
  246. if(cpt[s]) {
  247. cpdcache[s] = sbcs_decode(s);
  248. cpecache[s] = sbcs_encode(s);
  249. }
  250. }
  251. for(i = 0; i < dbcs_cache.length; ++i) {
  252. s = dbcs_cache[i];
  253. if(cpt[s]) {
  254. cpdcache[s] = dbcs_decode(s);
  255. cpecache[s] = dbcs_encode(s);
  256. }
  257. }
  258. for(i = 0; i < magic_cache.length; ++i) {
  259. s = magic_cache[i];
  260. if(magic_decode[s]) cpdcache[s] = magic_decode[s];
  261. if(magic_encode[s]) cpecache[s] = magic_encode[s];
  262. }
  263. }
  264. };
  265. var cp_decache = function cp_decache(cp) { cpdcache[cp] = cpecache[cp] = undefined; };
  266. var decache = function decache() {
  267. if(has_buf) {
  268. if(!cpdcache[sbcs_cache[0]]) return;
  269. sbcs_cache.forEach(cp_decache);
  270. dbcs_cache.forEach(cp_decache);
  271. magic_cache.forEach(cp_decache);
  272. }
  273. last_enc = last_cp = undefined;
  274. };
  275. var cache = {
  276. encache: encache,
  277. decache: decache,
  278. sbcs: sbcs_cache,
  279. dbcs: dbcs_cache
  280. };
  281. encache();
  282. var BM = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  283. var SetD = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'(),-./:?";
  284. var last_enc, last_cp;
  285. var encode = function encode(cp, data, ofmt) {
  286. if(cp === last_cp) { return last_enc(data, ofmt); }
  287. if(cpecache[cp] !== undefined) { last_enc = cpecache[last_cp=cp]; return last_enc(data, ofmt); }
  288. if(has_buf && Buffer.isBuffer(data)) data = data.toString('utf8');
  289. var len = data.length;
  290. var out = has_buf ? new Buffer(4*len) : [], w, i, j = 0, c, tt, ww;
  291. var C = cpt[cp], E, M;
  292. if(C && (E=C.enc)) for(i = 0; i < len; ++i, ++j) {
  293. w = E[data[i]];
  294. out[j] = w&255;
  295. if(w > 255) {
  296. out[j] = w>>8;
  297. out[++j] = w&255;
  298. }
  299. }
  300. else if((M=magic[cp])) switch(M) {
  301. case "utf8":
  302. if(has_buf && typeof data === "string") { out = new Buffer(data, M); j = out.length; break; }
  303. for(i = 0; i < len; ++i, ++j) {
  304. w = data[i].charCodeAt(0);
  305. if(w <= 0x007F) out[j] = w;
  306. else if(w <= 0x07FF) {
  307. out[j] = 192 + (w >> 6);
  308. out[++j] = 128 + (w&63);
  309. } else if(w >= 0xD800 && w <= 0xDFFF) {
  310. w -= 0xD800;
  311. ww = data[++i].charCodeAt(0) - 0xDC00 + (w << 10);
  312. out[j] = 240 + ((ww>>>18) & 0x07);
  313. out[++j] = 144 + ((ww>>>12) & 0x3F);
  314. out[++j] = 128 + ((ww>>>6) & 0x3F);
  315. out[++j] = 128 + (ww & 0x3F);
  316. } else {
  317. out[j] = 224 + (w >> 12);
  318. out[++j] = 128 + ((w >> 6)&63);
  319. out[++j] = 128 + (w&63);
  320. }
  321. }
  322. break;
  323. case "ascii":
  324. if(has_buf && typeof data === "string") { out = new Buffer(data, M); j = out.length; break; }
  325. for(i = 0; i < len; ++i, ++j) {
  326. w = data[i].charCodeAt(0);
  327. if(w <= 0x007F) out[j] = w;
  328. else throw new Error("bad ascii " + w);
  329. }
  330. break;
  331. case "utf16le":
  332. if(has_buf && typeof data === "string") { out = new Buffer(data, M); j = out.length; break; }
  333. for(i = 0; i < len; ++i) {
  334. w = data[i].charCodeAt(0);
  335. out[j++] = w&255;
  336. out[j++] = w>>8;
  337. }
  338. break;
  339. case "utf16be":
  340. for(i = 0; i < len; ++i) {
  341. w = data[i].charCodeAt(0);
  342. out[j++] = w>>8;
  343. out[j++] = w&255;
  344. }
  345. break;
  346. case "utf32le":
  347. for(i = 0; i < len; ++i) {
  348. w = data[i].charCodeAt(0);
  349. if(w >= 0xD800 && w <= 0xDFFF) w = 0x10000 + ((w - 0xD800) << 10) + (data[++i].charCodeAt(0) - 0xDC00);
  350. out[j++] = w&255; w >>= 8;
  351. out[j++] = w&255; w >>= 8;
  352. out[j++] = w&255; w >>= 8;
  353. out[j++] = w&255;
  354. }
  355. break;
  356. case "utf32be":
  357. for(i = 0; i < len; ++i) {
  358. w = data[i].charCodeAt(0);
  359. if(w >= 0xD800 && w <= 0xDFFF) w = 0x10000 + ((w - 0xD800) << 10) + (data[++i].charCodeAt(0) - 0xDC00);
  360. out[j+3] = w&255; w >>= 8;
  361. out[j+2] = w&255; w >>= 8;
  362. out[j+1] = w&255; w >>= 8;
  363. out[j] = w&255; w >>= 8;
  364. j+=4;
  365. }
  366. break;
  367. case "utf7":
  368. for(i = 0; i < len; i++) {
  369. c = data[i];
  370. if(c === "+") { out[j++] = 0x2b; out[j++] = 0x2d; continue; }
  371. if(SetD.indexOf(c) > -1) { out[j++] = c.charCodeAt(0); continue; }
  372. tt = encode(1201, c);
  373. out[j++] = 0x2b;
  374. out[j++] = BM.charCodeAt(tt[0]>>2);
  375. out[j++] = BM.charCodeAt(((tt[0]&0x03)<<4) + ((tt[1]||0)>>4));
  376. out[j++] = BM.charCodeAt(((tt[1]&0x0F)<<2) + ((tt[2]||0)>>6));
  377. out[j++] = 0x2d;
  378. }
  379. break;
  380. default: throw new Error("Unsupported magic: " + cp + " " + magic[cp]);
  381. }
  382. else throw new Error("Unrecognized CP: " + cp);
  383. out.length = j;
  384. out = out.slice(0,j);
  385. if(typeof Buffer === 'undefined') return (ofmt == 'str') ? out.map(sfcc).join("") : out;
  386. if(ofmt === undefined || ofmt === 'buf') return out;
  387. if(ofmt !== 'arr') return out.toString('binary');
  388. return [].slice.call(out);
  389. };
  390. var decode = function decode(cp, data) {
  391. var F; if((F=cpdcache[cp])) return F(data);
  392. var len = data.length, out = new Array(len), w, i, j = 1, k = 0, ww;
  393. var C = cpt[cp], D, M;
  394. if(C && (D=C.dec)) {
  395. if(typeof data === "string") data = data.split("").map(cca);
  396. for(i = 0; i < len; i+=j) {
  397. j = 2;
  398. w = D[(data[i]<<8)+ data[i+1]];
  399. if(!w) {
  400. j = 1;
  401. w = D[data[i]];
  402. }
  403. if(!w) throw new Error('Unrecognized code: ' + data[i] + ' ' + data[i+j-1] + ' ' + i + ' ' + j + ' ' + D[data[i]]);
  404. out[k++] = w;
  405. }
  406. }
  407. else if((M=magic[cp])) switch(M) {
  408. case "utf8":
  409. i = 0;
  410. if(len >= 3 && data[0] == 0xEF) if(data[1] == 0xBB && data[2] == 0xBF) i = 3;
  411. for(; i < len; i+=j) {
  412. j = 1;
  413. if(data[i] < 128) w = data[i];
  414. else if(data[i] < 224) { w=(data[i]&31)*64+(data[i+1]&63); j=2; }
  415. else if(data[i] < 240) { w=((data[i]&15)<<12)+(data[i+1]&63)*64+(data[i+2]&63); j=3; }
  416. else { w=(data[i]&7)*262144+((data[i+1]&63)<<12)+(data[i+2]&63)*64+(data[i+3]&63); j=4; }
  417. if(w < 65536) { out[k++] = String.fromCharCode(w); }
  418. else {
  419. w -= 65536; ww = 0xD800 + ((w>>10)&1023); w = 0xDC00 + (w&1023);
  420. out[k++] = String.fromCharCode(ww); out[k++] = String.fromCharCode(w);
  421. }
  422. }
  423. break;
  424. case "ascii":
  425. if(has_buf && Buffer.isBuffer(data)) return data.toString(M);
  426. for(i = 0; i < len; i++) out[i] = String.fromCharCode(data[i]);
  427. k = len; break;
  428. case "utf16le":
  429. i = 0;
  430. if(len >= 2 && data[0] == 0xFF) if(data[1] == 0xFE) i = 2;
  431. if(has_buf && Buffer.isBuffer(data)) return data.toString(M);
  432. j = 2;
  433. for(; i < len; i+=j) {
  434. out[k++] = String.fromCharCode((data[i+1]<<8) + data[i]);
  435. }
  436. break;
  437. case "utf16be":
  438. i = 0;
  439. if(len >= 2 && data[0] == 0xFE) if(data[1] == 0xFF) i = 2;
  440. j = 2;
  441. for(; i < len; i+=j) {
  442. out[k++] = String.fromCharCode((data[i]<<8) + data[i+1]);
  443. }
  444. break;
  445. case "utf32le":
  446. i = 0;
  447. if(len >= 4 && data[0] == 0xFF) if(data[1] == 0xFE && data[2] == 0 && data[3] == 0) i = 4;
  448. j = 4;
  449. for(; i < len; i+=j) {
  450. w = (data[i+3]<<24) + (data[i+2]<<16) + (data[i+1]<<8) + (data[i]);
  451. if(w > 0xFFFF) {
  452. w -= 0x10000;
  453. out[k++] = String.fromCharCode(0xD800 + ((w >> 10) & 0x3FF));
  454. out[k++] = String.fromCharCode(0xDC00 + (w & 0x3FF));
  455. }
  456. else out[k++] = String.fromCharCode(w);
  457. }
  458. break;
  459. case "utf32be":
  460. i = 0;
  461. if(len >= 4 && data[3] == 0xFF) if(data[2] == 0xFE && data[1] == 0 && data[0] == 0) i = 4;
  462. j = 4;
  463. for(; i < len; i+=j) {
  464. w = (data[i]<<24) + (data[i+1]<<16) + (data[i+2]<<8) + (data[i+3]);
  465. if(w > 0xFFFF) {
  466. w -= 0x10000;
  467. out[k++] = String.fromCharCode(0xD800 + ((w >> 10) & 0x3FF));
  468. out[k++] = String.fromCharCode(0xDC00 + (w & 0x3FF));
  469. }
  470. else out[k++] = String.fromCharCode(w);
  471. }
  472. break;
  473. case "utf7":
  474. i = 0;
  475. if(len >= 4 && data[0] == 0x2B && data[1] == 0x2F && data[2] == 0x76) {
  476. if(len >= 5 && data[3] == 0x38 && data[4] == 0x2D) i = 5;
  477. else if(data[3] == 0x38 || data[3] == 0x39 || data[3] == 0x2B || data[3] == 0x2F) i = 4;
  478. }
  479. for(; i < len; i+=j) {
  480. if(data[i] !== 0x2b) { j=1; out[k++] = String.fromCharCode(data[i]); continue; }
  481. j=1;
  482. if(data[i+1] === 0x2d) { j = 2; out[k++] = "+"; continue; }
  483. while(String.fromCharCode(data[i+j]).match(/[A-Za-z0-9+\/]/)) j++;
  484. var dash = 0;
  485. if(data[i+j] === 0x2d) { ++j; dash=1; }
  486. var tt = [];
  487. var o64;
  488. var c1, c2, c3;
  489. var e1, e2, e3, e4;
  490. for(var l = 1; l < j - dash;) {
  491. e1 = BM.indexOf(String.fromCharCode(data[i+l++]));
  492. e2 = BM.indexOf(String.fromCharCode(data[i+l++]));
  493. c1 = e1 << 2 | e2 >> 4;
  494. tt.push(c1);
  495. e3 = BM.indexOf(String.fromCharCode(data[i+l++]));
  496. if(e3 === -1) break;
  497. c2 = (e2 & 15) << 4 | e3 >> 2;
  498. tt.push(c2);
  499. e4 = BM.indexOf(String.fromCharCode(data[i+l++]));
  500. if(e4 === -1) break;
  501. c3 = (e3 & 3) << 6 | e4;
  502. if(e4 < 64) tt.push(c3);
  503. }
  504. if((tt.length & 1) === 1) tt.length--;
  505. o64 = decode(1201, tt);
  506. for(l = 0; l < o64.length; ++l) out[k++] = o64[l];
  507. }
  508. break;
  509. default: throw new Error("Unsupported magic: " + cp + " " + magic[cp]);
  510. }
  511. else throw new Error("Unrecognized CP: " + cp);
  512. out.length = k;
  513. return out.join("");
  514. };
  515. var hascp = function hascp(cp) { return cpt[cp] || magic[cp]; };
  516. cpt.utils = { decode: decode, encode: encode, hascp: hascp, magic: magic, cache:cache };
  517. return cpt;
  518. }));