qzdoom/src/zstring.h

251 lines
7.6 KiB
C
Raw Normal View History

#ifndef ZSTRING_H
#define ZSTRING_H
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include "tarray.h"
//#define NOPOOLS
class string
{
public:
string () : Chars(NULL) {}
// Copy constructors
string (const string &other) { Chars = NULL; *this = other; }
string (const char *copyStr);
string (const char *copyStr, size_t copyLen);
string (char oneChar);
// Concatenation constructors
string (const string &head, const string &tail);
string (const string &head, const char *tail);
string (const string &head, char tail);
string (const char *head, const string &tail);
string (const char *head, const char *tail);
string (char head, const string &tail);
~string ();
char *GetChars() const { return Chars; }
char &operator[] (int index) { return Chars[index]; }
string &operator = (const string &other);
string &operator = (const char *copyStr);
string operator + (const string &tail) const;
string operator + (const char *tail) const;
string operator + (char tail) const;
friend string operator + (const char *head, const string &tail);
friend string operator + (char head, const string &tail);
string &operator += (const string &tail);
string &operator += (const char *tail);
string &operator += (char tail);
string Left (size_t numChars) const;
string Right (size_t numChars) const;
string Mid (size_t pos, size_t numChars) const;
long IndexOf (const string &substr, long startIndex=0) const;
long IndexOf (const char *substr, long startIndex=0) const;
long IndexOf (char subchar, long startIndex=0) const;
long IndexOfAny (const string &charset, long startIndex=0) const;
long IndexOfAny (const char *charset, long startIndex=0) const;
long LastIndexOf (const string &substr) const;
long LastIndexOf (const char *substr) const;
long LastIndexOf (char subchar) const;
long LastIndexOf (const string &substr, long endIndex) const;
long LastIndexOf (const char *substr, long endIndex) const;
long LastIndexOf (char subchar, long endIndex) const;
long LastIndexOf (const char *substr, long endIndex, size_t substrlen) const;
long LastIndexOfAny (const string &charset) const;
long LastIndexOfAny (const char *charset) const;
long LastIndexOfAny (const string &charset, long endIndex) const;
long LastIndexOfAny (const char *charset, long endIndex) const;
void ToUpper ();
void ToLower ();
void SwapCase ();
void StripLeft ();
void StripLeft (const string &charset);
void StripLeft (const char *charset);
void StripRight ();
void StripRight (const string &charset);
void StripRight (const char *charset);
void StripLeftRight ();
void StripLeftRight (const string &charset);
void StripLeftRight (const char *charset);
void Insert (size_t index, const string &instr);
void Insert (size_t index, const char *instr);
void Insert (size_t index, const char *instr, size_t instrlen);
void ReplaceChars (char oldchar, char newchar);
void ReplaceChars (const char *oldcharset, char newchar);
void StripChars (char killchar);
void StripChars (const char *killchars);
void MergeChars (char merger);
void MergeChars (char merger, char newchar);
void MergeChars (const char *charset, char newchar);
void Substitute (const string &oldstr, const string &newstr);
void Substitute (const char *oldstr, const string &newstr);
void Substitute (const string &oldstr, const char *newstr);
void Substitute (const char *oldstr, const char *newstr);
void Substitute (const char *oldstr, const char *newstr, size_t oldstrlen, size_t newstrlen);
void Format (const char *fmt, ...);
void VFormat (const char *fmt, va_list arglist);
bool IsInt () const;
bool IsFloat () const;
long ToLong (int base=0) const;
unsigned long ToULong (int base=0) const;
double ToDouble () const;
size_t Len() const { return Chars == NULL ? 0 : ((StringHeader *)(Chars - sizeof(StringHeader)))->Len; }
bool IsEmpty() const { return Len() == 0; }
int Compare (const string &other) const { return strcmp (Chars, other.Chars); }
int Compare (const char *other) const { return strcmp (Chars, other); }
int CompareNoCase (const string &other) const { return stricmp (Chars, other.Chars); }
int CompareNoCase (const char *other) const { return stricmp (Chars, other); }
protected:
struct StringHeader
{
#ifndef NOPOOLS
string *Owner; // string this char array belongs to
#endif
size_t Len; // Length of string, excluding terminating null
};
struct Pool;
struct PoolGroup
{
#ifndef NOPOOLS
~PoolGroup ();
Pool *Pools;
Pool *FindPool (char *chars) const;
static StringHeader *GetHeader (char *chars);
#endif
char *Alloc (string *owner, size_t len);
char *Realloc (string *owner, char *chars, size_t newlen);
void Free (char *chars);
};
string (size_t len);
StringHeader *GetHeader () const;
static int FormatHelper (void *data, const char *str, int len);
static void StrCopy (char *to, const char *from, size_t len);
static void StrCopy (char *to, const string &from);
static PoolGroup Pond;
char *Chars;
#ifndef __GNUC__
template<> friend bool NeedsDestructor<string> () { return true; }
template<> friend void CopyForTArray<string> (string &dst, string &src)
{
// When a TArray is resized, we just need to update the Owner, because
// the old copy is going to go away very soon. No need to call the
// destructor, either, because full ownership is transferred to the
// new string.
char *chars = src.Chars;
dst.Chars = chars;
if (chars != NULL)
{
((string::StringHeader *)(chars - sizeof(string::StringHeader)))->Owner = &dst;
}
}
template<> friend void ConstructInTArray<string> (string *dst, const string &src)
{
new (dst) string(src);
}
template<> friend void ConstructEmptyInTArray<string> (string *dst)
{
new (dst) string;
}
#else
template<class string> friend inline void CopyForTArray (string &dst, string &src);
template<class string> friend inline void ConstructInTArray (string *dst, const string &src);
template<class string> friend inline void ConstructEmptyInTArray (string *dst);
#endif
private:
void *operator new (size_t size, string *addr)
{
return addr;
}
void operator delete (void *, string *)
{
}
};
#ifdef __GNUC__
template<> inline bool NeedsDestructor<string> () { return true; }
template<> inline void CopyForTArray<string> (string &dst, string &src)
{
// When a TArray is resized, we just need to update the Owner, because
// the old copy is going to go away very soon. No need to call the
// destructor, either, because full ownership is transferred to the
// new string.
char *chars = src.Chars;
dst.Chars = chars;
if (chars != NULL)
{
((string::StringHeader *)(chars - sizeof(string::StringHeader)))->Owner = &dst;
}
}
template<> inline void ConstructInTArray<string> (string *dst, const string &src)
{
new (dst) string(src);
}
template<> inline void ConstructEmptyInTArray<string> (string *dst)
{
new (dst) string;
}
#endif
namespace StringFormat
{
enum
{
// Format specification flags
F_MINUS = 1,
F_PLUS = 2,
F_ZERO = 4,
F_BLANK = 8,
F_HASH = 16,
F_SIGNED = 32,
F_NEGATIVE = 64,
F_ZEROVALUE = 128,
// Format specification size prefixes
F_HALFHALF = 0x1000, // hh
F_HALF = 0x2000, // h
F_LONG = 0x3000, // l
F_LONGLONG = 0x4000, // ll or I64
F_BIGI = 0x5000 // I
};
typedef int (*OutputFunc)(void *data, const char *str, int len);
int VWorker (OutputFunc output, void *outputData, const char *fmt, va_list arglist);
int Worker (OutputFunc output, void *outputData, const char *fmt, ...);
};
#endif