Merge pull request #297 from ermshiperete/4959
[mono.git] / mcs / class / corlib / Mono.Globalization.Unicode / create-collation-element-table.cs
1 //
2 // create-collation-element-table.cs :
3 //      supports creation of CollationElementTable.cs
4 //
5 // Author:
6 //      Atsushi Enomoto  <atsushi@ximian.com>
7 //
8 // Copyright (C) 2005 Novell, Inc (http://www.novell.com)
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
17 // 
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
20 // 
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 //
29
30 using System;
31 using System.Globalization;
32 using System.IO;
33
34 namespace Mono.Globalization.Unicode
35 {
36         internal class CollationElementTableCodeGenerator
37         {
38                 private int lineCount = 0;
39
40                 int keyCount = 1; // 0 indicates that there is no matching entry
41                 int [] collElem = new int [CollationElementTableUtil.Indexer.TotalCount];
42                 SortKeyValue [] keyValues = new SortKeyValue [32768];
43
44                 public static void Main ()
45                 {
46                         new CollationElementTableCodeGenerator ().Run ();
47                 }
48
49                 public void Run ()
50                 {
51                         try {
52                                 Parse ();
53                                 Serialize ();
54                         } catch (Exception) {
55                                 Console.Error.WriteLine ("Internal error at line " + lineCount);
56                                 throw;
57                         }
58                         /*
59                         int lastQ = -1;
60                         for (int x = 1; x < CollationElementTableUtil.Indexer.TotalCount; x++) {
61                                 int i = CollationElementTableUtil.Indexer.GetIndexForCodePoint (x);
62                                 int q = keyValues [collElem [i]].Quarternary;
63 //                              if (i != q && q != 0)
64 //                                      Console.Error.WriteLine ("differs : {0} -> {1}", i, q);
65                                 if (q != 0) {
66                                         if (lastQ >= q)
67                                                 Console.Error.WriteLine ("latter was smaller at {2} : {0} / {1}", lastQ, q, i);
68                                         lastQ = q;
69                                 }
70                         }
71                         */
72                 }
73
74                 private void Serialize ()
75                 {
76                         Console.WriteLine ("static readonly int [] collElem = new int [] {");
77                         DumpArray (collElem, CollationElementTableUtil.Indexer.TotalCount, true);
78                         Console.WriteLine ("};");
79                         Console.WriteLine ("static readonly SortKeyValue [] keyValues = new SortKeyValue [] {");
80                         for (int i = 0; i < keyCount; i++) {
81                                 SortKeyValue s = keyValues [i];
82                                 Console.WriteLine ("    new SortKeyValue ({0}, 0x{1:X04}, 0x{2:X04}, 0x{3:X04}, 0x{4:X04}),",
83                                         s.Alt ? "true" : "false", s.Primary, s.Secondary,
84                                         s.Thirtiary, s.Quarternary);
85                         }
86                         Console.WriteLine ("};");
87                 }
88
89                 private void DumpArray (int [] array, int count, bool getCP)
90                 {
91                         if (array.Length < count)
92                                 throw new ArgumentOutOfRangeException ("count");
93                         for (int i = 0; i < count; i++) {
94                                 if (array [i] == 0)
95                                         Console.Write ("0, ");
96                                 else
97                                         Console.Write ("0x{0:X}, ", array [i]);
98                                 if (i % 16 == 15) {
99                                         int l = getCP ? CollationElementTableUtil.Indexer.ToCodePoint (i) : i;
100                                         Console.WriteLine ("// {0:X04}-{1:X04}", l - 15, l);
101                                 }
102                         }
103                 }
104
105                 private void Parse ()
106                 {
107                         ushort [] v = new ushort [4];
108
109                         TextReader reader = Console.In;
110                         while (reader.Peek () != -1) {
111                                 string line = reader.ReadLine ();
112                                 lineCount++;
113                                 if (line.StartsWith ("@"))
114                                         continue; // @version, @variable etc.
115                                 int idx = line.IndexOf ('#');
116                                 if (idx >= 0)
117                                         line = line.Substring (0, idx);
118                                 if (line.Length == 0)
119                                         continue;
120
121                                 int cp = int.Parse (line.Substring (0, 5), NumberStyles.HexNumber);
122                                 int collElemIdx = CollationElementTableUtil.Indexer.ToIndex (cp);
123                                 if (collElemIdx < 0) {
124                                         Console.Error.WriteLine ("WARNING: handle character {0:x} in collation element table.", cp);
125                                         continue;
126                                 }
127
128                                 line = line.Substring (line.IndexOf (';') + 1).Trim ();
129                                 // count entries in a line
130                                 int entryPerLine = 0;
131                                 for (int e = 0; (e = line.IndexOf ('[', e) + 1) > 0;)
132                                         entryPerLine++;
133
134                                 int start = 0;
135                                 for (int e = 0; e < entryPerLine; e++) {
136                                         start = line.IndexOf ('[', start) + 1;
137                                         string s = line.Substring (start, line.IndexOf (']', start) - start);
138
139                                         bool alt = false;
140                                         if (s [0] == '*')
141                                                 alt = true;
142                                         string [] vslist = s.Substring (1).Split ('.');
143                                         bool skip = false;
144                                         for (int i = 0; i < 4; i++) {
145                                                 if (vslist [i].Length > 4)
146                                                         skip = true;
147                                                 else
148                                                         v [i] = ushort.Parse (vslist [i], NumberStyles.HexNumber);
149                                         }
150                                         if (skip) {
151 //                                              Console.Error.WriteLine ("WARNING: skipped entry {0:X}", cp);
152                                                 continue;
153                                         }
154                                         idx = keyCount;
155                                         if (entryPerLine == 1) {
156                                                 // idx = 0 means "no matching entry", so here we start from 1
157                                                 for (idx = 1; idx < keyCount; idx++) {
158                                                         SortKeyValue k = keyValues [idx];
159                                                         if (k.Alt == alt &&
160                                                                 k.Primary == v [0] &&
161                                                                 k.Secondary == v [1] &&
162                                                                 k.Thirtiary == v [2] &&
163                                                                 k.Quarternary == v [3])
164                                                                 break;
165                                                 }
166                                         }
167                                         if (idx == keyCount)
168                                                 AddEntry (alt, v);
169                                 }
170                                 if (entryPerLine == 1)
171                                         collElem [collElemIdx] = idx;
172                                 else
173                                         collElem [collElemIdx] = 
174                                                 (short) (keyCount - entryPerLine)
175                                                 + (short) (entryPerLine << 16);
176                         }
177                         reader.Close ();
178                 }
179
180                 private void AddEntry (bool alt, ushort [] v)
181                 {
182                         if (keyCount == keyValues.Length) {
183                                 SortKeyValue [] tmp = new SortKeyValue [keyCount * 2];
184                                 Array.Copy (keyValues, tmp, keyCount);
185                                 keyValues = tmp;
186                         }
187                         keyValues [keyCount] =
188                                 new SortKeyValue (alt,
189                                 v [0], (byte) v [1], (byte) v [2], v [3]);
190                         keyCount++;
191                 }
192         }
193 }
194