comparison dynamin/core/string.d @ 0:aa4efef0f0b1

Initial commit of code.
author Jordan Miner <jminer7@gmail.com>
date Mon, 15 Jun 2009 22:10:48 -0500
parents
children 3b0c5c599003
comparison
equal deleted inserted replaced
-1:000000000000 0:aa4efef0f0b1
1 // Written in the D programming language
2 // www.digitalmars.com/d/
3
4 /*
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
9 *
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
14 *
15 * The Original Code is the Dynamin library.
16 *
17 * The Initial Developer of the Original Code is Jordan Miner.
18 * Portions created by the Initial Developer are Copyright (C) 2006-2009
19 * the Initial Developer. All Rights Reserved.
20 *
21 * Contributor(s):
22 * Jordan Miner <jminer7@gmail.com>
23 *
24 */
25
26 /**
27 * These functions should all return a new string if it is possible for them
28 * to ever modify their input. If they will never modify their input, they
29 * should always return a slice.
30 */
31 module dynamin.core.string;
32
33 import tango.core.Exception;
34 import tango.text.convert.Utf;
35 import tango.text.convert.Layout;
36 import tango.text.Unicode;
37 import tango.text.Util;
38 import dynamin.core.global;
39 import dynamin.core.math;
40
41 /// Defined as a char[]
42 alias char[] string;
43
44 ///
45 char* toCharPtr(char[] str) {
46 return (str~'\0').ptr;
47 }
48 ///
49 wchar* toWcharPtr(char[] str) {
50 return toString16(str~'\0').ptr;
51 }
52
53 /*
54 string ToString(ulong num, uint base = 10) {
55 if(base > 16)
56 throw new Exception("ToString() - radix more than 16");
57 char[] digits = "0123456789abcdef";
58 string str;
59 ulong div = base;
60 ulong prevDiv = 1;
61 do {
62 uint rem = num % div;
63 str ~= digits[rem/prevDiv];
64 prevDiv = div;
65 div *= base;
66 num -= rem;
67 } while(num > 0);
68 str.reverse;
69 return str;
70 }
71 */
72 Layout!(char) formatter;
73 static this() {
74 formatter = new Layout!(char);
75 }
76 string format(char[] str, ...) {
77 return formatter.convert(_arguments, _argptr, str);
78 }
79 unittest {
80 assert(format("I am {}", 20) == "I am 20");
81 }
82
83 /**
84 * Converts all lowercase characters in the specified string to uppercase.
85 * Examples:
86 * -----
87 * "Bounce the ball.".upcase() == "BOUNCE THE BALL."
88 * "Mañana".upcase() == "MAÑANA"
89 * "æóëø".upcase() == "ÆÓËØ"
90 * -----
91 */
92 string upcase(string str) {
93 return toUpper(str);
94 }
95 unittest {
96 assert("Bounce the ball.".upcase() == "BOUNCE THE BALL.");
97 assert("Mañana".upcase() == "MAÑANA");
98 assert("æóëø".upcase() == "ÆÓËØ");
99 }
100 /**
101 * Converts all uppercase characters in the specified string to lowercase.
102 * Examples:
103 * -----
104 * "BoUnCe ThE BALL.".downcase() == "bounce the ball."
105 * "MAÑANA".downcase() == "mañana"
106 * "ÆÓËØ".downcase() == "æóëø"
107 * -----
108 */
109 string downcase(string str) {
110 return toLower(str);
111 }
112 unittest {
113 assert("BoUnCe ThE BALL.".downcase() == "bounce the ball.");
114 assert("MAÑANA".downcase() == "mañana");
115 assert("ÆÓËØ".downcase() == "æóëø");
116 }
117
118 // TODO: make more use of delegates in these?
119 // TODO; use templates so that these work with wchar and dchar?
120 bool startsWith(string str, string subStr, int start = 0) {
121 if(start+subStr.length > str.length)
122 return false;
123 return str[start..start+subStr.length] == subStr;
124 }
125 bool endsWith(string str, string subStr) {
126 return endsWith(str, subStr, str.length);
127 }
128 bool endsWith(string str, string subStr, int start) {
129 if(start-subStr.length < 0)
130 return false;
131 return str[str.length-subStr.length..str.length] == subStr;
132 }
133 int findLast(string str, string subStr) {
134 return findLast(str, subStr, str.length);
135 }
136 int findLast(string str, string subStr, int start) {
137 for(int i = start-subStr.length; i >= 0; --i)
138 if(str[i..i+subStr.length] == subStr)
139 return i;
140 return -1;
141 }
142 int find(string str, string subStr, int start = 0) {
143 for(int i = start; i < str.length-subStr.length; ++i)
144 if(str[i..i+subStr.length] == subStr)
145 return i;
146 return -1;
147 }
148 /**
149 * Tests whether or not the specified char is in the specified string.
150 * Returns: true if the specified char is in the string and false otherwise
151 * Examples:
152 * -----
153 * "Hello".contains('e') == true
154 * "Hello".contains('a') == false
155 * "".contains('e') == false
156 * -----
157 */
158 bool contains(string str, char c) {
159 foreach(char c2; str) {
160 if(c == c2)
161 return true;
162 }
163 return false;
164 }
165 /// ditto
166 bool contains(string str, dchar c) {
167 foreach(dchar c2; str) {
168 if(c == c2)
169 return true;
170 }
171 return false;
172 }
173 unittest {
174 assert("Hello".contains('e') == true);
175 assert("Hello".contains('a') == false);
176 assert("".contains('e') == false);
177 }
178 string remove(string str, int start, int count = 1) {
179 return str[0..start] ~ str[start+count..str.length];
180 }
181 // TODO: ?
182 // split(string str, int delegate(string s) func)
183 //string[] split(string str, string subStr) {
184 // return split(str, (string s) { return s.startsWith(subStr) ? subStr.length, : -1; };
185 //}
186 // TODO: return slices to string
187 //split1("50=20=10", "=") -> ["50", "20=10"]
188 string[] split1(string str, string subStr) {
189 if(subStr.length == 0)
190 return [str];
191 int index = find(str, subStr);
192 if(index == -1)
193 return [str];
194 string[] strs = new string[2];
195 strs[0] = str[0..index].dup;
196 strs[1] = str[index+subStr.length..str.length].dup;
197 return strs;
198 }
199 // TODO: return slices to string
200 //split("50=20=10", "=") -> ["50", "20", "10"]
201 string[] split(string str, string subStr) {
202 if(subStr.length == 0)
203 return [str];
204 string[] strs;
205 int index, searchFrom;
206 int i = 0;
207 while(searchFrom < str.length) {
208 index = find(str, subStr, searchFrom);
209 if(index == -1) index = str.length;
210 strs.length = strs.length+1;
211 strs[i] = str[searchFrom..index].dup;
212 ++i;
213 searchFrom = index+subStr.length;
214 }
215 return strs;
216 }
217 ///
218 enum Newline {
219 ///
220 Cr = 0,
221 ///
222 Lf = 1,
223 ///
224 Crlf = 2,
225 ///
226 Macintosh = 0,
227 ///
228 Linux = 1,
229 ///
230 Windows = 2
231 }
232 /**
233 * Changes every occurrence of a newline in the specified string to the specified newline.
234 * Examples:
235 * -----
236 * "\r\n\n\r".convertNewlines(Newline.Lf) == "\n\n\n"
237 * "\r\n\n\r".convertNewlines(Newline.Windows) == "\r\n\r\n\r\n"
238 * "\n\r\n".convertNewlines(Newline.Macintosh) == "\r\r"
239 * -----
240 */
241 string convertNewlines(string str, Newline nl) {
242 string lineSep;
243 switch(nl) {
244 case Newline.Cr: lineSep = "\r"; break;
245 case Newline.Lf: lineSep = "\n"; break;
246 case Newline.Crlf: lineSep = "\r\n"; break;
247 }
248 return str.replace([cast(string)"\r\n", "\r", "\n"], lineSep);
249 }
250 unittest {
251 assert("\r\n\n\r".convertNewlines(Newline.Lf) == "\n\n\n");
252 assert("\r\n\n\r".convertNewlines(Newline.Windows) == "\r\n\r\n\r\n");
253 assert("\n\r\n".convertNewlines(Newline.Macintosh) == "\r\r");
254 }
255
256 /**
257 * Joins all the strings in the specified array together into one string, putting
258 * the specified separator between them.
259 * Examples:
260 * -----
261 * join(["10", "15", "17"], " - ") == "10 - 15 - 17"
262 * join(["789", "672", "484"], ",") == "789,672,484"
263 * join(["aol.com", "join", "intro.html"], "/") == "aol.com/join/intro.html"
264 * -----
265 */
266 string join(string[] strs, string sep) {
267 if(strs.length == 0)
268 return "";
269 int len;
270 foreach(string s; strs)
271 len += s.length;
272 len += sep.length*(strs.length-1);
273
274 string newStr = new char[len];
275 newStr[0..strs[0].length] = strs[0];
276 int start = strs[0].length;
277 for(int i = 1; i < strs.length; ++i) {
278 auto str = strs[i];
279 newStr[start..start+sep.length] = sep;
280 start += sep.length;
281 newStr[start..start+str.length] = str;
282 start += str.length;
283 }
284 return newStr;
285 }
286 unittest {
287 // TODO: remove cast(string) when D has bugs fixed
288 assert(join(["10", "15", "17"], " - ") == "10 - 15 - 17");
289 assert(join(["789", "672", "484"], ",") == "789,672,484");
290 assert(join([cast(string)"aol.com", "join", "intro.html"], "/") == "aol.com/join/intro.html");
291 }
292
293 /**
294 * Multiplies the given string the specified number of times.
295 * Returns: a string that is the result of adding the specified string onto
296 * an empty string the specified number of times
297 * Examples:
298 * -----
299 * "Hi...".times(3) == "Hi...Hi...Hi..."
300 * "0".times(20) == "00000000000000000000"
301 * "Hi".times(0) == ""
302 * -----
303 */
304 string times(string str, int n) {
305 string newStr = new char[n * str.length];
306 for(int i = 0; i < newStr.length; i += str.length)
307 newStr[i..i+str.length] = str;
308 return newStr;
309 }
310 unittest {
311 assert("0".times(4) == "0000");
312 assert("Hello! ".times(2) == "Hello! Hello! ");
313 assert("".times(50) == "");
314 assert("Hi".times(0) == "");
315 }
316
317 // TODO: flesh out and make public
318 struct sbuilder {
319 int Count;
320 string Data;
321 void Add(char c) {
322 if(Count + 1 > Data.length)
323 Data.length = (Data.length + 1) * 2;
324 Data[Count] = c;
325 ++Count;
326 }
327 void Add(string str) {
328 if(Count + str.length > Data.length)
329 Data.length = max((Data.length + 1) * 2, Count + str.length);
330 Data[Count..Count+str.length] = str;
331 Count += str.length;
332 }
333 string ToString() {
334 return Data[0..Count].dup;
335 }
336 }
337 /**
338 * Replaces any occurrence of a specified search string in the specified string
339 * with corresponding replacement string. The length of the searchStrs array
340 * must equal the length of the replacements array.
341 * Examples:
342 * -----
343 * "Mississippi".replace(["is", "i"], ["..", "*"]) == "M..s..s*pp*"
344 * "Mississippi".replace("ss", "...") == "Mi...i...ippi"
345 * "Hello".replace("ll", "y") == "Heyo"
346 * "Hi".replace([], []) == "Hi"
347 * -----
348 * Note: If multiple search strings have the same prefix, the longer search
349 * strings must be given first. Otherwise, any occurrence will match a
350 * shorter one and will not have a chance to match any longer one.
351 * Examples:
352 * -----
353 * "Speaker".replace(["ea", "e"], ":") == "Sp:k:r"
354 * "Speaker".replace(["e", "ea"], ":") == "Sp:ak:r"
355 * -----
356 * Bug: If a search string has a length of zero, this method will go into an infinite loop.
357 */
358 string replace(string str, string[] searchStrs, string[] replacements) {
359 if(replacements.length == 1 && searchStrs.length > 1) {
360 string tmp = replacements[0];
361 replacements = new string[searchStrs.length];
362 foreach(i, dummy; searchStrs)
363 replacements[i] = tmp;
364 }
365 if(searchStrs.length != replacements.length)
366 throw new IllegalArgumentException(
367 "Replace(): searchStrs and replacements must be same length");
368 sbuilder builder;
369 loop:
370 for(int i = 0; i < str.length; ) {
371 foreach(j, subStr; searchStrs) {
372 if(i+subStr.length <= str.length && str[i..i+subStr.length] == subStr) {
373 // skip the part of string that matched
374 i += subStr.length;
375 builder.Add(replacements[j]);
376 continue loop;
377 }
378 }
379 builder.Add(str[i]);
380 ++i;
381 }
382 return builder.ToString();
383 }
384 /// ditto
385 string replace(string str, string[] searchStrs, string replacement) {
386 return str.replace(searchStrs, [replacement]);
387 }
388 /// ditto
389 string replace(string str, string searchStr, string replacement) {
390 return str.replace([searchStr], [replacement]);
391 }
392 unittest {
393 assert("Mississippi".replace([cast(string)"is", "i"], [cast(string)"..", "*"]) == "M..s..s*pp*");
394 assert("Mississippi".replace("ss", "...") == "Mi...i...ippi");
395 assert("Hello".replace("ll", "y") == "Heyo");
396 //assert("Hi".Replace(cast(string[])[], cast(string[])[]) == "Hi");
397 assert("Speaker".replace([cast(string)"ea", "e"], ":") == "Sp:k:r");
398 assert("Speaker".replace([cast(string)"e", "ea"], ":") == "Sp:ak:r");
399 }
400
401 /**
402 * Changes every occurrence of a specified character in chars to the
403 * corresponding character in escChars.
404 * Examples:
405 * -----
406 * "Line1\r\nLine2\\".escape() == "Line1\\r\\nLine2\\\\"
407 * "Line1\tLine2".escape() == "Line1\\tLine2"
408 * "Part1|Part2\r\n".escape("|\r\n", "|rn") == "Part1\\|Part2\\r\\n"
409 * -----
410 */
411 string escape(string str, char[] chars, char[] escChars) {
412 if(chars.length != escChars.length)
413 throw new IllegalArgumentException("Escape(): chars and escChars must be same length");
414 sbuilder builder;
415 loop:
416 foreach(i, c; str) {
417 foreach(j, c2; chars) {
418 if(c == '\\') { // always escape backslash
419 builder.Add('\\');
420 builder.Add('\\');
421 continue loop;
422 }
423 if(c == c2) {
424 builder.Add('\\');
425 builder.Add(escChars[j]);
426 continue loop;
427 }
428 }
429 builder.Add(c);
430 }
431 return builder.ToString();
432 }
433 /// ditto
434 string escape(string str) {
435 return str.escape("\t\r\n", "trn");
436 }
437 unittest {
438 assert("Line1\r\nLine2\\".escape() == "Line1\\r\\nLine2\\\\");
439 assert("Line1\tLine2".escape() == "Line1\\tLine2");
440 assert("Part1|Part2\r\n".escape("|\r\n", "|rn") == "Part1\\|Part2\\r\\n");
441 }
442 /**
443 * Changes every occurrence of a specified character in escChars to the
444 * corresponding character in chars.
445 * Examples:
446 * -----
447 * "Line1\\r\\nLine2".unescape() == "Line1\r\nLine2"
448 * "Line1\\tLine2".unescape() == "Line1\tLine2"
449 * "Part1\\|Part2\\r\\n".unescape("|rn", "|\r\n") == "Part1|Part2\r\n"
450 * // error:
451 * "test\\".unescape()
452 * -----
453 */
454 string unescape(string str, char[] escChars, char[] chars) {
455 if(escChars.length != chars.length)
456 throw new IllegalArgumentException("Unescape(): escChars and chars must be same length");
457 sbuilder builder;
458 loop:
459 foreach(i, c; str) {
460 if(c == '\\') {
461 if(i == str.length-1)
462 throw new IllegalArgumentException("Unescape(): partial escape sequence at end of string");
463 if(str[i+1] == '\\') {
464 builder.Add('\\');
465 ++i;
466 continue loop;
467 }
468 foreach(j, c2; escChars) {
469 if(str[i+1] == c2) {
470 builder.Add(chars[j]);
471 ++i;
472 continue loop;
473 }
474 }
475 throw new IllegalArgumentException("Unescape(): invalid escape sequence");
476 }
477 builder.Add(str[i]);
478 }
479 return builder.ToString();
480 }
481 /// ditto
482 string unescape(string str) {
483 return str.unescape("trn", "\t\r\n");
484 }
485 unittest {
486 assert("Line1\\r\\nLine2\\\\".unescape() == "Line1\r\nLine2\\");
487 assert("Line1\\tLine2".unescape() == "Line1\tLine2");
488 assert("Part1\\|Part2\\r\\n".unescape("|rn", "|\r\n") == "Part1|Part2\r\n");
489 }
490 unittest {
491 string str = r"C:\\n";
492 assert(str.escape().unescape() == str);
493 }
494 /**
495 * Removes all whitespace characters from the specified string.
496 * Examples:
497 * -----
498 * "4a d2 7c 3f".removeWhitespace() == "4ad27c3f"
499 * " Hello \r\n".removeWhitespace() == "Hello"
500 * "How are you?".removeWhitespace() == "Howareyou?"
501 * "\t \n\r\f\v".removeWhitespace() == ""
502 * -----
503 */
504 string removeWhitespace(string str) {
505 sbuilder builder;
506 foreach(c; str)
507 if(!" \t\n\r\v\f".contains(c))
508 builder.Add(c);
509 return builder.ToString();
510 }
511 unittest {
512 assert("4a d2 7c 3f".removeWhitespace() == "4ad27c3f");
513 assert(" Hello \r\n".removeWhitespace() == "Hello");
514 assert("How are you?".removeWhitespace() == "Howareyou?");
515 assert("\t \n\r\f\v".removeWhitespace() == "");
516 }
517 /**
518 * Removes all the whitespace characters from the start and from the end
519 * of the specified string. Returns a slice.
520 * Examples:
521 * -----
522 * " Hello \r\n".trim() == "Hello"
523 * "How are you?".trim() == "How are you?"
524 * "\n la di da ".trim() == "la di da"
525 * " \n".trim() == ""
526 * "".trim() == ""
527 * -----
528 */
529 string trim(string str) {
530 int start = -1, end = str.length;
531 while( --end >= 0 && " \t\n\r\v\f".contains(str[end]) ) { }
532 end++;
533 if(end == 0) // means all whitespace
534 return "";
535 while(" \t\n\r\v\f".contains(str[++start])) { }
536 return str[start..end];
537 }
538 unittest {
539 assert(" Hello \r\n".trim() == "Hello");
540 assert("How are you?".trim() == "How are you?");
541 assert("\n la di da ".trim() == "la di da");
542 assert(" \n".trim() == "");
543 assert("".trim() == "");
544 }
545 /**
546 * Removes all the whitespace characters from the start
547 * of the specified string. Returns a slice.
548 * Examples:
549 * -----
550 * " Hello \r\n".trimLeft() == "Hello \r\n"
551 * "How are you?".trimLeft() == "How are you?"
552 * "\n la di da ".trimLeft() == "la di da "
553 * " \n".trimLeft() == ""
554 * "".trimLeft() == ""
555 * -----
556 */
557 string trimLeft(string str) {
558 int start = -1;
559 while(++start < str.length && " \t\n\r\v\f".contains(str[start])) { }
560 return str[start..$];
561 }
562 unittest {
563 assert(" Hello \r\n".trimLeft() == "Hello \r\n");
564 assert("How are you?".trimLeft() == "How are you?");
565 assert("\n la di da ".trimLeft() == "la di da ");
566 assert(" \n".trimLeft() == "");
567 assert("".trimLeft() == "");
568 }
569 /**
570 * Removes all the whitespace characters from the start
571 * of the specified string. Returns a slice.
572 * Examples:
573 * -----
574 * " Hello \r\n".trimRight() == " Hello"
575 * "How are you?".trimRight() == "How are you?"
576 * "\n la di da ".trimRight() == "\n la di da"
577 * " \n".trimRight() == ""
578 * "".trimRight() == ""
579 * -----
580 */
581 string trimRight(string str) {
582 int end = str.length;
583 while( --end >= 0 && " \t\n\r\v\f".contains(str[end]) ) { }
584 end++;
585 return str[0..end];
586 }
587 unittest {
588 assert(" Hello \r\n".trimRight() == " Hello");
589 assert("How are you?".trimRight() == "How are you?");
590 assert("\n la di da ".trimRight() == "\n la di da");
591 assert(" \n".trimRight() == "");
592 assert("".trimRight() == "");
593 }
594
595
596 unittest {
597 assert(".NET Framework".startsWith(".N"));
598 assert(".NET Framework".startsWith("Frame", 5));
599 assert(!".NET Framework".startsWith(".NEW"));
600 assert(".NET Framework".find("NET") == 1);
601 assert(".NET Framework".find("NET", 2) == -1);
602 assert(".NET Framework".find("") == 0);
603 assert("Mississippi".findLast("ss") == 5);
604 assert("Mississippi".findLast("ss", 4) == 2);
605 assert("Jordan=20".split("=") == [cast(string)"Jordan", "20"]);
606 assert("Jordan".split("") == [cast(string)"Jordan"]);
607 assert("Jordan".split1("=") == [cast(string)"Jordan"]);
608 }
609
610 /*class Encoding {
611 private:
612 //TODO: remove dependency on std.utf
613 static Encoding[] encodings = [
614 //new Encoding("windows-1252".Str(), "Western European (Windows)".Str(), encodeTableWindows1252)
615 ];
616 String name;
617 String desc;
618 public:
619 //property
620 static Encoding[] Encodings() {
621 return encodings;
622 }
623 static Encoding GetEncoding(String name) {
624 }
625 static byte[] Convert(Encoding src, Encoding dst, byte[] bytes) {}
626
627 this(String name, String description, wchar[] table) {
628 this.name = name;
629 }
630 // example: utf-8
631 String Name() {
632 return name;
633 }
634 // example: Unicode (UTF-8)
635 String Description() {
636 return desc;
637 }
638 int GetEncodedCount() {}
639 byte[] Encode(String str) {
640 }
641 //Returns the number of characters
642 int GetDecodedLength() {
643 }
644 String Decode(byte[] bytes) {
645 }
646 }*/
647 //class Utf8Encoding : Encoding {
648 //public:
649 //}
650
651 //characters that cannot be mapped to unicode are 0xFFFD in the tables
652 wchar[] encodeTableWindows1252 = [
653 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008,
654 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, 0x0010, 0x0011,
655 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001A,
656 0x001B, 0x001C, 0x001D, 0x001E, 0x001F, 0x0020, 0x0021, 0x0022, 0x0023,
657 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C,
658 0x002D, 0x002E, 0x002F, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035,
659 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E,
660 0x003F, 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
661 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050,
662 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059,
663 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F, 0x0060, 0x0061, 0x0062,
664 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B,
665 0x006C, 0x006D, 0x006E, 0x006F, 0x0070, 0x0071, 0x0072, 0x0073, 0x0074,
666 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D,
667 0x007E, 0x007F, 0x20AC, 0xFFFD, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020,
668 0x2021, 0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0xFFFD, 0x017D, 0xFFFD,
669 0xFFFD, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x02DC,
670 0x2122, 0x0161, 0x203A, 0x0153, 0xFFFD, 0x017E, 0x0178, 0x00A0, 0x00A1,
671 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, 0x00A8, 0x00A9, 0x00AA,
672 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, 0x00B0, 0x00B1, 0x00B2, 0x00B3,
673 0x00B4, 0x00B5, 0x00B6, 0x00B7, 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC,
674 0x00BD, 0x00BE, 0x00BF, 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5,
675 0x00C6, 0x00C7, 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE,
676 0x00CF, 0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7,
677 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF, 0x00E0,
678 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, 0x00E8, 0x00E9,
679 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, 0x00F0, 0x00F1, 0x00F2,
680 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, 0x00F8, 0x00F9, 0x00FA, 0x00FB,
681 0x00FC, 0x00FD, 0x00FE, 0x00FF
682 ];
683
684 //iso8859-1 does not need a conversion table, as its values are all the same as Unicode's
685
686 wchar[] encodeTableIso8859_2 = [
687 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008,
688 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, 0x0010, 0x0011,
689 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001A,
690 0x001B, 0x001C, 0x001D, 0x001E, 0x001F, 0x0020, 0x0021, 0x0022, 0x0023,
691 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C,
692 0x002D, 0x002E, 0x002F, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035,
693 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E,
694 0x003F, 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
695 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050,
696 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059,
697 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F, 0x0060, 0x0061, 0x0062,
698 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B,
699 0x006C, 0x006D, 0x006E, 0x006F, 0x0070, 0x0071, 0x0072, 0x0073, 0x0074,
700 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D,
701 0x007E, 0x007F, 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086,
702 0x0087, 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F,
703 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, 0x0098,
704 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F, 0x00A0, 0x0104,
705 0x02D8, 0x0141, 0x00A4, 0x013D, 0x015A, 0x00A7, 0x00A8, 0x0160, 0x015E,
706 0x0164, 0x0179, 0x00AD, 0x017D, 0x017B, 0x00B0, 0x0105, 0x02DB, 0x0142,
707 0x00B4, 0x013E, 0x015B, 0x02C7, 0x00B8, 0x0161, 0x015F, 0x0165, 0x017A,
708 0x02DD, 0x017E, 0x017C, 0x0154, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x0139,
709 0x0106, 0x00C7, 0x010C, 0x00C9, 0x0118, 0x00CB, 0x011A, 0x00CD, 0x00CE,
710 0x010E, 0x0110, 0x0143, 0x0147, 0x00D3, 0x00D4, 0x0150, 0x00D6, 0x00D7,
711 0x0158, 0x016E, 0x00DA, 0x0170, 0x00DC, 0x00DD, 0x0162, 0x00DF, 0x0155,
712 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x013A, 0x0107, 0x00E7, 0x010D, 0x00E9,
713 0x0119, 0x00EB, 0x011B, 0x00ED, 0x00EE, 0x010F, 0x0111, 0x0144, 0x0148,
714 0x00F3, 0x00F4, 0x0151, 0x00F6, 0x00F7, 0x0159, 0x016F, 0x00FA, 0x0171,
715 0x00FC, 0x00FD, 0x0163, 0x02D9
716 ];
717
718 wchar[] encodeTableIso8859_3 = [
719 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008,
720 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, 0x0010, 0x0011,
721 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001A,
722 0x001B, 0x001C, 0x001D, 0x001E, 0x001F, 0x0020, 0x0021, 0x0022, 0x0023,
723 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C,
724 0x002D, 0x002E, 0x002F, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035,
725 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E,
726 0x003F, 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
727 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050,
728 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059,
729 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F, 0x0060, 0x0061, 0x0062,
730 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B,
731 0x006C, 0x006D, 0x006E, 0x006F, 0x0070, 0x0071, 0x0072, 0x0073, 0x0074,
732 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D,
733 0x007E, 0x007F, 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086,
734 0x0087, 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F,
735 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, 0x0098,
736 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F, 0x00A0, 0x0126,
737 0x02D8, 0x00A3, 0x00A4, 0x0124, 0x00A7, 0x00A8, 0x0130, 0x015E, 0x011E,
738 0x0134, 0x00AD, 0x017B, 0x00B0, 0x0127, 0x00B2, 0x00B3, 0x00B4, 0x00B5,
739 0x0125, 0x00B7, 0x00B8, 0x0131, 0x015F, 0x011F, 0x0135, 0x00BD, 0x017C,
740 0x00C0, 0x00C1, 0x00C2, 0x00C4, 0x010A, 0x0108, 0x00C7, 0x00C8, 0x00C9,
741 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, 0x00D1, 0x00D2, 0x00D3,
742 0x00D4, 0x0120, 0x00D6, 0x00D7, 0x011C, 0x00D9, 0x00DA, 0x00DB, 0x00DC,
743 0x016C, 0x015C, 0x00DF, 0x00E0, 0x00E1, 0x00E2, 0x00E4, 0x010B, 0x0109,
744 0x00E7, 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
745 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x0121, 0x00F6, 0x00F7, 0x011D, 0x00F9,
746 0x00FA, 0x00FB, 0x00FC, 0x016D, 0x015D, 0x02D9
747 ];