//------------------------------------------------------------------------------
// emString.h
//
// Copyright (C) 2004-2011,2014,2020 Oliver Hamann.
//
// Homepage: http://eaglemode.sourceforge.net/
//
// This program is free software: you can redistribute it and/or modify it under
// the terms of the GNU General Public License version 3 as published by the
// Free Software Foundation.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU General Public License version 3 for
// more details.
//
// You should have received a copy of the GNU General Public License version 3
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//------------------------------------------------------------------------------
#ifndef emString_h
#define emString_h
#ifndef emStd1_h
#include <emCore/emStd1.h>
#endif
//==============================================================================
//================================== emString ==================================
//==============================================================================
class emString {
public:
// Class for a dynamically allocated null-terminated character string
// with copy-on-write behavior. This string type is designed to minimize
// memory consumption. That means, each change of the length requires
// reallocation. If you plan to perform many length-changing operations
// on a string, you may decide to do it with an emArray<char> for a
// better performance.
emString();
// Construct an empty string.
emString(const emString & s);
// Construct a copied string.
// Arguments:
// s - The string to be copied.
emString(const char * p);
// Construct a copied string.
// Arguments:
// p - The null-terminated string to be copied.
emString(const char * p, int len);
// Construct a copied string.
// Arguments:
// p - The string to be copied.
// len - Number of bytes in p.
emString(const char * p, int len, const char * p2, int len2);
// Construct a string as a concatenated copy of two strings.
// Arguments:
// p - First source string.
// len - Number of bytes in p.
// p2 - Second source string.
// len2 - Number of bytes in p2.
emString(char c, int len=1);
// Construct a string by filling it with a byte.
// Arguments:
// c - The byte to be used for filling.
// len - The length of the resulting string.
~emString();
// Destructor.
static emString Format(const char * format, ...) EM_FUNC_ATTR_PRINTF(1);
static emString VFormat(const char * format, va_list args);
// This function creates a formatted string.
// Arguments:
// format - The format (like with printf).
// ... - Arguments to the format (like with printf).
// Returns: The formatted string.
emString & operator = (const emString & s);
emString & operator = (const char * p);
emString & operator = (char c);
// Copy a string or a byte to this string.
int GetCount() const;
int GetLen() const;
// Get the number of bytes in this string, excluding the
// terminating null. This really counts the bytes using strlen.
operator const char * () const;
const char * Get() const;
// Get a pointer to the internal null-terminated string for
// reading. At least because of the copy-on-write feature, the
// pointer is valid only until calling any non-const method or
// operator on this string, or giving this string as a non-const
// argument to any call in the world. Hint: Even methods like
// Add, Insert, Replace and GetSubString may make shallow
// copies, like the copy operator and copy constructor do.
char operator [] (int index) const;
char Get(int index) const;
// Get one byte from this string.
// Arguments:
// index - The index of the desired byte. This must be within
// the range of 0 to GetLen().
// Returns: The byte.
char * GetWritable();
char & GetWritable(int index);
// Like Get() and Get(index), but for modifying the bytes.
// There is no non-const version of the operator [], because
// compilers would make use of it too often. The rules for the
// validity of the pointer or reference are the same as with
// Get(), but modification is allowed only until doing something
// which could make a shallow copy of this string.
char * SetLenGetWritable(int len);
// Like GetWritable(), but even prepare for a new length of the
// string.
// Arguments:
// len - The length of the string you plan to produce.
// Returns:
// A pointer to the internal null-terminated string buffer for
// writing. The buffer contains up to len bytes of the
// original string, then there is a null, then there may be
// garbage (if len>GetLen()+1), and in any case there is a
// null at the end (at index len). You may modify all
// bytes within the index range of 0 to len-1.
void Add(const emString & s);
void Add(const char * p);
void Add(const char * p, int len);
void Add(char c, int len=1);
emString & operator += (const emString & s);
emString & operator += (const char * p);
emString & operator += (char c);
// Add a copy of something to the end of this string. Source and
// target memory may overlap.
// Arguments:
// s - A source string.
// p - A source string, null-terminated if len not given.
// c - A source byte.
// len - Length of string p, or how often to add byte c.
emString operator + (const emString & s) const;
emString operator + (const char * p) const;
emString operator + (char c) const;
friend emString operator + (const char * p, const emString & s);
friend emString operator + (char c, const emString & s);
// Add strings...
void Insert(int index, const emString & s);
void Insert(int index, const char * p);
void Insert(int index, const char * p, int len);
void Insert(int index, char c, int len=1);
// Insert a copy of something somewhere in this string. Source
// and target memory may overlap.
// Arguments:
// index - Position of insertion. This should be within the
// range of 0 to GetLen(), otherwise it is clipped
// accordingly.
// s - A source string to be copied for insertion.
// p - A source string to be copied for insertion,
// null-terminated if len not given.
// c - A source byte to be copied for insertion.
// len - Length of string p, or how often to insert
// byte c.
void Replace(int index, int exLen, const emString & s);
void Replace(int index, int exLen, const char * p);
void Replace(int index, int exLen, const char * p, int len);
void Replace(int index, int exLen, char c, int len=1);
// Replace something in this string by a copy of something.
// Source and target memory may overlap.
// Arguments:
// index - Position of replacement. This should be within the
// range of 0 to GetLen()-exLen, otherwise index and
// exLen are clipped accordingly.
// exLen - Number of bytes to be removed.
// s - A source string to be copied for insertion.
// p - A source string to be copied for insertion,
// null-terminated if len not given.
// c - A source byte to be copied for insertion.
// len - Length of string p, or how often to insert
// byte c.
emString GetSubString(int index, int len) const;
// Get a sub-string.
// Arguments:
// index - Index of the first byte of the sub-string.
// This should be within the range of 0 to
// GetLen()-len, otherwise index and len are clipped
// accordingly.
// len - Length of the sub-string.
// Returns: The sub-string.
emString Extract(int index, int len);
// Like GetSubString, but remove the sub-string from this
// string.
void Remove(int index, int len=1);
// Like Extract, but without returning the sub-string.
void Clear();
// Empty this string.
bool IsEmpty() const;
// Ask whether this string is empty.
bool operator == (const emString & s) const;
bool operator != (const emString & s) const;
bool operator <= (const emString & s) const;
bool operator >= (const emString & s) const;
bool operator < (const emString & s) const;
bool operator > (const emString & s) const;
bool operator == (const char * p) const;
bool operator != (const char * p) const;
bool operator <= (const char * p) const;
bool operator >= (const char * p) const;
bool operator < (const char * p) const;
bool operator > (const char * p) const;
friend bool operator == (const char * p, const emString & s);
friend bool operator != (const char * p, const emString & s);
friend bool operator <= (const char * p, const emString & s);
friend bool operator >= (const char * p, const emString & s);
friend bool operator < (const char * p, const emString & s);
friend bool operator > (const char * p, const emString & s);
// Compare null-terminated strings using strcmp.
unsigned int GetDataRefCount() const;
// Get number of references to the data behind this string.
void MakeNonShared();
// This must be called before handing the string to another
// thread.
private:
struct SharedData {
unsigned int RefCount;
char Buf[sizeof(unsigned int)];
};
emString(SharedData * d);
void FreeData();
void MakeWritable();
void PrivRep(int oldLen, int index, int exLen, const char * p, int len);
void PrivRep(int oldLen, int index, int exLen, char c, int len);
static SharedData EmptyData;
SharedData * Data;
};
#ifndef EM_NO_DATA_EXPORT
inline emString::emString()
{
Data=&EmptyData;
}
#endif
inline emString::emString(const emString & s)
{
Data=s.Data;
Data->RefCount++;
}
inline emString::~emString()
{
if (!--Data->RefCount) FreeData();
}
inline emString & emString::operator = (const emString & s)
{
s.Data->RefCount++;
if (!--Data->RefCount) FreeData();
Data=s.Data;
return *this;
}
inline int emString::GetCount() const
{
return strlen(Data->Buf);
}
inline int emString::GetLen() const
{
return strlen(Data->Buf);
}
inline emString::operator const char * () const
{
return Data->Buf;
}
inline const char * emString::Get() const
{
return Data->Buf;
}
inline char emString::operator [] (int index) const
{
return Data->Buf[index];
}
inline char emString::Get(int index) const
{
return Data->Buf[index];
}
inline char * emString::GetWritable()
{
if (Data->RefCount>1) MakeWritable();
return Data->Buf;
}
inline char & emString::GetWritable(int index)
{
if (Data->RefCount>1) MakeWritable();
return Data->Buf[index];
}
inline emString & emString::operator += (const emString & s)
{
Add(s);
return *this;
}
inline emString & emString::operator += (const char * p)
{
Add(p);
return *this;
}
inline emString & emString::operator += (char c)
{
Add(c);
return *this;
}
#ifndef EM_NO_DATA_EXPORT
inline void emString::Clear()
{
if (!--Data->RefCount) FreeData();
Data=&EmptyData;
}
#endif
inline bool emString::IsEmpty() const
{
return !*Data->Buf;
}
inline bool emString::operator == (const emString & s) const
{
return strcmp(Data->Buf,s.Data->Buf)==0;
}
inline bool emString::operator != (const emString & s) const
{
return strcmp(Data->Buf,s.Data->Buf)!=0;
}
inline bool emString::operator <= (const emString & s) const
{
return strcmp(Data->Buf,s.Data->Buf)<=0;
}
inline bool emString::operator >= (const emString & s) const
{
return strcmp(Data->Buf,s.Data->Buf)>=0;
}
inline bool emString::operator < (const emString & s) const
{
return strcmp(Data->Buf,s.Data->Buf)<0;
}
inline bool emString::operator > (const emString & s) const
{
return strcmp(Data->Buf,s.Data->Buf)>0;
}
inline bool emString::operator == (const char * p) const
{
return strcmp(Data->Buf,p)==0;
}
inline bool emString::operator != (const char * p) const
{
return strcmp(Data->Buf,p)!=0;
}
inline bool emString::operator <= (const char * p) const
{
return strcmp(Data->Buf,p)<=0;
}
inline bool emString::operator >= (const char * p) const
{
return strcmp(Data->Buf,p)>=0;
}
inline bool emString::operator < (const char * p) const
{
return strcmp(Data->Buf,p)<0;
}
inline bool emString::operator > (const char * p) const
{
return strcmp(Data->Buf,p)>0;
}
inline bool operator == (const char * p, const emString & s)
{
return strcmp(p,s.Data->Buf)==0;
}
inline bool operator != (const char * p, const emString & s)
{
return strcmp(p,s.Data->Buf)!=0;
}
inline bool operator <= (const char * p, const emString & s)
{
return strcmp(p,s.Data->Buf)<=0;
}
inline bool operator >= (const char * p, const emString & s)
{
return strcmp(p,s.Data->Buf)>=0;
}
inline bool operator < (const char * p, const emString & s)
{
return strcmp(p,s.Data->Buf)<0;
}
inline bool operator > (const char * p, const emString & s)
{
return strcmp(p,s.Data->Buf)>0;
}
inline void emString::MakeNonShared()
{
MakeWritable();
}
inline emString::emString(SharedData * d)
{
Data=d;
}
#endif