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