libnative-utilities/include/raknet/RakString.hpp

355 lines
12 KiB
C++
Raw Normal View History

2024-08-15 18:40:30 +08:00
/*
* 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.
*
*/
#ifndef __RAK_STRING_H
#define __RAK_STRING_H
#include "Export.hpp"
#include "DS_List.hpp"
#include "RakNetTypes.hpp" // int64_t
#include <stdio.h>
#include "stdarg.h"
#ifdef _WIN32
#include "WindowsIncludes.hpp"
#endif
namespace RakNet
{
/// Forward declarations
class SimpleMutex;
class BitStream;
/// \brief String class
/// \details Has the following improvements over std::string
/// -Reference counting: Suitable to store in lists
/// -Variadic assignment operator
/// -Doesn't cause linker errors
class RAK_DLL_EXPORT RakString
{
public:
// Constructors
RakString();
RakString(char input);
RakString(unsigned char input);
RakString(const unsigned char *format, ...);
RakString(const char *format, ...);
~RakString();
RakString( const RakString & rhs);
/// Implicit return of const char*
operator const char* () const {return sharedString->c_str;}
/// Same as std::string::c_str
const char *C_String(void) const {return sharedString->c_str;}
// Lets you modify the string. Do not make the string longer - however, you can make it shorter, or change the contents.
// Pointer is only valid in the scope of RakString itself
char *C_StringUnsafe(void) {Clone(); return sharedString->c_str;}
/// Assigment operators
RakString& operator = ( const RakString& rhs );
RakString& operator = ( const char *str );
RakString& operator = ( char *str );
RakString& operator = ( const unsigned char *str );
RakString& operator = ( char unsigned *str );
RakString& operator = ( const char c );
/// Concatenation
RakString& operator +=( const RakString& rhs);
RakString& operator += ( const char *str );
RakString& operator += ( char *str );
RakString& operator += ( const unsigned char *str );
RakString& operator += ( char unsigned *str );
RakString& operator += ( const char c );
/// Character index. Do not use to change the string however.
unsigned char operator[] ( const unsigned int position ) const;
#ifdef _WIN32
// Return as Wide char
// Deallocate with DeallocWideChar
WCHAR * ToWideChar(void);
void DeallocWideChar(WCHAR * w);
void FromWideChar(const wchar_t *source);
static RakNet::RakString FromWideChar_S(const wchar_t *source);
#endif
/// String class find replacement
/// Searches the string for the content specified in stringToFind and returns the position of the first occurrence in the string.
/// Search only includes characters on or after position pos, ignoring any possible occurrences in previous locations.
/// \param[in] stringToFind The string to find inside of this object's string
/// \param[in] pos The position in the string to start the search
/// \return Returns the position of the first occurrence in the string.
size_t Find(const char *stringToFind,size_t pos = 0 );
/// Equality
bool operator==(const RakString &rhs) const;
bool operator==(const char *str) const;
bool operator==(char *str) const;
// Comparison
bool operator < ( const RakString& right ) const;
bool operator <= ( const RakString& right ) const;
bool operator > ( const RakString& right ) const;
bool operator >= ( const RakString& right ) const;
/// Inequality
bool operator!=(const RakString &rhs) const;
bool operator!=(const char *str) const;
bool operator!=(char *str) const;
/// Change all characters to lowercase
const char * ToLower(void);
/// Change all characters to uppercase
const char * ToUpper(void);
/// Set the value of the string
void Set(const char *format, ...);
/// Sets a copy of a substring of str as the new content. The substring is the portion of str
/// that begins at the character position pos and takes up to n characters
/// (it takes less than n if the end of str is reached before).
/// \param[in] str The string to copy in
/// \param[in] pos The position on str to start the copy
/// \param[in] n How many chars to copy
/// \return Returns the string, note that the current string is set to that value as well
RakString Assign(const char *str,size_t pos, size_t n );
/// Returns if the string is empty. Also, C_String() would return ""
bool IsEmpty(void) const;
/// Returns the length of the string
size_t GetLength(void) const;
size_t GetLengthUTF8(void) const;
/// Replace character(s) in starting at index, for count, with c
void Replace(unsigned index, unsigned count, unsigned char c);
/// Replace character at index with c
void SetChar( unsigned index, unsigned char c );
/// Replace character at index with string s
void SetChar( unsigned index, RakNet::RakString s );
/// Make sure string is no longer than \a length
void Truncate(unsigned int length);
void TruncateUTF8(unsigned int length);
// Gets the substring starting at index for count characters
RakString SubStr(unsigned int index, unsigned int count) const;
/// Erase characters out of the string at index for count
void Erase(unsigned int index, unsigned int count);
/// Set the first instance of c with a NULL terminator
void TerminateAtFirstCharacter(char c);
/// Set the last instance of c with a NULL terminator
void TerminateAtLastCharacter(char c);
void StartAfterFirstCharacter(char c);
void StartAfterLastCharacter(char c);
/// Returns how many occurances there are of \a c in the string
int GetCharacterCount(char c);
/// Remove all instances of c
void RemoveCharacter(char c);
/// Create a RakString with a value, without doing printf style parsing
/// Equivalent to assignment operator
static RakNet::RakString NonVariadic(const char *str);
/// Hash the string into an unsigned int
static unsigned long ToInteger(const char *str);
static unsigned long ToInteger(const RakString &rs);
/// \brief Read an integer out of a substring
/// \param[in] str The string
/// \param[in] pos The position on str where the integer starts
/// \param[in] n How many chars to copy
static int ReadIntFromSubstring(const char *str, size_t pos, size_t n);
// Like strncat, but for a fixed length
void AppendBytes(const char *bytes, unsigned int count);
/// Compare strings (case sensitive)
int StrCmp(const RakString &rhs) const;
/// Compare strings (case sensitive), up to num characters
int StrNCmp(const RakString &rhs, size_t num) const;
/// Compare strings (not case sensitive)
int StrICmp(const RakString &rhs) const;
/// Clear the string
void Clear(void);
/// Print the string to the screen
void Printf(void);
/// Print the string to a file
void FPrintf(FILE *fp);
/// Does the given IP address match the IP address encoded into this string, accounting for wildcards?
bool IPAddressMatch(const char *IP);
/// Does the string contain non-printable characters other than spaces?
bool ContainsNonprintableExceptSpaces(void) const;
/// Is this a valid email address?
bool IsEmailAddress(void) const;
/// URL Encode the string. See http://www.codeguru.com/cpp/cpp/cpp_mfc/article.php/c4029/
RakNet::RakString& URLEncode(void);
/// URL decode the string
RakNet::RakString& URLDecode(void);
/// https://servers.api.rackspacecloud.com/v1.0 to https://, servers.api.rackspacecloud.com, /v1.0
void SplitURI(RakNet::RakString &header, RakNet::RakString &domain, RakNet::RakString &path);
/// Scan for quote, double quote, and backslash and prepend with backslash
RakNet::RakString& SQLEscape(void);
/// Format as a POST command that can be sent to a webserver
/// \param[in] uri For example, masterserver2.raknet.com/testServer
/// \param[in] contentType For example, text/plain; charset=UTF-8
/// \param[in] body Body of the post
/// \return Formatted string
static RakNet::RakString FormatForPOST(const char* uri, const char* contentType, const char* body, const char* extraHeaders="");
static RakNet::RakString FormatForPUT(const char* uri, const char* contentType, const char* body, const char* extraHeaders="");
/// Format as a GET command that can be sent to a webserver
/// \param[in] uri For example, masterserver2.raknet.com/testServer?__gameId=comprehensivePCGame
/// \return Formatted string
static RakNet::RakString FormatForGET(const char* uri, const char* extraHeaders="");
/// Format as a DELETE command that can be sent to a webserver
/// \param[in] uri For example, masterserver2.raknet.com/testServer?__gameId=comprehensivePCGame&__rowId=1
/// \return Formatted string
static RakNet::RakString FormatForDELETE(const char* uri, const char* extraHeaders="");
/// Fix to be a file path, ending with /
RakNet::RakString& MakeFilePath(void);
/// RakString uses a freeList of old no-longer used strings
/// Call this function to clear this memory on shutdown
static void FreeMemory(void);
/// \internal
static void FreeMemoryNoMutex(void);
/// Serialize to a bitstream, uncompressed (slightly faster)
/// \param[out] bs Bitstream to serialize to
void Serialize(BitStream *bs) const;
/// Static version of the Serialize function
static void Serialize(const char *str, BitStream *bs);
/// Serialize to a bitstream, compressed (better bandwidth usage)
/// \param[out] bs Bitstream to serialize to
/// \param[in] languageId languageId to pass to the StringCompressor class
/// \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)
/// \pre StringCompressor::AddReference must have been called to instantiate the class (Happens automatically from RakPeer::Startup())
void SerializeCompressed(BitStream *bs, uint8_t languageId=0, bool writeLanguageId=false) const;
/// Static version of the SerializeCompressed function
static void SerializeCompressed(const char *str, BitStream *bs, uint8_t languageId=0, bool writeLanguageId=false);
/// Deserialize what was written by Serialize
/// \param[in] bs Bitstream to serialize from
/// \return true if the deserialization was successful
bool Deserialize(BitStream *bs);
/// Static version of the Deserialize() function
static bool Deserialize(char *str, BitStream *bs);
/// Deserialize compressed string, written by SerializeCompressed
/// \param[in] bs Bitstream to serialize from
/// \param[in] readLanguageId If true, looks for the variable langaugeId in the data stream. Must match what was passed to SerializeCompressed
/// \return true if the deserialization was successful
/// \pre StringCompressor::AddReference must have been called to instantiate the class (Happens automatically from RakPeer::Startup())
bool DeserializeCompressed(BitStream *bs, bool readLanguageId=false);
/// Static version of the DeserializeCompressed() function
static bool DeserializeCompressed(char *str, BitStream *bs, bool readLanguageId=false);
static const char *ToString(int64_t i);
static const char *ToString(uint64_t i);
/// \internal
static size_t GetSizeToAllocate(size_t bytes)
{
const size_t smallStringSize = 128-sizeof(unsigned int)-sizeof(size_t)-sizeof(char*)*2;
if (bytes<=smallStringSize)
return smallStringSize;
else
return bytes*2;
}
/// \internal
struct SharedString
{
SimpleMutex *refCountMutex;
unsigned int refCount;
size_t bytesUsed;
char *bigString;
char *c_str;
char smallString[128-sizeof(unsigned int)-sizeof(size_t)-sizeof(char*)*2];
};
/// \internal
RakString( SharedString *_sharedString );
/// \internal
SharedString *sharedString;
// static SimpleMutex poolMutex;
// static DataStructures::MemoryPool<SharedString> pool;
/// \internal
static SharedString emptyString;
//static SharedString *sharedStringFreeList;
//static unsigned int sharedStringFreeListAllocationCount;
/// \internal
/// List of free objects to reduce memory reallocations
static DataStructures::List<SharedString*> freeList;
static int RakStringComp( RakString const &key, RakString const &data );
static void LockMutex(void);
static void UnlockMutex(void);
protected:
static RakNet::RakString FormatForPUTOrPost(const char* type, const char* uri, const char* contentType, const char* body, const char* extraHeaders);
void Allocate(size_t len);
void Assign(const char *str);
void Assign(const char *str, va_list ap);
void Clone(void);
void Free(void);
unsigned char ToLower(unsigned char c);
unsigned char ToUpper(unsigned char c);
void Realloc(SharedString *sharedString, size_t bytes);
};
}
const RakNet::RakString RAK_DLL_EXPORT operator+(const RakNet::RakString &lhs, const RakNet::RakString &rhs);
#endif