1 /* Copyright (C) 2014 Wildfire Games.
2 * This file is part of 0 A.D.
4 * 0 A.D. is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 2 of the License, or
7 * (at your option) any later version.
9 * 0 A.D. is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
21 * Description : Controls compilation of CStr class and
22 * : includes some function implementations.
24 #include "precompiled.h"
26 #ifndef CStr_CPP_FIRST
27 #define CStr_CPP_FIRST
29 #include "lib/fnv_hash.h"
31 #include "lib/byte_order.h"
32 #include "network/Serialization.h"
37 #define UNIDOUBLER_HEADER "CStr.cpp"
38 #include "UniDoubler.h"
41 // Only include these function definitions in the first instance of CStr.cpp:
44 * Convert CStr to UTF-8
46 * @return CStr8 converted string
48 CStr8
CStrW::ToUTF8() const
51 return utf8_from_wstring(*this, &err
);
55 * Convert UTF-8 to CStr
57 * @return CStrW converted string
59 CStrW
CStr8::FromUTF8() const
62 return wstring_from_utf8(*this, &err
);
67 // The following code is compiled twice, as CStrW then as CStr8:
74 #define tstringstream wstringstream
75 #define _istspace iswspace
76 #define _totlower towlower
77 #define _totupper towupper
79 #define tstringstream stringstream
80 #define _istspace isspace
81 #define _totlower tolower
82 #define _totupper toupper
85 CStr
CStr::Repeat(const CStr
& String
, size_t Reps
)
88 ret
.reserve(String
.length() * Reps
);
89 while (Reps
--) ret
+= String
;
93 // Construction from numbers:
95 CStr
CStr::FromInt(int n
)
97 std::tstringstream ss
;
102 CStr
CStr::FromUInt(unsigned int n
)
104 std::tstringstream ss
;
109 CStr
CStr::FromInt64(i64 n
)
111 std::tstringstream ss
;
116 CStr
CStr::FromDouble(double n
)
118 std::tstringstream ss
;
123 // Conversion to numbers:
125 int CStr::ToInt() const
128 std::tstringstream
str(*this);
133 unsigned int CStr::ToUInt() const
135 unsigned int ret
= 0;
136 std::tstringstream
str(*this);
141 long CStr::ToLong() const
144 std::tstringstream
str(*this);
149 unsigned long CStr::ToULong() const
151 unsigned long ret
= 0;
152 std::tstringstream
str(*this);
157 float CStr::ToFloat() const
160 std::tstringstream
str(*this);
165 double CStr::ToDouble() const
168 std::tstringstream
str(*this);
174 // Search the string for another string
175 long CStr::Find(const CStr
& Str
) const
177 size_t Pos
= find(Str
, 0);
185 // Search the string for another string
186 long CStr::Find(const tchar chr
) const
188 size_t Pos
= find(chr
, 0);
196 // Search the string for another string
197 long CStr::Find(const int start
, const tchar chr
) const
199 size_t Pos
= find(chr
, start
);
207 long CStr::FindInsensitive(const int start
, const tchar chr
) const { return LowerCase().Find(start
, _totlower(chr
)); }
208 long CStr::FindInsensitive(const tchar chr
) const { return LowerCase().Find(_totlower(chr
)); }
209 long CStr::FindInsensitive(const CStr
& Str
) const { return LowerCase().Find(Str
.LowerCase()); }
212 long CStr::ReverseFind(const CStr
& Str
) const
214 size_t Pos
= rfind(Str
, length() );
223 // Lowercase and uppercase
224 CStr
CStr::LowerCase() const
226 std::tstring NewString
= *this;
227 for (size_t i
= 0; i
< length(); i
++)
228 NewString
[i
] = (tchar
)_totlower((*this)[i
]);
233 CStr
CStr::UpperCase() const
235 std::tstring NewString
= *this;
236 for (size_t i
= 0; i
< length(); i
++)
237 NewString
[i
] = (tchar
)_totupper((*this)[i
]);
243 // Retrieve the substring of the first n characters
244 CStr
CStr::Left(size_t len
) const
246 ENSURE(len
<= length());
247 return substr(0, len
);
250 // Retrieve the substring of the last n characters
251 CStr
CStr::Right(size_t len
) const
253 ENSURE(len
<= length());
254 return substr(length()-len
, len
);
257 // Retrieve the substring following the last occurrence of Str
258 // (or the whole string if it doesn't contain Str)
259 CStr
CStr::AfterLast(const CStr
& Str
, size_t startPos
) const
261 size_t pos
= rfind(Str
, startPos
);
265 return substr(pos
+ Str
.length());
268 // Retrieve the substring preceding the last occurrence of Str
269 // (or the whole string if it doesn't contain Str)
270 CStr
CStr::BeforeLast(const CStr
& Str
, size_t startPos
) const
272 size_t pos
= rfind(Str
, startPos
);
276 return substr(0, pos
);
279 // Retrieve the substring following the first occurrence of Str
280 // (or the whole string if it doesn't contain Str)
281 CStr
CStr::AfterFirst(const CStr
& Str
, size_t startPos
) const
283 size_t pos
= find(Str
, startPos
);
287 return substr(pos
+ Str
.length());
290 // Retrieve the substring preceding the first occurrence of Str
291 // (or the whole string if it doesn't contain Str)
292 CStr
CStr::BeforeFirst(const CStr
& Str
, size_t startPos
) const
294 size_t pos
= find(Str
, startPos
);
298 return substr(0, pos
);
301 // Remove all occurrences of some character or substring
302 void CStr::Remove(const CStr
& Str
)
305 while (FoundAt
!= npos
)
307 FoundAt
= find(Str
, 0);
310 erase(FoundAt
, Str
.length());
314 // Replace all occurrences of some substring by another
315 void CStr::Replace(const CStr
& ToReplace
, const CStr
& ReplaceWith
)
321 Pos
= find(ToReplace
, Pos
);
324 erase(Pos
, ToReplace
.length());
325 insert(Pos
, ReplaceWith
);
326 Pos
+= ReplaceWith
.length();
331 std::string
CStr::EscapeToPrintableASCII() const
333 std::string NewString
;
334 for (size_t i
= 0; i
< length(); i
++)
336 tchar ch
= (*this)[i
];
338 if (ch
== '"') NewString
+= "\\\"";
339 else if (ch
== '\\') NewString
+= "\\\\";
340 else if (ch
== '\b') NewString
+= "\\b";
341 else if (ch
== '\f') NewString
+= "\\f";
342 else if (ch
== '\n') NewString
+= "\\n";
343 else if (ch
== '\r') NewString
+= "\\r";
344 else if (ch
== '\t') NewString
+= "\\t";
345 else if (ch
>= 32 && ch
<= 126)
349 std::stringstream ss
;
350 ss
<< "\\u" << std::hex
<< std::setfill('0') << std::setw(4) << (int)(unsigned char)ch
;
351 NewString
+= ss
.str();
357 // Returns a trimmed string, removes whitespace from the left/right/both
358 CStr
CStr::Trim(PS_TRIM_MODE Mode
) const
360 size_t Left
= 0, Right
= 0;
366 for (Left
= 0; Left
< length(); Left
++)
367 if (_istspace((*this)[Left
]) == false)
368 break; // end found, trim 0 to Left-1 inclusive
375 if (_istspace((*this)[Right
]) == false)
376 break; // end found, trim len-1 to Right+1 inclusive
381 for (Left
= 0; Left
< length(); Left
++)
382 if (_istspace((*this)[Left
]) == false)
383 break; // end found, trim 0 to Left-1 inclusive
387 if (_istspace((*this)[Right
]) == false)
388 break; // end found, trim len-1 to Right+1 inclusive
392 debug_warn(L
"CStr::Trim: invalid Mode");
396 return substr(Left
, Right
-Left
+1);
399 CStr
CStr::Pad(PS_TRIM_MODE Mode
, size_t Length
) const
401 size_t Left
= 0, Right
= 0;
403 if (Length
<= length())
406 // From here: Length-length() >= 1
411 Left
= Length
- length();
415 Right
= Length
- length();
419 Left
= (Length
- length() + 1)/2;
420 Right
= (Length
- length() - 1)/2; // cannot be negative
424 debug_warn(L
"CStr::Trim: invalid Mode");
427 return std::tstring(Left
, _T(' ')) + *this + std::tstring(Right
, _T(' '));
430 size_t CStr::GetHashCode() const
432 return (size_t)fnv_hash(data(), length()*sizeof(value_type
));
433 // janwas 2005-03-18: now use 32-bit version; 64 is slower and
434 // the result was truncated down to 32 anyway.
439 CStrW is always serialized to/from UTF-16
442 u8
* CStrW::Serialize(u8
* buffer
) const
444 size_t len
= length();
446 for (i
= 0; i
< len
; i
++)
448 const u16 bigEndian
= to_be16((*this)[i
]);
449 *(u16
*)(buffer
+ i
*2) = bigEndian
;
451 *(u16
*)(buffer
+ i
*2) = 0;
452 return buffer
+ len
*2 + 2;
455 const u8
* CStrW::Deserialize(const u8
* buffer
, const u8
* bufferend
)
457 const u16
*strend
= (const u16
*)buffer
;
458 while ((const u8
*)strend
< bufferend
&& *strend
) strend
++;
459 if ((const u8
*)strend
>= bufferend
) return NULL
;
461 resize(strend
- (const u16
*)buffer
);
462 const u16
*ptr
= (const u16
*)buffer
;
464 std::wstring::iterator str
= begin();
467 const u16 native
= to_be16(*(ptr
++)); // we want from_be16, but that's the same
468 *(str
++) = (tchar
)native
;
471 return (const u8
*)(strend
+1);
474 size_t CStr::GetSerializedLength() const
476 return size_t(length()*2 + 2);
481 CStr8 is always serialized to/from ASCII (or whatever 8-bit codepage stored
485 u8
* CStr8::Serialize(u8
* buffer
) const
487 size_t len
= length();
488 Serialize_int_4(buffer
, (u32
)len
);
490 for (i
= 0; i
< len
; i
++)
491 buffer
[i
] = (*this)[i
];
495 const u8
* CStr8::Deserialize(const u8
* buffer
, const u8
* bufferend
)
498 Deserialize_int_4(buffer
, len
);
499 if (buffer
+ len
> bufferend
)
501 *this = std::string(buffer
, buffer
+ len
);
505 size_t CStr::GetSerializedLength() const
512 // Clean up, to keep the second pass through unidoubler happy
521 #endif // CStr_CPP_FIRST