SLikeNet 0.1.3

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
RakWString.cpp
Go to the documentation of this file.
1 /*
2 * Original work: Copyright (c) 2014, Oculus VR, Inc.
3 * All rights reserved.
4 *
5 * This source code is licensed under the BSD-style license found in the
6 * RakNet License.txt file in the licenses directory of this source tree. An additional grant
7 * of patent rights can be found in the RakNet Patents.txt file in the same directory.
8 *
9 *
10 * Modified work: Copyright (c) 2016-2018, SLikeSoft UG (haftungsbeschränkt)
11 *
12 * This source code was modified by SLikeSoft. Modifications are licensed under the MIT-style
13 * license found in the license.txt file in the root directory of this source tree.
14 */
15
16 #include "slikenet/wstring.h"
17 #include "slikenet/BitStream.h"
18 #include <string.h>
19 #include <wchar.h>
20 #include <stdlib.h>
21 #include "slikenet/linux_adapter.h"
22 #include "slikenet/osx_adapter.h"
23
24 using namespace SLNet;
25
26 // From http://www.joelonsoftware.com/articles/Unicode.html
27 // Only code points 128 and above are stored using 2, 3, in fact, up to 6 bytes.
28 #define MAX_BYTES_PER_UNICODE_CHAR sizeof(wchar_t)
29
30 RakWString::RakWString()
31 {
32 c_str=0;
33 c_strCharLength=0;
34 }
35 RakWString::RakWString( const RakString &right )
36 {
37 c_str=0;
38 c_strCharLength=0;
39 *this=right;
40 }
41 RakWString::RakWString( const char *input )
42 {
43 c_str=0;
44 c_strCharLength=0;
45 *this = input;
46 }
47 RakWString::RakWString( const wchar_t *input )
48 {
49 c_str=0;
50 c_strCharLength=0;
51 *this = input;
52 }
53 RakWString::RakWString( const RakWString & right)
54 {
55 c_str=0;
56 c_strCharLength=0;
57 *this = right;
58 }
59 RakWString::~RakWString()
60 {
61 rakFree_Ex(c_str,_FILE_AND_LINE_);
62 }
63 RakWString& RakWString::operator = ( const RakWString& right )
64 {
65 Clear();
66 if (right.IsEmpty())
67 return *this;
68 c_str = (wchar_t *) rakMalloc_Ex( (right.GetLength() + 1) * MAX_BYTES_PER_UNICODE_CHAR, _FILE_AND_LINE_);
69 if (!c_str)
70 {
71 c_strCharLength=0;
72 notifyOutOfMemory(_FILE_AND_LINE_);
73 return *this;
74 }
75 c_strCharLength = right.GetLength();
76 memcpy(c_str,right.C_String(),(right.GetLength() + 1) * MAX_BYTES_PER_UNICODE_CHAR);
77
78 return *this;
79 }
80 RakWString& RakWString::operator = ( const RakString& right )
81 {
82 return *this = right.C_String();
83 }
84 RakWString& RakWString::operator = ( const wchar_t * const str )
85 {
86 Clear();
87 if (str==0)
88 return *this;
89 c_strCharLength = wcslen(str);
90 if (c_strCharLength==0)
91 return *this;
92 c_str = (wchar_t *) rakMalloc_Ex( (c_strCharLength + 1) * MAX_BYTES_PER_UNICODE_CHAR, _FILE_AND_LINE_);
93 if (!c_str)
94 {
95 c_strCharLength=0;
96 notifyOutOfMemory(_FILE_AND_LINE_);
97 return *this;
98 }
99 wcscpy_s(c_str,c_strCharLength+1,str);
100
101 return *this;
102 }
103 RakWString& RakWString::operator = ( wchar_t *str )
104 {
105 *this = ( const wchar_t * const) str;
106 return *this;
107 }
108 RakWString& RakWString::operator = ( const char * const str )
109 {
110 Clear();
111
112 // Not supported on android
113 #if !defined(ANDROID)
114 if (str==0)
115 return *this;
116 if (str[0]==0)
117 return *this;
118
119 mbstowcs_s(&c_strCharLength, NULL, 0, str, 0);
120 c_str = (wchar_t *) rakMalloc_Ex( (c_strCharLength + 1) * MAX_BYTES_PER_UNICODE_CHAR, _FILE_AND_LINE_);
121 if (!c_str)
122 {
123 c_strCharLength=0;
124 notifyOutOfMemory(_FILE_AND_LINE_);
125 return *this;
126 }
127
128 mbstowcs_s(&c_strCharLength, c_str, c_strCharLength + 1, str, c_strCharLength);
129 if (c_strCharLength == (size_t) (-1))
130 {
131 RAKNET_DEBUG_PRINTF("Couldn't convert string--invalid multibyte character.\n");
132 Clear();
133 return *this;
134 }
135 #else
136 // mbstowcs not supported on android
137 RakAssert("mbstowcs not supported on Android" && 0);
138 #endif // defined(ANDROID)
139
140 return *this;
141 }
142 RakWString& RakWString::operator = ( char *str )
143 {
144 *this = ( const char * const) str;
145 return *this;
146 }
147 RakWString& RakWString::operator +=( const RakWString& right)
148 {
149 if (right.IsEmpty())
150 return *this;
151 size_t newCharLength = c_strCharLength + right.GetLength();
152 wchar_t *newCStr;
153 bool isEmpty = IsEmpty();
154 if (isEmpty)
155 newCStr = (wchar_t *) rakMalloc_Ex( (newCharLength + 1) * MAX_BYTES_PER_UNICODE_CHAR, _FILE_AND_LINE_);
156 else
157 newCStr = (wchar_t *) rakRealloc_Ex( c_str, (newCharLength + 1) * MAX_BYTES_PER_UNICODE_CHAR, _FILE_AND_LINE_);
158 if (!newCStr)
159 {
160 notifyOutOfMemory(_FILE_AND_LINE_);
161 return *this;
162 }
163 c_str = newCStr;
164 c_strCharLength = newCharLength;
165 if (isEmpty)
166 {
167 memcpy(newCStr,right.C_String(),(right.GetLength() + 1) * MAX_BYTES_PER_UNICODE_CHAR);
168 }
169 else
170 {
171 wcscat_s(c_str, newCharLength + 1, right.C_String());
172 }
173
174 return *this;
175 }
176 RakWString& RakWString::operator += ( const wchar_t * const right )
177 {
178 if (right==0)
179 return *this;
180 size_t rightLength = wcslen(right);
181 size_t newCharLength = c_strCharLength + rightLength;
182 wchar_t *newCStr;
183 bool isEmpty = IsEmpty();
184 if (isEmpty)
185 newCStr = (wchar_t *) rakMalloc_Ex( (newCharLength + 1) * MAX_BYTES_PER_UNICODE_CHAR, _FILE_AND_LINE_);
186 else
187 newCStr = (wchar_t *) rakRealloc_Ex( c_str, (newCharLength + 1) * MAX_BYTES_PER_UNICODE_CHAR, _FILE_AND_LINE_);
188 if (!newCStr)
189 {
190 notifyOutOfMemory(_FILE_AND_LINE_);
191 return *this;
192 }
193 c_str = newCStr;
194 c_strCharLength = newCharLength;
195 if (isEmpty)
196 {
197 memcpy(newCStr,right,(rightLength + 1) * MAX_BYTES_PER_UNICODE_CHAR);
198 }
199 else
200 {
201 wcscat_s(c_str, newCharLength + 1, right);
202 }
203
204 return *this;
205 }
206 RakWString& RakWString::operator += ( wchar_t *right )
207 {
208 return *this += (const wchar_t * const) right;
209 }
210 bool RakWString::operator==(const RakWString &right) const
211 {
212 if (GetLength()!=right.GetLength())
213 return false;
214 return wcscmp(C_String(),right.C_String())==0;
215 }
216 bool RakWString::operator < ( const RakWString& right ) const
217 {
218 return wcscmp(C_String(),right.C_String())<0;
219 }
220 bool RakWString::operator <= ( const RakWString& right ) const
221 {
222 return wcscmp(C_String(),right.C_String())<=0;
223 }
224 bool RakWString::operator > ( const RakWString& right ) const
225 {
226 return wcscmp(C_String(),right.C_String())>0;
227 }
228 bool RakWString::operator >= ( const RakWString& right ) const
229 {
230 return wcscmp(C_String(),right.C_String())>=0;
231 }
232 bool RakWString::operator!=(const RakWString &right) const
233 {
234 if (GetLength()!=right.GetLength())
235 return true;
236 return wcscmp(C_String(),right.C_String())!=0;
237 }
238 void RakWString::Set( wchar_t *str )
239 {
240 *this = str;
241 }
242 bool RakWString::IsEmpty(void) const
243 {
244 return GetLength()==0;
245 }
246 size_t RakWString::GetLength(void) const
247 {
248 return c_strCharLength;
249 }
250 unsigned long RakWString::ToInteger(const RakWString &rs)
251 {
252 unsigned long hash = 0;
253 int c;
254
255 const char *str = (const char *)rs.C_String();
256 size_t i;
257 for (i=0; i < rs.GetLength()*MAX_BYTES_PER_UNICODE_CHAR*sizeof(wchar_t); i++)
258 {
259 c = *str++;
260 hash = c + (hash << 6) + (hash << 16) - hash;
261 }
262
263 return hash;
264 }
265 int RakWString::StrCmp(const RakWString &right) const
266 {
267 return wcscmp(C_String(), right.C_String());
268 }
269 int RakWString::StrICmp(const RakWString &right) const
270 {
271 #ifdef _WIN32
272 return _wcsicmp(C_String(), right.C_String());
273 #else
274 // Not supported
275 return wcscmp(C_String(), right.C_String());
276 #endif
277 }
278 void RakWString::Clear(void)
279 {
280 rakFree_Ex(c_str,_FILE_AND_LINE_);
281 c_str=0;
282 c_strCharLength=0;
283 }
284 void RakWString::Printf(void)
285 {
286 printf("%ls", C_String());
287 }
288 void RakWString::FPrintf(FILE *fp)
289 {
290 fprintf(fp,"%ls", C_String());
291 }
292 void RakWString::Serialize(BitStream *bs) const
293 {
294 Serialize(C_String(), bs);
295 }
296 void RakWString::Serialize(const wchar_t * const str, BitStream *bs)
297 {
298 #if 0
299 char *multiByteBuffer;
300 size_t allocated = wcslen(str)*MAX_BYTES_PER_UNICODE_CHAR;
301 multiByteBuffer = (char*) rakMalloc_Ex(allocated, _FILE_AND_LINE_);
302 size_t used = wcstombs(multiByteBuffer, str, allocated);
303 bs->WriteCasted<unsigned short>(used);
304 bs->WriteAlignedBytes((const unsigned char*) multiByteBuffer,(const unsigned int) used);
305 rakFree_Ex(multiByteBuffer, _FILE_AND_LINE_);
306 #else
307 size_t mbByteLength = wcslen(str);
308 bs->WriteCasted<unsigned short>(mbByteLength);
309 for (unsigned int i=0; i < mbByteLength; i++)
310 {
311 uint16_t t;
312 t = (uint16_t) str[i];
313 // Force endian swapping, and write to 16 bits
314 bs->Write(t);
315 }
316 #endif
317 }
318 bool RakWString::Deserialize(BitStream *bs)
319 {
320 Clear();
321
322 size_t mbByteLength;
323 bs->ReadCasted<unsigned short>(mbByteLength);
324 if (mbByteLength>0)
325 {
326 #if 0
327 char *multiByteBuffer;
328 multiByteBuffer = (char*) rakMalloc_Ex(mbByteLength+1, _FILE_AND_LINE_);
329 bool result = bs->ReadAlignedBytes((unsigned char*) multiByteBuffer,(const unsigned int) mbByteLength);
330 if (result==false)
331 {
332 rakFree_Ex(multiByteBuffer, _FILE_AND_LINE_);
333 return false;
334 }
335 multiByteBuffer[mbByteLength]=0;
336 c_str = (wchar_t *) rakMalloc_Ex( (mbByteLength + 1) * MAX_BYTES_PER_UNICODE_CHAR, _FILE_AND_LINE_);
337 mbstowcs_s(&c_strCharLength, c_str, mbByteLength + 1, multiByteBuffer, mbByteLength);
338 rakFree_Ex(multiByteBuffer, _FILE_AND_LINE_);
339 c_str[c_strCharLength]=0;
340 #else
341 c_str = (wchar_t*) rakMalloc_Ex((mbByteLength+1) * MAX_BYTES_PER_UNICODE_CHAR, _FILE_AND_LINE_);
342 c_strCharLength = mbByteLength;
343 for (unsigned int i=0; i < mbByteLength; i++)
344 {
345 uint16_t t;
346 // Force endian swapping, and read 16 bits
347 bs->Read(t);
348 c_str[i]=t;
349 }
350 c_str[mbByteLength]=0;
351 #endif
352 return true;
353 }
354 else
355 {
356 return true;
357 }
358 }
359 bool RakWString::Deserialize(wchar_t *str, BitStream *bs)
360 {
361 size_t mbByteLength;
362 bs->ReadCasted<unsigned short>(mbByteLength);
363 if (mbByteLength > 0)
364 {
365 #if 0
366 char *multiByteBuffer;
367 multiByteBuffer = (char*)rakMalloc_Ex(mbByteLength + 1, _FILE_AND_LINE_);
368 bool result = bs->ReadAlignedBytes((unsigned char*)multiByteBuffer, (const unsigned int)mbByteLength);
369 if (result == false)
370 {
371 rakFree_Ex(multiByteBuffer, _FILE_AND_LINE_);
372 return false;
373 }
374 multiByteBuffer[mbByteLength] = 0;
375 size_t c_strCharLength;
376 mbstowcs(&c_strCharLength, str, multiByteBuffer, mbByteLength);
377 rakFree_Ex(multiByteBuffer, _FILE_AND_LINE_);
378 str[c_strCharLength] = 0;
379 #else
380 for (unsigned int i = 0; i < mbByteLength; i++)
381 {
382 uint16_t t;
383 // Force endian swapping, and read 16 bits
384 bs->Read(t);
385 str[i] = t;
386 }
387 str[mbByteLength] = 0;
388 #endif
389 return true;
390 }
391 else
392 {
393 #pragma warning(push)
394 #pragma warning(disable:4996)
395 wcscpy(str, L"");
396 #pragma warning(pop)
397 }
398 return true;
399 }
400 bool RakWString::Deserialize(wchar_t *str, size_t strLength, BitStream *bs)
401 {
402 size_t mbByteLength;
403 bs->ReadCasted<unsigned short>(mbByteLength);
404 if (mbByteLength>0)
405 {
406 #if 0
407 char *multiByteBuffer;
408 multiByteBuffer = (char*) rakMalloc_Ex(mbByteLength+1, _FILE_AND_LINE_);
409 bool result = bs->ReadAlignedBytes((unsigned char*) multiByteBuffer,(const unsigned int) mbByteLength);
410 if (result==false)
411 {
412 rakFree_Ex(multiByteBuffer, _FILE_AND_LINE_);
413 return false;
414 }
415 multiByteBuffer[mbByteLength]=0;
416 size_t c_strCharLength;
417 mbstowcs_s(&c_strCharLength, str, strLength, multiByteBuffer, mbByteLength);
418 rakFree_Ex(multiByteBuffer, _FILE_AND_LINE_);
419 str[c_strCharLength]=0;
420 #else
421 for (unsigned int i=0; i < mbByteLength; i++)
422 {
423 uint16_t t;
424 // Force endian swapping, and read 16 bits
425 bs->Read(t);
426 str[i]=t;
427 }
428 str[mbByteLength]=0;
429 #endif
430 return true;
431 }
432 else
433 {
434 wcscpy_s(str,strLength,L"");
435 }
436 return true;
437 }
438
439 const SLNet::RakWString operator+(const SLNet::RakWString &lhs, const SLNet::RakWString &rhs)
440 {
441 SLNet::RakWString returnvalue(lhs);
442 returnvalue += rhs;
443 return returnvalue;
444 }
445
446 /*
447 SLNet::BitStream bsTest;
448 SLNet::RakWString testString("cat"), testString2;
449 testString = "Hllo";
450 testString = L"Hello";
451 testString += L" world";
452 testString2 += testString2;
453 SLNet::RakWString ts3(L" from here");
454 testString2+=ts3;
455 SLNet::RakWString ts4(L" 222");
456 testString2=ts4;
457 SLNet::RakString rs("rakstring");
458 testString2+=rs;
459 testString2=rs;
460 bsTest.Write(L"one");
461 bsTest.Write(testString2);
462 bsTest.SetReadOffset(0);
463 SLNet::RakWString ts5, ts6;
464 wchar_t buff[99];
465 wchar_t *wptr = (wchar_t*)buff;
466 bsTest.Read(wptr);
467 bsTest.Read(ts5);
468 */