1 // Copyright (c) 1997 James Clark, 2000 Matthias Clasen
2 // See the file COPYING for copying permission.
3 
4 #ifndef CharMap_INCLUDED
5 #define CharMap_INCLUDED 1
6 
7 #include "types.h"
8 #include "Resource.h"
9 
10 #ifdef SP_NAMESPACE
11 namespace SP_NAMESPACE {
12 #endif
13 
14 #ifdef SP_MULTI_BYTE
15 
16 class CharMapBits {
17 public:
18   // 21 bits are enough for the UTF-16 range
19   enum { level0 = 5, level1 = 8, level2 = 4, level3 = 4 };
20 
21   enum {
22     planes = (1 << CharMapBits::level0) ,
23     pagesPerPlane = (1 << CharMapBits::level1),
24     columnsPerPage = (1 << CharMapBits::level2),
25     cellsPerColumn = (1 << CharMapBits::level3),
26     planeSize = (1 << (CharMapBits::level1 + CharMapBits::level2 + CharMapBits::level3)),
27     pageSize = (1 << (CharMapBits::level2 + CharMapBits::level3)),
28     columnSize = (1 << CharMapBits::level3)
29   };
30 
planeIndex(size_t c)31   static size_t planeIndex(size_t c) {
32     return (c >> (CharMapBits::level1 + CharMapBits::level2 + CharMapBits::level3));
33   }
pageIndex(size_t c)34   static size_t pageIndex(size_t c) {
35     return ((c >> (CharMapBits::level2 + CharMapBits::level3)) & (pagesPerPlane - 1));
36   }
columnIndex(size_t c)37   static size_t columnIndex(size_t c) {
38     return ((c >> CharMapBits::level3) & (columnsPerPage - 1));
39   }
cellIndex(size_t c)40   static size_t cellIndex(size_t c) {
41     return (c & (cellsPerColumn - 1));
42   }
maxInPlane(size_t c)43   static size_t maxInPlane(size_t c) {
44     return (c | (planeSize - 1));
45   }
maxInPage(size_t c)46   static size_t maxInPage(size_t c) {
47     return (c | (pageSize - 1));
48   }
maxInColumn(size_t c)49   static size_t maxInColumn(size_t c) {
50     return (c | (columnSize - 1));
51   }
52 };
53 
54 #if 0
55 // These are defines rather than static member functions of CharMapBits,
56 // since gcc chokes on them in array allocations.
57 #define planes         (1 << CharMapBits::level0)
58 #define pagesPerPlane  (1 << CharMapBits::level1)
59 #define columnsPerPage (1 << CharMapBits::level2)
60 #define cellsPerColumn (1 << CharMapBits::level3)
61 #define planeSize      (1 << (CharMapBits::level1 + CharMapBits::level2 + CharMapBits::level3))
62 #define pageSize       (1 << (CharMapBits::level2 + CharMapBits::level3))
63 #define columnSize     (1 << CharMapBits::level3)
64 #define planeIndex(c)  ((c) >> (CharMapBits::level1 + CharMapBits::level2 + CharMapBits::level3))
65 #define pageIndex(c)   (((c) >> (CharMapBits::level2 + CharMapBits::level3)) & (pagesPerPlane - 1))
66 #define columnIndex(c) (((c) >> CharMapBits::level3) & (columnsPerPage - 1))
67 #define cellIndex(c)   ((c) & (cellsPerColumn - 1))
68 #define maxInPlane(c)  ((c) | (planeSize - 1))
69 #define maxInPage(c)   ((c) | (pageSize - 1))
70 #define maxInColumn(c) ((c) | (columnSize - 1))
71 #endif
72 
73 template<class T>
74 class CharMapColumn {
75 public:
76   CharMapColumn();
77   CharMapColumn(const CharMapColumn<T> &);
78   void operator=(const CharMapColumn<T> &);
79   ~CharMapColumn();
80   T *values;
81   T value;
82 };
83 
84 template<class T>
85 class CharMapPage {
86 public:
87   CharMapPage();
88   CharMapPage(const CharMapPage<T> &);
89   void operator=(const CharMapPage<T> &);
90   ~CharMapPage();
91   void swap(CharMapPage<T> &);
92   CharMapColumn<T> *values;
93   T value;
94 };
95 
96 template<class T>
97 class CharMapPlane {
98 public:
99   CharMapPlane();
100   CharMapPlane(const CharMapPlane<T> &);
101   void operator=(const CharMapPlane<T> &);
102   ~CharMapPlane();
103   void swap(CharMapPlane<T> &);
104   CharMapPage<T> *values;
105   T value;
106 };
107 #endif /* SP_MULTI_BYTE */
108 
109 template<class T>
110 class CharMap {
111 public:
112   CharMap();
113   CharMap(T);
114   T operator[](Char) const;
115   T getRange(Char from, Char &to) const;
116   void swap(CharMap<T> &);
117   void setChar(Char, T);
118   void setRange(Char from, Char to, T val);
119   void setAll(T);
120 private:
121 #ifdef SP_MULTI_BYTE
122 
123   CharMapPlane<T> values_[CharMapBits::planes];
124   T lo_[256];
125 #else
126   T values_[256];
127 #endif
128 };
129 
130 template<class T>
131 class CharMapResource : public CharMap<T>, public Resource {
132 public:
CharMapResource()133   CharMapResource() { }
CharMapResource(T t)134   CharMapResource(T t) : CharMap<T>(t) { }
135 };
136 
137 #ifdef SP_MULTI_BYTE
138 
139 template<class T>
140 inline
141 T CharMap<T>::operator[](Char c) const
142 {
143   if (c < 256)
144     return lo_[c];
145   const CharMapPlane<T> &pl = values_[CharMapBits::planeIndex(c)];
146   if (pl.values) {
147     const CharMapPage<T> &pg = pl.values[CharMapBits::pageIndex(c)];
148     if (pg.values) {
149       const CharMapColumn<T> &column = pg.values[CharMapBits::columnIndex(c)];
150       if (column.values)
151         return column.values[CharMapBits::cellIndex(c)];
152       else
153         return column.value;
154     }
155     else
156       return pg.value;
157   }
158   else
159     return pl.value;
160 }
161 
162 template<class T>
163 inline
getRange(Char c,Char & max)164 T CharMap<T>::getRange(Char c, Char &max) const
165 {
166   if (c < 256) {
167     max = c;
168     return lo_[c];
169   }
170   const CharMapPlane<T> &pl = values_[CharMapBits::planeIndex(c)];
171   if (pl.values) {
172     const CharMapPage<T> &pg = pl.values[CharMapBits::pageIndex(c)];
173     if (pg.values) {
174       const CharMapColumn<T> &column = pg.values[CharMapBits::columnIndex(c)];
175       if (column.values) {
176         max = c;
177         return column.values[CharMapBits::cellIndex(c)];
178       }
179       else {
180         max = CharMapBits::maxInColumn(c);
181         return column.value;
182       }
183     }
184     else {
185       max = CharMapBits::maxInPage(c);
186       return pg.value;
187     }
188   }
189   else {
190     max = CharMapBits::maxInPlane(c);
191     return pl.value;
192   }
193 }
194 
195 #else
196 
197 template<class T>
198 inline
199 T CharMap<T>::operator[](Char c) const
200 {
201   return values_[c];
202 }
203 
204 template<class T>
205 inline
getRange(Char c,Char & max)206 T CharMap<T>::getRange(Char c, Char &max) const
207 {
208   max = c;
209   return values_[c];
210 }
211 
212 template<class T>
213 inline
setChar(Char c,T val)214 void CharMap<T>::setChar(Char c, T val)
215 {
216   values_[c] = val;
217 }
218 
219 #endif
220 
221 #ifdef SP_NAMESPACE
222 }
223 #endif
224 
225 #endif /* not CharMap_INCLUDED */
226 
227 #ifdef SP_DEFINE_TEMPLATES
228 #include "CharMap.cxx"
229 #endif
230