| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412 |
- /*
- * Copyright (c) 2014, Oculus VR, Inc.
- * All rights reserved.
- *
- * This source code is licensed under the BSD-style license found in the
- * LICENSE file in the root directory of this source tree. An additional grant
- * of patent rights can be found in the PATENTS file in the same directory.
- *
- */
- #include "RakWString.h"
- #include "BitStream.h"
- #include <string.h>
- #include <wchar.h>
- #include <stdlib.h>
- using namespace RakNet;
- // From http://www.joelonsoftware.com/articles/Unicode.html
- // Only code points 128 and above are stored using 2, 3, in fact, up to 6 bytes.
- #define MAX_BYTES_PER_UNICODE_CHAR sizeof(wchar_t)
- RakWString::RakWString()
- {
- c_str=0;
- c_strCharLength=0;
- }
- RakWString::RakWString( const RakString &right )
- {
- c_str=0;
- c_strCharLength=0;
- *this=right;
- }
- RakWString::RakWString( const char *input )
- {
- c_str=0;
- c_strCharLength=0;
- *this = input;
- }
- RakWString::RakWString( const wchar_t *input )
- {
- c_str=0;
- c_strCharLength=0;
- *this = input;
- }
- RakWString::RakWString( const RakWString & right)
- {
- c_str=0;
- c_strCharLength=0;
- *this = right;
- }
- RakWString::~RakWString()
- {
- rakFree_Ex(c_str,_FILE_AND_LINE_);
- }
- RakWString& RakWString::operator = ( const RakWString& right )
- {
- Clear();
- if (right.IsEmpty())
- return *this;
- c_str = (wchar_t *) rakMalloc_Ex( (right.GetLength() + 1) * MAX_BYTES_PER_UNICODE_CHAR, _FILE_AND_LINE_);
- if (!c_str)
- {
- c_strCharLength=0;
- notifyOutOfMemory(_FILE_AND_LINE_);
- return *this;
- }
- c_strCharLength = right.GetLength();
- memcpy(c_str,right.C_String(),(right.GetLength() + 1) * MAX_BYTES_PER_UNICODE_CHAR);
- return *this;
- }
- RakWString& RakWString::operator = ( const RakString& right )
- {
- return *this = right.C_String();
- }
- RakWString& RakWString::operator = ( const wchar_t * const str )
- {
- Clear();
- if (str==0)
- return *this;
- c_strCharLength = wcslen(str);
- if (c_strCharLength==0)
- return *this;
- c_str = (wchar_t *) rakMalloc_Ex( (c_strCharLength + 1) * MAX_BYTES_PER_UNICODE_CHAR, _FILE_AND_LINE_);
- if (!c_str)
- {
- c_strCharLength=0;
- notifyOutOfMemory(_FILE_AND_LINE_);
- return *this;
- }
- wcscpy(c_str,str);
- return *this;
- }
- RakWString& RakWString::operator = ( wchar_t *str )
- {
- *this = ( const wchar_t * const) str;
- return *this;
- }
- RakWString& RakWString::operator = ( const char * const str )
- {
- Clear();
- // Not supported on android
- #if !defined(ANDROID)
- if (str==0)
- return *this;
- if (str[0]==0)
- return *this;
- c_strCharLength = mbstowcs(NULL, str, 0);
- c_str = (wchar_t *) rakMalloc_Ex( (c_strCharLength + 1) * MAX_BYTES_PER_UNICODE_CHAR, _FILE_AND_LINE_);
- if (!c_str)
- {
- c_strCharLength=0;
- notifyOutOfMemory(_FILE_AND_LINE_);
- return *this;
- }
- c_strCharLength = mbstowcs(c_str, str, c_strCharLength+1);
- if (c_strCharLength == (size_t) (-1))
- {
- RAKNET_DEBUG_PRINTF("Couldn't convert string--invalid multibyte character.\n");
- Clear();
- return *this;
- }
- #else
- // mbstowcs not supported on android
- RakAssert("mbstowcs not supported on Android" && 0);
- #endif // defined(ANDROID)
- return *this;
- }
- RakWString& RakWString::operator = ( char *str )
- {
- *this = ( const char * const) str;
- return *this;
- }
- RakWString& RakWString::operator +=( const RakWString& right)
- {
- if (right.IsEmpty())
- return *this;
- size_t newCharLength = c_strCharLength + right.GetLength();
- wchar_t *newCStr;
- bool isEmpty = IsEmpty();
- if (isEmpty)
- newCStr = (wchar_t *) rakMalloc_Ex( (newCharLength + 1) * MAX_BYTES_PER_UNICODE_CHAR, _FILE_AND_LINE_);
- else
- newCStr = (wchar_t *) rakRealloc_Ex( c_str, (newCharLength + 1) * MAX_BYTES_PER_UNICODE_CHAR, _FILE_AND_LINE_);
- if (!newCStr)
- {
- notifyOutOfMemory(_FILE_AND_LINE_);
- return *this;
- }
- c_str = newCStr;
- c_strCharLength = newCharLength;
- if (isEmpty)
- {
- memcpy(newCStr,right.C_String(),(right.GetLength() + 1) * MAX_BYTES_PER_UNICODE_CHAR);
- }
- else
- {
- wcscat(c_str, right.C_String());
- }
- return *this;
- }
- RakWString& RakWString::operator += ( const wchar_t * const right )
- {
- if (right==0)
- return *this;
- size_t rightLength = wcslen(right);
- size_t newCharLength = c_strCharLength + rightLength;
- wchar_t *newCStr;
- bool isEmpty = IsEmpty();
- if (isEmpty)
- newCStr = (wchar_t *) rakMalloc_Ex( (newCharLength + 1) * MAX_BYTES_PER_UNICODE_CHAR, _FILE_AND_LINE_);
- else
- newCStr = (wchar_t *) rakRealloc_Ex( c_str, (newCharLength + 1) * MAX_BYTES_PER_UNICODE_CHAR, _FILE_AND_LINE_);
- if (!newCStr)
- {
- notifyOutOfMemory(_FILE_AND_LINE_);
- return *this;
- }
- c_str = newCStr;
- c_strCharLength = newCharLength;
- if (isEmpty)
- {
- memcpy(newCStr,right,(rightLength + 1) * MAX_BYTES_PER_UNICODE_CHAR);
- }
- else
- {
- wcscat(c_str, right);
- }
- return *this;
- }
- RakWString& RakWString::operator += ( wchar_t *right )
- {
- return *this += (const wchar_t * const) right;
- }
- bool RakWString::operator==(const RakWString &right) const
- {
- if (GetLength()!=right.GetLength())
- return false;
- return wcscmp(C_String(),right.C_String())==0;
- }
- bool RakWString::operator < ( const RakWString& right ) const
- {
- return wcscmp(C_String(),right.C_String())<0;
- }
- bool RakWString::operator <= ( const RakWString& right ) const
- {
- return wcscmp(C_String(),right.C_String())<=0;
- }
- bool RakWString::operator > ( const RakWString& right ) const
- {
- return wcscmp(C_String(),right.C_String())>0;
- }
- bool RakWString::operator >= ( const RakWString& right ) const
- {
- return wcscmp(C_String(),right.C_String())>=0;
- }
- bool RakWString::operator!=(const RakWString &right) const
- {
- if (GetLength()!=right.GetLength())
- return true;
- return wcscmp(C_String(),right.C_String())!=0;
- }
- void RakWString::Set( wchar_t *str )
- {
- *this = str;
- }
- bool RakWString::IsEmpty(void) const
- {
- return GetLength()==0;
- }
- size_t RakWString::GetLength(void) const
- {
- return c_strCharLength;
- }
- unsigned long RakWString::ToInteger(const RakWString &rs)
- {
- unsigned long hash = 0;
- int c;
- const char *str = (const char *)rs.C_String();
- size_t i;
- for (i=0; i < rs.GetLength()*MAX_BYTES_PER_UNICODE_CHAR*sizeof(wchar_t); i++)
- {
- c = *str++;
- hash = c + (hash << 6) + (hash << 16) - hash;
- }
- return hash;
- }
- int RakWString::StrCmp(const RakWString &right) const
- {
- return wcscmp(C_String(), right.C_String());
- }
- int RakWString::StrICmp(const RakWString &right) const
- {
- #ifdef _WIN32
- return _wcsicmp(C_String(), right.C_String());
- #else
- // Not supported
- return wcscmp(C_String(), right.C_String());
- #endif
- }
- void RakWString::Clear(void)
- {
- rakFree_Ex(c_str,_FILE_AND_LINE_);
- c_str=0;
- c_strCharLength=0;
- }
- void RakWString::Printf(void)
- {
- printf("%ls", C_String());
- }
- void RakWString::FPrintf(FILE *fp)
- {
- fprintf(fp,"%ls", C_String());
- }
- void RakWString::Serialize(BitStream *bs) const
- {
- Serialize(C_String(), bs);
- }
- void RakWString::Serialize(const wchar_t * const str, BitStream *bs)
- {
- #if 0
- char *multiByteBuffer;
- size_t allocated = wcslen(str)*MAX_BYTES_PER_UNICODE_CHAR;
- multiByteBuffer = (char*) rakMalloc_Ex(allocated, _FILE_AND_LINE_);
- size_t used = wcstombs(multiByteBuffer, str, allocated);
- bs->WriteCasted<unsigned short>(used);
- bs->WriteAlignedBytes((const unsigned char*) multiByteBuffer,(const unsigned int) used);
- rakFree_Ex(multiByteBuffer, _FILE_AND_LINE_);
- #else
- size_t mbByteLength = wcslen(str);
- bs->WriteCasted<unsigned short>(mbByteLength);
- for (unsigned int i=0; i < mbByteLength; i++)
- {
- uint16_t t;
- t = (uint16_t) str[i];
- // Force endian swapping, and write to 16 bits
- bs->Write(t);
- }
- #endif
- }
- bool RakWString::Deserialize(BitStream *bs)
- {
- Clear();
- size_t mbByteLength;
- bs->ReadCasted<unsigned short>(mbByteLength);
- if (mbByteLength>0)
- {
- #if 0
- char *multiByteBuffer;
- multiByteBuffer = (char*) rakMalloc_Ex(mbByteLength+1, _FILE_AND_LINE_);
- bool result = bs->ReadAlignedBytes((unsigned char*) multiByteBuffer,(const unsigned int) mbByteLength);
- if (result==false)
- {
- rakFree_Ex(multiByteBuffer, _FILE_AND_LINE_);
- return false;
- }
- multiByteBuffer[mbByteLength]=0;
- c_str = (wchar_t *) rakMalloc_Ex( (mbByteLength + 1) * MAX_BYTES_PER_UNICODE_CHAR, _FILE_AND_LINE_);
- c_strCharLength = mbstowcs(c_str, multiByteBuffer, mbByteLength);
- rakFree_Ex(multiByteBuffer, _FILE_AND_LINE_);
- c_str[c_strCharLength]=0;
- #else
- c_str = (wchar_t*) rakMalloc_Ex((mbByteLength+1) * MAX_BYTES_PER_UNICODE_CHAR, _FILE_AND_LINE_);
- c_strCharLength = mbByteLength;
- for (unsigned int i=0; i < mbByteLength; i++)
- {
- uint16_t t;
- // Force endian swapping, and read 16 bits
- bs->Read(t);
- c_str[i]=t;
- }
- c_str[mbByteLength]=0;
- #endif
- return true;
- }
- else
- {
- return true;
- }
- }
- bool RakWString::Deserialize(wchar_t *str, BitStream *bs)
- {
- size_t mbByteLength;
- bs->ReadCasted<unsigned short>(mbByteLength);
- if (mbByteLength>0)
- {
- #if 0
- char *multiByteBuffer;
- multiByteBuffer = (char*) rakMalloc_Ex(mbByteLength+1, _FILE_AND_LINE_);
- bool result = bs->ReadAlignedBytes((unsigned char*) multiByteBuffer,(const unsigned int) mbByteLength);
- if (result==false)
- {
- rakFree_Ex(multiByteBuffer, _FILE_AND_LINE_);
- return false;
- }
- multiByteBuffer[mbByteLength]=0;
- size_t c_strCharLength = mbstowcs(str, multiByteBuffer, mbByteLength);
- rakFree_Ex(multiByteBuffer, _FILE_AND_LINE_);
- str[c_strCharLength]=0;
- #else
- for (unsigned int i=0; i < mbByteLength; i++)
- {
- uint16_t t;
- // Force endian swapping, and read 16 bits
- bs->Read(t);
- str[i]=t;
- }
- str[mbByteLength]=0;
- #endif
- return true;
- }
- else
- {
- wcscpy(str,L"");
- }
- return true;
- }
- /*
- RakNet::BitStream bsTest;
- RakNet::RakWString testString("cat"), testString2;
- testString = "Hllo";
- testString = L"Hello";
- testString += L" world";
- testString2 += testString2;
- RakNet::RakWString ts3(L" from here");
- testString2+=ts3;
- RakNet::RakWString ts4(L" 222");
- testString2=ts4;
- RakNet::RakString rs("rakstring");
- testString2+=rs;
- testString2=rs;
- bsTest.Write(L"one");
- bsTest.Write(testString2);
- bsTest.SetReadOffset(0);
- RakNet::RakWString ts5, ts6;
- wchar_t buff[99];
- wchar_t *wptr = (wchar_t*)buff;
- bsTest.Read(wptr);
- bsTest.Read(ts5);
- */
|