2005-07-27 Atsushi Enomoto <atsushi@ximian.com>
[mono.git] / mcs / class / corlib / Mono.Globalization.Unicode / CodePointIndexer.cs
1 using System;
2 using System.Globalization;
3 using System.Text;
4
5 namespace Mono.Globalization.Unicode
6 {
7         internal class CodePointIndexer
8         {
9                 public static Array CompressArray (
10                         Array source, Type type, CodePointIndexer indexer)
11                 {
12                         int totalCount = 0;
13                         for (int i = 0; i < indexer.ranges.Length; i++)
14                                 totalCount += indexer.ranges [i].Count;
15
16                         Array ret = Array.CreateInstance (type, totalCount);
17                         for (int i = 0; i < indexer.ranges.Length; i++)
18                                 Array.Copy (
19                                         source,
20                                         indexer.ranges [i].Start,
21                                         ret,
22                                         indexer.ranges [i].IndexStart,
23                                         indexer.ranges [i].Count);
24                         return ret;
25                 }
26
27                 // This class is used to compactize indexes to limited areas so that
28                 // we can save extraneous 0,0,0,0,0... in the tables.
29                 internal class TableRange
30                 {
31                         public TableRange (int start, int end, int indexStart)
32                         {
33                                 Start = start;
34                                 End = end;
35                                 Count = End - Start;
36                                 IndexStart = indexStart;
37                                 IndexEnd = IndexStart + Count;
38                         }
39
40                         public readonly int Start;
41                         public readonly int End;
42                         public readonly int Count;
43                         public readonly int IndexStart;
44                         public readonly int IndexEnd;
45                 }
46
47                 readonly TableRange [] ranges;
48
49                 public readonly int TotalCount;
50
51                 int defaultIndex;
52                 int defaultCP;
53
54                 public CodePointIndexer (int [] starts, int [] ends, int defaultIndex, int defaultCP)
55                 {
56                         this.defaultIndex = defaultIndex;
57                         this.defaultCP = defaultCP;
58                         ranges = new TableRange [starts.Length];
59                         for (int i = 0; i < ranges.Length; i++)
60                                 ranges [i] = new TableRange (starts [i],
61                                         ends [i], i == 0 ? 0 :
62                                         ranges [i - 1].IndexStart +
63                                         ranges [i - 1].Count);
64                         for (int i = 0; i < ranges.Length; i++)
65                                 TotalCount += ranges [i].Count;
66
67 //                      for (int i = 0; i < ranges.Length; i++)
68 //                              Console.Error.WriteLine ("RANGES [{0}] : {1:x} to {2:x} index {3:x} to {4:x}. total {5:x}", i, ranges [i].Start, ranges [i].End, ranges [i].IndexStart, ranges [i].IndexEnd, ranges [i].Count);
69 //                      Console.Error.WriteLine ("Total items: {0:X} ({1})", TotalCount, TotalCount);
70                 }
71
72                 public int ToIndex (int cp)
73                 {
74                         for (int t = 0; t < ranges.Length; t++) {
75                                 if (cp < ranges [t].Start)
76                                         return defaultIndex;
77                                 else if (cp < ranges [t].End)
78                                         return cp - ranges [t].Start + ranges [t].IndexStart;
79                         }
80                         return defaultIndex;
81 //                      throw new SystemException (String.Format ("Should not happen: no map definition for cp {0:x}({1})", cp, (char) cp));
82                 }
83
84                 public int ToCodePoint (int i)
85                 {
86                         for (int t = 0; t < ranges.Length; t++) {
87 /*
88                                 if (t > 0 && i < ranges [t - 1].IndexEnd)
89                                         return defaultCP; // unexpected out of range
90                                 if (ranges [t].IndexStart <= i &&
91                                         i < ranges [t].IndexEnd)
92                                         return i - ranges [t].IndexStart
93                                                 + ranges [t].Start;
94 */
95                                 if (i < ranges [t].IndexStart)
96                                         return defaultCP;
97                                 if (i < ranges [t].IndexEnd)
98                                         return i - ranges [t].IndexStart
99                                                 + ranges [t].Start;
100                         }
101                         return defaultCP;
102 //                      throw new SystemException (String.Format ("Should not happen: no map definition for index {0:x}({1})", i, i));
103                 }
104         }
105 }