// JLStr.h: Simple string type
#ifndef INCL_JLSTR_H
#define INCL_JLSTR_H
#include <string>
#include "JLRefPtr.h"
#include <assert.h>
using namespace std;
///////////////////////////////////////////////////////////////
// Simple string class inherits from "string".
//
// This was originally done to avoid a bug in MSVC++,
// because using string, which is really a specialization
// of basic_string<>, results in template names that are
// too long for MSVC++, making it crash.
//
// This has evolved to be a string class with some additional
// function, such as reference-counting, and also provides
// a single point for optimization of memory allocation.
///////////////////////////////////////////////////////////////
class JLStr : public string, public RefCount
{
public:
// ctor
JLStr() { makeValid(); }
JLStr(const char* s) : string(s) { makeValid(); }
JLStr(const JLStr& s) : string(s) { makeValid(); }
JLStr(const string& s) : string(s) { makeValid(); }
JLStr(size_type st, char c) : string(st, c) { makeValid(); }
JLStr(const_iterator iter1, const_iterator iter2) : string(iter1, iter2) { makeValid(); }
~JLStr() { assertValid(); makeInvalid(); }
// assignment must be passed through explicitly
JLStr& operator=(const JLStr& rhs)
{
assertValid();
rhs.assertValid();
string::operator=(rhs);
return *this;
}
JLStr& operator=(const string& rhs)
{
assertValid();
string::operator=(rhs);
return *this;
}
JLStr& operator=(const char* rhs)
{
assertValid();
string::operator=(rhs);
return *this;
}
JLStr& operator=(char rhs)
{
assertValid();
string::operator=(rhs);
return *this;
}
// Additional operations
// Convert and deconvert '\' escapes
JLStr Escape(bool keepDoubleBackslash = false) const;
JLStr UnEscape() const;
// Remove leading chars
JLStr StripLeading(
char stripChar,
int maxToStrip = INT_MAX
) const;
// Remove trailing chars
JLStr StripTrailing(
char stripChar,
int maxToStrip = INT_MAX
) const;
// Trim characters from front and back
JLStr Trim(
char charToTrim = ' ',
int maxToStrip = INT_MAX
) const;
// Truncate a string (extract a substring)
JLStr Truncate(int offset, int maxlen) const;
// Empty static string useful for default reference arguments
static JLStr Empty;
private:
// For debugging -- checks against use of invalid object and bitwise copy
#ifndef NDEBUG
enum { MAGIC = 0x8723 };
unsigned short magic;
JLStr* thisPtr; // guard against bitwise assignment
#endif
void assertValid() const { assert(magic == MAGIC && thisPtr == this); };
void makeValid() {
#ifndef NDEBUG
magic = MAGIC;
thisPtr = this;
#endif
}
void makeInvalid() {
#ifndef NDEBUG
magic = 0;
#endif
}
};
typedef refcnt_ptr<JLStr> JLStrRef;
typedef refcnt_cptr<JLStr> JLStrCRef;
// Global operators that accept JLStr and produce JLStr
inline JLStr operator + (const JLStr& lhs, const JLStr& rhs)
{
return JLStr(lhs).append(rhs);
}
inline JLStr operator + (const JLStr& lhs, const char* rhs)
{
return JLStr(lhs).append(rhs);
}
inline JLStr operator + (const char* lhs, const JLStr& rhs)
{
return JLStr(lhs).append(rhs);
}
inline JLStr operator + (const JLStr& lhs, const string& rhs)
{
return JLStr(lhs).append(rhs);
}
inline JLStr operator + (const string& lhs, const JLStr& rhs)
{
return JLStr(lhs).append(rhs);
}
#endif