2005-07-14 Atsushi Enomoto <atsushi@ximian.com>
[mono.git] / mcs / class / corlib / Mono.Globalization.Unicode / create-collation-element-table.cs
1 //
2 //
3 // CollationbElementTableCodeGenerator.cs
4 //
5 // Author:
6 //      Atsushi Enomoto  <atsushi@ximian.com>
7 //
8 // Copyright 2005 Novell, Inc
9 //
10 // It supports creation of CollationElementTable.cs
11 //
12
13 using System;
14 using System.Globalization;
15 using System.IO;
16
17 namespace Mono.Globalization.Unicode
18 {
19         internal class CollationElementTableCodeGenerator
20         {
21                 private int lineCount = 0;
22
23                 int keyCount = 1; // 0 indicates that there is no matching entry
24                 int [] collElem = new int [CollationElementTableUtil.Indexer.TotalCount];
25                 SortKeyValue [] keyValues = new SortKeyValue [32768];
26
27                 public static void Main ()
28                 {
29                         new CollationElementTableCodeGenerator ().Run ();
30                 }
31
32                 public void Run ()
33                 {
34                         try {
35                                 Parse ();
36                                 Serialize ();
37                         } catch (Exception) {
38                                 Console.Error.WriteLine ("Internal error at line " + lineCount);
39                                 throw;
40                         }
41                         /*
42                         int lastQ = -1;
43                         for (int x = 1; x < CollationElementTableUtil.Indexer.TotalCount; x++) {
44                                 int i = CollationElementTableUtil.Indexer.GetIndexForCodePoint (x);
45                                 int q = keyValues [collElem [i]].Quarternary;
46 //                              if (i != q && q != 0)
47 //                                      Console.Error.WriteLine ("differs : {0} -> {1}", i, q);
48                                 if (q != 0) {
49                                         if (lastQ >= q)
50                                                 Console.Error.WriteLine ("latter was smaller at {2} : {0} / {1}", lastQ, q, i);
51                                         lastQ = q;
52                                 }
53                         }
54                         */
55                 }
56
57                 private void Serialize ()
58                 {
59                         Console.WriteLine ("static readonly int [] collElem = new int [] {");
60                         DumpArray (collElem, CollationElementTableUtil.Indexer.TotalCount, true);
61                         Console.WriteLine ("};");
62                         Console.WriteLine ("static readonly SortKeyValue [] keyValues = new SortKeyValue [] {");
63                         for (int i = 0; i < keyCount; i++) {
64                                 SortKeyValue s = keyValues [i];
65                                 Console.WriteLine ("    new SortKeyValue ({0}, 0x{1:X04}, 0x{2:X04}, 0x{3:X04}, 0x{4:X04}),",
66                                         s.Alt ? "true" : "false", s.Primary, s.Secondary,
67                                         s.Thirtiary, s.Quarternary);
68                         }
69                         Console.WriteLine ("};");
70                 }
71
72                 private void DumpArray (int [] array, int count, bool getCP)
73                 {
74                         if (array.Length < count)
75                                 throw new ArgumentOutOfRangeException ("count");
76                         for (int i = 0; i < count; i++) {
77                                 if (array [i] == 0)
78                                         Console.Write ("0, ");
79                                 else
80                                         Console.Write ("0x{0:X}, ", array [i]);
81                                 if (i % 16 == 15) {
82                                         int l = getCP ? CollationElementTableUtil.Indexer.ToCodePoint (i) : i;
83                                         Console.WriteLine ("// {0:X04}-{1:X04}", l - 15, l);
84                                 }
85                         }
86                 }
87
88                 private void Parse ()
89                 {
90                         ushort [] v = new ushort [4];
91
92                         TextReader reader = Console.In;
93                         while (reader.Peek () != -1) {
94                                 string line = reader.ReadLine ();
95                                 lineCount++;
96                                 if (line.StartsWith ("@"))
97                                         continue; // @version, @variable etc.
98                                 int idx = line.IndexOf ('#');
99                                 if (idx >= 0)
100                                         line = line.Substring (0, idx);
101                                 if (line.Length == 0)
102                                         continue;
103
104                                 int cp = int.Parse (line.Substring (0, 5), NumberStyles.HexNumber);
105                                 int collElemIdx = CollationElementTableUtil.Indexer.ToIndex (cp);
106                                 if (collElemIdx < 0) {
107                                         Console.Error.WriteLine ("WARNING: handle character {0:x} in collation element table.", cp);
108                                         continue;
109                                 }
110
111                                 line = line.Substring (line.IndexOf (';') + 1).Trim ();
112                                 // count entries in a line
113                                 int entryPerLine = 0;
114                                 for (int e = 0; (e = line.IndexOf ('[', e) + 1) > 0;)
115                                         entryPerLine++;
116
117                                 int start = 0;
118                                 for (int e = 0; e < entryPerLine; e++) {
119                                         start = line.IndexOf ('[', start) + 1;
120                                         string s = line.Substring (start, line.IndexOf (']', start) - start);
121
122                                         bool alt = false;
123                                         if (s [0] == '*')
124                                                 alt = true;
125                                         string [] vslist = s.Substring (1).Split ('.');
126                                         bool skip = false;
127                                         for (int i = 0; i < 4; i++) {
128                                                 if (vslist [i].Length > 4)
129                                                         skip = true;
130                                                 else
131                                                         v [i] = ushort.Parse (vslist [i], NumberStyles.HexNumber);
132                                         }
133                                         if (skip) {
134 //                                              Console.Error.WriteLine ("WARNING: skipped entry {0:X}", cp);
135                                                 continue;
136                                         }
137                                         idx = keyCount;
138                                         if (entryPerLine == 1) {
139                                                 // idx = 0 means "no matching entry", so here we start from 1
140                                                 for (idx = 1; idx < keyCount; idx++) {
141                                                         SortKeyValue k = keyValues [idx];
142                                                         if (k.Alt == alt &&
143                                                                 k.Primary == v [0] &&
144                                                                 k.Secondary == v [1] &&
145                                                                 k.Thirtiary == v [2] &&
146                                                                 k.Quarternary == v [3])
147                                                                 break;
148                                                 }
149                                         }
150                                         if (idx == keyCount)
151                                                 AddEntry (alt, v);
152                                 }
153                                 if (entryPerLine == 1)
154                                         collElem [collElemIdx] = idx;
155                                 else
156                                         collElem [collElemIdx] = 
157                                                 (short) (keyCount - entryPerLine)
158                                                 + (short) (entryPerLine << 16);
159                         }
160                         reader.Close ();
161                 }
162
163                 private void AddEntry (bool alt, ushort [] v)
164                 {
165                         if (keyCount == keyValues.Length) {
166                                 SortKeyValue [] tmp = new SortKeyValue [keyCount * 2];
167                                 Array.Copy (keyValues, tmp, keyCount);
168                                 keyValues = tmp;
169                         }
170                         keyValues [keyCount] =
171                                 new SortKeyValue (alt,
172                                 v [0], (byte) v [1], (byte) v [2], v [3]);
173                         keyCount++;
174                 }
175         }
176 }
177