00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifndef _terimber_strrep_hpp_
00029 #define _terimber_strrep_hpp_
00030
00031 #include "strrep.h"
00032
00033 BEGIN_TERIMBER_NAMESPACE
00034
00035
00036
00037
00038
00039
00040 template < unsigned char N >
00041 backet_tank< N >::backet_tank(byte_allocator& all) : _states(0)
00042 {
00043 _head = (char*)all.allocate(ROOMS * LENGTH);
00044 }
00045
00046 template < unsigned char N >
00047 bool
00048 backet_tank< N >::full() const
00049 {
00050 return _states == 0;
00051 }
00052
00053 template < unsigned char N >
00054 bool
00055 backet_tank< N >::empty() const
00056 {
00057 return _states == (rooms_type_t)-1;
00058 }
00059
00060 template < unsigned char N >
00061 char*
00062 backet_tank< N >::get_chunk()
00063 {
00064 #ifdef DEBUG
00065 if (empty())
00066 {
00067 assert(false);
00068 return 0;
00069 }
00070 #endif
00071
00072
00073 unsigned char offset = 0x0;
00074
00075 rooms_type_t lowbit = ~_states & ~(~_states - 1);
00076 _states |= lowbit;
00077
00078 if (!(lowbit & 0xffffffff))
00079 {
00080 offset += 32;
00081 lowbit >>= 32;
00082 }
00083
00084 if (!(lowbit & 0xffff))
00085 {
00086 offset += 16;
00087 lowbit >>= 16;
00088 }
00089
00090 if (!(lowbit & 0xff))
00091 {
00092 offset += 8;
00093 lowbit >>= 8;
00094 }
00095
00096 if (!(lowbit & 0xf))
00097 {
00098 offset += 4;
00099 lowbit >>= 4;
00100 }
00101
00102 switch (lowbit & 0xf)
00103 {
00104 case 0:
00105 assert(false);
00106 break;
00107 case 1:
00108 case 3:
00109 case 5:
00110 case 7:
00111 case 9:
00112 case 11:
00113 case 13:
00114 case 15:
00115 break;
00116 case 2:
00117 case 6:
00118 case 10:
00119 case 14:
00120 offset += 1;
00121 break;
00122 case 4:
00123 case 12:
00124 offset += 2;
00125 break;
00126 case 8:
00127 offset += 3;
00128 break;
00129 }
00130
00131
00132 char* ret = _head + (offset * LENGTH);
00133 *ret = (char)N;
00134 *(ret + 1) = (char)offset;
00135
00136 return ret;
00137 }
00138
00139 template < unsigned char N >
00140 void
00141 backet_tank< N >::put_chunk(char* ptr)
00142 {
00143 unsigned char* chunk = (unsigned char*)(ptr - 4);
00144 #ifdef DEBUG
00145 if (*chunk != N)
00146 {
00147 assert(false);
00148 return;
00149 }
00150 #endif
00151 unsigned char offset = *(chunk + 1);
00152
00153 rooms_type_t mask = 0x01 << offset;
00154
00155 #ifdef DEBUG
00156 if (!(_states & mask))
00157 {
00158 assert(false);
00159 return;
00160 }
00161 #endif
00162
00163 _states &= ~mask;
00164 }
00165
00166 template < unsigned char N >
00167 void
00168 backet_tank< N >::reset()
00169 {
00170 _states = 0;
00171 }
00172
00173 template < unsigned char N, int M >
00174 string_backet< N, M >::string_backet() : _all( backet_tank< N >::LENGTH * M), _page(0)
00175 {
00176 reset();
00177 }
00178
00179 template < unsigned char N, int M >
00180 string_backet< N, M >::~string_backet()
00181 {
00182 }
00183
00184 template < unsigned char N, int M >
00185 char*
00186 string_backet< N, M >::allocate()
00187 {
00188 char* ret = 0;
00189
00190 while (_page < M && _pages[_page] && _pages[_page]->empty())
00191 ++_page;
00192
00193 if (_page == M)
00194 return 0;
00195
00196 if (!_pages[_page])
00197 {
00198 _pages[_page] = new (_all.allocate(sizeof(backet_tank< N >))) backet_tank< N >(_all);
00199 if (!_pages[_page])
00200 return 0;
00201 }
00202
00203 ret = _pages[_page]->get_chunk();
00204
00205 #ifdef DEBUG
00206 assert(ret != 0);
00207 #endif
00208
00209 *(ret + 2) = (char)((_page & 0xff00) >> 8);
00210 *(ret + 3) = (char)(_page & 0x00ff);
00211
00212 ret += 4;
00213 return ret;
00214 }
00215
00216 template < unsigned char N, int M >
00217 void
00218 string_backet< N, M >::deallocate(char* ptr)
00219 {
00220 unsigned char* backet = (unsigned char*)ptr - 4;
00221 #ifdef DEBUG
00222 if (*backet != N)
00223 {
00224 assert(false);
00225 return;
00226 }
00227 #endif
00228 unsigned short page_high = (unsigned short)*(backet + 2) & 0x00ff;
00229 unsigned short page_low = (unsigned short)*(backet + 3) & 0x00ff;
00230 unsigned short p = (page_high << 8 | page_low);
00231
00232 #ifdef DEBUG
00233 if (p >= M || !_pages[p])
00234 {
00235 assert(false);
00236 return;
00237 }
00238 #endif
00239 _pages[p]->put_chunk(ptr);
00240 if (p < _page)
00241 _page = p;
00242 }
00243
00244 template < unsigned char N, int M >
00245 void
00246 string_backet< N, M >::reset()
00247 {
00248 memset(_pages, 0, sizeof(void*) * M);
00249 _all.reset();
00250 }
00251
00252 template < unsigned char N, int M >
00253 void
00254 string_backet< N, M >::release()
00255 {
00256 for (int p = M; p > 0; --p)
00257 if (_pages[p - 1] && !_pages[p - 1]->full())
00258 return;
00259
00260 reset();
00261 }
00262
00263
00264 inline
00265 char*
00266 string_repository::allocate(size_t len)
00267 {
00268 if (!len)
00269 return 0;
00270
00271 char* ret = 0;
00272 size_t rounded_size = 4;
00273 int shift = len >> rounded_size;
00274
00275 while (shift > 1)
00276 {
00277 ++rounded_size;
00278 shift >>= 1;
00279 }
00280
00281 switch (rounded_size)
00282 {
00283 case 4:
00284 if (ret = _backet4.allocate())
00285 break;
00286 case 5:
00287 if (ret = _backet5.allocate())
00288 break;
00289 case 6:
00290 if (ret = _backet6.allocate())
00291 break;
00292 case 7:
00293 if (ret = _backet7.allocate())
00294 break;
00295 case 8:
00296 if (ret = _backet8.allocate())
00297 break;
00298 case 9:
00299 if (ret = _backet9.allocate())
00300 break;
00301 case 10:
00302 if (ret = _backet10.allocate())
00303 break;
00304 case 11:
00305 if (ret = _backet11.allocate())
00306 break;
00307 case 12:
00308 if (ret = _backet12.allocate())
00309 break;
00310 case 13:
00311 if (ret = _backet13.allocate())
00312 break;
00313 default:
00314 ret = new char[len + 4];
00315 if (ret)
00316 {
00317 memset(ret, 0, 4);
00318 ret += 4;
00319 }
00320 }
00321
00322 return ret;
00323 }
00324
00325 inline
00326 void
00327 string_repository::deallocate(char* ptr)
00328 {
00329 unsigned char* backet = (unsigned char*)ptr - 4;
00330 switch (*backet)
00331 {
00332 case 4:
00333 _backet4.deallocate(ptr);
00334 break;
00335 case 5:
00336 _backet5.deallocate(ptr);
00337 break;
00338 case 6:
00339 _backet6.deallocate(ptr);
00340 break;
00341 case 7:
00342 _backet7.deallocate(ptr);
00343 break;
00344 case 8:
00345 _backet8.deallocate(ptr);
00346 break;
00347 case 9:
00348 _backet9.deallocate(ptr);
00349 break;
00350 case 10:
00351 _backet10.deallocate(ptr);
00352 break;
00353 case 11:
00354 _backet11.deallocate(ptr);
00355 break;
00356 case 12:
00357 _backet12.deallocate(ptr);
00358 break;
00359 case 13:
00360 _backet13.deallocate(ptr);
00361 break;
00362 case 0:
00363 delete [] backet;
00364 break;
00365 default:
00366 assert(false);
00367 }
00368 }
00369
00370
00371 END_TERIMBER_NAMESPACE
00372
00373 #endif // _terimber_strrep_hpp_