1 ////////////////////////////////////////////////////////////////////////////////
2 // The author of this code is Justin Randall
4 // I have made modifications to the ByteStream
5 // and AutoByteStream classes in order to make them suitable
6 // for use in messaging systems which require objects that
7 // are copyable and assignable. It is also desirable for
8 // the ByteStream object to use a flexible allocator system
9 // that may support multi-threaded programming models.
12 #ifndef BASE_ARCHIVE_H
13 #define BASE_ARCHIVE_H
23 #if defined _MT || defined _REENTRANT
24 # define USE_ARCHIVE_MUTEX
28 # include "win32/Archive.h"
30 # include "linux/Archive.h"
32 # include "solaris/Archive.h"
34 #error /Base/Archive.h: Undefine platform type
37 #ifdef EXTERNAL_DISTRO
45 const unsigned MAX_ARRAY_SIZE
= 1024;
48 ////////////////////////////////////////////////////////////////////////////////
50 #if defined(USE_ARCHIVE_MUTEX)
51 extern CMutex ByteStreamMutex
;
60 ReadIterator(const ReadIterator
& source
);
61 explicit ReadIterator(const ByteStream
& source
);
64 ReadIterator
& operator = (const ReadIterator
& source
);
65 void advance (const unsigned int distance
);
66 void get (void * target
, const unsigned long int readSize
);
67 const unsigned int getSize () const;
68 const unsigned char * const getBuffer () const;
69 const unsigned int getReadPosition () const;
73 const ByteStream
* stream
;
78 typedef Base::ReadIterator ReadIterator
;
83 friend class ByteStream
;
84 friend class Base::ReadIterator
;
88 static Data
* getNewData();
90 const int getRef () const;
94 unsigned char * buffer
;
101 std::vector
<ByteStream::Data
*>::iterator i
;
102 for(i
= freeList
.begin(); i
!= freeList
.end(); ++i
)
107 std::vector
<Data
*> freeList
;
110 //explicit Data(unsigned char * buffer);
111 static std::vector
<Data
*> & getDataFreeList();
112 static void releaseOldData(Data
* oldData
);
117 friend class Base::ReadIterator
;
120 ByteStream(const unsigned char * const buffer
, const unsigned int bufferSize
);
121 ByteStream(const ByteStream
& source
);
122 virtual ~ByteStream();
125 ByteStream(ReadIterator
& source
);
126 ByteStream
& operator = (const ByteStream
& source
);
127 ByteStream
& operator = (ReadIterator
& source
);
128 const ReadIterator
& begin() const;
130 const unsigned char * const getBuffer() const;
131 const unsigned int getSize() const;
132 void put(const void * const source
, const unsigned int sourceSize
);
135 void get(void * target
, ReadIterator
& readIterator
, const unsigned long int readSize
) const;
136 void growToAtLeast(const unsigned int targetSize
);
137 void reAllocate(const unsigned int newSize
);
140 unsigned int allocatedSize
;
141 ReadIterator beginReadIterator
;
148 inline ByteStream::Data::Data() :
155 inline ByteStream::Data::~Data()
157 #if defined(USE_ARCHIVE_MUTEX)
158 ByteStreamMutex
.Lock();
164 #if defined(USE_ARCHIVE_MUTEX)
165 ByteStreamMutex
.Unlock();
169 inline void ByteStream::Data::deref()
171 #if defined(USE_ARCHIVE_MUTEX)
172 ByteStreamMutex
.Lock();
177 #if defined(USE_ARCHIVE_MUTEX)
178 ByteStreamMutex
.Unlock();
182 releaseOldData(this);
185 inline std::vector
<ByteStream::Data
*> & ByteStream::Data::getDataFreeList()
187 static DataFreeList freeList
;
188 return freeList
.freeList
;
191 inline ByteStream::Data
* ByteStream::Data::getNewData()
193 #if defined(USE_ARCHIVE_MUTEX)
194 ByteStreamMutex
.Lock();
198 if(getDataFreeList().empty())
204 result
= getDataFreeList().back();
205 getDataFreeList().pop_back();
207 result
->refCount
= 1;
209 #if defined(USE_ARCHIVE_MUTEX)
210 ByteStreamMutex
.Unlock();
216 inline const int ByteStream::Data::getRef() const
221 inline void ByteStream::Data::ref()
223 #if defined(USE_ARCHIVE_MUTEX)
224 ByteStreamMutex
.Lock();
229 #if defined(USE_ARCHIVE_MUTEX)
230 ByteStreamMutex
.Unlock();
234 inline void ByteStream::Data::releaseOldData(ByteStream::Data
* oldData
)
236 #if defined(USE_ARCHIVE_MUTEX)
237 ByteStreamMutex
.Lock();
240 getDataFreeList().push_back(oldData
);
241 oldData
->refCount
= 0;
243 #if defined(USE_ARCHIVE_MUTEX)
244 ByteStreamMutex
.Unlock();
248 inline ByteStream::ReadIterator
& ByteStream::ReadIterator::operator = (const ByteStream::ReadIterator
& rhs
)
252 readPtr
= rhs
.readPtr
;
258 inline void ByteStream::ReadIterator::get(void * target
, const unsigned long int readSize
)
261 stream
->get(target
, *this, readSize
);
265 inline const unsigned int ByteStream::ReadIterator::getSize() const
268 return stream
->getSize() - readPtr
;
271 inline const ByteStream::ReadIterator
& ByteStream::begin() const
273 return beginReadIterator
;
276 inline void ByteStream::ReadIterator::advance(const unsigned int distance
)
281 inline const unsigned int ByteStream::ReadIterator::getReadPosition() const
286 inline const unsigned char * const ByteStream::ReadIterator::getBuffer() const
289 return &stream
->data
->buffer
[readPtr
];
294 inline void ByteStream::clear()
296 #if defined(USE_ARCHIVE_MUTEX)
297 ByteStreamMutex
.Lock();
302 #if defined(USE_ARCHIVE_MUTEX)
303 ByteStreamMutex
.Unlock();
307 inline const unsigned char * const ByteStream::getBuffer() const
312 inline const unsigned int ByteStream::getSize() const
317 inline void ByteStream::growToAtLeast(const unsigned int targetSize
)
319 if(allocatedSize
< targetSize
)
321 reAllocate(allocatedSize
+ allocatedSize
+ targetSize
);
326 ////////////////////////////////////////////////////////////////////////////////
329 inline void get(ByteStream::ReadIterator
& source
, ByteStream
& target
)
331 target
.put(source
.getBuffer(), source
.getSize());
332 source
.advance(source
.getSize());
335 inline void get(ByteStream::ReadIterator
& source
, double & target
)
337 source
.get(&target
, 8);
338 target
= byteSwap(target
);
341 inline void get(ByteStream::ReadIterator
& source
, float & target
)
343 source
.get(&target
, 4);
344 target
= byteSwap(target
);
347 inline void get(ByteStream::ReadIterator
& source
, uint64
& target
)
349 source
.get(&target
, 8);
350 target
= byteSwap(target
);
353 inline void get(ByteStream::ReadIterator
& source
, int64
& target
)
355 source
.get(&target
, 8);
356 target
= byteSwap(target
);
359 inline void get(ByteStream::ReadIterator
& source
, uint32
& target
)
361 source
.get(&target
, 4);
362 target
= byteSwap(target
);
365 inline void get(ByteStream::ReadIterator
& source
, int32
& target
)
367 source
.get(&target
, 4);
368 target
= byteSwap(target
);
371 inline void get(ByteStream::ReadIterator
& source
, uint16
& target
)
373 source
.get(&target
, 2);
374 target
= byteSwap(target
);
377 inline void get(ByteStream::ReadIterator
& source
, int16
& target
)
379 source
.get(&target
, 2);
380 target
= byteSwap(target
);
383 inline void get(ByteStream::ReadIterator
& source
, uint8
& target
)
385 source
.get(&target
, 1);
388 inline void get(ByteStream::ReadIterator
& source
, int8
& target
)
390 source
.get(&target
, 1);
393 inline void get(ByteStream::ReadIterator
& source
, unsigned char * const target
, const unsigned int targetSize
)
395 source
.get(target
, targetSize
);
398 inline void get(ByteStream::ReadIterator
& source
, bool & target
)
400 source
.get(&target
, 1);
404 ////////////////////////////////////////////////////////////////////////////////
407 inline void put(ByteStream
& target
, ByteStream::ReadIterator
& source
)
409 target
.put(source
.getBuffer(), source
.getSize());
410 source
.advance(source
.getSize());
413 inline void put(ByteStream
& target
, const double value
)
415 double temp
= byteSwap(value
);
416 target
.put(&temp
, 8);
419 inline void put(ByteStream
& target
, const float value
)
421 float temp
= byteSwap(value
);
422 target
.put(&temp
, 4);
425 inline void put(ByteStream
& target
, const uint64 value
)
427 uint64 temp
= byteSwap(value
);
428 target
.put(&temp
, 8);
431 inline void put(ByteStream
& target
, const int64 value
)
433 int64 temp
= byteSwap(value
);
434 target
.put(&temp
, 8);
437 inline void put(ByteStream
& target
, const uint32 value
)
439 uint32 temp
= byteSwap(value
);
440 target
.put(&temp
, 4);
443 inline void put(ByteStream
& target
, const int32 value
)
445 int32 temp
= byteSwap(value
);
446 target
.put(&temp
, 4);
449 inline void put(ByteStream
& target
, const uint16 value
)
451 uint16 temp
= byteSwap(value
);
452 target
.put(&temp
, 2);
455 inline void put(ByteStream
& target
, const int16 value
)
457 int16 temp
= byteSwap(value
);
458 target
.put(&temp
, 2);
461 inline void put(ByteStream
& target
, const uint8 value
)
463 target
.put(&value
, 1);
466 inline void put(ByteStream
& target
, const int8 value
)
468 target
.put(&value
, 1);
471 inline void put(ByteStream
& target
, const bool & source
)
473 target
.put(&source
, 1);
477 inline void put(ByteStream
& target
, const unsigned char * const source
, const unsigned int sourceSize
)
479 target
.put(source
, sourceSize
);
482 inline void put(ByteStream
& target
, const ByteStream
& source
)
484 target
.put(source
.begin().getBuffer(), source
.begin().getSize());
487 void get(ByteStream::ReadIterator
& source
, std::string
& target
);
488 void put(ByteStream
& target
, const std::string
& source
);
491 ////////////////////////////////////////////////////////////////////////////////
494 class AutoVariableBase
498 virtual ~AutoVariableBase();
500 virtual void pack(ByteStream
& target
) const = 0;
501 virtual void unpack(ByteStream::ReadIterator
& source
) = 0;
505 ////////////////////////////////////////////////////////////////////////////////
512 virtual ~AutoByteStream();
513 void addVariable(AutoVariableBase
& newVariable
);
514 virtual const unsigned int getItemCount() const;
515 virtual void pack(ByteStream
& target
) const;
516 virtual void unpack(ByteStream::ReadIterator
& source
);
518 std::vector
<AutoVariableBase
*> members
;
520 AutoByteStream(const AutoByteStream
& source
);
524 ////////////////////////////////////////////////////////////////////////////////
527 template<class ValueType
>
528 class AutoVariable
: public AutoVariableBase
532 explicit AutoVariable(const ValueType
& source
);
533 virtual ~AutoVariable();
535 const ValueType
& get() const;
536 virtual void pack(ByteStream
& target
) const;
537 void set(const ValueType
& rhs
);
538 virtual void unpack(ByteStream::ReadIterator
& source
);
544 template<class ValueType
>
545 AutoVariable
<ValueType
>::AutoVariable() :
551 template<class ValueType
>
552 AutoVariable
<ValueType
>::AutoVariable(const ValueType
& source
) :
558 template<class ValueType
>
559 AutoVariable
<ValueType
>::~AutoVariable()
563 template<class ValueType
>
564 const ValueType
& AutoVariable
<ValueType
>::get() const
569 template<class ValueType
>
570 void AutoVariable
<ValueType
>::pack(ByteStream
& target
) const
572 Base::put(target
, value
);
575 template<class ValueType
>
576 void AutoVariable
<ValueType
>::set(const ValueType
& rhs
)
581 template<class ValueType
>
582 void AutoVariable
<ValueType
>::unpack(ByteStream::ReadIterator
& source
)
584 Base::get(source
, value
);
588 ////////////////////////////////////////////////////////////////////////////////
591 template<class ValueType
>
592 class AutoArray
: public AutoVariableBase
596 AutoArray(const AutoArray
& source
);
599 const std::vector
<ValueType
> & get() const;
600 void set(const std::vector
<ValueType
> & source
);
602 virtual void pack(ByteStream
& target
) const;
603 virtual void unpack(ByteStream::ReadIterator
& source
);
606 std::vector
<ValueType
> array
;
609 template<class ValueType
>
610 inline AutoArray
<ValueType
>::AutoArray()
614 template<class ValueType
>
615 inline AutoArray
<ValueType
>::AutoArray(const AutoArray
& source
) :
620 template<class ValueType
>
621 inline AutoArray
<ValueType
>::~AutoArray()
625 template<class ValueType
>
626 inline const std::vector
<ValueType
> & AutoArray
<ValueType
>::get() const
631 template<class ValueType
>
632 inline void AutoArray
<ValueType
>::set(const std::vector
<ValueType
> & source
)
637 template<class ValueType
>
638 inline void AutoArray
<ValueType
>::pack(ByteStream
& target
) const
640 unsigned int arraySize
= array
.size();
641 Base::put(target
, arraySize
);
643 typename
std::vector
<ValueType
>::const_iterator i
;
644 for(i
= array
.begin(); i
!= array
.end(); ++i
)
647 Base::put(target
, v
);
651 template<class ValueType
>
652 inline void AutoArray
<ValueType
>::unpack(ByteStream::ReadIterator
& source
)
654 unsigned int arraySize
;
655 Base::get(source
, arraySize
);
658 if (arraySize
> MAX_ARRAY_SIZE
)
661 for(unsigned int i
= 0; i
< arraySize
; ++i
)
663 Base::get(source
, v
);
669 #ifdef EXTERNAL_DISTRO