# Home    # nevrax.com   
Nevrax
Nevrax.org
#News
#Mailing-list
#Documentation
#CVS
#Bugs
#License
Docs
 
Documentation  
Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages   Search  

ps_attrib.h

Go to the documentation of this file.
00001 
00007 /* Copyright, 2001 Nevrax Ltd.
00008  *
00009  * This file is part of NEVRAX NEL.
00010  * NEVRAX NEL is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2, or (at your option)
00013  * any later version.
00014 
00015  * NEVRAX NEL is distributed in the hope that it will be useful, but
00016  * WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00018  * General Public License for more details.
00019 
00020  * You should have received a copy of the GNU General Public License
00021  * along with NEVRAX NEL; see the file COPYING. If not, write to the
00022  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00023  * MA 02111-1307, USA.
00024  */
00025 
00026 #ifndef NL_PS_ATTRIB_H
00027 #define NL_PS_ATTRIB_H
00028 
00029 
00030 
00031 #include "nel/misc/types_nl.h"
00032 #include "nel/misc/stream.h"
00033 #include "nel/3d/animation_time.h"
00034 #include "nel/misc/vector.h"
00035 #include "nel/misc/rgba.h"
00036 #include "nel/misc/common.h"
00037 
00038 
00039 namespace NL3D {
00040 
00043 template <class T, const uint snapPower = 5>
00044 class CSnappedVector
00045 {
00046 public:
00047         typedef T *iterator;    
00048         typedef const T *const_iterator;
00049         typedef T value_type;
00050 
00051         CSnappedVector() : _Size(0), _Capacity(0), _Start(NULL), _Tab(NULL) {}
00052         ~CSnappedVector() 
00053         { 
00054                 nlassert(_Size <= _Capacity);
00055                 for (iterator it = _Tab, endIt = _Tab + _Size; it != endIt; ++it)
00056                 {
00057                         it->~T();
00058                 }
00059                 delete _Start; 
00060         }
00061         iterator begin(void) { return _Tab; }
00062         const_iterator begin(void) const { return _Tab; }
00063         iterator end(void) { return _Tab + _Size; }
00064         const_iterator end(void) const { return _Tab + _Size; }
00065 
00066         T &operator[](uint index) { nlassert(index < _Size && _Size); return _Tab[index]; }
00067         const T &operator[](uint index) const { nlassert(index < _Size && _Size); return _Tab[index]; }
00068 
00070         void reserve(uint capacity)
00071         {       
00072                 if (capacity < _Capacity) return;
00073                 uint8 *newStart = NULL;
00074                 try
00075                 {                       
00076                         newStart = new uint8[sizeof(T) * capacity + (1 << snapPower)];
00077                         T *newTab = (T *) ( (uint) (newStart + (1 << snapPower))  & ~((1 << snapPower) - 1)); // snap to a page
00078 
00079                         
00080                 
00081                         for (iterator src = _Tab, end = _Tab + (capacity < _Size ? capacity : _Size), dest = newTab 
00082                                 ; src != end 
00083                                 ; ++ src, ++dest)
00084                         {
00085                                 new ((void *) dest) T(*src); // copy object
00086                         }
00087 
00088                         // swap datas
00089                         std::swap(_Start, newStart);
00090                         std::swap(_Tab, newTab);
00091 
00092                         // destroy previous objects. We assume that we can't have exceptions raised from destructors
00093                         for (iterator it = newTab /* old tab */, endIt = newTab + _Size; it != endIt; ++ it)
00094                         {
00095                                 it->~T();
00096                         }
00097 
00098                         // set new size
00099                         _Capacity = capacity;
00100                         _Size    = capacity < _Size ? capacity : _Size;
00101 
00102 
00103                         // delete old vect (that was swapped with the new one)
00104                         delete [] newStart;
00105                         nlassert(_Size <= _Capacity);
00106                 }
00107                 catch (...)
00108                 {
00109                         delete [] newStart;
00110                         throw;
00111                 }
00112         
00113         }
00114         void resize(uint size)
00115         {
00116                 nlassert(size < (1 << 16));
00117                 if (size < _Size)
00118                 {
00119                         for (iterator it = _Tab + size, endIt = _Tab + _Size; it != endIt; ++it)
00120                         {
00121                                 it->~T();
00122                         }                       
00123                 }
00124                 else
00125                 {
00126                         if (size > _Capacity) 
00127                         {
00128                                 reserve(size);
00129                         }
00130                         for (iterator it = _Tab + _Size, endIt = _Tab + size; it != endIt; ++it)
00131                         {
00132                                 new ((void *) it) T();
00133                         }
00134                 }
00135 
00136                 _Size = size;
00137                 nlassert(_Size <= _Capacity);
00138         }
00139 
00140         void push_back(const T &t)
00141         {
00142                 if (!_Size)
00143                 {
00144                         reserve(2);
00145                         new ((void *) _Tab) T(t);
00146                         _Size = 1;
00147                 }
00148                 else
00149                 if (_Size < _Capacity)
00150                 {
00151                         new ((void *) (_Tab + _Size)) T(t);
00152                         ++_Size;
00153                 }
00154                 else                            
00155                 if (_Size == _Capacity) 
00156                 { 
00157                         if (_Capacity == 1) 
00158                         {
00159                                 reserve(2);
00160                         }
00161                         else
00162                         {
00163                                 reserve(_Capacity + (_Capacity>>1));
00164                         }
00165                         nlassert(_Size <= _Capacity);
00166                         new ((void *) (_Tab + _Size)) T(t);
00167                         ++_Size;
00168                 }
00169         }
00170 
00171         void pop_back()
00172         {
00173                 nlassert(_Size);
00174                 _Tab[_Size - 1].~T();
00175                 --_Size;
00176         }
00177 
00178 
00179         uint capacity() const  { return _Capacity; }
00180         uint size() const { return _Size; }
00181 
00183         void serial(NLMISC::IStream &f) throw(NLMISC::EStream)
00184         {
00185                 if (f.isReading())
00186                 {
00187                         clear();
00188                         uint32 size, maxsize;
00189                         f.serial(size, maxsize);
00190                         reserve(maxsize);
00191                         for (uint k = 0; k < size; ++k)
00192                         {
00193                                 T tmp;
00194                                 f.serial(tmp);
00195                                 push_back(tmp);
00196                         }
00197                 }
00198                 else
00199                 {
00200                         f.serial(_Size, _Capacity);
00201                         for (uint k = 0; k < _Size; ++k)
00202                         {
00203                                 f.serial(_Tab[k]);
00204                         }
00205                 }               
00206         }
00207 
00208         // clear
00209         void clear() { resize(0); }
00210 
00211 protected:
00212 
00213         uint8 *_Start;   // real allocation address
00214         T *_Tab;       // first element
00215         uint32 _Size;    // used elements
00216         uint32 _Capacity; // max size
00217 };
00218 
00219 
00220 
00221 
00222 
00223 
00233 template <typename T> class CPSAttrib
00234 {
00235 public:
00236 
00238 
00239 
00240                         CPSAttrib();
00241 
00243                         void serial(NLMISC::IStream &f) throw(NLMISC::EStream);
00245 
00247 
00248 
00251                 //typedef CSnappedVector<T> TContType;
00252                         typedef std::vector<T> TContType;
00253 
00255                 typedef T value_type;
00256 
00258                 typedef typename TContType::iterator iterator;
00260                 typedef typename TContType::const_iterator const_iterator;
00262 
00263 
00265 
00266 
00269                 void                                    resize(uint32 nbInstances);
00270 
00272                 uint32 getSize(void) const { return _Tab.size(); }
00273 
00275                 uint32 getMaxSize(void) const { return _MaxSize; }
00276 
00278 
00279 
00281 
00282 
00283                 const T &                               operator[](uint32 index) const 
00284                 { 
00285                         #ifdef NL_DEBUG
00286                                 nlassert(index < _Tab.size());
00287                         #endif
00288                         return _Tab[index]; 
00289                 }
00290 
00292                 T &                                             operator[](uint32 index) 
00293                 { 
00294                         #ifdef NL_DEBUG
00295                                 nlassert(index < _Tab.size());
00296                         #endif
00297                         return _Tab[index]; 
00298                 }
00300 
00301 
00302 
00304 
00305 
00306 
00308                 iterator                                begin(void) { return _Tab.begin(); }
00309 
00311                 iterator                                end(void) { return _Tab.end(); }        
00312 
00314                 const_iterator                  begin(void) const { return _Tab.begin(); }
00315 
00317                 const_iterator                  end(void) const { return _Tab.end(); }  
00319         
00321 
00322 
00326                 sint32 insert(const T &t = T() );               
00327 
00329                 void remove(uint32 index); 
00330 
00332                 void clear(void)
00333                 {
00334                         _Tab.clear();                   
00335                 }
00337 
00338 protected:                      
00339         TContType _Tab; 
00340         uint32    _MaxSize; // the max number of elements that can be stored
00341 };
00342 
00343 
00344 
00345 
00346 
00348 //                                      IMPLEMENTATION                                                                     //
00350 
00351 template <typename T> 
00352 CPSAttrib<T>::CPSAttrib()
00353 {
00354         _MaxSize = DefaultMaxLocatedInstance;
00355 }
00356 
00357 
00358 template <typename T> 
00359 void CPSAttrib<T>::resize(uint32 nbInstances)
00360 {       
00361         nlassert(nbInstances < (1 << 16));
00362         _Tab.reserve(nbInstances);
00363         _MaxSize = nbInstances;
00364 }
00365 
00366 
00367 template <typename T> 
00368 sint32 CPSAttrib<T>::insert(const T &t)
00369 {       
00370         if (_Tab.size() == _MaxSize && _Tab.size() > DefaultMaxLocatedInstance) 
00371         {
00372                 return -1;
00373         }       
00374         _Tab.push_back(t);
00375         return _Tab.size() - 1; 
00376 }
00377 
00378 
00379 template <typename T> 
00380 void CPSAttrib<T>::remove(uint32 index)
00381 {       
00382         nlassert(index < _Tab.size());
00383         // we copy the last element in place of this one
00384         if (index != _Tab.size() - 1)
00385         {
00386                 _Tab[index] = _Tab[_Tab.size() - 1];
00387         }
00388         _Tab.pop_back();
00389         
00390 }
00391 
00392 template <typename T> 
00393 void CPSAttrib<T>::serial(NLMISC::IStream &f) throw(NLMISC::EStream)
00394 {       
00395         sint ver = f.serialVersion(3);
00396 
00397         // in the first version, size was duplicated, we were using a std::vector ...
00398         if (ver == 1)
00399         {               
00400                 if(f.isReading())
00401                 {       
00402                         uint32 size;
00403                         f.serial(size);
00404                         f.serial(_MaxSize);
00405                         _Tab.reserve(_MaxSize);
00406                         f.serial(size); // useless but, we were previously doing a serialCont... compatibility purpose only
00407                         T tmp;
00408                         // Read the vector
00409                         for(uint i = 0; i < size; i++)
00410                         {
00411                                 f.serial(tmp);
00412                                 _Tab.push_back(tmp);
00413                         }
00414                         nlassert(_Tab.size() == size);
00415                 }
00416                 else
00417                 {
00418                         uint32 size = _Tab.size();
00419                         f.serial(size);
00420                         f.serial(_MaxSize);             
00421                         f.serial(size);
00422                         // write the vector
00423                         for(uint i = 0; i < size; i++)
00424                         {
00425                                 f.serial(_Tab[i]);                              
00426                         }
00427                 }
00428         }
00429 
00430         if (ver == 2) // this version didn't work well, it relied on the capacity of the container to store the max number of instances
00431         {
00432                 nlassert(0);
00433         /*      f.serial(_Tab);
00434                 if (f.isReading())
00435                 {
00436                         _MaxSize = _Tab.capacity();
00437                 }*/
00438         }       
00439 
00440         if (ver == 3)
00441         {
00442                 f.serial(_MaxSize);
00443                 _Tab.reserve(_MaxSize);
00444                 //f.serial(_Tab);
00445 
00446 
00447                 if (f.isReading())
00448                 {
00449                         _Tab.clear();
00450                         uint32 size, maxsize;
00451                         f.serial(size, maxsize);
00452                         _Tab.reserve(maxsize);
00453                         for (uint k = 0; k < size; ++k)
00454                         {
00455                                 T tmp;
00456                                 f.serial(tmp);
00457                                 _Tab.push_back(tmp);
00458                         }
00459                 }
00460                 else
00461                 {
00462                         uint32 size = _Tab.size(), capacity = _Tab.capacity();
00463                         f.serial(size, capacity);
00464                         for (uint k = 0; k < size; ++k)
00465                         {
00466                                 f.serial(_Tab[k]);
00467                         }
00468                 }
00469         }
00470 }
00471 
00472 
00473 
00474 
00475 // here we give some definition for common types
00476 
00477 typedef CPSAttrib<NLMISC::CVector> TPSAttribVector;
00478 typedef CPSAttrib<NLMISC::CRGBA>   TPSAttribRGBA;
00479 typedef CPSAttrib<float>                   TPSAttribFloat;      
00480 typedef CPSAttrib<uint32>                  TPSAttribUInt;       
00481 typedef CPSAttrib<uint8>                   TPSAttribUInt8;      
00482 typedef CPSAttrib<TAnimationTime>  TPSAttribTime;
00483 
00484 
00485 
00486 
00487 
00488 } // NL3D
00489 
00490 
00491 #endif // NL_PS_ATTRIB_H
00492 
00493 /* End of ps_attrib.h */