1 // Copyright (c) 1997 James Clark
2 // See the file COPYING for copying permission.
3 
4 #ifndef CharMap_DEF_INCLUDED
5 #define CharMap_DEF_INCLUDED 1
6 
7 #ifdef SP_NAMESPACE
8 namespace SP_NAMESPACE {
9 #endif
10 
11 #ifdef SP_MULTI_BYTE
12 
13 template<class T>
CharMap()14 CharMap<T>::CharMap()
15 {
16 }
17 
18 template<class T>
CharMap(T dflt)19 CharMap<T>::CharMap(T dflt)
20 {
21   for (size_t i = 0; i < (1 << CharMapBits::level1); i++)
22     pages_[i].value = dflt;
23 }
24 
25 template<class T>
setAll(T val)26 void CharMap<T>::setAll(T val)
27 {
28   for (size_t i = 0; i < (1 << CharMapBits::level1); i++) {
29     pages_[i].value = val;
30     delete [] pages_[i].values;
31     pages_[i].values = 0;
32   }
33 }
34 
35 template<class T>
swap(CharMap<T> & map)36 void CharMap<T>::swap(CharMap<T> &map)
37 {
38   for (size_t i = 0; i < (1 << CharMapBits::level1); i++)
39     pages_[i].swap(map.pages_[i]);
40 }
41 
42 template<class T>
setChar(Char c,T val)43 void CharMap<T>::setChar(Char c, T val)
44 {
45   CharMapPage<T> &pg = pages_[c >> (CharMapBits::level2 + CharMapBits::level3)];
46   if (pg.values) {
47     CharMapColumn<T> &column = pg.values[(c >> CharMapBits::level3) & ((1 << CharMapBits::level2) - 1)];
48     if (column.values)
49       column.values[c & ((1 << CharMapBits::level3) - 1)] = val;
50     else if (val != column.value) {
51       column.values = new T[1 << CharMapBits::level3];
52       for (size_t i = 0; i < (1 << CharMapBits::level3); i++)
53 	column.values[i] = column.value;
54       column.values[c & ((1 << CharMapBits::level3) - 1)] = val;
55     }
56   }
57   else if (val != pg.value) {
58     pg.values = new CharMapColumn<T>[1 << CharMapBits::level2];
59     for (size_t i = 0; i < (1 << CharMapBits::level2); i++)
60       pg.values[i].value = pg.value;
61     CharMapColumn<T> &column = pg.values[(c >> CharMapBits::level3) & ((1 << CharMapBits::level2) - 1)];
62     column.values = new T[1 << CharMapBits::level3];
63     for (size_t i = 0; i < (1 << CharMapBits::level3); i++)
64       column.values[i] = column.value;
65     column.values[c & ((1 << CharMapBits::level3) - 1)] = val;
66   }
67 }
68 
69 template<class T>
setRange(Char from,Char to,T val)70 void CharMap<T>::setRange(Char from, Char to, T val)
71 {
72   do {
73     if ((from & ((1 << CharMapBits::level3) - 1)) == 0
74         && to - from >= (1 << CharMapBits::level3) - 1) {
75       if ((from & ((1 << (CharMapBits::level2 + CharMapBits::level3)) - 1)) == 0
76 	  && to - from >= (1 << (CharMapBits::level2 + CharMapBits::level3)) - 1) {
77 	// Set a complete page.
78 	CharMapPage<T> &pg = pages_[from >> (CharMapBits::level2 + CharMapBits::level3)];
79 	pg.value = val;
80 	delete [] pg.values;
81 	pg.values = 0;
82 	from += (1 << (CharMapBits::level2 + CharMapBits::level3)) - 1;
83       }
84       else {
85 	// Set a complete column.
86 	CharMapPage<T> &pg = pages_[from >> (CharMapBits::level2 + CharMapBits::level3)];
87 	if (pg.values) {
88 	  CharMapColumn<T> &column = pg.values[(from >> CharMapBits::level3) & ((1 << CharMapBits::level2) - 1)];
89 	  column.value = val;
90 	  delete [] column.values;
91 	  column.values = 0;
92 	}
93 	else if (val != pg.value) {
94 	  // split the page
95 	  pg.values = new CharMapColumn<T>[1 << CharMapBits::level2];
96           for (size_t i = 0; i < (1 << CharMapBits::level2); i++)
97 	    pg.values[i].value = pg.value;
98 	  CharMapColumn<T> &column = pg.values[(from >> CharMapBits::level3) & ((1 << CharMapBits::level2) - 1)];
99 	  column.value = val;
100 	}
101 	from += (1 << CharMapBits::level2) - 1;
102       }
103     }
104     else
105       setChar(from, val);
106   } while (from++ != to);
107 }
108 
109 template<class T>
CharMapPage()110 CharMapPage<T>::CharMapPage()
111 : values(0)
112 {
113 }
114 
115 template<class T>
CharMapPage(const CharMapPage<T> & pg)116 CharMapPage<T>::CharMapPage(const CharMapPage<T> &pg)
117 {
118   if (pg.values) {
119     values = new CharMapColumn<T>[1 << CharMapBits::level2];
120     for (size_t i = 0; i < (1 << CharMapBits::level2); i++)
121       values[i] = pg.values[i];
122   }
123   else {
124     value = pg.value;
125     values = 0;
126   }
127 }
128 
129 template<class T>
operator =(const CharMapPage<T> & pg)130 void CharMapPage<T>::operator=(const CharMapPage<T> &pg)
131 {
132   if (pg.values) {
133     if (!values)
134       values = new CharMapColumn<T>[1 << CharMapBits::level2];
135     for (size_t i = 0; i < (1 << CharMapBits::level2); i++)
136       values[i] = pg.values[i];
137   }
138   else {
139     if (values) {
140       delete [] values;
141       values = 0;
142     }
143     value = pg.value;
144   }
145 }
146 
147 template<class T>
~CharMapPage()148 CharMapPage<T>::~CharMapPage()
149 {
150   delete [] values;
151 }
152 
153 template<class T>
swap(CharMapPage<T> & pg)154 void CharMapPage<T>::swap(CharMapPage<T> &pg)
155 {
156   {
157     CharMapColumn<T> *tem = values;
158     values = pg.values;
159     pg.values = tem;
160   }
161   {
162     T tem(value);
163     value = pg.value;
164     pg.value = tem;
165   }
166 }
167 
168 template<class T>
CharMapColumn()169 CharMapColumn<T>::CharMapColumn()
170 : values(0)
171 {
172 }
173 
174 template<class T>
CharMapColumn(const CharMapColumn<T> & col)175 CharMapColumn<T>::CharMapColumn(const CharMapColumn<T> &col)
176 {
177   if (col.values) {
178     values = new T[1 << CharMapBits::level3];
179     for (size_t i = 0; i < (1 << CharMapBits::level3); i++)
180       values[i] = col.values[i];
181   }
182   else {
183     values = 0;
184     value = col.value;
185   }
186 }
187 
188 template<class T>
operator =(const CharMapColumn<T> & col)189 void CharMapColumn<T>::operator=(const CharMapColumn<T> &col)
190 {
191   if (col.values) {
192     if (!values)
193       values = new T[1 << CharMapBits::level3];
194     for (size_t i = 0; i < (1 << CharMapBits::level3); i++)
195       values[i] = col.values[i];
196   }
197   else {
198     if (values) {
199       delete [] values;
200       values = 0;
201     }
202     value = col.value;
203   }
204 }
205 
206 template<class T>
~CharMapColumn()207 CharMapColumn<T>::~CharMapColumn()
208 {
209   delete [] values;
210 }
211 
212 #else /* not SP_MULTI_BYTE */
213 
214 template<class T>
215 CharMap<T>::CharMap()
216 {
217 }
218 
219 template<class T>
220 CharMap<T>::CharMap(T dflt)
221 {
222   for (int i = 0; i < 256; i++)
223     values_[i] = dflt;
224 }
225 
226 template<class T>
227 void CharMap<T>::setAll(T val)
228 {
229   for (size_t i = 0; i < 256; i++)
230     values_[i] = val;
231 }
232 
233 template<class T>
234 void CharMap<T>::setRange(Char from, Char to, T val)
235 {
236   do {
237     values_[from] = val;
238   } while (from++ != to);
239 }
240 
241 template<class T>
242 void CharMap<T>::swap(CharMap<T> &map)
243 {
244   for (size_t i = 0; i < 256; i++) {
245     T tem(values_[i]);
246     values_[i] = map.values_[i];
247     map.values_[i] = tem;
248   }
249 }
250 
251 #endif /* not SP_MULTI_BYTE */
252 
253 #ifdef SP_NAMESPACE
254 }
255 #endif
256 
257 #endif /* not CharMap_DEF_INCLUDED */
258