encoding.js 98 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289
  1. // This is free and unencumbered software released into the public domain.
  2. // See LICENSE.md for more information.
  3. // If we're in node require encoding-indexes and attach it to the global.
  4. import codeIndexes from './encoding-indexes.js';
  5. //
  6. // Utilities
  7. //
  8. /**
  9. * @param {number} a The number to test.
  10. * @param {number} min The minimum value in the range, inclusive.
  11. * @param {number} max The maximum value in the range, inclusive.
  12. * @return {boolean} True if a >= min and a <= max.
  13. */
  14. function inRange(a, min, max) {
  15. return min <= a && a <= max;
  16. }
  17. /**
  18. * @param {!Array.<*>} array The array to check.
  19. * @param {*} item The item to look for in the array.
  20. * @return {boolean} True if the item appears in the array.
  21. */
  22. function includes(array, item) {
  23. return array.indexOf(item) !== -1;
  24. }
  25. var floor = Math.floor;
  26. /**
  27. * @param {*} o
  28. * @return {Object}
  29. */
  30. function ToDictionary(o) {
  31. if (o === undefined) return {};
  32. if (o === Object(o)) return o;
  33. throw TypeError('Could not convert argument to dictionary');
  34. }
  35. /**
  36. * @param {string} string Input string of UTF-16 code units.
  37. * @return {!Array.<number>} Code points.
  38. */
  39. function stringToCodePoints(string) {
  40. // https://heycam.github.io/webidl/#dfn-obtain-unicode
  41. // 1. Let S be the DOMString value.
  42. var s = String(string);
  43. // 2. Let n be the length of S.
  44. var n = s.length;
  45. // 3. Initialize i to 0.
  46. var i = 0;
  47. // 4. Initialize U to be an empty sequence of Unicode characters.
  48. var u = [];
  49. // 5. While i < n:
  50. while (i < n) {
  51. // 1. Let c be the code unit in S at index i.
  52. var c = s.charCodeAt(i);
  53. // 2. Depending on the value of c:
  54. // c < 0xD800 or c > 0xDFFF
  55. if (c < 0xD800 || c > 0xDFFF) {
  56. // Append to U the Unicode character with code point c.
  57. u.push(c);
  58. }
  59. // 0xDC00 ≤ c ≤ 0xDFFF
  60. else if (0xDC00 <= c && c <= 0xDFFF) {
  61. // Append to U a U+FFFD REPLACEMENT CHARACTER.
  62. u.push(0xFFFD);
  63. }
  64. // 0xD800 ≤ c ≤ 0xDBFF
  65. else if (0xD800 <= c && c <= 0xDBFF) {
  66. // 1. If i = n−1, then append to U a U+FFFD REPLACEMENT
  67. // CHARACTER.
  68. if (i === n - 1) {
  69. u.push(0xFFFD);
  70. }
  71. // 2. Otherwise, i < n−1:
  72. else {
  73. // 1. Let d be the code unit in S at index i+1.
  74. var d = s.charCodeAt(i + 1);
  75. // 2. If 0xDC00 ≤ d ≤ 0xDFFF, then:
  76. if (0xDC00 <= d && d <= 0xDFFF) {
  77. // 1. Let a be c & 0x3FF.
  78. var a = c & 0x3FF;
  79. // 2. Let b be d & 0x3FF.
  80. var b = d & 0x3FF;
  81. // 3. Append to U the Unicode character with code point
  82. // 2^16+2^10*a+b.
  83. u.push(0x10000 + (a << 10) + b);
  84. // 4. Set i to i+1.
  85. i += 1;
  86. }
  87. // 3. Otherwise, d < 0xDC00 or d > 0xDFFF. Append to U a
  88. // U+FFFD REPLACEMENT CHARACTER.
  89. else {
  90. u.push(0xFFFD);
  91. }
  92. }
  93. }
  94. // 3. Set i to i+1.
  95. i += 1;
  96. }
  97. // 6. Return U.
  98. return u;
  99. }
  100. /**
  101. * @param {!Array.<number>} code_points Array of code points.
  102. * @return {string} string String of UTF-16 code units.
  103. */
  104. function codePointsToString(code_points) {
  105. var s = '';
  106. for (var i = 0; i < code_points.length; ++i) {
  107. var cp = code_points[i];
  108. if (cp <= 0xFFFF) {
  109. s += String.fromCharCode(cp);
  110. } else {
  111. cp -= 0x10000;
  112. s += String.fromCharCode((cp >> 10) + 0xD800,
  113. (cp & 0x3FF) + 0xDC00);
  114. }
  115. }
  116. return s;
  117. }
  118. //
  119. // Implementation of Encoding specification
  120. // https://encoding.spec.whatwg.org/
  121. //
  122. //
  123. // 4. Terminology
  124. //
  125. /**
  126. * An ASCII byte is a byte in the range 0x00 to 0x7F, inclusive.
  127. * @param {number} a The number to test.
  128. * @return {boolean} True if a is in the range 0x00 to 0x7F, inclusive.
  129. */
  130. function isASCIIByte(a) {
  131. return 0x00 <= a && a <= 0x7F;
  132. }
  133. /**
  134. * An ASCII code point is a code point in the range U+0000 to
  135. * U+007F, inclusive.
  136. */
  137. var isASCIICodePoint = isASCIIByte;
  138. /**
  139. * End-of-stream is a special token that signifies no more tokens
  140. * are in the stream.
  141. * @const
  142. */ var end_of_stream = -1;
  143. /**
  144. * A stream represents an ordered sequence of tokens.
  145. *
  146. * @constructor
  147. * @param {!(Array.<number>|Uint8Array)} tokens Array of tokens that provide
  148. * the stream.
  149. */
  150. function Stream(tokens) {
  151. /** @type {!Array.<number>} */
  152. this.tokens = [].slice.call(tokens);
  153. // Reversed as push/pop is more efficient than shift/unshift.
  154. this.tokens.reverse();
  155. }
  156. Stream.prototype = {
  157. /**
  158. * @return {boolean} True if end-of-stream has been hit.
  159. */
  160. endOfStream: function() {
  161. return !this.tokens.length;
  162. },
  163. /**
  164. * When a token is read from a stream, the first token in the
  165. * stream must be returned and subsequently removed, and
  166. * end-of-stream must be returned otherwise.
  167. *
  168. * @return {number} Get the next token from the stream, or
  169. * end_of_stream.
  170. */
  171. read: function() {
  172. if (!this.tokens.length)
  173. return end_of_stream;
  174. return this.tokens.pop();
  175. },
  176. /**
  177. * When one or more tokens are prepended to a stream, those tokens
  178. * must be inserted, in given order, before the first token in the
  179. * stream.
  180. *
  181. * @param {(number|!Array.<number>)} token The token(s) to prepend to the
  182. * stream.
  183. */
  184. prepend: function(token) {
  185. if (Array.isArray(token)) {
  186. var tokens = /**@type {!Array.<number>}*/(token);
  187. while (tokens.length)
  188. this.tokens.push(tokens.pop());
  189. } else {
  190. this.tokens.push(token);
  191. }
  192. },
  193. /**
  194. * When one or more tokens are pushed to a stream, those tokens
  195. * must be inserted, in given order, after the last token in the
  196. * stream.
  197. *
  198. * @param {(number|!Array.<number>)} token The tokens(s) to push to the
  199. * stream.
  200. */
  201. push: function(token) {
  202. if (Array.isArray(token)) {
  203. var tokens = /**@type {!Array.<number>}*/(token);
  204. while (tokens.length)
  205. this.tokens.unshift(tokens.shift());
  206. } else {
  207. this.tokens.unshift(token);
  208. }
  209. }
  210. };
  211. //
  212. // 5. Encodings
  213. //
  214. // 5.1 Encoders and decoders
  215. /** @const */
  216. var finished = -1;
  217. /**
  218. * @param {boolean} fatal If true, decoding errors raise an exception.
  219. * @param {number=} opt_code_point Override the standard fallback code point.
  220. * @return {number} The code point to insert on a decoding error.
  221. */
  222. function decoderError(fatal, opt_code_point) {
  223. if (fatal)
  224. throw TypeError('Decoder error');
  225. return opt_code_point || 0xFFFD;
  226. }
  227. /**
  228. * @param {number} code_point The code point that could not be encoded.
  229. * @return {number} Always throws, no value is actually returned.
  230. */
  231. function encoderError(code_point) {
  232. throw TypeError('The code point ' + code_point + ' could not be encoded.');
  233. }
  234. /** @interface */
  235. function Decoder() {}
  236. Decoder.prototype = {
  237. /**
  238. * @param {Stream} stream The stream of bytes being decoded.
  239. * @param {number} bite The next byte read from the stream.
  240. * @return {?(number|!Array.<number>)} The next code point(s)
  241. * decoded, or null if not enough data exists in the input
  242. * stream to decode a complete code point, or |finished|.
  243. */
  244. handler: function(stream, bite) {}
  245. };
  246. /** @interface */
  247. function Encoder() {}
  248. Encoder.prototype = {
  249. /**
  250. * @param {Stream} stream The stream of code points being encoded.
  251. * @param {number} code_point Next code point read from the stream.
  252. * @return {(number|!Array.<number>)} Byte(s) to emit, or |finished|.
  253. */
  254. handler: function(stream, code_point) {}
  255. };
  256. // 5.2 Names and labels
  257. // TODO: Define @typedef for Encoding: {name:string,labels:Array.<string>}
  258. // https://github.com/google/closure-compiler/issues/247
  259. /**
  260. * @param {string} label The encoding label.
  261. * @return {?{name:string,labels:Array.<string>}}
  262. */
  263. function getEncoding(label) {
  264. // 1. Remove any leading and trailing ASCII whitespace from label.
  265. label = String(label).trim().toLowerCase();
  266. // 2. If label is an ASCII case-insensitive match for any of the
  267. // labels listed in the table below, return the corresponding
  268. // encoding, and failure otherwise.
  269. if (Object.prototype.hasOwnProperty.call(label_to_encoding, label)) {
  270. return label_to_encoding[label];
  271. }
  272. return null;
  273. }
  274. /**
  275. * Encodings table: https://encoding.spec.whatwg.org/encodings.json
  276. * @const
  277. * @type {!Array.<{
  278. * heading: string,
  279. * encodings: Array.<{name:string,labels:Array.<string>}>
  280. * }>}
  281. */
  282. var encodings = [
  283. {
  284. "encodings": [
  285. {
  286. "labels": [
  287. "unicode-1-1-utf-8",
  288. "utf-8",
  289. "utf8"
  290. ],
  291. "name": "UTF-8"
  292. }
  293. ],
  294. "heading": "The Encoding"
  295. },
  296. {
  297. "encodings": [
  298. {
  299. "labels": [
  300. "866",
  301. "cp866",
  302. "csibm866",
  303. "ibm866"
  304. ],
  305. "name": "IBM866"
  306. },
  307. {
  308. "labels": [
  309. "csisolatin2",
  310. "iso-8859-2",
  311. "iso-ir-101",
  312. "iso8859-2",
  313. "iso88592",
  314. "iso_8859-2",
  315. "iso_8859-2:1987",
  316. "l2",
  317. "latin2"
  318. ],
  319. "name": "ISO-8859-2"
  320. },
  321. {
  322. "labels": [
  323. "csisolatin3",
  324. "iso-8859-3",
  325. "iso-ir-109",
  326. "iso8859-3",
  327. "iso88593",
  328. "iso_8859-3",
  329. "iso_8859-3:1988",
  330. "l3",
  331. "latin3"
  332. ],
  333. "name": "ISO-8859-3"
  334. },
  335. {
  336. "labels": [
  337. "csisolatin4",
  338. "iso-8859-4",
  339. "iso-ir-110",
  340. "iso8859-4",
  341. "iso88594",
  342. "iso_8859-4",
  343. "iso_8859-4:1988",
  344. "l4",
  345. "latin4"
  346. ],
  347. "name": "ISO-8859-4"
  348. },
  349. {
  350. "labels": [
  351. "csisolatincyrillic",
  352. "cyrillic",
  353. "iso-8859-5",
  354. "iso-ir-144",
  355. "iso8859-5",
  356. "iso88595",
  357. "iso_8859-5",
  358. "iso_8859-5:1988"
  359. ],
  360. "name": "ISO-8859-5"
  361. },
  362. {
  363. "labels": [
  364. "arabic",
  365. "asmo-708",
  366. "csiso88596e",
  367. "csiso88596i",
  368. "csisolatinarabic",
  369. "ecma-114",
  370. "iso-8859-6",
  371. "iso-8859-6-e",
  372. "iso-8859-6-i",
  373. "iso-ir-127",
  374. "iso8859-6",
  375. "iso88596",
  376. "iso_8859-6",
  377. "iso_8859-6:1987"
  378. ],
  379. "name": "ISO-8859-6"
  380. },
  381. {
  382. "labels": [
  383. "csisolatingreek",
  384. "ecma-118",
  385. "elot_928",
  386. "greek",
  387. "greek8",
  388. "iso-8859-7",
  389. "iso-ir-126",
  390. "iso8859-7",
  391. "iso88597",
  392. "iso_8859-7",
  393. "iso_8859-7:1987",
  394. "sun_eu_greek"
  395. ],
  396. "name": "ISO-8859-7"
  397. },
  398. {
  399. "labels": [
  400. "csiso88598e",
  401. "csisolatinhebrew",
  402. "hebrew",
  403. "iso-8859-8",
  404. "iso-8859-8-e",
  405. "iso-ir-138",
  406. "iso8859-8",
  407. "iso88598",
  408. "iso_8859-8",
  409. "iso_8859-8:1988",
  410. "visual"
  411. ],
  412. "name": "ISO-8859-8"
  413. },
  414. {
  415. "labels": [
  416. "csiso88598i",
  417. "iso-8859-8-i",
  418. "logical"
  419. ],
  420. "name": "ISO-8859-8-I"
  421. },
  422. {
  423. "labels": [
  424. "csisolatin6",
  425. "iso-8859-10",
  426. "iso-ir-157",
  427. "iso8859-10",
  428. "iso885910",
  429. "l6",
  430. "latin6"
  431. ],
  432. "name": "ISO-8859-10"
  433. },
  434. {
  435. "labels": [
  436. "iso-8859-13",
  437. "iso8859-13",
  438. "iso885913"
  439. ],
  440. "name": "ISO-8859-13"
  441. },
  442. {
  443. "labels": [
  444. "iso-8859-14",
  445. "iso8859-14",
  446. "iso885914"
  447. ],
  448. "name": "ISO-8859-14"
  449. },
  450. {
  451. "labels": [
  452. "csisolatin9",
  453. "iso-8859-15",
  454. "iso8859-15",
  455. "iso885915",
  456. "iso_8859-15",
  457. "l9"
  458. ],
  459. "name": "ISO-8859-15"
  460. },
  461. {
  462. "labels": [
  463. "iso-8859-16"
  464. ],
  465. "name": "ISO-8859-16"
  466. },
  467. {
  468. "labels": [
  469. "cskoi8r",
  470. "koi",
  471. "koi8",
  472. "koi8-r",
  473. "koi8_r"
  474. ],
  475. "name": "KOI8-R"
  476. },
  477. {
  478. "labels": [
  479. "koi8-ru",
  480. "koi8-u"
  481. ],
  482. "name": "KOI8-U"
  483. },
  484. {
  485. "labels": [
  486. "csmacintosh",
  487. "mac",
  488. "macintosh",
  489. "x-mac-roman"
  490. ],
  491. "name": "macintosh"
  492. },
  493. {
  494. "labels": [
  495. "dos-874",
  496. "iso-8859-11",
  497. "iso8859-11",
  498. "iso885911",
  499. "tis-620",
  500. "windows-874"
  501. ],
  502. "name": "windows-874"
  503. },
  504. {
  505. "labels": [
  506. "cp1250",
  507. "windows-1250",
  508. "x-cp1250"
  509. ],
  510. "name": "windows-1250"
  511. },
  512. {
  513. "labels": [
  514. "cp1251",
  515. "windows-1251",
  516. "x-cp1251"
  517. ],
  518. "name": "windows-1251"
  519. },
  520. {
  521. "labels": [
  522. "ansi_x3.4-1968",
  523. "ascii",
  524. "cp1252",
  525. "cp819",
  526. "csisolatin1",
  527. "ibm819",
  528. "iso-8859-1",
  529. "iso-ir-100",
  530. "iso8859-1",
  531. "iso88591",
  532. "iso_8859-1",
  533. "iso_8859-1:1987",
  534. "l1",
  535. "latin1",
  536. "us-ascii",
  537. "windows-1252",
  538. "x-cp1252"
  539. ],
  540. "name": "windows-1252"
  541. },
  542. {
  543. "labels": [
  544. "cp1253",
  545. "windows-1253",
  546. "x-cp1253"
  547. ],
  548. "name": "windows-1253"
  549. },
  550. {
  551. "labels": [
  552. "cp1254",
  553. "csisolatin5",
  554. "iso-8859-9",
  555. "iso-ir-148",
  556. "iso8859-9",
  557. "iso88599",
  558. "iso_8859-9",
  559. "iso_8859-9:1989",
  560. "l5",
  561. "latin5",
  562. "windows-1254",
  563. "x-cp1254"
  564. ],
  565. "name": "windows-1254"
  566. },
  567. {
  568. "labels": [
  569. "cp1255",
  570. "windows-1255",
  571. "x-cp1255"
  572. ],
  573. "name": "windows-1255"
  574. },
  575. {
  576. "labels": [
  577. "cp1256",
  578. "windows-1256",
  579. "x-cp1256"
  580. ],
  581. "name": "windows-1256"
  582. },
  583. {
  584. "labels": [
  585. "cp1257",
  586. "windows-1257",
  587. "x-cp1257"
  588. ],
  589. "name": "windows-1257"
  590. },
  591. {
  592. "labels": [
  593. "cp1258",
  594. "windows-1258",
  595. "x-cp1258"
  596. ],
  597. "name": "windows-1258"
  598. },
  599. {
  600. "labels": [
  601. "x-mac-cyrillic",
  602. "x-mac-ukrainian"
  603. ],
  604. "name": "x-mac-cyrillic"
  605. }
  606. ],
  607. "heading": "Legacy single-byte encodings"
  608. },
  609. {
  610. "encodings": [
  611. {
  612. "labels": [
  613. "chinese",
  614. "csgb2312",
  615. "csiso58gb231280",
  616. "gb2312",
  617. "gb_2312",
  618. "gb_2312-80",
  619. "gbk",
  620. "iso-ir-58",
  621. "x-gbk"
  622. ],
  623. "name": "GBK"
  624. },
  625. {
  626. "labels": [
  627. "gb18030"
  628. ],
  629. "name": "gb18030"
  630. }
  631. ],
  632. "heading": "Legacy multi-byte Chinese (simplified) encodings"
  633. },
  634. {
  635. "encodings": [
  636. {
  637. "labels": [
  638. "big5",
  639. "big5-hkscs",
  640. "cn-big5",
  641. "csbig5",
  642. "x-x-big5"
  643. ],
  644. "name": "Big5"
  645. }
  646. ],
  647. "heading": "Legacy multi-byte Chinese (traditional) encodings"
  648. },
  649. {
  650. "encodings": [
  651. {
  652. "labels": [
  653. "cseucpkdfmtjapanese",
  654. "euc-jp",
  655. "x-euc-jp"
  656. ],
  657. "name": "EUC-JP"
  658. },
  659. {
  660. "labels": [
  661. "csiso2022jp",
  662. "iso-2022-jp"
  663. ],
  664. "name": "ISO-2022-JP"
  665. },
  666. {
  667. "labels": [
  668. "csshiftjis",
  669. "ms932",
  670. "ms_kanji",
  671. "shift-jis",
  672. "shift_jis",
  673. "sjis",
  674. "windows-31j",
  675. "x-sjis"
  676. ],
  677. "name": "Shift_JIS"
  678. }
  679. ],
  680. "heading": "Legacy multi-byte Japanese encodings"
  681. },
  682. {
  683. "encodings": [
  684. {
  685. "labels": [
  686. "cseuckr",
  687. "csksc56011987",
  688. "euc-kr",
  689. "iso-ir-149",
  690. "korean",
  691. "ks_c_5601-1987",
  692. "ks_c_5601-1989",
  693. "ksc5601",
  694. "ksc_5601",
  695. "windows-949"
  696. ],
  697. "name": "EUC-KR"
  698. }
  699. ],
  700. "heading": "Legacy multi-byte Korean encodings"
  701. },
  702. {
  703. "encodings": [
  704. {
  705. "labels": [
  706. "csiso2022kr",
  707. "hz-gb-2312",
  708. "iso-2022-cn",
  709. "iso-2022-cn-ext",
  710. "iso-2022-kr"
  711. ],
  712. "name": "replacement"
  713. },
  714. {
  715. "labels": [
  716. "utf-16be"
  717. ],
  718. "name": "UTF-16BE"
  719. },
  720. {
  721. "labels": [
  722. "utf-16",
  723. "utf-16le"
  724. ],
  725. "name": "UTF-16LE"
  726. },
  727. {
  728. "labels": [
  729. "x-user-defined"
  730. ],
  731. "name": "x-user-defined"
  732. }
  733. ],
  734. "heading": "Legacy miscellaneous encodings"
  735. }
  736. ];
  737. // Label to encoding registry.
  738. /** @type {Object.<string,{name:string,labels:Array.<string>}>} */
  739. var label_to_encoding = {};
  740. encodings.forEach(function(category) {
  741. category.encodings.forEach(function(encoding) {
  742. encoding.labels.forEach(function(label) {
  743. label_to_encoding[label] = encoding;
  744. });
  745. });
  746. });
  747. // Registry of of encoder/decoder factories, by encoding name.
  748. /** @type {Object.<string, function({fatal:boolean}): Encoder>} */
  749. var encoders = {};
  750. /** @type {Object.<string, function({fatal:boolean}): Decoder>} */
  751. var decoders = {};
  752. //
  753. // 6. Indexes
  754. //
  755. /**
  756. * @param {number} pointer The |pointer| to search for.
  757. * @param {(!Array.<?number>|undefined)} index The |index| to search within.
  758. * @return {?number} The code point corresponding to |pointer| in |index|,
  759. * or null if |code point| is not in |index|.
  760. */
  761. function indexCodePointFor(pointer, index) {
  762. if (!index) return null;
  763. return index[pointer] || null;
  764. }
  765. /**
  766. * @param {number} code_point The |code point| to search for.
  767. * @param {!Array.<?number>} index The |index| to search within.
  768. * @return {?number} The first pointer corresponding to |code point| in
  769. * |index|, or null if |code point| is not in |index|.
  770. */
  771. function indexPointerFor(code_point, index) {
  772. var pointer = index.indexOf(code_point);
  773. return pointer === -1 ? null : pointer;
  774. }
  775. /**
  776. * @param {string} name Name of the index.
  777. * @return {(!Array.<number>|!Array.<Array.<number>>)}
  778. * */
  779. function index(name) {
  780. if (!codeIndexes) {
  781. throw Error("Indexes missing." +
  782. " Did you forget to include encoding-indexes.js first?");
  783. }
  784. return codeIndexes[name];
  785. }
  786. /**
  787. * @param {number} pointer The |pointer| to search for in the gb18030 index.
  788. * @return {?number} The code point corresponding to |pointer| in |index|,
  789. * or null if |code point| is not in the gb18030 index.
  790. */
  791. function indexGB18030RangesCodePointFor(pointer) {
  792. // 1. If pointer is greater than 39419 and less than 189000, or
  793. // pointer is greater than 1237575, return null.
  794. if ((pointer > 39419 && pointer < 189000) || (pointer > 1237575))
  795. return null;
  796. // 2. If pointer is 7457, return code point U+E7C7.
  797. if (pointer === 7457) return 0xE7C7;
  798. // 3. Let offset be the last pointer in index gb18030 ranges that
  799. // is equal to or less than pointer and let code point offset be
  800. // its corresponding code point.
  801. var offset = 0;
  802. var code_point_offset = 0;
  803. var idx = index('gb18030-ranges');
  804. var i;
  805. for (i = 0; i < idx.length; ++i) {
  806. /** @type {!Array.<number>} */
  807. var entry = idx[i];
  808. if (entry[0] <= pointer) {
  809. offset = entry[0];
  810. code_point_offset = entry[1];
  811. } else {
  812. break;
  813. }
  814. }
  815. // 4. Return a code point whose value is code point offset +
  816. // pointer − offset.
  817. return code_point_offset + pointer - offset;
  818. }
  819. /**
  820. * @param {number} code_point The |code point| to locate in the gb18030 index.
  821. * @return {number} The first pointer corresponding to |code point| in the
  822. * gb18030 index.
  823. */
  824. function indexGB18030RangesPointerFor(code_point) {
  825. // 1. If code point is U+E7C7, return pointer 7457.
  826. if (code_point === 0xE7C7) return 7457;
  827. // 2. Let offset be the last code point in index gb18030 ranges
  828. // that is equal to or less than code point and let pointer offset
  829. // be its corresponding pointer.
  830. var offset = 0;
  831. var pointer_offset = 0;
  832. var idx = index('gb18030-ranges');
  833. var i;
  834. for (i = 0; i < idx.length; ++i) {
  835. /** @type {!Array.<number>} */
  836. var entry = idx[i];
  837. if (entry[1] <= code_point) {
  838. offset = entry[1];
  839. pointer_offset = entry[0];
  840. } else {
  841. break;
  842. }
  843. }
  844. // 3. Return a pointer whose value is pointer offset + code point
  845. // − offset.
  846. return pointer_offset + code_point - offset;
  847. }
  848. /**
  849. * @param {number} code_point The |code_point| to search for in the Shift_JIS
  850. * index.
  851. * @return {?number} The code point corresponding to |pointer| in |index|,
  852. * or null if |code point| is not in the Shift_JIS index.
  853. */
  854. function indexShiftJISPointerFor(code_point) {
  855. // 1. Let index be index jis0208 excluding all entries whose
  856. // pointer is in the range 8272 to 8835, inclusive.
  857. shift_jis_index = shift_jis_index ||
  858. index('jis0208').map(function(code_point, pointer) {
  859. return inRange(pointer, 8272, 8835) ? null : code_point;
  860. });
  861. var index_ = shift_jis_index;
  862. // 2. Return the index pointer for code point in index.
  863. return index_.indexOf(code_point);
  864. }
  865. var shift_jis_index;
  866. /**
  867. * @param {number} code_point The |code_point| to search for in the big5
  868. * index.
  869. * @return {?number} The code point corresponding to |pointer| in |index|,
  870. * or null if |code point| is not in the big5 index.
  871. */
  872. function indexBig5PointerFor(code_point) {
  873. // 1. Let index be index Big5 excluding all entries whose pointer
  874. big5_index_no_hkscs = big5_index_no_hkscs ||
  875. index('big5').map(function(code_point, pointer) {
  876. return (pointer < (0xA1 - 0x81) * 157) ? null : code_point;
  877. });
  878. var index_ = big5_index_no_hkscs;
  879. // 2. If code point is U+2550, U+255E, U+2561, U+256A, U+5341, or
  880. // U+5345, return the last pointer corresponding to code point in
  881. // index.
  882. if (code_point === 0x2550 || code_point === 0x255E ||
  883. code_point === 0x2561 || code_point === 0x256A ||
  884. code_point === 0x5341 || code_point === 0x5345) {
  885. return index_.lastIndexOf(code_point);
  886. }
  887. // 3. Return the index pointer for code point in index.
  888. return indexPointerFor(code_point, index_);
  889. }
  890. var big5_index_no_hkscs;
  891. //
  892. // 8. API
  893. //
  894. /** @const */ var DEFAULT_ENCODING = 'utf-8';
  895. // 8.1 Interface TextDecoder
  896. /**
  897. * @constructor
  898. * @param {string=} label The label of the encoding;
  899. * defaults to 'utf-8'.
  900. * @param {Object=} options
  901. */
  902. function TextDecoder(label, options) {
  903. // Web IDL conventions
  904. if (!(this instanceof TextDecoder))
  905. throw TypeError('Called as a function. Did you forget \'new\'?');
  906. label = label !== undefined ? String(label) : DEFAULT_ENCODING;
  907. options = ToDictionary(options);
  908. // A TextDecoder object has an associated encoding, decoder,
  909. // stream, ignore BOM flag (initially unset), BOM seen flag
  910. // (initially unset), error mode (initially replacement), and do
  911. // not flush flag (initially unset).
  912. /** @private */
  913. this._encoding = null;
  914. /** @private @type {?Decoder} */
  915. this._decoder = null;
  916. /** @private @type {boolean} */
  917. this._ignoreBOM = false;
  918. /** @private @type {boolean} */
  919. this._BOMseen = false;
  920. /** @private @type {string} */
  921. this._error_mode = 'replacement';
  922. /** @private @type {boolean} */
  923. this._do_not_flush = false;
  924. // 1. Let encoding be the result of getting an encoding from
  925. // label.
  926. var encoding = getEncoding(label);
  927. // 2. If encoding is failure or replacement, throw a RangeError.
  928. if (encoding === null || encoding.name === 'replacement')
  929. throw RangeError('Unknown encoding: ' + label);
  930. if (!decoders[encoding.name]) {
  931. throw Error('Decoder not present.' +
  932. ' Did you forget to include encoding-indexes.js first?');
  933. }
  934. // 3. Let dec be a new TextDecoder object.
  935. var dec = this;
  936. // 4. Set dec's encoding to encoding.
  937. dec._encoding = encoding;
  938. // 5. If options's fatal member is true, set dec's error mode to
  939. // fatal.
  940. if (Boolean(options['fatal']))
  941. dec._error_mode = 'fatal';
  942. // 6. If options's ignoreBOM member is true, set dec's ignore BOM
  943. // flag.
  944. if (Boolean(options['ignoreBOM']))
  945. dec._ignoreBOM = true;
  946. // For pre-ES5 runtimes:
  947. if (!Object.defineProperty) {
  948. this.encoding = dec._encoding.name.toLowerCase();
  949. this.fatal = dec._error_mode === 'fatal';
  950. this.ignoreBOM = dec._ignoreBOM;
  951. }
  952. // 7. Return dec.
  953. return dec;
  954. }
  955. if (Object.defineProperty) {
  956. // The encoding attribute's getter must return encoding's name.
  957. Object.defineProperty(TextDecoder.prototype, 'encoding', {
  958. /** @this {TextDecoder} */
  959. get: function() { return this._encoding.name.toLowerCase(); }
  960. });
  961. // The fatal attribute's getter must return true if error mode
  962. // is fatal, and false otherwise.
  963. Object.defineProperty(TextDecoder.prototype, 'fatal', {
  964. /** @this {TextDecoder} */
  965. get: function() { return this._error_mode === 'fatal'; }
  966. });
  967. // The ignoreBOM attribute's getter must return true if ignore
  968. // BOM flag is set, and false otherwise.
  969. Object.defineProperty(TextDecoder.prototype, 'ignoreBOM', {
  970. /** @this {TextDecoder} */
  971. get: function() { return this._ignoreBOM; }
  972. });
  973. }
  974. /**
  975. * @param {BufferSource=} input The buffer of bytes to decode.
  976. * @param {Object=} options
  977. * @return {string} The decoded string.
  978. */
  979. TextDecoder.prototype.decode = function decode(input, options) {
  980. var bytes;
  981. if (typeof input === 'object' && input instanceof ArrayBuffer) {
  982. bytes = new Uint8Array(input);
  983. } else if (typeof input === 'object' && 'buffer' in input &&
  984. input.buffer instanceof ArrayBuffer) {
  985. bytes = new Uint8Array(input.buffer,
  986. input.byteOffset,
  987. input.byteLength);
  988. } else {
  989. bytes = new Uint8Array(0);
  990. }
  991. options = ToDictionary(options);
  992. // 1. If the do not flush flag is unset, set decoder to a new
  993. // encoding's decoder, set stream to a new stream, and unset the
  994. // BOM seen flag.
  995. if (!this._do_not_flush) {
  996. this._decoder = decoders[this._encoding.name]({
  997. fatal: this._error_mode === 'fatal'});
  998. this._BOMseen = false;
  999. }
  1000. // 2. If options's stream is true, set the do not flush flag, and
  1001. // unset the do not flush flag otherwise.
  1002. this._do_not_flush = Boolean(options['stream']);
  1003. // 3. If input is given, push a copy of input to stream.
  1004. // TODO: Align with spec algorithm - maintain stream on instance.
  1005. var input_stream = new Stream(bytes);
  1006. // 4. Let output be a new stream.
  1007. var output = [];
  1008. /** @type {?(number|!Array.<number>)} */
  1009. var result;
  1010. // 5. While true:
  1011. while (true) {
  1012. // 1. Let token be the result of reading from stream.
  1013. var token = input_stream.read();
  1014. // 2. If token is end-of-stream and the do not flush flag is
  1015. // set, return output, serialized.
  1016. // TODO: Align with spec algorithm.
  1017. if (token === end_of_stream)
  1018. break;
  1019. // 3. Otherwise, run these subsubsteps:
  1020. // 1. Let result be the result of processing token for decoder,
  1021. // stream, output, and error mode.
  1022. result = this._decoder.handler(input_stream, token);
  1023. // 2. If result is finished, return output, serialized.
  1024. if (result === finished)
  1025. break;
  1026. if (result !== null) {
  1027. if (Array.isArray(result))
  1028. output.push.apply(output, /**@type {!Array.<number>}*/(result));
  1029. else
  1030. output.push(result);
  1031. }
  1032. // 3. Otherwise, if result is error, throw a TypeError.
  1033. // (Thrown in handler)
  1034. // 4. Otherwise, do nothing.
  1035. }
  1036. // TODO: Align with spec algorithm.
  1037. if (!this._do_not_flush) {
  1038. do {
  1039. result = this._decoder.handler(input_stream, input_stream.read());
  1040. if (result === finished)
  1041. break;
  1042. if (result === null)
  1043. continue;
  1044. if (Array.isArray(result))
  1045. output.push.apply(output, /**@type {!Array.<number>}*/(result));
  1046. else
  1047. output.push(result);
  1048. } while (!input_stream.endOfStream());
  1049. this._decoder = null;
  1050. }
  1051. // A TextDecoder object also has an associated serialize stream
  1052. // algorithm...
  1053. /**
  1054. * @param {!Array.<number>} stream
  1055. * @return {string}
  1056. * @this {TextDecoder}
  1057. */
  1058. function serializeStream(stream) {
  1059. // 1. Let token be the result of reading from stream.
  1060. // (Done in-place on array, rather than as a stream)
  1061. // 2. If encoding is UTF-8, UTF-16BE, or UTF-16LE, and ignore
  1062. // BOM flag and BOM seen flag are unset, run these subsubsteps:
  1063. if (includes(['UTF-8', 'UTF-16LE', 'UTF-16BE'], this._encoding.name) &&
  1064. !this._ignoreBOM && !this._BOMseen) {
  1065. if (stream.length > 0 && stream[0] === 0xFEFF) {
  1066. // 1. If token is U+FEFF, set BOM seen flag.
  1067. this._BOMseen = true;
  1068. stream.shift();
  1069. } else if (stream.length > 0) {
  1070. // 2. Otherwise, if token is not end-of-stream, set BOM seen
  1071. // flag and append token to stream.
  1072. this._BOMseen = true;
  1073. } else {
  1074. // 3. Otherwise, if token is not end-of-stream, append token
  1075. // to output.
  1076. // (no-op)
  1077. }
  1078. }
  1079. // 4. Otherwise, return output.
  1080. return codePointsToString(stream);
  1081. }
  1082. return serializeStream.call(this, output);
  1083. };
  1084. // 8.2 Interface TextEncoder
  1085. /**
  1086. * @constructor
  1087. * @param {string=} label The label of the encoding. NONSTANDARD.
  1088. * @param {Object=} options NONSTANDARD.
  1089. */
  1090. function TextEncoder(label, options) {
  1091. // Web IDL conventions
  1092. if (!(this instanceof TextEncoder))
  1093. throw TypeError('Called as a function. Did you forget \'new\'?');
  1094. options = ToDictionary(options);
  1095. // A TextEncoder object has an associated encoding and encoder.
  1096. /** @private */
  1097. this._encoding = null;
  1098. /** @private @type {?Encoder} */
  1099. this._encoder = null;
  1100. // Non-standard
  1101. /** @private @type {boolean} */
  1102. this._do_not_flush = false;
  1103. /** @private @type {string} */
  1104. this._fatal = Boolean(options['fatal']) ? 'fatal' : 'replacement';
  1105. // 1. Let enc be a new TextEncoder object.
  1106. var enc = this;
  1107. // 2. Set enc's encoding to UTF-8's encoder.
  1108. if (Boolean(options['NONSTANDARD_allowLegacyEncoding'])) {
  1109. // NONSTANDARD behavior.
  1110. label = label !== undefined ? String(label) : DEFAULT_ENCODING;
  1111. var encoding = getEncoding(label);
  1112. if (encoding === null || encoding.name === 'replacement')
  1113. throw RangeError('Unknown encoding: ' + label);
  1114. if (!encoders[encoding.name]) {
  1115. throw Error('Encoder not present.' +
  1116. ' Did you forget to include encoding-indexes.js first?');
  1117. }
  1118. enc._encoding = encoding;
  1119. } else {
  1120. // Standard behavior.
  1121. enc._encoding = getEncoding('utf-8');
  1122. // if (label !== undefined && 'console' in global) {
  1123. // console.warn('TextEncoder constructor called with encoding label, '
  1124. // + 'which is ignored.');
  1125. // }
  1126. }
  1127. // For pre-ES5 runtimes:
  1128. if (!Object.defineProperty)
  1129. this.encoding = enc._encoding.name.toLowerCase();
  1130. // 3. Return enc.
  1131. return enc;
  1132. }
  1133. if (Object.defineProperty) {
  1134. // The encoding attribute's getter must return encoding's name.
  1135. Object.defineProperty(TextEncoder.prototype, 'encoding', {
  1136. /** @this {TextEncoder} */
  1137. get: function() { return this._encoding.name.toLowerCase(); }
  1138. });
  1139. }
  1140. /**
  1141. * @param {string=} opt_string The string to encode.
  1142. * @param {Object=} options
  1143. * @return {!Uint8Array} Encoded bytes, as a Uint8Array.
  1144. */
  1145. TextEncoder.prototype.encode = function encode(opt_string, options) {
  1146. opt_string = opt_string === undefined ? '' : String(opt_string);
  1147. options = ToDictionary(options);
  1148. // NOTE: This option is nonstandard. None of the encodings
  1149. // permitted for encoding (i.e. UTF-8, UTF-16) are stateful when
  1150. // the input is a USVString so streaming is not necessary.
  1151. if (!this._do_not_flush)
  1152. this._encoder = encoders[this._encoding.name]({
  1153. fatal: this._fatal === 'fatal'});
  1154. this._do_not_flush = Boolean(options['stream']);
  1155. // 1. Convert input to a stream.
  1156. var input = new Stream(stringToCodePoints(opt_string));
  1157. // 2. Let output be a new stream
  1158. var output = [];
  1159. /** @type {?(number|!Array.<number>)} */
  1160. var result;
  1161. // 3. While true, run these substeps:
  1162. while (true) {
  1163. // 1. Let token be the result of reading from input.
  1164. var token = input.read();
  1165. if (token === end_of_stream)
  1166. break;
  1167. // 2. Let result be the result of processing token for encoder,
  1168. // input, output.
  1169. result = this._encoder.handler(input, token);
  1170. if (result === finished)
  1171. break;
  1172. if (Array.isArray(result))
  1173. output.push.apply(output, /**@type {!Array.<number>}*/(result));
  1174. else
  1175. output.push(result);
  1176. }
  1177. // TODO: Align with spec algorithm.
  1178. if (!this._do_not_flush) {
  1179. while (true) {
  1180. result = this._encoder.handler(input, input.read());
  1181. if (result === finished)
  1182. break;
  1183. if (Array.isArray(result))
  1184. output.push.apply(output, /**@type {!Array.<number>}*/(result));
  1185. else
  1186. output.push(result);
  1187. }
  1188. this._encoder = null;
  1189. }
  1190. // 3. If result is finished, convert output into a byte sequence,
  1191. // and then return a Uint8Array object wrapping an ArrayBuffer
  1192. // containing output.
  1193. return new Uint8Array(output);
  1194. };
  1195. //
  1196. // 9. The encoding
  1197. //
  1198. // 9.1 utf-8
  1199. // 9.1.1 utf-8 decoder
  1200. /**
  1201. * @constructor
  1202. * @implements {Decoder}
  1203. * @param {{fatal: boolean}} options
  1204. */
  1205. function UTF8Decoder(options) {
  1206. var fatal = options.fatal;
  1207. // utf-8's decoder's has an associated utf-8 code point, utf-8
  1208. // bytes seen, and utf-8 bytes needed (all initially 0), a utf-8
  1209. // lower boundary (initially 0x80), and a utf-8 upper boundary
  1210. // (initially 0xBF).
  1211. var /** @type {number} */ utf8_code_point = 0,
  1212. /** @type {number} */ utf8_bytes_seen = 0,
  1213. /** @type {number} */ utf8_bytes_needed = 0,
  1214. /** @type {number} */ utf8_lower_boundary = 0x80,
  1215. /** @type {number} */ utf8_upper_boundary = 0xBF;
  1216. /**
  1217. * @param {Stream} stream The stream of bytes being decoded.
  1218. * @param {number} bite The next byte read from the stream.
  1219. * @return {?(number|!Array.<number>)} The next code point(s)
  1220. * decoded, or null if not enough data exists in the input
  1221. * stream to decode a complete code point.
  1222. */
  1223. this.handler = function(stream, bite) {
  1224. // 1. If byte is end-of-stream and utf-8 bytes needed is not 0,
  1225. // set utf-8 bytes needed to 0 and return error.
  1226. if (bite === end_of_stream && utf8_bytes_needed !== 0) {
  1227. utf8_bytes_needed = 0;
  1228. return decoderError(fatal);
  1229. }
  1230. // 2. If byte is end-of-stream, return finished.
  1231. if (bite === end_of_stream)
  1232. return finished;
  1233. // 3. If utf-8 bytes needed is 0, based on byte:
  1234. if (utf8_bytes_needed === 0) {
  1235. // 0x00 to 0x7F
  1236. if (inRange(bite, 0x00, 0x7F)) {
  1237. // Return a code point whose value is byte.
  1238. return bite;
  1239. }
  1240. // 0xC2 to 0xDF
  1241. else if (inRange(bite, 0xC2, 0xDF)) {
  1242. // 1. Set utf-8 bytes needed to 1.
  1243. utf8_bytes_needed = 1;
  1244. // 2. Set UTF-8 code point to byte & 0x1F.
  1245. utf8_code_point = bite & 0x1F;
  1246. }
  1247. // 0xE0 to 0xEF
  1248. else if (inRange(bite, 0xE0, 0xEF)) {
  1249. // 1. If byte is 0xE0, set utf-8 lower boundary to 0xA0.
  1250. if (bite === 0xE0)
  1251. utf8_lower_boundary = 0xA0;
  1252. // 2. If byte is 0xED, set utf-8 upper boundary to 0x9F.
  1253. if (bite === 0xED)
  1254. utf8_upper_boundary = 0x9F;
  1255. // 3. Set utf-8 bytes needed to 2.
  1256. utf8_bytes_needed = 2;
  1257. // 4. Set UTF-8 code point to byte & 0xF.
  1258. utf8_code_point = bite & 0xF;
  1259. }
  1260. // 0xF0 to 0xF4
  1261. else if (inRange(bite, 0xF0, 0xF4)) {
  1262. // 1. If byte is 0xF0, set utf-8 lower boundary to 0x90.
  1263. if (bite === 0xF0)
  1264. utf8_lower_boundary = 0x90;
  1265. // 2. If byte is 0xF4, set utf-8 upper boundary to 0x8F.
  1266. if (bite === 0xF4)
  1267. utf8_upper_boundary = 0x8F;
  1268. // 3. Set utf-8 bytes needed to 3.
  1269. utf8_bytes_needed = 3;
  1270. // 4. Set UTF-8 code point to byte & 0x7.
  1271. utf8_code_point = bite & 0x7;
  1272. }
  1273. // Otherwise
  1274. else {
  1275. // Return error.
  1276. return decoderError(fatal);
  1277. }
  1278. // Return continue.
  1279. return null;
  1280. }
  1281. // 4. If byte is not in the range utf-8 lower boundary to utf-8
  1282. // upper boundary, inclusive, run these substeps:
  1283. if (!inRange(bite, utf8_lower_boundary, utf8_upper_boundary)) {
  1284. // 1. Set utf-8 code point, utf-8 bytes needed, and utf-8
  1285. // bytes seen to 0, set utf-8 lower boundary to 0x80, and set
  1286. // utf-8 upper boundary to 0xBF.
  1287. utf8_code_point = utf8_bytes_needed = utf8_bytes_seen = 0;
  1288. utf8_lower_boundary = 0x80;
  1289. utf8_upper_boundary = 0xBF;
  1290. // 2. Prepend byte to stream.
  1291. stream.prepend(bite);
  1292. // 3. Return error.
  1293. return decoderError(fatal);
  1294. }
  1295. // 5. Set utf-8 lower boundary to 0x80 and utf-8 upper boundary
  1296. // to 0xBF.
  1297. utf8_lower_boundary = 0x80;
  1298. utf8_upper_boundary = 0xBF;
  1299. // 6. Set UTF-8 code point to (UTF-8 code point << 6) | (byte &
  1300. // 0x3F)
  1301. utf8_code_point = (utf8_code_point << 6) | (bite & 0x3F);
  1302. // 7. Increase utf-8 bytes seen by one.
  1303. utf8_bytes_seen += 1;
  1304. // 8. If utf-8 bytes seen is not equal to utf-8 bytes needed,
  1305. // continue.
  1306. if (utf8_bytes_seen !== utf8_bytes_needed)
  1307. return null;
  1308. // 9. Let code point be utf-8 code point.
  1309. var code_point = utf8_code_point;
  1310. // 10. Set utf-8 code point, utf-8 bytes needed, and utf-8 bytes
  1311. // seen to 0.
  1312. utf8_code_point = utf8_bytes_needed = utf8_bytes_seen = 0;
  1313. // 11. Return a code point whose value is code point.
  1314. return code_point;
  1315. };
  1316. }
  1317. // 9.1.2 utf-8 encoder
  1318. /**
  1319. * @constructor
  1320. * @implements {Encoder}
  1321. * @param {{fatal: boolean}} options
  1322. */
  1323. function UTF8Encoder(options) {
  1324. var fatal = options.fatal;
  1325. /**
  1326. * @param {Stream} stream Input stream.
  1327. * @param {number} code_point Next code point read from the stream.
  1328. * @return {(number|!Array.<number>)} Byte(s) to emit.
  1329. */
  1330. this.handler = function(stream, code_point) {
  1331. // 1. If code point is end-of-stream, return finished.
  1332. if (code_point === end_of_stream)
  1333. return finished;
  1334. // 2. If code point is an ASCII code point, return a byte whose
  1335. // value is code point.
  1336. if (isASCIICodePoint(code_point))
  1337. return code_point;
  1338. // 3. Set count and offset based on the range code point is in:
  1339. var count, offset;
  1340. // U+0080 to U+07FF, inclusive:
  1341. if (inRange(code_point, 0x0080, 0x07FF)) {
  1342. // 1 and 0xC0
  1343. count = 1;
  1344. offset = 0xC0;
  1345. }
  1346. // U+0800 to U+FFFF, inclusive:
  1347. else if (inRange(code_point, 0x0800, 0xFFFF)) {
  1348. // 2 and 0xE0
  1349. count = 2;
  1350. offset = 0xE0;
  1351. }
  1352. // U+10000 to U+10FFFF, inclusive:
  1353. else if (inRange(code_point, 0x10000, 0x10FFFF)) {
  1354. // 3 and 0xF0
  1355. count = 3;
  1356. offset = 0xF0;
  1357. }
  1358. // 4. Let bytes be a byte sequence whose first byte is (code
  1359. // point >> (6 × count)) + offset.
  1360. var bytes = [(code_point >> (6 * count)) + offset];
  1361. // 5. Run these substeps while count is greater than 0:
  1362. while (count > 0) {
  1363. // 1. Set temp to code point >> (6 × (count − 1)).
  1364. var temp = code_point >> (6 * (count - 1));
  1365. // 2. Append to bytes 0x80 | (temp & 0x3F).
  1366. bytes.push(0x80 | (temp & 0x3F));
  1367. // 3. Decrease count by one.
  1368. count -= 1;
  1369. }
  1370. // 6. Return bytes bytes, in order.
  1371. return bytes;
  1372. };
  1373. }
  1374. /** @param {{fatal: boolean}} options */
  1375. encoders['UTF-8'] = function(options) {
  1376. return new UTF8Encoder(options);
  1377. };
  1378. /** @param {{fatal: boolean}} options */
  1379. decoders['UTF-8'] = function(options) {
  1380. return new UTF8Decoder(options);
  1381. };
  1382. //
  1383. // 10. Legacy single-byte encodings
  1384. //
  1385. // 10.1 single-byte decoder
  1386. /**
  1387. * @constructor
  1388. * @implements {Decoder}
  1389. * @param {!Array.<number>} index The encoding index.
  1390. * @param {{fatal: boolean}} options
  1391. */
  1392. function SingleByteDecoder(index, options) {
  1393. var fatal = options.fatal;
  1394. /**
  1395. * @param {Stream} stream The stream of bytes being decoded.
  1396. * @param {number} bite The next byte read from the stream.
  1397. * @return {?(number|!Array.<number>)} The next code point(s)
  1398. * decoded, or null if not enough data exists in the input
  1399. * stream to decode a complete code point.
  1400. */
  1401. this.handler = function(stream, bite) {
  1402. // 1. If byte is end-of-stream, return finished.
  1403. if (bite === end_of_stream)
  1404. return finished;
  1405. // 2. If byte is an ASCII byte, return a code point whose value
  1406. // is byte.
  1407. if (isASCIIByte(bite))
  1408. return bite;
  1409. // 3. Let code point be the index code point for byte − 0x80 in
  1410. // index single-byte.
  1411. var code_point = index[bite - 0x80];
  1412. // 4. If code point is null, return error.
  1413. if (code_point === null)
  1414. return decoderError(fatal);
  1415. // 5. Return a code point whose value is code point.
  1416. return code_point;
  1417. };
  1418. }
  1419. // 10.2 single-byte encoder
  1420. /**
  1421. * @constructor
  1422. * @implements {Encoder}
  1423. * @param {!Array.<?number>} index The encoding index.
  1424. * @param {{fatal: boolean}} options
  1425. */
  1426. function SingleByteEncoder(index, options) {
  1427. var fatal = options.fatal;
  1428. /**
  1429. * @param {Stream} stream Input stream.
  1430. * @param {number} code_point Next code point read from the stream.
  1431. * @return {(number|!Array.<number>)} Byte(s) to emit.
  1432. */
  1433. this.handler = function(stream, code_point) {
  1434. // 1. If code point is end-of-stream, return finished.
  1435. if (code_point === end_of_stream)
  1436. return finished;
  1437. // 2. If code point is an ASCII code point, return a byte whose
  1438. // value is code point.
  1439. if (isASCIICodePoint(code_point))
  1440. return code_point;
  1441. // 3. Let pointer be the index pointer for code point in index
  1442. // single-byte.
  1443. var pointer = indexPointerFor(code_point, index);
  1444. // 4. If pointer is null, return error with code point.
  1445. if (pointer === null)
  1446. encoderError(code_point);
  1447. // 5. Return a byte whose value is pointer + 0x80.
  1448. return pointer + 0x80;
  1449. };
  1450. }
  1451. (function() {
  1452. if (!codeIndexes)
  1453. return;
  1454. encodings.forEach(function(category) {
  1455. if (category.heading !== 'Legacy single-byte encodings')
  1456. return;
  1457. category.encodings.forEach(function(encoding) {
  1458. var name = encoding.name;
  1459. var idx = index(name.toLowerCase());
  1460. /** @param {{fatal: boolean}} options */
  1461. decoders[name] = function(options) {
  1462. return new SingleByteDecoder(idx, options);
  1463. };
  1464. /** @param {{fatal: boolean}} options */
  1465. encoders[name] = function(options) {
  1466. return new SingleByteEncoder(idx, options);
  1467. };
  1468. });
  1469. });
  1470. }());
  1471. //
  1472. // 11. Legacy multi-byte Chinese (simplified) encodings
  1473. //
  1474. // 11.1 gbk
  1475. // 11.1.1 gbk decoder
  1476. // gbk's decoder is gb18030's decoder.
  1477. /** @param {{fatal: boolean}} options */
  1478. decoders['GBK'] = function(options) {
  1479. return new GB18030Decoder(options);
  1480. };
  1481. // 11.1.2 gbk encoder
  1482. // gbk's encoder is gb18030's encoder with its gbk flag set.
  1483. /** @param {{fatal: boolean}} options */
  1484. encoders['GBK'] = function(options) {
  1485. return new GB18030Encoder(options, true);
  1486. };
  1487. // 11.2 gb18030
  1488. // 11.2.1 gb18030 decoder
  1489. /**
  1490. * @constructor
  1491. * @implements {Decoder}
  1492. * @param {{fatal: boolean}} options
  1493. */
  1494. function GB18030Decoder(options) {
  1495. var fatal = options.fatal;
  1496. // gb18030's decoder has an associated gb18030 first, gb18030
  1497. // second, and gb18030 third (all initially 0x00).
  1498. var /** @type {number} */ gb18030_first = 0x00,
  1499. /** @type {number} */ gb18030_second = 0x00,
  1500. /** @type {number} */ gb18030_third = 0x00;
  1501. /**
  1502. * @param {Stream} stream The stream of bytes being decoded.
  1503. * @param {number} bite The next byte read from the stream.
  1504. * @return {?(number|!Array.<number>)} The next code point(s)
  1505. * decoded, or null if not enough data exists in the input
  1506. * stream to decode a complete code point.
  1507. */
  1508. this.handler = function(stream, bite) {
  1509. // 1. If byte is end-of-stream and gb18030 first, gb18030
  1510. // second, and gb18030 third are 0x00, return finished.
  1511. if (bite === end_of_stream && gb18030_first === 0x00 &&
  1512. gb18030_second === 0x00 && gb18030_third === 0x00) {
  1513. return finished;
  1514. }
  1515. // 2. If byte is end-of-stream, and gb18030 first, gb18030
  1516. // second, or gb18030 third is not 0x00, set gb18030 first,
  1517. // gb18030 second, and gb18030 third to 0x00, and return error.
  1518. if (bite === end_of_stream &&
  1519. (gb18030_first !== 0x00 || gb18030_second !== 0x00 ||
  1520. gb18030_third !== 0x00)) {
  1521. gb18030_first = 0x00;
  1522. gb18030_second = 0x00;
  1523. gb18030_third = 0x00;
  1524. decoderError(fatal);
  1525. }
  1526. var code_point;
  1527. // 3. If gb18030 third is not 0x00, run these substeps:
  1528. if (gb18030_third !== 0x00) {
  1529. // 1. Let code point be null.
  1530. code_point = null;
  1531. // 2. If byte is in the range 0x30 to 0x39, inclusive, set
  1532. // code point to the index gb18030 ranges code point for
  1533. // (((gb18030 first − 0x81) × 10 + gb18030 second − 0x30) ×
  1534. // 126 + gb18030 third − 0x81) × 10 + byte − 0x30.
  1535. if (inRange(bite, 0x30, 0x39)) {
  1536. code_point = indexGB18030RangesCodePointFor(
  1537. (((gb18030_first - 0x81) * 10 + gb18030_second - 0x30) * 126 +
  1538. gb18030_third - 0x81) * 10 + bite - 0x30);
  1539. }
  1540. // 3. Let buffer be a byte sequence consisting of gb18030
  1541. // second, gb18030 third, and byte, in order.
  1542. var buffer = [gb18030_second, gb18030_third, bite];
  1543. // 4. Set gb18030 first, gb18030 second, and gb18030 third to
  1544. // 0x00.
  1545. gb18030_first = 0x00;
  1546. gb18030_second = 0x00;
  1547. gb18030_third = 0x00;
  1548. // 5. If code point is null, prepend buffer to stream and
  1549. // return error.
  1550. if (code_point === null) {
  1551. stream.prepend(buffer);
  1552. return decoderError(fatal);
  1553. }
  1554. // 6. Return a code point whose value is code point.
  1555. return code_point;
  1556. }
  1557. // 4. If gb18030 second is not 0x00, run these substeps:
  1558. if (gb18030_second !== 0x00) {
  1559. // 1. If byte is in the range 0x81 to 0xFE, inclusive, set
  1560. // gb18030 third to byte and return continue.
  1561. if (inRange(bite, 0x81, 0xFE)) {
  1562. gb18030_third = bite;
  1563. return null;
  1564. }
  1565. // 2. Prepend gb18030 second followed by byte to stream, set
  1566. // gb18030 first and gb18030 second to 0x00, and return error.
  1567. stream.prepend([gb18030_second, bite]);
  1568. gb18030_first = 0x00;
  1569. gb18030_second = 0x00;
  1570. return decoderError(fatal);
  1571. }
  1572. // 5. If gb18030 first is not 0x00, run these substeps:
  1573. if (gb18030_first !== 0x00) {
  1574. // 1. If byte is in the range 0x30 to 0x39, inclusive, set
  1575. // gb18030 second to byte and return continue.
  1576. if (inRange(bite, 0x30, 0x39)) {
  1577. gb18030_second = bite;
  1578. return null;
  1579. }
  1580. // 2. Let lead be gb18030 first, let pointer be null, and set
  1581. // gb18030 first to 0x00.
  1582. var lead = gb18030_first;
  1583. var pointer = null;
  1584. gb18030_first = 0x00;
  1585. // 3. Let offset be 0x40 if byte is less than 0x7F and 0x41
  1586. // otherwise.
  1587. var offset = bite < 0x7F ? 0x40 : 0x41;
  1588. // 4. If byte is in the range 0x40 to 0x7E, inclusive, or 0x80
  1589. // to 0xFE, inclusive, set pointer to (lead − 0x81) × 190 +
  1590. // (byte − offset).
  1591. if (inRange(bite, 0x40, 0x7E) || inRange(bite, 0x80, 0xFE))
  1592. pointer = (lead - 0x81) * 190 + (bite - offset);
  1593. // 5. Let code point be null if pointer is null and the index
  1594. // code point for pointer in index gb18030 otherwise.
  1595. code_point = pointer === null ? null :
  1596. indexCodePointFor(pointer, index('gb18030'));
  1597. // 6. If code point is null and byte is an ASCII byte, prepend
  1598. // byte to stream.
  1599. if (code_point === null && isASCIIByte(bite))
  1600. stream.prepend(bite);
  1601. // 7. If code point is null, return error.
  1602. if (code_point === null)
  1603. return decoderError(fatal);
  1604. // 8. Return a code point whose value is code point.
  1605. return code_point;
  1606. }
  1607. // 6. If byte is an ASCII byte, return a code point whose value
  1608. // is byte.
  1609. if (isASCIIByte(bite))
  1610. return bite;
  1611. // 7. If byte is 0x80, return code point U+20AC.
  1612. if (bite === 0x80)
  1613. return 0x20AC;
  1614. // 8. If byte is in the range 0x81 to 0xFE, inclusive, set
  1615. // gb18030 first to byte and return continue.
  1616. if (inRange(bite, 0x81, 0xFE)) {
  1617. gb18030_first = bite;
  1618. return null;
  1619. }
  1620. // 9. Return error.
  1621. return decoderError(fatal);
  1622. };
  1623. }
  1624. // 11.2.2 gb18030 encoder
  1625. /**
  1626. * @constructor
  1627. * @implements {Encoder}
  1628. * @param {{fatal: boolean}} options
  1629. * @param {boolean=} gbk_flag
  1630. */
  1631. function GB18030Encoder(options, gbk_flag) {
  1632. var fatal = options.fatal;
  1633. // gb18030's decoder has an associated gbk flag (initially unset).
  1634. /**
  1635. * @param {Stream} stream Input stream.
  1636. * @param {number} code_point Next code point read from the stream.
  1637. * @return {(number|!Array.<number>)} Byte(s) to emit.
  1638. */
  1639. this.handler = function(stream, code_point) {
  1640. // 1. If code point is end-of-stream, return finished.
  1641. if (code_point === end_of_stream)
  1642. return finished;
  1643. // 2. If code point is an ASCII code point, return a byte whose
  1644. // value is code point.
  1645. if (isASCIICodePoint(code_point))
  1646. return code_point;
  1647. // 3. If code point is U+E5E5, return error with code point.
  1648. if (code_point === 0xE5E5)
  1649. return encoderError(code_point);
  1650. // 4. If the gbk flag is set and code point is U+20AC, return
  1651. // byte 0x80.
  1652. if (gbk_flag && code_point === 0x20AC)
  1653. return 0x80;
  1654. // 5. Let pointer be the index pointer for code point in index
  1655. // gb18030.
  1656. var pointer = indexPointerFor(code_point, index('gb18030'));
  1657. // 6. If pointer is not null, run these substeps:
  1658. if (pointer !== null) {
  1659. // 1. Let lead be floor(pointer / 190) + 0x81.
  1660. var lead = floor(pointer / 190) + 0x81;
  1661. // 2. Let trail be pointer % 190.
  1662. var trail = pointer % 190;
  1663. // 3. Let offset be 0x40 if trail is less than 0x3F and 0x41 otherwise.
  1664. var offset = trail < 0x3F ? 0x40 : 0x41;
  1665. // 4. Return two bytes whose values are lead and trail + offset.
  1666. return [lead, trail + offset];
  1667. }
  1668. // 7. If gbk flag is set, return error with code point.
  1669. if (gbk_flag)
  1670. return encoderError(code_point);
  1671. // 8. Set pointer to the index gb18030 ranges pointer for code
  1672. // point.
  1673. pointer = indexGB18030RangesPointerFor(code_point);
  1674. // 9. Let byte1 be floor(pointer / 10 / 126 / 10).
  1675. var byte1 = floor(pointer / 10 / 126 / 10);
  1676. // 10. Set pointer to pointer − byte1 × 10 × 126 × 10.
  1677. pointer = pointer - byte1 * 10 * 126 * 10;
  1678. // 11. Let byte2 be floor(pointer / 10 / 126).
  1679. var byte2 = floor(pointer / 10 / 126);
  1680. // 12. Set pointer to pointer − byte2 × 10 × 126.
  1681. pointer = pointer - byte2 * 10 * 126;
  1682. // 13. Let byte3 be floor(pointer / 10).
  1683. var byte3 = floor(pointer / 10);
  1684. // 14. Let byte4 be pointer − byte3 × 10.
  1685. var byte4 = pointer - byte3 * 10;
  1686. // 15. Return four bytes whose values are byte1 + 0x81, byte2 +
  1687. // 0x30, byte3 + 0x81, byte4 + 0x30.
  1688. return [byte1 + 0x81,
  1689. byte2 + 0x30,
  1690. byte3 + 0x81,
  1691. byte4 + 0x30];
  1692. };
  1693. }
  1694. /** @param {{fatal: boolean}} options */
  1695. encoders['gb18030'] = function(options) {
  1696. return new GB18030Encoder(options);
  1697. };
  1698. /** @param {{fatal: boolean}} options */
  1699. decoders['gb18030'] = function(options) {
  1700. return new GB18030Decoder(options);
  1701. };
  1702. //
  1703. // 12. Legacy multi-byte Chinese (traditional) encodings
  1704. //
  1705. // 12.1 Big5
  1706. // 12.1.1 Big5 decoder
  1707. /**
  1708. * @constructor
  1709. * @implements {Decoder}
  1710. * @param {{fatal: boolean}} options
  1711. */
  1712. function Big5Decoder(options) {
  1713. var fatal = options.fatal;
  1714. // Big5's decoder has an associated Big5 lead (initially 0x00).
  1715. var /** @type {number} */ Big5_lead = 0x00;
  1716. /**
  1717. * @param {Stream} stream The stream of bytes being decoded.
  1718. * @param {number} bite The next byte read from the stream.
  1719. * @return {?(number|!Array.<number>)} The next code point(s)
  1720. * decoded, or null if not enough data exists in the input
  1721. * stream to decode a complete code point.
  1722. */
  1723. this.handler = function(stream, bite) {
  1724. // 1. If byte is end-of-stream and Big5 lead is not 0x00, set
  1725. // Big5 lead to 0x00 and return error.
  1726. if (bite === end_of_stream && Big5_lead !== 0x00) {
  1727. Big5_lead = 0x00;
  1728. return decoderError(fatal);
  1729. }
  1730. // 2. If byte is end-of-stream and Big5 lead is 0x00, return
  1731. // finished.
  1732. if (bite === end_of_stream && Big5_lead === 0x00)
  1733. return finished;
  1734. // 3. If Big5 lead is not 0x00, let lead be Big5 lead, let
  1735. // pointer be null, set Big5 lead to 0x00, and then run these
  1736. // substeps:
  1737. if (Big5_lead !== 0x00) {
  1738. var lead = Big5_lead;
  1739. var pointer = null;
  1740. Big5_lead = 0x00;
  1741. // 1. Let offset be 0x40 if byte is less than 0x7F and 0x62
  1742. // otherwise.
  1743. var offset = bite < 0x7F ? 0x40 : 0x62;
  1744. // 2. If byte is in the range 0x40 to 0x7E, inclusive, or 0xA1
  1745. // to 0xFE, inclusive, set pointer to (lead − 0x81) × 157 +
  1746. // (byte − offset).
  1747. if (inRange(bite, 0x40, 0x7E) || inRange(bite, 0xA1, 0xFE))
  1748. pointer = (lead - 0x81) * 157 + (bite - offset);
  1749. // 3. If there is a row in the table below whose first column
  1750. // is pointer, return the two code points listed in its second
  1751. // column
  1752. // Pointer | Code points
  1753. // --------+--------------
  1754. // 1133 | U+00CA U+0304
  1755. // 1135 | U+00CA U+030C
  1756. // 1164 | U+00EA U+0304
  1757. // 1166 | U+00EA U+030C
  1758. switch (pointer) {
  1759. case 1133: return [0x00CA, 0x0304];
  1760. case 1135: return [0x00CA, 0x030C];
  1761. case 1164: return [0x00EA, 0x0304];
  1762. case 1166: return [0x00EA, 0x030C];
  1763. }
  1764. // 4. Let code point be null if pointer is null and the index
  1765. // code point for pointer in index Big5 otherwise.
  1766. var code_point = (pointer === null) ? null :
  1767. indexCodePointFor(pointer, index('big5'));
  1768. // 5. If code point is null and byte is an ASCII byte, prepend
  1769. // byte to stream.
  1770. if (code_point === null && isASCIIByte(bite))
  1771. stream.prepend(bite);
  1772. // 6. If code point is null, return error.
  1773. if (code_point === null)
  1774. return decoderError(fatal);
  1775. // 7. Return a code point whose value is code point.
  1776. return code_point;
  1777. }
  1778. // 4. If byte is an ASCII byte, return a code point whose value
  1779. // is byte.
  1780. if (isASCIIByte(bite))
  1781. return bite;
  1782. // 5. If byte is in the range 0x81 to 0xFE, inclusive, set Big5
  1783. // lead to byte and return continue.
  1784. if (inRange(bite, 0x81, 0xFE)) {
  1785. Big5_lead = bite;
  1786. return null;
  1787. }
  1788. // 6. Return error.
  1789. return decoderError(fatal);
  1790. };
  1791. }
  1792. // 12.1.2 Big5 encoder
  1793. /**
  1794. * @constructor
  1795. * @implements {Encoder}
  1796. * @param {{fatal: boolean}} options
  1797. */
  1798. function Big5Encoder(options) {
  1799. var fatal = options.fatal;
  1800. /**
  1801. * @param {Stream} stream Input stream.
  1802. * @param {number} code_point Next code point read from the stream.
  1803. * @return {(number|!Array.<number>)} Byte(s) to emit.
  1804. */
  1805. this.handler = function(stream, code_point) {
  1806. // 1. If code point is end-of-stream, return finished.
  1807. if (code_point === end_of_stream)
  1808. return finished;
  1809. // 2. If code point is an ASCII code point, return a byte whose
  1810. // value is code point.
  1811. if (isASCIICodePoint(code_point))
  1812. return code_point;
  1813. // 3. Let pointer be the index Big5 pointer for code point.
  1814. var pointer = indexBig5PointerFor(code_point);
  1815. // 4. If pointer is null, return error with code point.
  1816. if (pointer === null)
  1817. return encoderError(code_point);
  1818. // 5. Let lead be floor(pointer / 157) + 0x81.
  1819. var lead = floor(pointer / 157) + 0x81;
  1820. // 6. If lead is less than 0xA1, return error with code point.
  1821. if (lead < 0xA1)
  1822. return encoderError(code_point);
  1823. // 7. Let trail be pointer % 157.
  1824. var trail = pointer % 157;
  1825. // 8. Let offset be 0x40 if trail is less than 0x3F and 0x62
  1826. // otherwise.
  1827. var offset = trail < 0x3F ? 0x40 : 0x62;
  1828. // Return two bytes whose values are lead and trail + offset.
  1829. return [lead, trail + offset];
  1830. };
  1831. }
  1832. /** @param {{fatal: boolean}} options */
  1833. encoders['Big5'] = function(options) {
  1834. return new Big5Encoder(options);
  1835. };
  1836. /** @param {{fatal: boolean}} options */
  1837. decoders['Big5'] = function(options) {
  1838. return new Big5Decoder(options);
  1839. };
  1840. //
  1841. // 13. Legacy multi-byte Japanese encodings
  1842. //
  1843. // 13.1 euc-jp
  1844. // 13.1.1 euc-jp decoder
  1845. /**
  1846. * @constructor
  1847. * @implements {Decoder}
  1848. * @param {{fatal: boolean}} options
  1849. */
  1850. function EUCJPDecoder(options) {
  1851. var fatal = options.fatal;
  1852. // euc-jp's decoder has an associated euc-jp jis0212 flag
  1853. // (initially unset) and euc-jp lead (initially 0x00).
  1854. var /** @type {boolean} */ eucjp_jis0212_flag = false,
  1855. /** @type {number} */ eucjp_lead = 0x00;
  1856. /**
  1857. * @param {Stream} stream The stream of bytes being decoded.
  1858. * @param {number} bite The next byte read from the stream.
  1859. * @return {?(number|!Array.<number>)} The next code point(s)
  1860. * decoded, or null if not enough data exists in the input
  1861. * stream to decode a complete code point.
  1862. */
  1863. this.handler = function(stream, bite) {
  1864. // 1. If byte is end-of-stream and euc-jp lead is not 0x00, set
  1865. // euc-jp lead to 0x00, and return error.
  1866. if (bite === end_of_stream && eucjp_lead !== 0x00) {
  1867. eucjp_lead = 0x00;
  1868. return decoderError(fatal);
  1869. }
  1870. // 2. If byte is end-of-stream and euc-jp lead is 0x00, return
  1871. // finished.
  1872. if (bite === end_of_stream && eucjp_lead === 0x00)
  1873. return finished;
  1874. // 3. If euc-jp lead is 0x8E and byte is in the range 0xA1 to
  1875. // 0xDF, inclusive, set euc-jp lead to 0x00 and return a code
  1876. // point whose value is 0xFF61 − 0xA1 + byte.
  1877. if (eucjp_lead === 0x8E && inRange(bite, 0xA1, 0xDF)) {
  1878. eucjp_lead = 0x00;
  1879. return 0xFF61 - 0xA1 + bite;
  1880. }
  1881. // 4. If euc-jp lead is 0x8F and byte is in the range 0xA1 to
  1882. // 0xFE, inclusive, set the euc-jp jis0212 flag, set euc-jp lead
  1883. // to byte, and return continue.
  1884. if (eucjp_lead === 0x8F && inRange(bite, 0xA1, 0xFE)) {
  1885. eucjp_jis0212_flag = true;
  1886. eucjp_lead = bite;
  1887. return null;
  1888. }
  1889. // 5. If euc-jp lead is not 0x00, let lead be euc-jp lead, set
  1890. // euc-jp lead to 0x00, and run these substeps:
  1891. if (eucjp_lead !== 0x00) {
  1892. var lead = eucjp_lead;
  1893. eucjp_lead = 0x00;
  1894. // 1. Let code point be null.
  1895. var code_point = null;
  1896. // 2. If lead and byte are both in the range 0xA1 to 0xFE,
  1897. // inclusive, set code point to the index code point for (lead
  1898. // − 0xA1) × 94 + byte − 0xA1 in index jis0208 if the euc-jp
  1899. // jis0212 flag is unset and in index jis0212 otherwise.
  1900. if (inRange(lead, 0xA1, 0xFE) && inRange(bite, 0xA1, 0xFE)) {
  1901. code_point = indexCodePointFor(
  1902. (lead - 0xA1) * 94 + (bite - 0xA1),
  1903. index(!eucjp_jis0212_flag ? 'jis0208' : 'jis0212'));
  1904. }
  1905. // 3. Unset the euc-jp jis0212 flag.
  1906. eucjp_jis0212_flag = false;
  1907. // 4. If byte is not in the range 0xA1 to 0xFE, inclusive,
  1908. // prepend byte to stream.
  1909. if (!inRange(bite, 0xA1, 0xFE))
  1910. stream.prepend(bite);
  1911. // 5. If code point is null, return error.
  1912. if (code_point === null)
  1913. return decoderError(fatal);
  1914. // 6. Return a code point whose value is code point.
  1915. return code_point;
  1916. }
  1917. // 6. If byte is an ASCII byte, return a code point whose value
  1918. // is byte.
  1919. if (isASCIIByte(bite))
  1920. return bite;
  1921. // 7. If byte is 0x8E, 0x8F, or in the range 0xA1 to 0xFE,
  1922. // inclusive, set euc-jp lead to byte and return continue.
  1923. if (bite === 0x8E || bite === 0x8F || inRange(bite, 0xA1, 0xFE)) {
  1924. eucjp_lead = bite;
  1925. return null;
  1926. }
  1927. // 8. Return error.
  1928. return decoderError(fatal);
  1929. };
  1930. }
  1931. // 13.1.2 euc-jp encoder
  1932. /**
  1933. * @constructor
  1934. * @implements {Encoder}
  1935. * @param {{fatal: boolean}} options
  1936. */
  1937. function EUCJPEncoder(options) {
  1938. var fatal = options.fatal;
  1939. /**
  1940. * @param {Stream} stream Input stream.
  1941. * @param {number} code_point Next code point read from the stream.
  1942. * @return {(number|!Array.<number>)} Byte(s) to emit.
  1943. */
  1944. this.handler = function(stream, code_point) {
  1945. // 1. If code point is end-of-stream, return finished.
  1946. if (code_point === end_of_stream)
  1947. return finished;
  1948. // 2. If code point is an ASCII code point, return a byte whose
  1949. // value is code point.
  1950. if (isASCIICodePoint(code_point))
  1951. return code_point;
  1952. // 3. If code point is U+00A5, return byte 0x5C.
  1953. if (code_point === 0x00A5)
  1954. return 0x5C;
  1955. // 4. If code point is U+203E, return byte 0x7E.
  1956. if (code_point === 0x203E)
  1957. return 0x7E;
  1958. // 5. If code point is in the range U+FF61 to U+FF9F, inclusive,
  1959. // return two bytes whose values are 0x8E and code point −
  1960. // 0xFF61 + 0xA1.
  1961. if (inRange(code_point, 0xFF61, 0xFF9F))
  1962. return [0x8E, code_point - 0xFF61 + 0xA1];
  1963. // 6. If code point is U+2212, set it to U+FF0D.
  1964. if (code_point === 0x2212)
  1965. code_point = 0xFF0D;
  1966. // 7. Let pointer be the index pointer for code point in index
  1967. // jis0208.
  1968. var pointer = indexPointerFor(code_point, index('jis0208'));
  1969. // 8. If pointer is null, return error with code point.
  1970. if (pointer === null)
  1971. return encoderError(code_point);
  1972. // 9. Let lead be floor(pointer / 94) + 0xA1.
  1973. var lead = floor(pointer / 94) + 0xA1;
  1974. // 10. Let trail be pointer % 94 + 0xA1.
  1975. var trail = pointer % 94 + 0xA1;
  1976. // 11. Return two bytes whose values are lead and trail.
  1977. return [lead, trail];
  1978. };
  1979. }
  1980. /** @param {{fatal: boolean}} options */
  1981. encoders['EUC-JP'] = function(options) {
  1982. return new EUCJPEncoder(options);
  1983. };
  1984. /** @param {{fatal: boolean}} options */
  1985. decoders['EUC-JP'] = function(options) {
  1986. return new EUCJPDecoder(options);
  1987. };
  1988. // 13.2 iso-2022-jp
  1989. // 13.2.1 iso-2022-jp decoder
  1990. /**
  1991. * @constructor
  1992. * @implements {Decoder}
  1993. * @param {{fatal: boolean}} options
  1994. */
  1995. function ISO2022JPDecoder(options) {
  1996. var fatal = options.fatal;
  1997. /** @enum */
  1998. var states = {
  1999. ASCII: 0,
  2000. Roman: 1,
  2001. Katakana: 2,
  2002. LeadByte: 3,
  2003. TrailByte: 4,
  2004. EscapeStart: 5,
  2005. Escape: 6
  2006. };
  2007. // iso-2022-jp's decoder has an associated iso-2022-jp decoder
  2008. // state (initially ASCII), iso-2022-jp decoder output state
  2009. // (initially ASCII), iso-2022-jp lead (initially 0x00), and
  2010. // iso-2022-jp output flag (initially unset).
  2011. var /** @type {number} */ iso2022jp_decoder_state = states.ASCII,
  2012. /** @type {number} */ iso2022jp_decoder_output_state = states.ASCII,
  2013. /** @type {number} */ iso2022jp_lead = 0x00,
  2014. /** @type {boolean} */ iso2022jp_output_flag = false;
  2015. /**
  2016. * @param {Stream} stream The stream of bytes being decoded.
  2017. * @param {number} bite The next byte read from the stream.
  2018. * @return {?(number|!Array.<number>)} The next code point(s)
  2019. * decoded, or null if not enough data exists in the input
  2020. * stream to decode a complete code point.
  2021. */
  2022. this.handler = function(stream, bite) {
  2023. // switching on iso-2022-jp decoder state:
  2024. switch (iso2022jp_decoder_state) {
  2025. default:
  2026. case states.ASCII:
  2027. // ASCII
  2028. // Based on byte:
  2029. // 0x1B
  2030. if (bite === 0x1B) {
  2031. // Set iso-2022-jp decoder state to escape start and return
  2032. // continue.
  2033. iso2022jp_decoder_state = states.EscapeStart;
  2034. return null;
  2035. }
  2036. // 0x00 to 0x7F, excluding 0x0E, 0x0F, and 0x1B
  2037. if (inRange(bite, 0x00, 0x7F) && bite !== 0x0E
  2038. && bite !== 0x0F && bite !== 0x1B) {
  2039. // Unset the iso-2022-jp output flag and return a code point
  2040. // whose value is byte.
  2041. iso2022jp_output_flag = false;
  2042. return bite;
  2043. }
  2044. // end-of-stream
  2045. if (bite === end_of_stream) {
  2046. // Return finished.
  2047. return finished;
  2048. }
  2049. // Otherwise
  2050. // Unset the iso-2022-jp output flag and return error.
  2051. iso2022jp_output_flag = false;
  2052. return decoderError(fatal);
  2053. case states.Roman:
  2054. // Roman
  2055. // Based on byte:
  2056. // 0x1B
  2057. if (bite === 0x1B) {
  2058. // Set iso-2022-jp decoder state to escape start and return
  2059. // continue.
  2060. iso2022jp_decoder_state = states.EscapeStart;
  2061. return null;
  2062. }
  2063. // 0x5C
  2064. if (bite === 0x5C) {
  2065. // Unset the iso-2022-jp output flag and return code point
  2066. // U+00A5.
  2067. iso2022jp_output_flag = false;
  2068. return 0x00A5;
  2069. }
  2070. // 0x7E
  2071. if (bite === 0x7E) {
  2072. // Unset the iso-2022-jp output flag and return code point
  2073. // U+203E.
  2074. iso2022jp_output_flag = false;
  2075. return 0x203E;
  2076. }
  2077. // 0x00 to 0x7F, excluding 0x0E, 0x0F, 0x1B, 0x5C, and 0x7E
  2078. if (inRange(bite, 0x00, 0x7F) && bite !== 0x0E && bite !== 0x0F
  2079. && bite !== 0x1B && bite !== 0x5C && bite !== 0x7E) {
  2080. // Unset the iso-2022-jp output flag and return a code point
  2081. // whose value is byte.
  2082. iso2022jp_output_flag = false;
  2083. return bite;
  2084. }
  2085. // end-of-stream
  2086. if (bite === end_of_stream) {
  2087. // Return finished.
  2088. return finished;
  2089. }
  2090. // Otherwise
  2091. // Unset the iso-2022-jp output flag and return error.
  2092. iso2022jp_output_flag = false;
  2093. return decoderError(fatal);
  2094. case states.Katakana:
  2095. // Katakana
  2096. // Based on byte:
  2097. // 0x1B
  2098. if (bite === 0x1B) {
  2099. // Set iso-2022-jp decoder state to escape start and return
  2100. // continue.
  2101. iso2022jp_decoder_state = states.EscapeStart;
  2102. return null;
  2103. }
  2104. // 0x21 to 0x5F
  2105. if (inRange(bite, 0x21, 0x5F)) {
  2106. // Unset the iso-2022-jp output flag and return a code point
  2107. // whose value is 0xFF61 − 0x21 + byte.
  2108. iso2022jp_output_flag = false;
  2109. return 0xFF61 - 0x21 + bite;
  2110. }
  2111. // end-of-stream
  2112. if (bite === end_of_stream) {
  2113. // Return finished.
  2114. return finished;
  2115. }
  2116. // Otherwise
  2117. // Unset the iso-2022-jp output flag and return error.
  2118. iso2022jp_output_flag = false;
  2119. return decoderError(fatal);
  2120. case states.LeadByte:
  2121. // Lead byte
  2122. // Based on byte:
  2123. // 0x1B
  2124. if (bite === 0x1B) {
  2125. // Set iso-2022-jp decoder state to escape start and return
  2126. // continue.
  2127. iso2022jp_decoder_state = states.EscapeStart;
  2128. return null;
  2129. }
  2130. // 0x21 to 0x7E
  2131. if (inRange(bite, 0x21, 0x7E)) {
  2132. // Unset the iso-2022-jp output flag, set iso-2022-jp lead
  2133. // to byte, iso-2022-jp decoder state to trail byte, and
  2134. // return continue.
  2135. iso2022jp_output_flag = false;
  2136. iso2022jp_lead = bite;
  2137. iso2022jp_decoder_state = states.TrailByte;
  2138. return null;
  2139. }
  2140. // end-of-stream
  2141. if (bite === end_of_stream) {
  2142. // Return finished.
  2143. return finished;
  2144. }
  2145. // Otherwise
  2146. // Unset the iso-2022-jp output flag and return error.
  2147. iso2022jp_output_flag = false;
  2148. return decoderError(fatal);
  2149. case states.TrailByte:
  2150. // Trail byte
  2151. // Based on byte:
  2152. // 0x1B
  2153. if (bite === 0x1B) {
  2154. // Set iso-2022-jp decoder state to escape start and return
  2155. // continue.
  2156. iso2022jp_decoder_state = states.EscapeStart;
  2157. return decoderError(fatal);
  2158. }
  2159. // 0x21 to 0x7E
  2160. if (inRange(bite, 0x21, 0x7E)) {
  2161. // 1. Set the iso-2022-jp decoder state to lead byte.
  2162. iso2022jp_decoder_state = states.LeadByte;
  2163. // 2. Let pointer be (iso-2022-jp lead − 0x21) × 94 + byte − 0x21.
  2164. var pointer = (iso2022jp_lead - 0x21) * 94 + bite - 0x21;
  2165. // 3. Let code point be the index code point for pointer in
  2166. // index jis0208.
  2167. var code_point = indexCodePointFor(pointer, index('jis0208'));
  2168. // 4. If code point is null, return error.
  2169. if (code_point === null)
  2170. return decoderError(fatal);
  2171. // 5. Return a code point whose value is code point.
  2172. return code_point;
  2173. }
  2174. // end-of-stream
  2175. if (bite === end_of_stream) {
  2176. // Set the iso-2022-jp decoder state to lead byte, prepend
  2177. // byte to stream, and return error.
  2178. iso2022jp_decoder_state = states.LeadByte;
  2179. stream.prepend(bite);
  2180. return decoderError(fatal);
  2181. }
  2182. // Otherwise
  2183. // Set iso-2022-jp decoder state to lead byte and return
  2184. // error.
  2185. iso2022jp_decoder_state = states.LeadByte;
  2186. return decoderError(fatal);
  2187. case states.EscapeStart:
  2188. // Escape start
  2189. // 1. If byte is either 0x24 or 0x28, set iso-2022-jp lead to
  2190. // byte, iso-2022-jp decoder state to escape, and return
  2191. // continue.
  2192. if (bite === 0x24 || bite === 0x28) {
  2193. iso2022jp_lead = bite;
  2194. iso2022jp_decoder_state = states.Escape;
  2195. return null;
  2196. }
  2197. // 2. Prepend byte to stream.
  2198. stream.prepend(bite);
  2199. // 3. Unset the iso-2022-jp output flag, set iso-2022-jp
  2200. // decoder state to iso-2022-jp decoder output state, and
  2201. // return error.
  2202. iso2022jp_output_flag = false;
  2203. iso2022jp_decoder_state = iso2022jp_decoder_output_state;
  2204. return decoderError(fatal);
  2205. case states.Escape:
  2206. // Escape
  2207. // 1. Let lead be iso-2022-jp lead and set iso-2022-jp lead to
  2208. // 0x00.
  2209. var lead = iso2022jp_lead;
  2210. iso2022jp_lead = 0x00;
  2211. // 2. Let state be null.
  2212. var state = null;
  2213. // 3. If lead is 0x28 and byte is 0x42, set state to ASCII.
  2214. if (lead === 0x28 && bite === 0x42)
  2215. state = states.ASCII;
  2216. // 4. If lead is 0x28 and byte is 0x4A, set state to Roman.
  2217. if (lead === 0x28 && bite === 0x4A)
  2218. state = states.Roman;
  2219. // 5. If lead is 0x28 and byte is 0x49, set state to Katakana.
  2220. if (lead === 0x28 && bite === 0x49)
  2221. state = states.Katakana;
  2222. // 6. If lead is 0x24 and byte is either 0x40 or 0x42, set
  2223. // state to lead byte.
  2224. if (lead === 0x24 && (bite === 0x40 || bite === 0x42))
  2225. state = states.LeadByte;
  2226. // 7. If state is non-null, run these substeps:
  2227. if (state !== null) {
  2228. // 1. Set iso-2022-jp decoder state and iso-2022-jp decoder
  2229. // output state to states.
  2230. iso2022jp_decoder_state = iso2022jp_decoder_state = state;
  2231. // 2. Let output flag be the iso-2022-jp output flag.
  2232. var output_flag = iso2022jp_output_flag;
  2233. // 3. Set the iso-2022-jp output flag.
  2234. iso2022jp_output_flag = true;
  2235. // 4. Return continue, if output flag is unset, and error
  2236. // otherwise.
  2237. return !output_flag ? null : decoderError(fatal);
  2238. }
  2239. // 8. Prepend lead and byte to stream.
  2240. stream.prepend([lead, bite]);
  2241. // 9. Unset the iso-2022-jp output flag, set iso-2022-jp
  2242. // decoder state to iso-2022-jp decoder output state and
  2243. // return error.
  2244. iso2022jp_output_flag = false;
  2245. iso2022jp_decoder_state = iso2022jp_decoder_output_state;
  2246. return decoderError(fatal);
  2247. }
  2248. };
  2249. }
  2250. // 13.2.2 iso-2022-jp encoder
  2251. /**
  2252. * @constructor
  2253. * @implements {Encoder}
  2254. * @param {{fatal: boolean}} options
  2255. */
  2256. function ISO2022JPEncoder(options) {
  2257. var fatal = options.fatal;
  2258. // iso-2022-jp's encoder has an associated iso-2022-jp encoder
  2259. // state which is one of ASCII, Roman, and jis0208 (initially
  2260. // ASCII).
  2261. /** @enum */
  2262. var states = {
  2263. ASCII: 0,
  2264. Roman: 1,
  2265. jis0208: 2
  2266. };
  2267. var /** @type {number} */ iso2022jp_state = states.ASCII;
  2268. /**
  2269. * @param {Stream} stream Input stream.
  2270. * @param {number} code_point Next code point read from the stream.
  2271. * @return {(number|!Array.<number>)} Byte(s) to emit.
  2272. */
  2273. this.handler = function(stream, code_point) {
  2274. // 1. If code point is end-of-stream and iso-2022-jp encoder
  2275. // state is not ASCII, prepend code point to stream, set
  2276. // iso-2022-jp encoder state to ASCII, and return three bytes
  2277. // 0x1B 0x28 0x42.
  2278. if (code_point === end_of_stream &&
  2279. iso2022jp_state !== states.ASCII) {
  2280. stream.prepend(code_point);
  2281. iso2022jp_state = states.ASCII;
  2282. return [0x1B, 0x28, 0x42];
  2283. }
  2284. // 2. If code point is end-of-stream and iso-2022-jp encoder
  2285. // state is ASCII, return finished.
  2286. if (code_point === end_of_stream && iso2022jp_state === states.ASCII)
  2287. return finished;
  2288. // 3. If ISO-2022-JP encoder state is ASCII or Roman, and code
  2289. // point is U+000E, U+000F, or U+001B, return error with U+FFFD.
  2290. if ((iso2022jp_state === states.ASCII ||
  2291. iso2022jp_state === states.Roman) &&
  2292. (code_point === 0x000E || code_point === 0x000F ||
  2293. code_point === 0x001B)) {
  2294. return encoderError(0xFFFD);
  2295. }
  2296. // 4. If iso-2022-jp encoder state is ASCII and code point is an
  2297. // ASCII code point, return a byte whose value is code point.
  2298. if (iso2022jp_state === states.ASCII &&
  2299. isASCIICodePoint(code_point))
  2300. return code_point;
  2301. // 5. If iso-2022-jp encoder state is Roman and code point is an
  2302. // ASCII code point, excluding U+005C and U+007E, or is U+00A5
  2303. // or U+203E, run these substeps:
  2304. if (iso2022jp_state === states.Roman &&
  2305. ((isASCIICodePoint(code_point) &&
  2306. code_point !== 0x005C && code_point !== 0x007E) ||
  2307. (code_point == 0x00A5 || code_point == 0x203E))) {
  2308. // 1. If code point is an ASCII code point, return a byte
  2309. // whose value is code point.
  2310. if (isASCIICodePoint(code_point))
  2311. return code_point;
  2312. // 2. If code point is U+00A5, return byte 0x5C.
  2313. if (code_point === 0x00A5)
  2314. return 0x5C;
  2315. // 3. If code point is U+203E, return byte 0x7E.
  2316. if (code_point === 0x203E)
  2317. return 0x7E;
  2318. }
  2319. // 6. If code point is an ASCII code point, and iso-2022-jp
  2320. // encoder state is not ASCII, prepend code point to stream, set
  2321. // iso-2022-jp encoder state to ASCII, and return three bytes
  2322. // 0x1B 0x28 0x42.
  2323. if (isASCIICodePoint(code_point) &&
  2324. iso2022jp_state !== states.ASCII) {
  2325. stream.prepend(code_point);
  2326. iso2022jp_state = states.ASCII;
  2327. return [0x1B, 0x28, 0x42];
  2328. }
  2329. // 7. If code point is either U+00A5 or U+203E, and iso-2022-jp
  2330. // encoder state is not Roman, prepend code point to stream, set
  2331. // iso-2022-jp encoder state to Roman, and return three bytes
  2332. // 0x1B 0x28 0x4A.
  2333. if ((code_point === 0x00A5 || code_point === 0x203E) &&
  2334. iso2022jp_state !== states.Roman) {
  2335. stream.prepend(code_point);
  2336. iso2022jp_state = states.Roman;
  2337. return [0x1B, 0x28, 0x4A];
  2338. }
  2339. // 8. If code point is U+2212, set it to U+FF0D.
  2340. if (code_point === 0x2212)
  2341. code_point = 0xFF0D;
  2342. // 9. Let pointer be the index pointer for code point in index
  2343. // jis0208.
  2344. var pointer = indexPointerFor(code_point, index('jis0208'));
  2345. // 10. If pointer is null, return error with code point.
  2346. if (pointer === null)
  2347. return encoderError(code_point);
  2348. // 11. If iso-2022-jp encoder state is not jis0208, prepend code
  2349. // point to stream, set iso-2022-jp encoder state to jis0208,
  2350. // and return three bytes 0x1B 0x24 0x42.
  2351. if (iso2022jp_state !== states.jis0208) {
  2352. stream.prepend(code_point);
  2353. iso2022jp_state = states.jis0208;
  2354. return [0x1B, 0x24, 0x42];
  2355. }
  2356. // 12. Let lead be floor(pointer / 94) + 0x21.
  2357. var lead = floor(pointer / 94) + 0x21;
  2358. // 13. Let trail be pointer % 94 + 0x21.
  2359. var trail = pointer % 94 + 0x21;
  2360. // 14. Return two bytes whose values are lead and trail.
  2361. return [lead, trail];
  2362. };
  2363. }
  2364. /** @param {{fatal: boolean}} options */
  2365. encoders['ISO-2022-JP'] = function(options) {
  2366. return new ISO2022JPEncoder(options);
  2367. };
  2368. /** @param {{fatal: boolean}} options */
  2369. decoders['ISO-2022-JP'] = function(options) {
  2370. return new ISO2022JPDecoder(options);
  2371. };
  2372. // 13.3 Shift_JIS
  2373. // 13.3.1 Shift_JIS decoder
  2374. /**
  2375. * @constructor
  2376. * @implements {Decoder}
  2377. * @param {{fatal: boolean}} options
  2378. */
  2379. function ShiftJISDecoder(options) {
  2380. var fatal = options.fatal;
  2381. // Shift_JIS's decoder has an associated Shift_JIS lead (initially
  2382. // 0x00).
  2383. var /** @type {number} */ Shift_JIS_lead = 0x00;
  2384. /**
  2385. * @param {Stream} stream The stream of bytes being decoded.
  2386. * @param {number} bite The next byte read from the stream.
  2387. * @return {?(number|!Array.<number>)} The next code point(s)
  2388. * decoded, or null if not enough data exists in the input
  2389. * stream to decode a complete code point.
  2390. */
  2391. this.handler = function(stream, bite) {
  2392. // 1. If byte is end-of-stream and Shift_JIS lead is not 0x00,
  2393. // set Shift_JIS lead to 0x00 and return error.
  2394. if (bite === end_of_stream && Shift_JIS_lead !== 0x00) {
  2395. Shift_JIS_lead = 0x00;
  2396. return decoderError(fatal);
  2397. }
  2398. // 2. If byte is end-of-stream and Shift_JIS lead is 0x00,
  2399. // return finished.
  2400. if (bite === end_of_stream && Shift_JIS_lead === 0x00)
  2401. return finished;
  2402. // 3. If Shift_JIS lead is not 0x00, let lead be Shift_JIS lead,
  2403. // let pointer be null, set Shift_JIS lead to 0x00, and then run
  2404. // these substeps:
  2405. if (Shift_JIS_lead !== 0x00) {
  2406. var lead = Shift_JIS_lead;
  2407. var pointer = null;
  2408. Shift_JIS_lead = 0x00;
  2409. // 1. Let offset be 0x40, if byte is less than 0x7F, and 0x41
  2410. // otherwise.
  2411. var offset = (bite < 0x7F) ? 0x40 : 0x41;
  2412. // 2. Let lead offset be 0x81, if lead is less than 0xA0, and
  2413. // 0xC1 otherwise.
  2414. var lead_offset = (lead < 0xA0) ? 0x81 : 0xC1;
  2415. // 3. If byte is in the range 0x40 to 0x7E, inclusive, or 0x80
  2416. // to 0xFC, inclusive, set pointer to (lead − lead offset) ×
  2417. // 188 + byte − offset.
  2418. if (inRange(bite, 0x40, 0x7E) || inRange(bite, 0x80, 0xFC))
  2419. pointer = (lead - lead_offset) * 188 + bite - offset;
  2420. // 4. If pointer is in the range 8836 to 10715, inclusive,
  2421. // return a code point whose value is 0xE000 − 8836 + pointer.
  2422. if (inRange(pointer, 8836, 10715))
  2423. return 0xE000 - 8836 + pointer;
  2424. // 5. Let code point be null, if pointer is null, and the
  2425. // index code point for pointer in index jis0208 otherwise.
  2426. var code_point = (pointer === null) ? null :
  2427. indexCodePointFor(pointer, index('jis0208'));
  2428. // 6. If code point is null and byte is an ASCII byte, prepend
  2429. // byte to stream.
  2430. if (code_point === null && isASCIIByte(bite))
  2431. stream.prepend(bite);
  2432. // 7. If code point is null, return error.
  2433. if (code_point === null)
  2434. return decoderError(fatal);
  2435. // 8. Return a code point whose value is code point.
  2436. return code_point;
  2437. }
  2438. // 4. If byte is an ASCII byte or 0x80, return a code point
  2439. // whose value is byte.
  2440. if (isASCIIByte(bite) || bite === 0x80)
  2441. return bite;
  2442. // 5. If byte is in the range 0xA1 to 0xDF, inclusive, return a
  2443. // code point whose value is 0xFF61 − 0xA1 + byte.
  2444. if (inRange(bite, 0xA1, 0xDF))
  2445. return 0xFF61 - 0xA1 + bite;
  2446. // 6. If byte is in the range 0x81 to 0x9F, inclusive, or 0xE0
  2447. // to 0xFC, inclusive, set Shift_JIS lead to byte and return
  2448. // continue.
  2449. if (inRange(bite, 0x81, 0x9F) || inRange(bite, 0xE0, 0xFC)) {
  2450. Shift_JIS_lead = bite;
  2451. return null;
  2452. }
  2453. // 7. Return error.
  2454. return decoderError(fatal);
  2455. };
  2456. }
  2457. // 13.3.2 Shift_JIS encoder
  2458. /**
  2459. * @constructor
  2460. * @implements {Encoder}
  2461. * @param {{fatal: boolean}} options
  2462. */
  2463. function ShiftJISEncoder(options) {
  2464. var fatal = options.fatal;
  2465. /**
  2466. * @param {Stream} stream Input stream.
  2467. * @param {number} code_point Next code point read from the stream.
  2468. * @return {(number|!Array.<number>)} Byte(s) to emit.
  2469. */
  2470. this.handler = function(stream, code_point) {
  2471. // 1. If code point is end-of-stream, return finished.
  2472. if (code_point === end_of_stream)
  2473. return finished;
  2474. // 2. If code point is an ASCII code point or U+0080, return a
  2475. // byte whose value is code point.
  2476. if (isASCIICodePoint(code_point) || code_point === 0x0080)
  2477. return code_point;
  2478. // 3. If code point is U+00A5, return byte 0x5C.
  2479. if (code_point === 0x00A5)
  2480. return 0x5C;
  2481. // 4. If code point is U+203E, return byte 0x7E.
  2482. if (code_point === 0x203E)
  2483. return 0x7E;
  2484. // 5. If code point is in the range U+FF61 to U+FF9F, inclusive,
  2485. // return a byte whose value is code point − 0xFF61 + 0xA1.
  2486. if (inRange(code_point, 0xFF61, 0xFF9F))
  2487. return code_point - 0xFF61 + 0xA1;
  2488. // 6. If code point is U+2212, set it to U+FF0D.
  2489. if (code_point === 0x2212)
  2490. code_point = 0xFF0D;
  2491. // 7. Let pointer be the index Shift_JIS pointer for code point.
  2492. var pointer = indexShiftJISPointerFor(code_point);
  2493. // 8. If pointer is null, return error with code point.
  2494. if (pointer === null)
  2495. return encoderError(code_point);
  2496. // 9. Let lead be floor(pointer / 188).
  2497. var lead = floor(pointer / 188);
  2498. // 10. Let lead offset be 0x81, if lead is less than 0x1F, and
  2499. // 0xC1 otherwise.
  2500. var lead_offset = (lead < 0x1F) ? 0x81 : 0xC1;
  2501. // 11. Let trail be pointer % 188.
  2502. var trail = pointer % 188;
  2503. // 12. Let offset be 0x40, if trail is less than 0x3F, and 0x41
  2504. // otherwise.
  2505. var offset = (trail < 0x3F) ? 0x40 : 0x41;
  2506. // 13. Return two bytes whose values are lead + lead offset and
  2507. // trail + offset.
  2508. return [lead + lead_offset, trail + offset];
  2509. };
  2510. }
  2511. /** @param {{fatal: boolean}} options */
  2512. encoders['Shift_JIS'] = function(options) {
  2513. return new ShiftJISEncoder(options);
  2514. };
  2515. /** @param {{fatal: boolean}} options */
  2516. decoders['Shift_JIS'] = function(options) {
  2517. return new ShiftJISDecoder(options);
  2518. };
  2519. //
  2520. // 14. Legacy multi-byte Korean encodings
  2521. //
  2522. // 14.1 euc-kr
  2523. // 14.1.1 euc-kr decoder
  2524. /**
  2525. * @constructor
  2526. * @implements {Decoder}
  2527. * @param {{fatal: boolean}} options
  2528. */
  2529. function EUCKRDecoder(options) {
  2530. var fatal = options.fatal;
  2531. // euc-kr's decoder has an associated euc-kr lead (initially 0x00).
  2532. var /** @type {number} */ euckr_lead = 0x00;
  2533. /**
  2534. * @param {Stream} stream The stream of bytes being decoded.
  2535. * @param {number} bite The next byte read from the stream.
  2536. * @return {?(number|!Array.<number>)} The next code point(s)
  2537. * decoded, or null if not enough data exists in the input
  2538. * stream to decode a complete code point.
  2539. */
  2540. this.handler = function(stream, bite) {
  2541. // 1. If byte is end-of-stream and euc-kr lead is not 0x00, set
  2542. // euc-kr lead to 0x00 and return error.
  2543. if (bite === end_of_stream && euckr_lead !== 0) {
  2544. euckr_lead = 0x00;
  2545. return decoderError(fatal);
  2546. }
  2547. // 2. If byte is end-of-stream and euc-kr lead is 0x00, return
  2548. // finished.
  2549. if (bite === end_of_stream && euckr_lead === 0)
  2550. return finished;
  2551. // 3. If euc-kr lead is not 0x00, let lead be euc-kr lead, let
  2552. // pointer be null, set euc-kr lead to 0x00, and then run these
  2553. // substeps:
  2554. if (euckr_lead !== 0x00) {
  2555. var lead = euckr_lead;
  2556. var pointer = null;
  2557. euckr_lead = 0x00;
  2558. // 1. If byte is in the range 0x41 to 0xFE, inclusive, set
  2559. // pointer to (lead − 0x81) × 190 + (byte − 0x41).
  2560. if (inRange(bite, 0x41, 0xFE))
  2561. pointer = (lead - 0x81) * 190 + (bite - 0x41);
  2562. // 2. Let code point be null, if pointer is null, and the
  2563. // index code point for pointer in index euc-kr otherwise.
  2564. var code_point = (pointer === null)
  2565. ? null : indexCodePointFor(pointer, index('euc-kr'));
  2566. // 3. If code point is null and byte is an ASCII byte, prepend
  2567. // byte to stream.
  2568. if (pointer === null && isASCIIByte(bite))
  2569. stream.prepend(bite);
  2570. // 4. If code point is null, return error.
  2571. if (code_point === null)
  2572. return decoderError(fatal);
  2573. // 5. Return a code point whose value is code point.
  2574. return code_point;
  2575. }
  2576. // 4. If byte is an ASCII byte, return a code point whose value
  2577. // is byte.
  2578. if (isASCIIByte(bite))
  2579. return bite;
  2580. // 5. If byte is in the range 0x81 to 0xFE, inclusive, set
  2581. // euc-kr lead to byte and return continue.
  2582. if (inRange(bite, 0x81, 0xFE)) {
  2583. euckr_lead = bite;
  2584. return null;
  2585. }
  2586. // 6. Return error.
  2587. return decoderError(fatal);
  2588. };
  2589. }
  2590. // 14.1.2 euc-kr encoder
  2591. /**
  2592. * @constructor
  2593. * @implements {Encoder}
  2594. * @param {{fatal: boolean}} options
  2595. */
  2596. function EUCKREncoder(options) {
  2597. var fatal = options.fatal;
  2598. /**
  2599. * @param {Stream} stream Input stream.
  2600. * @param {number} code_point Next code point read from the stream.
  2601. * @return {(number|!Array.<number>)} Byte(s) to emit.
  2602. */
  2603. this.handler = function(stream, code_point) {
  2604. // 1. If code point is end-of-stream, return finished.
  2605. if (code_point === end_of_stream)
  2606. return finished;
  2607. // 2. If code point is an ASCII code point, return a byte whose
  2608. // value is code point.
  2609. if (isASCIICodePoint(code_point))
  2610. return code_point;
  2611. // 3. Let pointer be the index pointer for code point in index
  2612. // euc-kr.
  2613. var pointer = indexPointerFor(code_point, index('euc-kr'));
  2614. // 4. If pointer is null, return error with code point.
  2615. if (pointer === null)
  2616. return encoderError(code_point);
  2617. // 5. Let lead be floor(pointer / 190) + 0x81.
  2618. var lead = floor(pointer / 190) + 0x81;
  2619. // 6. Let trail be pointer % 190 + 0x41.
  2620. var trail = (pointer % 190) + 0x41;
  2621. // 7. Return two bytes whose values are lead and trail.
  2622. return [lead, trail];
  2623. };
  2624. }
  2625. /** @param {{fatal: boolean}} options */
  2626. encoders['EUC-KR'] = function(options) {
  2627. return new EUCKREncoder(options);
  2628. };
  2629. /** @param {{fatal: boolean}} options */
  2630. decoders['EUC-KR'] = function(options) {
  2631. return new EUCKRDecoder(options);
  2632. };
  2633. //
  2634. // 15. Legacy miscellaneous encodings
  2635. //
  2636. // 15.1 replacement
  2637. // Not needed - API throws RangeError
  2638. // 15.2 Common infrastructure for utf-16be and utf-16le
  2639. /**
  2640. * @param {number} code_unit
  2641. * @param {boolean} utf16be
  2642. * @return {!Array.<number>} bytes
  2643. */
  2644. function convertCodeUnitToBytes(code_unit, utf16be) {
  2645. // 1. Let byte1 be code unit >> 8.
  2646. var byte1 = code_unit >> 8;
  2647. // 2. Let byte2 be code unit & 0x00FF.
  2648. var byte2 = code_unit & 0x00FF;
  2649. // 3. Then return the bytes in order:
  2650. // utf-16be flag is set: byte1, then byte2.
  2651. if (utf16be)
  2652. return [byte1, byte2];
  2653. // utf-16be flag is unset: byte2, then byte1.
  2654. return [byte2, byte1];
  2655. }
  2656. // 15.2.1 shared utf-16 decoder
  2657. /**
  2658. * @constructor
  2659. * @implements {Decoder}
  2660. * @param {boolean} utf16_be True if big-endian, false if little-endian.
  2661. * @param {{fatal: boolean}} options
  2662. */
  2663. function UTF16Decoder(utf16_be, options) {
  2664. var fatal = options.fatal;
  2665. var /** @type {?number} */ utf16_lead_byte = null,
  2666. /** @type {?number} */ utf16_lead_surrogate = null;
  2667. /**
  2668. * @param {Stream} stream The stream of bytes being decoded.
  2669. * @param {number} bite The next byte read from the stream.
  2670. * @return {?(number|!Array.<number>)} The next code point(s)
  2671. * decoded, or null if not enough data exists in the input
  2672. * stream to decode a complete code point.
  2673. */
  2674. this.handler = function(stream, bite) {
  2675. // 1. If byte is end-of-stream and either utf-16 lead byte or
  2676. // utf-16 lead surrogate is not null, set utf-16 lead byte and
  2677. // utf-16 lead surrogate to null, and return error.
  2678. if (bite === end_of_stream && (utf16_lead_byte !== null ||
  2679. utf16_lead_surrogate !== null)) {
  2680. return decoderError(fatal);
  2681. }
  2682. // 2. If byte is end-of-stream and utf-16 lead byte and utf-16
  2683. // lead surrogate are null, return finished.
  2684. if (bite === end_of_stream && utf16_lead_byte === null &&
  2685. utf16_lead_surrogate === null) {
  2686. return finished;
  2687. }
  2688. // 3. If utf-16 lead byte is null, set utf-16 lead byte to byte
  2689. // and return continue.
  2690. if (utf16_lead_byte === null) {
  2691. utf16_lead_byte = bite;
  2692. return null;
  2693. }
  2694. // 4. Let code unit be the result of:
  2695. var code_unit;
  2696. if (utf16_be) {
  2697. // utf-16be decoder flag is set
  2698. // (utf-16 lead byte << 8) + byte.
  2699. code_unit = (utf16_lead_byte << 8) + bite;
  2700. } else {
  2701. // utf-16be decoder flag is unset
  2702. // (byte << 8) + utf-16 lead byte.
  2703. code_unit = (bite << 8) + utf16_lead_byte;
  2704. }
  2705. // Then set utf-16 lead byte to null.
  2706. utf16_lead_byte = null;
  2707. // 5. If utf-16 lead surrogate is not null, let lead surrogate
  2708. // be utf-16 lead surrogate, set utf-16 lead surrogate to null,
  2709. // and then run these substeps:
  2710. if (utf16_lead_surrogate !== null) {
  2711. var lead_surrogate = utf16_lead_surrogate;
  2712. utf16_lead_surrogate = null;
  2713. // 1. If code unit is in the range U+DC00 to U+DFFF,
  2714. // inclusive, return a code point whose value is 0x10000 +
  2715. // ((lead surrogate − 0xD800) << 10) + (code unit − 0xDC00).
  2716. if (inRange(code_unit, 0xDC00, 0xDFFF)) {
  2717. return 0x10000 + (lead_surrogate - 0xD800) * 0x400 +
  2718. (code_unit - 0xDC00);
  2719. }
  2720. // 2. Prepend the sequence resulting of converting code unit
  2721. // to bytes using utf-16be decoder flag to stream and return
  2722. // error.
  2723. stream.prepend(convertCodeUnitToBytes(code_unit, utf16_be));
  2724. return decoderError(fatal);
  2725. }
  2726. // 6. If code unit is in the range U+D800 to U+DBFF, inclusive,
  2727. // set utf-16 lead surrogate to code unit and return continue.
  2728. if (inRange(code_unit, 0xD800, 0xDBFF)) {
  2729. utf16_lead_surrogate = code_unit;
  2730. return null;
  2731. }
  2732. // 7. If code unit is in the range U+DC00 to U+DFFF, inclusive,
  2733. // return error.
  2734. if (inRange(code_unit, 0xDC00, 0xDFFF))
  2735. return decoderError(fatal);
  2736. // 8. Return code point code unit.
  2737. return code_unit;
  2738. };
  2739. }
  2740. // 15.2.2 shared utf-16 encoder
  2741. /**
  2742. * @constructor
  2743. * @implements {Encoder}
  2744. * @param {boolean} utf16_be True if big-endian, false if little-endian.
  2745. * @param {{fatal: boolean}} options
  2746. */
  2747. function UTF16Encoder(utf16_be, options) {
  2748. var fatal = options.fatal;
  2749. /**
  2750. * @param {Stream} stream Input stream.
  2751. * @param {number} code_point Next code point read from the stream.
  2752. * @return {(number|!Array.<number>)} Byte(s) to emit.
  2753. */
  2754. this.handler = function(stream, code_point) {
  2755. // 1. If code point is end-of-stream, return finished.
  2756. if (code_point === end_of_stream)
  2757. return finished;
  2758. // 2. If code point is in the range U+0000 to U+FFFF, inclusive,
  2759. // return the sequence resulting of converting code point to
  2760. // bytes using utf-16be encoder flag.
  2761. if (inRange(code_point, 0x0000, 0xFFFF))
  2762. return convertCodeUnitToBytes(code_point, utf16_be);
  2763. // 3. Let lead be ((code point − 0x10000) >> 10) + 0xD800,
  2764. // converted to bytes using utf-16be encoder flag.
  2765. var lead = convertCodeUnitToBytes(
  2766. ((code_point - 0x10000) >> 10) + 0xD800, utf16_be);
  2767. // 4. Let trail be ((code point − 0x10000) & 0x3FF) + 0xDC00,
  2768. // converted to bytes using utf-16be encoder flag.
  2769. var trail = convertCodeUnitToBytes(
  2770. ((code_point - 0x10000) & 0x3FF) + 0xDC00, utf16_be);
  2771. // 5. Return a byte sequence of lead followed by trail.
  2772. return lead.concat(trail);
  2773. };
  2774. }
  2775. // 15.3 utf-16be
  2776. // 15.3.1 utf-16be decoder
  2777. /** @param {{fatal: boolean}} options */
  2778. encoders['UTF-16BE'] = function(options) {
  2779. return new UTF16Encoder(true, options);
  2780. };
  2781. // 15.3.2 utf-16be encoder
  2782. /** @param {{fatal: boolean}} options */
  2783. decoders['UTF-16BE'] = function(options) {
  2784. return new UTF16Decoder(true, options);
  2785. };
  2786. // 15.4 utf-16le
  2787. // 15.4.1 utf-16le decoder
  2788. /** @param {{fatal: boolean}} options */
  2789. encoders['UTF-16LE'] = function(options) {
  2790. return new UTF16Encoder(false, options);
  2791. };
  2792. // 15.4.2 utf-16le encoder
  2793. /** @param {{fatal: boolean}} options */
  2794. decoders['UTF-16LE'] = function(options) {
  2795. return new UTF16Decoder(false, options);
  2796. };
  2797. // 15.5 x-user-defined
  2798. // 15.5.1 x-user-defined decoder
  2799. /**
  2800. * @constructor
  2801. * @implements {Decoder}
  2802. * @param {{fatal: boolean}} options
  2803. */
  2804. function XUserDefinedDecoder(options) {
  2805. var fatal = options.fatal;
  2806. /**
  2807. * @param {Stream} stream The stream of bytes being decoded.
  2808. * @param {number} bite The next byte read from the stream.
  2809. * @return {?(number|!Array.<number>)} The next code point(s)
  2810. * decoded, or null if not enough data exists in the input
  2811. * stream to decode a complete code point.
  2812. */
  2813. this.handler = function(stream, bite) {
  2814. // 1. If byte is end-of-stream, return finished.
  2815. if (bite === end_of_stream)
  2816. return finished;
  2817. // 2. If byte is an ASCII byte, return a code point whose value
  2818. // is byte.
  2819. if (isASCIIByte(bite))
  2820. return bite;
  2821. // 3. Return a code point whose value is 0xF780 + byte − 0x80.
  2822. return 0xF780 + bite - 0x80;
  2823. };
  2824. }
  2825. // 15.5.2 x-user-defined encoder
  2826. /**
  2827. * @constructor
  2828. * @implements {Encoder}
  2829. * @param {{fatal: boolean}} options
  2830. */
  2831. function XUserDefinedEncoder(options) {
  2832. var fatal = options.fatal;
  2833. /**
  2834. * @param {Stream} stream Input stream.
  2835. * @param {number} code_point Next code point read from the stream.
  2836. * @return {(number|!Array.<number>)} Byte(s) to emit.
  2837. */
  2838. this.handler = function(stream, code_point) {
  2839. // 1.If code point is end-of-stream, return finished.
  2840. if (code_point === end_of_stream)
  2841. return finished;
  2842. // 2. If code point is an ASCII code point, return a byte whose
  2843. // value is code point.
  2844. if (isASCIICodePoint(code_point))
  2845. return code_point;
  2846. // 3. If code point is in the range U+F780 to U+F7FF, inclusive,
  2847. // return a byte whose value is code point − 0xF780 + 0x80.
  2848. if (inRange(code_point, 0xF780, 0xF7FF))
  2849. return code_point - 0xF780 + 0x80;
  2850. // 4. Return error with code point.
  2851. return encoderError(code_point);
  2852. };
  2853. }
  2854. /** @param {{fatal: boolean}} options */
  2855. encoders['x-user-defined'] = function(options) {
  2856. return new XUserDefinedEncoder(options);
  2857. };
  2858. /** @param {{fatal: boolean}} options */
  2859. decoders['x-user-defined'] = function(options) {
  2860. return new XUserDefinedDecoder(options);
  2861. };
  2862. export default {
  2863. TextEncoder: TextEncoder,
  2864. TextDecoder: TextDecoder,
  2865. EncodingIndexes: codeIndexes
  2866. };