1 #ifndef __RAK_STRING_H
2 #define __RAK_STRING_H
3 
4 #include "Export.h"
5 #include "DS_List.h"
6 #include "RakNetTypes.h" // int64_t
7 #include <stdio.h>
8 #include "stdarg.h"
9 
10 class SimpleMutex;
11 
12 namespace RakNet
13 {
14 
15 class BitStream;
16 
17 /// \brief String class
18 /// \details Has the following improvements over std::string
19 /// -Reference counting: Suitable to store in lists
20 /// -Variadic assignment operator
21 /// -Doesn't cause linker errors
22 class RAK_DLL_EXPORT RakString
23 {
24 public:
25 	// Constructors
26 	RakString();
27 	RakString(char input);
28 	RakString(unsigned char input);
29 	RakString(const unsigned char *format, ...);
30 	RakString(const char *format, ...);
31 	~RakString();
32 	RakString( const RakString & rhs);
33 
34 	/// Implicit return of const char*
35 	operator const char* () const {return sharedString->c_str;}
36 
37 	/// Same as std::string::c_str
C_String(void)38 	const char *C_String(void) const {return sharedString->c_str;}
39 
40 	// Lets you modify the string. Do not make the string longer - however, you can make it shorter, or change the contents.
41 	// Pointer is only valid in the scope of RakString itself
C_StringUnsafe(void)42 	char *C_StringUnsafe(void) {Clone(); return sharedString->c_str;}
43 
44 	/// Assigment operators
45 	RakString& operator = ( const RakString& rhs );
46 	RakString& operator = ( const char *str );
47 	RakString& operator = ( char *str );
48 	RakString& operator = ( const unsigned char *str );
49 	RakString& operator = ( char unsigned *str );
50 	RakString& operator = ( const char c );
51 
52 	/// Concatenation
53 	RakString& operator +=( const RakString& rhs);
54 	RakString& operator += ( const char *str );
55 	RakString& operator += ( char *str );
56 	RakString& operator += ( const unsigned char *str );
57 	RakString& operator += ( char unsigned *str );
58 	RakString& operator += ( const char c );
59 
60 	/// Character index. Do not use to change the string however.
61 	unsigned char operator[] ( const unsigned int position ) const;
62 
63 
64 	///String class find replacement
65 	///Searches the string for the content specified in stringToFind and returns the position of the first occurrence in the string.
66 	///Search only includes characters on or after position pos, ignoring any possible occurrences in previous locations.
67 	/// \param[in] stringToFind The string to find inside of this object's string
68 	/// \param[in] pos The position in the string to start the search
69 	/// \return Returns the position of the first occurrence in the string.
70 	size_t Find(const char *stringToFind,size_t pos = 0 );
71 
72 	/// Equality
73 	bool operator==(const RakString &rhs) const;
74 	bool operator==(const char *str) const;
75 	bool operator==(char *str) const;
76 
77 	// Comparison
78 	bool operator < ( const RakString& right ) const;
79 	bool operator <= ( const RakString& right ) const;
80 	bool operator > ( const RakString& right ) const;
81 	bool operator >= ( const RakString& right ) const;
82 
83 	/// Inequality
84 	bool operator!=(const RakString &rhs) const;
85 	bool operator!=(const char *str) const;
86 	bool operator!=(char *str) const;
87 
88 	/// Change all characters to lowercase
89 	const char * ToLower(void);
90 
91 	/// Change all characters to uppercase
92 	const char * ToUpper(void);
93 
94 	/// Set the value of the string
95 	void Set(const char *format, ...);
96 
97 	/// Sets a copy of a substring of str as the new content. The substring is the portion of str
98 	/// that begins at the character position pos and takes up to n characters
99 	/// (it takes less than n if the end of str is reached before).
100 	/// \param[in] str The string to copy in
101 	/// \param[in] pos The position on str to start the copy
102 	/// \param[in] n How many chars to copy
103 	/// \return Returns the string, note that the current string is set to that value as well
104 	RakString Assign(const char *str,size_t pos, size_t n );
105 
106 	/// Returns if the string is empty. Also, C_String() would return ""
107 	bool IsEmpty(void) const;
108 
109 	/// Returns the length of the string
110 	size_t GetLength(void) const;
111 
112 	/// Replace character(s) in starting at index, for count, with c
113 	void Replace(unsigned index, unsigned count, unsigned char c);
114 
115 	/// Replace character at index with c
116 	void SetChar( unsigned index, unsigned char c );
117 
118 	/// Replace character at index with string s
119 	void SetChar( unsigned index, RakNet::RakString s );
120 
121 	/// Make sure string is no longer than \a length
122 	void Truncate(unsigned length);
123 
124 	// Gets the substring starting at index for count characters
125 	RakString SubStr(unsigned int index, unsigned int count) const;
126 
127 	/// Erase characters out of the string at index for count
128 	void Erase(unsigned int index, unsigned int count);
129 
130 	/// Set the first instance of c with a NULL terminator
131 	void TerminateAtFirstCharacter(char c);
132 	/// Set the last instance of c with a NULL terminator
133 	void TerminateAtLastCharacter(char c);
134 
135 	/// Remove all instances of c
136 	void RemoveCharacter(char c);
137 
138 	/// Create a RakString with a value, without doing printf style parsing
139 	/// Equivalent to assignment operator
140 	static RakNet::RakString NonVariadic(const char *str);
141 
142 	/// Has the string into an unsigned int
143 	static unsigned long ToInteger(const char *str);
144 	static unsigned long ToInteger(const RakString &rs);
145 
146 	// Like strncat, but for a fixed length
147 	void AppendBytes(const char *bytes, unsigned int count);
148 
149 	/// Compare strings (case sensitive)
150 	int StrCmp(const RakString &rhs) const;
151 
152 	/// Compare strings (not case sensitive)
153 	int StrICmp(const RakString &rhs) const;
154 
155 	/// Clear the string
156 	void Clear(void);
157 
158 	/// Print the string to the screen
159 	void Printf(void);
160 
161 	/// Print the string to a file
162 	void FPrintf(FILE *fp);
163 
164 	/// Does the given IP address match the IP address encoded into this string, accounting for wildcards?
165 	bool IPAddressMatch(const char *IP);
166 
167 	/// Does the string contain non-printable characters other than spaces?
168 	bool ContainsNonprintableExceptSpaces(void) const;
169 
170 	/// Is this a valid email address?
171 	bool IsEmailAddress(void) const;
172 
173 	/// URL Encode the string. See http://www.codeguru.com/cpp/cpp/cpp_mfc/article.php/c4029/
174 	RakNet::RakString& URLEncode(void);
175 
176 	/// URL decode the string
177 	RakNet::RakString& URLDecode(void);
178 
179 	/// Scan for quote, double quote, and backslash and prepend with backslash
180 	RakNet::RakString& SQLEscape(void);
181 
182 	/// Fix to be a file path, ending with /
183 	RakNet::RakString& MakeFilePath(void);
184 
185 	/// RakString uses a freeList of old no-longer used strings
186 	/// Call this function to clear this memory on shutdown
187 	static void FreeMemory(void);
188 	/// \internal
189 	static void FreeMemoryNoMutex(void);
190 
191 	/// Serialize to a bitstream, uncompressed (slightly faster)
192 	/// \param[out] bs Bitstream to serialize to
193 	void Serialize(BitStream *bs) const;
194 
195 	/// Static version of the Serialize function
196 	static void Serialize(const char *str, BitStream *bs);
197 
198 	/// Serialize to a bitstream, compressed (better bandwidth usage)
199 	/// \param[out]  bs Bitstream to serialize to
200 	/// \param[in] languageId languageId to pass to the StringCompressor class
201 	/// \param[in] writeLanguageId encode the languageId variable in the stream. If false, 0 is assumed, and DeserializeCompressed will not look for this variable in the stream (saves bandwidth)
202 	/// \pre StringCompressor::AddReference must have been called to instantiate the class (Happens automatically from RakPeer::Startup())
203 	void SerializeCompressed(BitStream *bs, int languageId=0, bool writeLanguageId=false) const;
204 
205 	/// Static version of the SerializeCompressed function
206 	static void SerializeCompressed(const char *str, BitStream *bs, int languageId=0, bool writeLanguageId=false);
207 
208 	/// Deserialize what was written by Serialize
209 	/// \param[in] bs Bitstream to serialize from
210 	/// \return true if the deserialization was successful
211 	bool Deserialize(BitStream *bs);
212 
213 	/// Static version of the Deserialize() function
214 	static bool Deserialize(char *str, BitStream *bs);
215 
216 	/// Deserialize compressed string, written by SerializeCompressed
217 	/// \param[in] bs Bitstream to serialize from
218 	/// \param[in] readLanguageId If true, looks for the variable langaugeId in the data stream. Must match what was passed to SerializeCompressed
219 	/// \return true if the deserialization was successful
220 	/// \pre StringCompressor::AddReference must have been called to instantiate the class (Happens automatically from RakPeer::Startup())
221 	bool DeserializeCompressed(BitStream *bs, bool readLanguageId=false);
222 
223 	/// Static version of the DeserializeCompressed() function
224 	static bool DeserializeCompressed(char *str, BitStream *bs, bool readLanguageId=false);
225 
226 	static const char *ToString(int64_t i);
227 	static const char *ToString(uint64_t i);
228 
229 	/// \internal
GetSizeToAllocate(size_t bytes)230 	static size_t GetSizeToAllocate(size_t bytes)
231 	{
232 		const size_t smallStringSize = 128-sizeof(unsigned int)-sizeof(size_t)-sizeof(char*)*2;
233 		if (bytes<=smallStringSize)
234 			return smallStringSize;
235 		else
236 			return bytes*2;
237 	}
238 
239 	/// \internal
240 	struct SharedString
241 	{
242 		SimpleMutex *refCountMutex;
243 		unsigned int refCount;
244 		size_t bytesUsed;
245 		char *bigString;
246 		char *c_str;
247 		char smallString[128-sizeof(unsigned int)-sizeof(size_t)-sizeof(char*)*2];
248 	};
249 
250 	/// \internal
251 	RakString( SharedString *_sharedString );
252 
253 	/// \internal
254 	SharedString *sharedString;
255 
256 //	static SimpleMutex poolMutex;
257 //	static DataStructures::MemoryPool<SharedString> pool;
258 	/// \internal
259 	static SharedString emptyString;
260 
261 	//static SharedString *sharedStringFreeList;
262 	//static unsigned int sharedStringFreeListAllocationCount;
263 	/// \internal
264 	/// List of free objects to reduce memory reallocations
265 	static DataStructures::List<SharedString*> freeList;
266 
267 	/// Means undefined position
268 	static unsigned int nPos;
269 
270 
271 	static int RakStringComp( RakString const &key, RakString const &data );
272 
273 	static void LockMutex(void);
274 	static void UnlockMutex(void);
275 
276 protected:
277 	void Allocate(size_t len);
278 	void Assign(const char *str);
279 	void Assign(const char *str, va_list ap);
280 
281 	void Clone(void);
282 	void Free(void);
283 	unsigned char ToLower(unsigned char c);
284 	unsigned char ToUpper(unsigned char c);
285 	void Realloc(SharedString *sharedString, size_t bytes);
286 };
287 
288 }
289 
290 const RakNet::RakString RAK_DLL_EXPORT operator+(const RakNet::RakString &lhs, const RakNet::RakString &rhs);
291 
292 
293 #endif
294