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