jedi-academy/code/Ratl/string_vs.h
2013-04-23 16:54:20 +10:00

366 lines
9.8 KiB
C++

////////////////////////////////////////////////////////////////////////////////////////
// RAVEN STANDARD TEMPLATE LIBRARY
// (c) 2002 Activision
//
//
// String
// ------
// Simple wrapper around a char[SIZE] array.
//
//
//
// NOTES:
//
//
//
////////////////////////////////////////////////////////////////////////////////////////
#if !defined(RATL_STRING_VS_INC)
#define RATL_STRING_VS_INC
////////////////////////////////////////////////////////////////////////////////////////
// Includes
////////////////////////////////////////////////////////////////////////////////////////
#if !defined(RATL_COMMON_INC)
#include "ratl_common.h"
#endif
namespace ratl
{
////////////////////////////////////////////////////////////////////////////////////////
// The String Class
////////////////////////////////////////////////////////////////////////////////////////
template<int ARG_CAPACITY>
class string_vs : public ratl_base
{
public:
////////////////////////////////////////////////////////////////////////////////////
// Capacity Enum
////////////////////////////////////////////////////////////////////////////////////
enum
{
CAPACITY = ARG_CAPACITY,
};
private:
////////////////////////////////////////////////////////////////////////////////////
// Data
////////////////////////////////////////////////////////////////////////////////////
#ifdef _DEBUG
char mData[CAPACITY+4];
#else
char mData[CAPACITY];
#endif
void FillTerminator()
{
#ifdef _DEBUG
mData[CAPACITY]='e';
mData[CAPACITY+1]='n';
mData[CAPACITY+2]='d';
mData[CAPACITY+3]=0;
#endif
}
public:
////////////////////////////////////////////////////////////////////////////////////
// Constructor
////////////////////////////////////////////////////////////////////////////////////
string_vs()
{
mData[0]=0;
FillTerminator();
}
#ifdef _DEBUG
~string_vs()
{
//if you hit the below asserts, the end of the string was overwritten
assert(mData[CAPACITY]=='e');
assert(mData[CAPACITY+1]=='n');
assert(mData[CAPACITY+2]=='d');
assert(mData[CAPACITY+3]==0);
}
#endif
////////////////////////////////////////////////////////////////////////////////////
// Copy Constructor
////////////////////////////////////////////////////////////////////////////////////
string_vs(const string_vs<CAPACITY> &o)
{
assert(str::len(o.mData)<CAPACITY);
str::ncpy(mData, o.mData, CAPACITY); // Safe String Copy
mData[CAPACITY-1] = 0; // Make Sure We Have A Null Terminated Str
FillTerminator();
}
////////////////////////////////////////////////////////////////////////////////////
// Copy Constructor
////////////////////////////////////////////////////////////////////////////////////
string_vs(const char *s)
{
assert(str::len(s)<CAPACITY);
str::ncpy(mData, s, CAPACITY); // Safe String Copy
mData[CAPACITY-1] = 0; // Make Sure We Have A Null Terminated Str
FillTerminator();
}
////////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////////
string_vs& operator=(const char *s)
{
assert(str::len(s)<CAPACITY);
str::ncpy(mData, s, CAPACITY); // Safe String Copy
mData[CAPACITY-1] = 0; // Make Sure We Have A Null Terminated Str
FillTerminator();
return *this;
}
////////////////////////////////////////////////////////////////////////////////////
// Access To Raw Array
////////////////////////////////////////////////////////////////////////////////////
char* c_str()
{
return mData;
}
////////////////////////////////////////////////////////////////////////////////////
// Access To Raw Array
////////////////////////////////////////////////////////////////////////////////////
const char* c_str() const
{
return mData;
}
////////////////////////////////////////////////////////////////////////////////////
// Access To Raw Array
////////////////////////////////////////////////////////////////////////////////////
operator const char *()
{
return mData;
}
////////////////////////////////////////////////////////////////////////////////////
// Access To Raw Array
////////////////////////////////////////////////////////////////////////////////////
const char* operator*()
{
return mData;
}
////////////////////////////////////////////////////////////////////////////////////
// How Many Characters Can This Hold
////////////////////////////////////////////////////////////////////////////////////
int capacity() const
{
return CAPACITY;
}
////////////////////////////////////////////////////////////////////////////////////
// Length
////////////////////////////////////////////////////////////////////////////////////
int length() const
{
assert(str::len(mData)<CAPACITY-1);
return str::len(mData);
}
////////////////////////////////////////////////////////////////////////////////////
// Character Bracket Operator
////////////////////////////////////////////////////////////////////////////////////
char operator[](int index)
{
assert(index<CAPACITY);
return mData[index];
}
////////////////////////////////////////////////////////////////////////////////////
// Equality Operator
////////////////////////////////////////////////////////////////////////////////////
bool operator==(const string_vs &o) const
{
if (!Q_stricmp(mData,o.mData))
{
return true;
}
return false;
}
////////////////////////////////////////////////////////////////////////////////////
// InEquality Operator
////////////////////////////////////////////////////////////////////////////////////
bool operator!=(const string_vs &o) const
{
if (str::icmp(mData,o.mData)!=0)
{
return true;
}
return false;
}
////////////////////////////////////////////////////////////////////////////////////
// Compare Less Than
////////////////////////////////////////////////////////////////////////////////////
bool operator<(const string_vs &o) const
{
if (str::icmp(mData,o.mData)<0)
{
return true;
}
return false;
}
////////////////////////////////////////////////////////////////////////////////////
// Compare Greater Than
////////////////////////////////////////////////////////////////////////////////////
bool operator>(const string_vs &o) const
{
if (str::icmp(mData,o.mData)>0)
{
return true;
}
return false;
}
////////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////////
void operator+=(const string_vs &o)
{
if ( (str::len(mData)+o.length())<CAPACITY ) // Only If It Is Safe
{
str::cat(mData, o.c_str());
}
else
{
assert(!"string_vs overflow\n");
}
}
////////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////////
void operator+=(const char *s)
{
if ( (str::len(mData)+str::len(s))<CAPACITY ) // Only If It Is Safe
{
str::cat(mData, s);
}
else
{
assert(!"string_vs overflow\n");
}
}
////////////////////////////////////////////////////////////////////////////////////
// Tokenizer
//
// The string tokenizer class is similar to an iterator in that it essentially
// iterates over all the tokens in the string seperated by a common series of
// delinating sequences. For example: " ,\t\n" would seperate tokens on spaces
// commas, tabs and linefeeds.
//
// Iterating over string tokens is just like normal iteration:
//
// for (string_vs<CAPACITY>::tokenizer it=MyString.begin(" ,\t\n"); it!=MyString.end(); it++)
// {
// const char* token = *it;
// }
//
//
// NOTE: This class is built upon the c library function strtok() which uses a
// static working area, so having multiple tokenizers in multiple threads or just
// plain at the same time is not safe.
//
////////////////////////////////////////////////////////////////////////////////////
class tokenizer
{
enum
{
TOKEN_GAP_LEN = 15,
};
public:
// Constructors
//--------------
tokenizer() : mLoc(0)
{}
tokenizer(const char* t, const char* gap)
{
strncpy(mGap, gap, TOKEN_GAP_LEN); // Safe String Copy
mGap[TOKEN_GAP_LEN-1] = 0; // Make Sure We Have A Null Terminated Str
char* temp = (char*)t;
mLoc = str::tok(temp, mGap);
}
// Assignment Operator
//---------------------
void operator= (const tokenizer &t)
{
mLoc = t.mLoc;
str::cpy(mGap, t.mGap);
}
// Equality Operators
//--------------------
bool operator==(const tokenizer &t) {return (mLoc==t.mLoc);}
bool operator!=(const tokenizer &t) {return !(operator==(t));}
// DeReference Operator
//----------------------
const char* operator*()
{
assert(mLoc);
return mLoc;
}
// Inc & Dec Operators
//--------------------
void operator++(int)
{
assert(mLoc && mGap[0]);
mLoc = str::tok(NULL, mGap);
}
// Data
//------
private:
char* mLoc;
char mGap[TOKEN_GAP_LEN];
};
////////////////////////////////////////////////////////////////////////////////////
// Get An Iterator To The First Token Seperated By Gap
////////////////////////////////////////////////////////////////////////////////////
tokenizer begin(const char* gap)
{
return tokenizer(mData, gap);
}
////////////////////////////////////////////////////////////////////////////////////
// The Invalid Iterator, Use As A Stop Condition In Your For Loops
////////////////////////////////////////////////////////////////////////////////////
tokenizer end()
{
return tokenizer();
}
};
}
//fixme get rid of these
typedef ratl::string_vs<256> TString_vs;
typedef ratl::string_vs<128> TUIString_vs;
#endif