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
00029
00030 #ifndef ACEDIA_UTIL_H
00031 #define ACEDIA_UTIL_H
00032
00033 #include "acedia_config.hpp"
00034
00035 #ifdef ACEDIA_WINDOWS
00036 #include <Winsock2.h>
00037 #include <Windows.h>
00038 #else
00039 #include <netinet/in.h>
00040 #endif
00041
00042 #include <list>
00043 #include <limits>
00044 #include <vector>
00045 #include <sstream>
00046
00047 #include "unit.hpp"
00048 #include "acedia_config.hpp"
00049 #include "acedia_atomic.hpp"
00050 #include "acedia_string.hpp"
00051 #include "acedia_preprocessor.hpp"
00052
00053 #include <boost/cstdint.hpp>
00054 #include <boost/thread/mutex.hpp>
00055 #include <boost/static_assert.hpp>
00056 #include <boost/thread/condition_variable.hpp>
00057
00058 #ifdef ACEDIA_WINDOWS
00059 #include <winsock2.h>
00060 #include <ws2tcpip.h>
00061 #include <windows.h>
00062 typedef int ssize_t;
00063 #pragma comment(lib, "wininet.lib")
00064 #else
00065 #include <sys/types.h>
00066 #include <sys/socket.h>
00067 #include <netinet/in.h>
00068 #include <netdb.h>
00069 #endif
00070
00071 namespace acedia
00072 {
00073 static const ::ssize_t ui32Size = (::ssize_t) sizeof(boost::uint32_t);
00074
00075 # ifdef ACEDIA_WINDOWS
00076 typedef SOCKET NativeSocketType;
00077 typedef const char* SocketSendPtr;
00078 typedef char* SocketRecvPtr;
00079 # else
00080 typedef int NativeSocketType;
00081 typedef const void* SocketSendPtr;
00082 typedef void* SocketRecvPtr;
00083 inline void closesocket(NativeSocketType s) { close(s); }
00084 # endif
00085
00086 namespace details
00087 {
00088 class AnyArrayProcessor;
00089 struct SocketIOStreamPrivate;
00090
00091 template<class NativeContainer>
00092 class SharedContainerImpl : public NativeContainer
00093 {
00094
00095 volatile boost::int32_t m_rc;
00096
00097 public:
00098
00099 using NativeContainer::const_iterator;
00100
00101 inline SharedContainerImpl() : NativeContainer(), m_rc(1) { }
00102
00103 inline void ref() { (void) atomic::addAndFetch(&m_rc, 1); }
00104 inline bool deref() { return 0 != atomic::addAndFetch(&m_rc, -1); }
00105 inline bool unique() const { return 1 == m_rc; }
00106
00107 inline SharedContainerImpl* deep_copy() const
00108 {
00109 SharedContainerImpl* copy = new SharedContainerImpl;
00110 copy->insert(copy->begin(), this->begin(), this->end());
00111 return copy;
00112 }
00113
00114 inline bool operator==(const SharedContainerImpl& other)
00115 {
00116 return ((NativeContainer&) *this) == ((const NativeContainer&) other);
00117 }
00118
00119 };
00120
00121 }
00122 }
00123
00124 namespace acedia
00125 {
00126
00127 static const boost::int32_t Int32Minimum = 0x80000000;
00128 static const boost::uint32_t UInt32Maximum = 0xFFFFFFFF;
00129
00133 namespace util
00134 {
00135
00136
00137 class no_instances
00138 {
00139 no_instances();
00140 };
00141
00142 template<typename T, class ListImpl, class IteratorImpl>
00143 class ContainerIterator
00144 {
00145
00146 ListImpl* list;
00147 IteratorImpl nativeIterator;
00148
00149 public:
00150
00151 ContainerIterator(ListImpl* nl, IteratorImpl ni) :
00152 list(nl),
00153 nativeIterator(ni)
00154 {
00155 nl->ref();
00156 }
00157
00158 ContainerIterator(const ContainerIterator& other) :
00159 list(other.list),
00160 nativeIterator(other.nativeIterator)
00161 {
00162 other.list->ref();
00163 }
00164
00165 ~ContainerIterator()
00166 {
00167 if (!list->deref()) delete list;
00168 }
00169
00170 const T& operator*() { return *nativeIterator; }
00171
00172 const T* operator->() { return &(*nativeIterator); }
00173
00174 ContainerIterator& operator++()
00175 {
00176 ++nativeIterator;
00177 return *this;
00178 }
00179
00180 ContainerIterator operator++(int)
00181 {
00182 ContainerIterator tmp(*this);
00183 ++(*this);
00184 return tmp;
00185 }
00186
00187 ContainerIterator& operator--()
00188 {
00189 --nativeIterator;
00190 return *this;
00191 }
00192
00193 ContainerIterator operator--(int)
00194 {
00195 ContainerIterator tmp(*this);
00196 --(*this);
00197 return tmp;
00198 }
00199
00200 ContainerIterator& operator=(const ContainerIterator& other)
00201 {
00202 if (!list->deref()) delete list;
00203 other.list->ref();
00204 list = other.list;
00205 nativeIterator = other.nativeIterator;
00206 return *this;
00207 }
00208
00209 bool operator==(const ContainerIterator& other)
00210 {
00211 return list == other.list
00212 && nativeIterator == other.nativeIterator;
00213 }
00214
00215 bool operator!=(const ContainerIterator& other)
00216 {
00217 return !((*this) == other);
00218 }
00219
00220 };
00221
00222 template<typename T, class SharedContainer>
00223 class Container
00224 {
00225
00226 protected:
00227
00228 SharedContainer* d;
00229
00230 void detach()
00231 {
00232 if (!d->unique())
00233 {
00234 SharedContainer* nd = d->deep_copy();
00235 if (!d->deref()) delete d;
00236 d = nd;
00237 }
00238 }
00239
00240 public:
00241
00242 typedef ContainerIterator<T, SharedContainer, typename SharedContainer::const_iterator> ConstIterator;
00243
00244 Container() : d(new SharedContainer) { }
00245
00246 Container(const Container& other) : d(other.d) { other.d->ref(); }
00247
00248 virtual ~Container() { if (!d->deref()) delete d; }
00249
00250 ::size_t size() const { return d->size(); }
00251
00252 Container& append(const T& element)
00253 {
00254 detach();
00255 d->push_back(element);
00256 return *this;
00257 }
00258
00259 ConstIterator begin() const
00260 {
00261 return ConstIterator(d, d->begin());
00262 }
00263
00264 ConstIterator end() const
00265 {
00266 return ConstIterator(d, d->end());
00267 }
00268
00269 bool operator==(const Container& other) const
00270 {
00271 if (d == other.d) return true;
00272 else return (*d) == (*other.d);
00273 }
00274
00278 void serialize(boost::archive::text_oarchive &ar,
00279 const unsigned int) const
00280 {
00281 boost::uint32_t s = size();
00282 ar << s;
00283 for (ConstIterator i = this->begin(); i != this->end(); ++i)
00284 {
00285 ar << (*i);
00286 }
00287 }
00288
00292 void serialize(boost::archive::text_iarchive &ar,
00293 const unsigned int)
00294 {
00295 detach();
00296 boost::uint32_t s;
00297 ar >> s;
00298 for (boost::uint32_t i = 0; i < s; ++i)
00299 {
00300 T element;
00301 ar >> element;
00302 append(element);
00303 }
00304 }
00305
00306 };
00307
00313 template<typename T>
00314 class List : public Container< T, details::SharedContainerImpl< std::list<T> > >
00315 {
00316
00317 typedef Container< T, details::SharedContainerImpl< std::list<T> > > ListBase;
00318
00319 public:
00320
00321 List() { }
00322 List(const T& firstElement) { append(firstElement); }
00323 List(const List& other) : ListBase(other) { }
00324
00325 };
00326
00327 template<typename T>
00328 class Vector : public Container< T, details::SharedContainerImpl< std::vector<T> > >
00329 {
00330
00331 typedef Container< T, details::SharedContainerImpl< std::vector<T> > > VectorBase;
00332
00333 public:
00334
00335 Vector() { }
00336 Vector(const T& firstElement) { append(firstElement); }
00337 Vector(const Vector& other) : VectorBase(other) { }
00338
00339 const T& operator[](::size_t i) const { return (*(this->d))[i]; }
00340
00341 };
00342
00346 class Semaphore
00347 {
00348
00349 volatile boost::int32_t m_value;
00350 boost::mutex m_mutex;
00351 boost::condition_variable m_condition;
00352
00353 public:
00354
00355 inline Semaphore(boost::int32_t initValue = 0) throw() :
00356 m_value(initValue)
00357 {
00358 }
00359
00363 void release(boost::int32_t n = 1);
00364
00370 void acquire(boost::int32_t n = 1);
00371
00379 bool tryAcquire(boost::int32_t n = 1);
00380
00389 bool tryAcquire(boost::int32_t n, boost::uint16_t msTimeout);
00390
00394 inline int available () const throw() { return m_value; }
00395
00396 };
00397
00407 class Spinlock
00408 {
00409
00410 volatile boost::int32_t m_value;
00411
00412 public:
00413
00414 inline Spinlock() throw() : m_value(0) { }
00415
00416 void lock() throw();
00417
00418 inline void unlock() throw()
00419 {
00420
00421
00422
00423 ACEDIA_MEMORY_BARRIER();
00424 assert(atomic::compareAndSwap(&m_value, 1, 0));
00425 }
00426
00427 };
00428
00433 class SpinlockGuard
00434 {
00435
00436 Spinlock &slock;
00437
00438 public:
00439
00440
00441 SpinlockGuard(Spinlock &spinlock);
00442
00443
00444 ~SpinlockGuard();
00445 };
00446
00454 class RWSpinlock
00455 {
00456
00457 volatile boost::int32_t m_value;
00458
00459 public:
00460
00461 inline RWSpinlock() throw() : m_value(0) { }
00462
00463 void sharedLock();
00464
00465 inline void sharedUnlock()
00466 {
00467 ACEDIA_MEMORY_BARRIER();
00468 (void) atomic::addAndFetch(&m_value, -1);
00469 }
00470
00471 void exclusiveLock();
00472
00473 inline void exclusiveUnlock()
00474 {
00475 ACEDIA_MEMORY_BARRIER();
00476 assert(atomic::compareAndSwap(&m_value, Int32Minimum, 0));
00477 }
00478
00479 };
00480
00485 class SharedLockGuard
00486 {
00487 RWSpinlock &rwlock;
00488 public:
00489 SharedLockGuard(RWSpinlock &rwlock);
00490 ~SharedLockGuard();
00491 };
00492
00497 class ExclusiveLockGuard
00498 {
00499 RWSpinlock &rwlock;
00500 public:
00501 ExclusiveLockGuard(RWSpinlock &rwlock);
00502 ~ExclusiveLockGuard();
00503 };
00504
00509 String eraseWhitespaces(const char *input);
00510
00511
00512
00513
00514
00515
00520 template<int VAL, typename T1, typename T2>
00521 struct IfElseType { typedef T1 type; };
00522
00523 template<typename T1, typename T2>
00524 struct IfElseType<0,T1,T2> { typedef T2 type; };
00525
00526
00527
00528
00529
00530
00537 template<int N, ACEDIA_DEF_WITH_DEFAULT_T1_TO_T10() >
00538 struct ResultOf {};
00539
00540 template<ACEDIA_DEF_T1_TO_T10()>
00541 struct ResultOf<0,ACEDIA_GET_T1_TO_T10()> { typedef T1 type; };
00542
00543 template<ACEDIA_DEF_T1_TO_T10()>
00544 struct ResultOf<1,ACEDIA_GET_T1_TO_T10()> { typedef T2 type; };
00545
00546 template<ACEDIA_DEF_T1_TO_T10()>
00547 struct ResultOf<2,ACEDIA_GET_T1_TO_T10()> { typedef T3 type; };
00548
00549 template<ACEDIA_DEF_T1_TO_T10()>
00550 struct ResultOf<3,ACEDIA_GET_T1_TO_T10()> { typedef T4 type; };
00551
00552 template<ACEDIA_DEF_T1_TO_T10()>
00553 struct ResultOf<4,ACEDIA_GET_T1_TO_T10()> { typedef T5 type; };
00554
00555 template<ACEDIA_DEF_T1_TO_T10()>
00556 struct ResultOf<5,ACEDIA_GET_T1_TO_T10()> { typedef T6 type; };
00557
00558 template<ACEDIA_DEF_T1_TO_T10()>
00559 struct ResultOf<6,ACEDIA_GET_T1_TO_T10()> { typedef T7 type; };
00560
00561 template<ACEDIA_DEF_T1_TO_T10()>
00562 struct ResultOf<7,ACEDIA_GET_T1_TO_T10()> { typedef T8 type; };
00563
00564 template<ACEDIA_DEF_T1_TO_T10()>
00565 struct ResultOf<8,ACEDIA_GET_T1_TO_T10()> { typedef T9 type; };
00566
00567 template<ACEDIA_DEF_T1_TO_T10()>
00568 struct ResultOf<9,ACEDIA_GET_T1_TO_T10()> { typedef T10 type; };
00569
00570
00571
00572
00573 template<class C>
00574 struct UnboxUtil
00575 {
00576 typedef Unit UnboxedRuleBuilder;
00577 static UnboxedRuleBuilder doUnbox(details::AnyArrayProcessor*)
00578 {
00579 return Unit();
00580 }
00581 };
00582
00583
00584
00585
00586 template<class T> struct IsUnit { enum { VALUE = 0 }; };
00587 template<> struct IsUnit<Unit> { enum { VALUE = 1 }; };
00588
00589
00590
00591
00592
00593
00594
00595
00596 template<class T> struct IsCaseClass { enum { VALUE = 0 }; };
00597 template<> struct IsCaseClass<Unit> { enum { VALUE = 1 }; };
00598
00599
00600
00601
00602
00603
00604
00605
00606 template<typename T> struct HasBuiltInToString{enum{VALUE = 0};};
00607 template<> struct HasBuiltInToString<float>{enum{VALUE = 1};};
00608 template<> struct HasBuiltInToString<double>{enum{VALUE = 1};};
00609 template<> struct HasBuiltInToString<boost::int8_t>{enum{VALUE = 1};};
00610 template<> struct HasBuiltInToString<boost::uint8_t>{enum{VALUE = 1};};
00611 template<> struct HasBuiltInToString<boost::int16_t>{enum{VALUE = 1};};
00612 template<> struct HasBuiltInToString<boost::uint16_t>{enum{VALUE = 1};};
00613 template<> struct HasBuiltInToString<boost::int32_t>{enum{VALUE = 1};};
00614 template<> struct HasBuiltInToString<boost::uint32_t>{enum{VALUE = 1};};
00615 template<> struct HasBuiltInToString<boost::int64_t>{enum{VALUE = 1};};
00616 template<> struct HasBuiltInToString<boost::uint64_t>{enum{VALUE = 1};};
00617 template<> struct HasBuiltInToString<std::string>{enum{VALUE = 1};};
00618
00619
00620
00621
00622 template<int N, typename T>
00623 struct BuiltInToString
00624 {
00625 inline static void appendTo(std::ostringstream &stream, const T &)
00626 {
00627 stream << "-?-";
00628 }
00629 };
00630 template<typename T>
00631 struct BuiltInToString<1, T>
00632 {
00633 inline static void appendTo(std::ostringstream &stream, const T &what)
00634 {
00635 stream << what;
00636 }
00637 };
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647 template<typename T>
00648 struct AsString
00649 {
00650 static String get(const T& what)
00651 {
00652 if (HasBuiltInToString<T>::VALUE)
00653 {
00654 std::ostringstream out;
00655 BuiltInToString<HasBuiltInToString<T>::VALUE,T>
00656 ::appendTo(out, what);
00657 return out.str();
00658 }
00659 else return "-?-";
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674 }
00675 };
00676
00677 template<>
00678 struct AsString<bool>
00679 {
00680 inline static String get(bool value)
00681 {
00682 return value ? "true" : "false";
00683 }
00684 };
00685
00686 template<>
00687 struct AsString<String>
00688 {
00689 inline static String get(const String& value)
00690 {
00691 return value;
00692 }
00693 };
00694
00695
00696
00697
00698 template<typename T> struct IsIntegerType {enum{VALUE = 0};};
00699 template<> struct IsIntegerType<boost::int8_t>{enum{VALUE = 1};};
00700 template<> struct IsIntegerType<boost::uint8_t>{enum{VALUE = 1};};
00701 template<> struct IsIntegerType<boost::int16_t>{enum{VALUE = 1};};
00702 template<> struct IsIntegerType<boost::uint16_t>{enum{VALUE = 1};};
00703 template<> struct IsIntegerType<boost::int32_t>{enum{VALUE = 1};};
00704 template<> struct IsIntegerType<boost::uint32_t>{enum{VALUE = 1};};
00705 template<> struct IsIntegerType<boost::int64_t>{enum{VALUE = 1};};
00706 template<> struct IsIntegerType<boost::uint64_t>{enum{VALUE = 1};};
00707
00708 template<int X, typename T>
00709 struct SingletonAccess
00710 {
00711 inline static T get() { throw 666; }
00712 };
00713
00714 template<typename T>
00715 struct SingletonAccess<1, T>
00716 {
00717 inline static T get() { return T::instance(); }
00718 };
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757 template<class C>
00758 class Singleton
00759 {
00760
00761 volatile C* m_instance;
00762 Spinlock m_lock;
00763
00764 public:
00765
00766 Singleton() : m_instance(NULL) { }
00767
00768 C* instance()
00769 {
00770 C* tmp = const_cast<C*>(m_instance);
00771 ACEDIA_MEMORY_BARRIER();
00772 if (NULL == tmp)
00773 {
00774 SpinlockGuard guard(m_lock);
00775
00776 tmp = const_cast<C*>(m_instance);
00777 if (NULL == tmp)
00778 {
00779 tmp = new C;
00780
00781
00782
00783 ACEDIA_MEMORY_BARRIER();
00784 m_instance = tmp;
00785 }
00786 }
00787 return tmp;
00788 }
00789
00790 };
00791
00792
00793
00794
00803 class EndianConverter
00804 {
00805
00806 typedef boost::int64_t (*Int64Fun)(boost::int64_t);
00807
00808 Int64Fun m_int64Fun;
00809 EndianConverter(const EndianConverter& other);
00810 EndianConverter& operator=(const EndianConverter& other);
00811
00812 public:
00813
00814 EndianConverter();
00815
00819 inline boost::int8_t operator()(boost::int8_t i) const { return i; }
00820
00824 inline boost::int16_t operator()(boost::int16_t i) const
00825 {
00826 return htons(i);
00827 }
00828
00832 inline boost::int32_t operator()(boost::int32_t i) const
00833 {
00834 return htonl(i);
00835 }
00836
00840 inline boost::int64_t operator()(boost::int64_t i) const
00841 {
00842 return m_int64Fun(i);
00843 }
00844
00848 inline boost::uint8_t operator()(boost::uint8_t i) const {return i;}
00849
00853 inline boost::uint16_t operator()(boost::uint16_t i) const
00854 {
00855 return htons(i);
00856 }
00857
00861 inline boost::uint32_t operator()(boost::uint32_t i) const
00862 {
00863 return htonl(i);
00864 }
00865
00869 inline boost::uint64_t operator()(boost::uint64_t i) const
00870 {
00871 return (boost::uint64_t) m_int64Fun((boost::int64_t) i);
00872 }
00873
00874 };
00875
00879 struct AbstractEndianAwareStream
00880 {
00881 virtual ~AbstractEndianAwareStream();
00885 const acedia::util::EndianConverter convert;
00886 };
00887
00891 struct EndianAwareInputStream : public virtual AbstractEndianAwareStream
00892 {
00896 virtual void read(char* buffer, ::size_t numBytes) = 0;
00897
00902 template<typename T>
00903 void readInt(T& value)
00904 {
00905 BOOST_STATIC_ASSERT(std::numeric_limits<T>::is_integer);
00906 read((char*) &value, sizeof(T));
00907 value = convert(value);
00908 }
00909 };
00910
00914 struct EndianAwareOutputStream: public virtual AbstractEndianAwareStream
00915 {
00919 virtual void write(const char* buffer, ::size_t numBytes) = 0;
00920
00925 template<typename T>
00926 void writeInt(const T& value)
00927 {
00928 BOOST_STATIC_ASSERT(std::numeric_limits<T>::is_integer);
00929 T tmp = convert(value);
00930 write((const char*) &tmp, sizeof(T));
00931 }
00932 };
00933
00937 struct EndianAwareStream : public EndianAwareInputStream
00938 , public EndianAwareOutputStream
00939 {
00940 };
00941
00945 inline EndianAwareOutputStream& operator<<(EndianAwareOutputStream& s,
00946 boost::int8_t value)
00947 {
00948 s.writeInt(value);
00949 return s;
00950 }
00951
00955 inline EndianAwareOutputStream& operator<<(EndianAwareOutputStream& s,
00956 boost::int16_t value)
00957 {
00958 s.writeInt(value);
00959 return s;
00960 }
00961
00965 inline EndianAwareOutputStream& operator<<(EndianAwareOutputStream& s,
00966 boost::int32_t value)
00967 {
00968 s.writeInt(value);
00969 return s;
00970 }
00971
00975 inline EndianAwareOutputStream& operator<<(EndianAwareOutputStream& s,
00976 boost::int64_t value)
00977 {
00978 s.writeInt(value);
00979 return s;
00980 }
00981
00985 inline EndianAwareOutputStream& operator<<(EndianAwareOutputStream& s,
00986 boost::uint8_t value)
00987 {
00988 s.writeInt(value);
00989 return s;
00990 }
00991
00995 inline EndianAwareOutputStream& operator<<(EndianAwareOutputStream& s,
00996 boost::uint16_t value)
00997 {
00998 s.writeInt(value);
00999 return s;
01000 }
01001
01005 inline EndianAwareOutputStream& operator<<(EndianAwareOutputStream& s,
01006 boost::uint32_t value)
01007 {
01008 s.writeInt(value);
01009 return s;
01010 }
01011
01015 inline EndianAwareOutputStream& operator<<(EndianAwareOutputStream& s,
01016 boost::uint64_t value)
01017 {
01018 s.writeInt(value);
01019 return s;
01020 }
01021
01026 EndianAwareOutputStream& operator<<(EndianAwareOutputStream& s,
01027 const std::string& str);
01028
01033 inline EndianAwareOutputStream& operator<<(EndianAwareOutputStream& s,
01034 const acedia::String& str)
01035 {
01036 s << (str.const_str());
01037 return s;
01038 }
01039
01043 inline void operator>>(EndianAwareInputStream& s, boost::int8_t& value)
01044 {
01045 s.readInt(value);
01046 }
01047
01051 inline void operator>>(EndianAwareInputStream& s, boost::int16_t& value)
01052 {
01053 s.readInt(value);
01054 }
01055
01059 inline void operator>>(EndianAwareInputStream& s, boost::int32_t& value)
01060 {
01061 s.readInt(value);
01062 }
01063
01067 inline void operator>>(EndianAwareInputStream& s, boost::int64_t& value)
01068 {
01069 s.readInt(value);
01070 }
01071
01075 inline void operator>>(EndianAwareInputStream& s, boost::uint8_t& value)
01076 {
01077 s.readInt(value);
01078 }
01079
01083 inline void operator>>(EndianAwareInputStream& s, boost::uint16_t& val)
01084 {
01085 s.readInt(val);
01086 }
01087
01091 inline void operator>>(EndianAwareInputStream& s, boost::uint32_t& val)
01092 {
01093 s.readInt(val);
01094 }
01095
01099 inline void operator>>(EndianAwareInputStream& s, boost::uint64_t& val)
01100 {
01101 s.readInt(val);
01102 }
01103
01108 void operator>>(EndianAwareInputStream& s, acedia::String& str);
01109
01114 void operator>>(EndianAwareInputStream& s, std::string& str);
01115
01116 class SocketIOStream : public EndianAwareStream
01117 {
01118
01119 details::SocketIOStreamPrivate* d;
01120 SocketIOStream& operator=(const SocketIOStream& other);
01121
01122 public:
01123
01127 SocketIOStream(NativeSocketType socketDescriptor);
01128
01129 SocketIOStream(const SocketIOStream& other);
01130
01134 void close();
01135
01139 ~SocketIOStream();
01140
01150 void readStringToBuffer();
01151
01152 const char* buffer();
01153
01157 void write (const char* what, ::size_t size);
01158
01162 void read (char* what, ::size_t size);
01163
01167 void readToBuffer(::size_t size);
01168
01169 };
01170
01171 }
01172 }
01173
01174
01175
01176 #endif // ACEDIA_UTIL_H