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         if (typeof unescape === "function" && typeof encodeURIComponent === "function") {
 55             return unescape(encodeURIComponent(string));
 56         }
 57 
 58         for (n = 0; n < len; n++) {
 59             c = string.charCodeAt(n);
 60 
 61             if (c < 128) {
 62                 utftext += String.fromCharCode(c);
 63             } else if (c > 127 && c < 2048) {
 64                 utftext += String.fromCharCode((c >> 6) | 192);
 65                 utftext += String.fromCharCode((c & 63) | 128);
 66             } else {
 67                 utftext += String.fromCharCode((c >> 12) | 224);
 68                 utftext += String.fromCharCode(((c >> 6) & 63) | 128);
 69                 utftext += String.fromCharCode((c & 63) | 128);
 70             }
 71         }
 72 
 73         return utftext;
 74     },
 75 
 76     /**
 77      * Decode a string from utf-8.
 78      * @param {String} utftext to decode
 79      * @returns {String} utf8 decoded string
 80      */
 81     decode: function (utftext) {
 82         /*
 83                  The following code is a translation from C99 to JavaScript.
 84 
 85                  The original C99 code can be found at
 86                     https://bjoern.hoehrmann.de/utf-8/decoder/dfa/
 87 
 88                  Original copyright note:
 89 
 90                  Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de>
 91 
 92                  License: MIT License (see LICENSE.MIT)
 93             */
 94 
 95         var i,
 96             charCode,
 97             type,
 98             j = 0,
 99             codepoint = 0,
100             state = UTF8_ACCEPT,
101             chars = [],
102             len = utftext.length,
103             results = [];
104 
105         for (i = 0; i < len; i++) {
106             charCode = utftext.charCodeAt(i);
107             type = UTF8D[charCode];
108 
109             if (state !== UTF8_ACCEPT) {
110                 codepoint = (charCode & 0x3f) | (codepoint << 6);
111             } else {
112                 codepoint = (0xff >> type) & charCode;
113             }
114 
115             state = UTF8D[256 + state + type];
116 
117             if (state === UTF8_ACCEPT) {
118                 if (codepoint > 0xffff) {
119                     chars.push(0xd7c0 + (codepoint >> 10), 0xdc00 + (codepoint & 0x3ff));
120                 } else {
121                     chars.push(codepoint);
122                 }
123 
124                 j++;
125 
126                 if (j % 10000 === 0) {
127                     results.push(String.fromCharCode.apply(null, chars));
128                     chars = [];
129                 }
130             }
131         }
132         results.push(String.fromCharCode.apply(null, chars));
133         return results.join("");
134     },
135 
136     /**
137      * Extends the standard charCodeAt() method of the String class to find the ASCII char code of
138      * a character at a given position in a UTF8 encoded string.
139      * @param {String} str
140      * @param {Number} i position of the character
141      * @returns {Number}
142      */
143     asciiCharCodeAt: function (str, i) {
144         var c = str.charCodeAt(i);
145 
146         if (c > 255) {
147             switch (c) {
148                 case 8364:
149                     c = 128;
150                     break;
151                 case 8218:
152                     c = 130;
153                     break;
154                 case 402:
155                     c = 131;
156                     break;
157                 case 8222:
158                     c = 132;
159                     break;
160                 case 8230:
161                     c = 133;
162                     break;
163                 case 8224:
164                     c = 134;
165                     break;
166                 case 8225:
167                     c = 135;
168                     break;
169                 case 710:
170                     c = 136;
171                     break;
172                 case 8240:
173                     c = 137;
174                     break;
175                 case 352:
176                     c = 138;
177                     break;
178                 case 8249:
179                     c = 139;
180                     break;
181                 case 338:
182                     c = 140;
183                     break;
184                 case 381:
185                     c = 142;
186                     break;
187                 case 8216:
188                     c = 145;
189                     break;
190                 case 8217:
191                     c = 146;
192                     break;
193                 case 8220:
194                     c = 147;
195                     break;
196                 case 8221:
197                     c = 148;
198                     break;
199                 case 8226:
200                     c = 149;
201                     break;
202                 case 8211:
203                     c = 150;
204                     break;
205                 case 8212:
206                     c = 151;
207                     break;
208                 case 732:
209                     c = 152;
210                     break;
211                 case 8482:
212                     c = 153;
213                     break;
214                 case 353:
215                     c = 154;
216                     break;
217                 case 8250:
218                     c = 155;
219                     break;
220                 case 339:
221                     c = 156;
222                     break;
223                 case 382:
224                     c = 158;
225                     break;
226                 case 376:
227                     c = 159;
228                     break;
229                 default:
230                     break;
231             }
232         }
233         return c;
234     }
235 };
236 
237 export default JXG.Util.UTF8;
238