1 /*global JXG: true, define: true, escape: true, unescape: true*/ 2 /*jslint nomen: true, plusplus: true, bitwise: true*/ 3 4 import JXG from "../jxg"; 5 6 // constants 7 var UTF8_ACCEPT = 0, 8 UTF8_REJECT = 12, 9 UTF8D = [ 10 // The first part of the table maps bytes to character classes that 11 // to reduce the size of the transition table and create bitmasks. 12 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 17 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 18 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 19 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 10, 3, 3, 3, 3, 3, 3, 3, 20 3, 3, 3, 3, 3, 4, 3, 3, 11, 6, 6, 6, 5, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 21 22 // The second part is a transition table that maps a combination 23 // of a state of the automaton and a character class to a state. 24 0, 12, 24, 36, 60, 96, 84, 12, 12, 12, 48, 72, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 25 12, 12, 12, 0, 12, 12, 12, 12, 12, 0, 12, 0, 12, 12, 12, 24, 12, 12, 12, 12, 12, 24, 12, 26 24, 12, 12, 12, 12, 12, 12, 12, 12, 12, 24, 12, 12, 12, 12, 12, 24, 12, 12, 12, 12, 12, 27 12, 12, 24, 12, 12, 12, 12, 12, 12, 12, 12, 12, 36, 12, 36, 12, 12, 12, 36, 12, 12, 12, 28 12, 12, 36, 12, 36, 12, 12, 12, 36, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12 29 ]; 30 31 // Util namespace 32 JXG.Util = JXG.Util || {}; 33 34 /** 35 * UTF8 encoding routines 36 * @namespace 37 */ 38 JXG.Util.UTF8 = { 39 /** 40 * Encode a string to utf-8. 41 * @param {String} string 42 * @returns {String} utf8 encoded string 43 */ 44 encode: function (string) { 45 var n, 46 c, 47 utftext = "", 48 len = string.length; 49 50 string = string.replace(/\r\n/g, "\n"); 51 52 // See 53 // http://ecmanaut.blogspot.ca/2006/07/encoding-decoding-utf8-in-javascript.html 54 // http://monsur.hossa.in/2012/07/20/utf-8-in-javascript.html 55 if (typeof unescape === "function" && typeof encodeURIComponent === "function") { 56 return unescape(encodeURIComponent(string)); 57 } 58 59 for (n = 0; n < len; n++) { 60 c = string.charCodeAt(n); 61 62 if (c < 128) { 63 utftext += String.fromCharCode(c); 64 } else if (c > 127 && c < 2048) { 65 utftext += String.fromCharCode((c >> 6) | 192); 66 utftext += String.fromCharCode((c & 63) | 128); 67 } else { 68 utftext += String.fromCharCode((c >> 12) | 224); 69 utftext += String.fromCharCode(((c >> 6) & 63) | 128); 70 utftext += String.fromCharCode((c & 63) | 128); 71 } 72 } 73 74 return utftext; 75 }, 76 77 /** 78 * Decode a string from utf-8. 79 * @param {String} utftext to decode 80 * @returns {String} utf8 decoded string 81 */ 82 decode: function (utftext) { 83 /* 84 The following code is a translation from C99 to JavaScript. 85 86 The original C99 code can be found at 87 http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ 88 89 Original copyright note: 90 91 Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de> 92 93 License: MIT License (see LICENSE.MIT) 94 */ 95 96 var i, 97 charCode, 98 type, 99 j = 0, 100 codepoint = 0, 101 state = UTF8_ACCEPT, 102 chars = [], 103 len = utftext.length, 104 results = []; 105 106 for (i = 0; i < len; i++) { 107 charCode = utftext.charCodeAt(i); 108 type = UTF8D[charCode]; 109 110 if (state !== UTF8_ACCEPT) { 111 codepoint = (charCode & 0x3f) | (codepoint << 6); 112 } else { 113 codepoint = (0xff >> type) & charCode; 114 } 115 116 state = UTF8D[256 + state + type]; 117 118 if (state === UTF8_ACCEPT) { 119 if (codepoint > 0xffff) { 120 chars.push(0xd7c0 + (codepoint >> 10), 0xdc00 + (codepoint & 0x3ff)); 121 } else { 122 chars.push(codepoint); 123 } 124 125 j++; 126 127 if (j % 10000 === 0) { 128 results.push(String.fromCharCode.apply(null, chars)); 129 chars = []; 130 } 131 } 132 } 133 results.push(String.fromCharCode.apply(null, chars)); 134 return results.join(""); 135 }, 136 137 /** 138 * Extends the standard charCodeAt() method of the String class to find the ASCII char code of 139 * a character at a given position in a UTF8 encoded string. 140 * @param {String} str 141 * @param {Number} i position of the character 142 * @returns {Number} 143 */ 144 asciiCharCodeAt: function (str, i) { 145 var c = str.charCodeAt(i); 146 147 if (c > 255) { 148 switch (c) { 149 case 8364: 150 c = 128; 151 break; 152 case 8218: 153 c = 130; 154 break; 155 case 402: 156 c = 131; 157 break; 158 case 8222: 159 c = 132; 160 break; 161 case 8230: 162 c = 133; 163 break; 164 case 8224: 165 c = 134; 166 break; 167 case 8225: 168 c = 135; 169 break; 170 case 710: 171 c = 136; 172 break; 173 case 8240: 174 c = 137; 175 break; 176 case 352: 177 c = 138; 178 break; 179 case 8249: 180 c = 139; 181 break; 182 case 338: 183 c = 140; 184 break; 185 case 381: 186 c = 142; 187 break; 188 case 8216: 189 c = 145; 190 break; 191 case 8217: 192 c = 146; 193 break; 194 case 8220: 195 c = 147; 196 break; 197 case 8221: 198 c = 148; 199 break; 200 case 8226: 201 c = 149; 202 break; 203 case 8211: 204 c = 150; 205 break; 206 case 8212: 207 c = 151; 208 break; 209 case 732: 210 c = 152; 211 break; 212 case 8482: 213 c = 153; 214 break; 215 case 353: 216 c = 154; 217 break; 218 case 8250: 219 c = 155; 220 break; 221 case 339: 222 c = 156; 223 break; 224 case 382: 225 c = 158; 226 break; 227 case 376: 228 c = 159; 229 break; 230 default: 231 break; 232 } 233 } 234 return c; 235 } 236 }; 237 238 export default JXG.Util.UTF8; 239