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