blob: 15aa09470bca222cef52bd547833defc66f61f8b [file] [log] [blame]
// Copyright (C) 1999-2005 Open Source Telecom Corporation.
// Copyright (C) 2006-2010 David Sugar, Tycho Softworks.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// 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 for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//
// As a special exception, you may use this file as part of a free software
// library without restriction. Specifically, if other files instantiate
// templates or use macros or inline functions from this file, or you compile
// this file and link it with other files to produce an executable, this
// file does not by itself cause the resulting executable to be covered by
// the GNU General Public License. This exception does not however
// invalidate any other reasons why the executable file might be covered by
// the GNU General Public License.
//
// This exception applies only to the code released under the name GNU
// Common C++. If you copy code from other releases into a copy of GNU
// Common C++, as the General Public License permits, the exception does
// not apply to the code that you add in this way. To avoid misleading
// anyone as to the status of such modified files, you must delete
// this exception notice from them.
//
// If you write modifications of your own for GNU Common C++, it is your choice
// whether to permit this exception to apply to your modifications.
// If you do not wish that, delete this exception notice.
//
/**
* @file string.h
* @short Common C++ generic string class
**/
#ifndef CCXX_STRING_H_
#define CCXX_STRING_H_
#ifndef CCXX_MISSING_H_
#include <cc++/missing.h>
#endif
#ifndef CCXX_STRCHAR_H_
#include <cc++/strchar.h>
#endif
#ifdef CCXX_NAMESPACES
namespace ost {
#endif
class MemPager;
/**
* This is a generic and portable string class. It uses optimized
* memory allocation strategies to efficiently handle smaller string
* content by grouping strings into 32 byte aligned slots that can
* be re-allocated from a free list directly.
*
* While meant to cover the basic functionality of the ANSI C++
* string class in form and function, this class offers some important
* enhancements, including the ability to derive class type specific
* versions of itself. The latter might be used to derive a unicode
* string, a string for data and time data types, or to add case
* insensitive comparisons, for example.
*
* @author David Sugar <dyfet@ostel.com>
* @short Generic string class.
*/
class __EXPORT String
{
protected:
static const unsigned minsize;
static const unsigned slotsize;
static const unsigned pagesize;
static const unsigned slotlimit;
static const unsigned slotcount;
friend class StringObject;
private:
friend class MemPager;
static MemPager *pager;
static char **idx;
#ifdef CCXX_PACKED
#pragma pack(1)
#endif
union {
struct {
char *text;
size_t size;
size_t length;
} bigstring;
struct {
char text[(sizeof(char *) + (sizeof(size_t) * 2) + 1)];
char length : 6;
bool big : 1;
} ministring;
} content;
#ifdef CCXX_PACKED
#pragma pack()
#endif
protected:
/**
* Determine if string is allocated in local variable or an
* external reference.
*
* @return true if external heap is used.
*/
inline bool isBig(void) const
{return content.ministring.big;};
/**
* Set the content of the string variable to the specified
* string value, and use smart re-allocation strategies if
* appropriate to shrink the size of the variable.
*
* @param str string to set.
* @param len length of string if passed.
*/
const char *set(const char *str, size_t len = 0);
/**
* Set the content of the string variable to that of another
* variable. Uses the string set method.
*
* @param str string to copy from.
*/
void set(const String &str);
#ifdef HAVE_SNPRINTF
/**
* Set the content of the string variable to that of a
* formatted printf style string.
*
* @param size of string data to set.
* @param format of string to write into object.
*/
const char *set(size_t size, const char *format, ...);
#endif
/**
* Impliment the copy constructor, used internally. Will always
* create a minimum sized string allocation.
*
* @param str string to copy from.
*/
void copy(const String &str);
/**
* Used to initialize a string object.
*/
void init(void);
/**
* Used to fetch memory, if needed, based on the size, from the
* pager, or the system heap.
*
* @return string pointer to space.
* @param size of space needed.
*/
static char *getSpace(size_t size);
/**
* Set the size of allocated space in the string variable
* (capacity) to a known value. The value is recomputed and
* adjusted based on allocation method.
*
* @param size in bytes.
*/
size_t setSize(size_t size);
/**
* Set the length value of the string content.
*
* @param len size in bytes.
*/
void setLength(size_t len);
/**
* A derivable low level comparison operator. This can be used
* to create custom comparison data types in derived string
* classes.
*
* @return 0 if match, or value for ordering.
* @param text text to compare.
* @param len length of text to compare.
* @param index offset from start of string, used in searchs.
*/
virtual int compare(const char *text, size_t len = 0, size_t index = 0) const;
/**
* An internal method used to search for a substring starting at
* a known offset. Used by find and count methods.
*
* @return npos if fails, or offset to text found.
* @param text text to search for.
* @param clen length of search text.
* @param offset offset to start from.
*/
size_t search(const char *text, size_t clen = 0, size_t offset = 0) const;
public:
static const size_t npos;
typedef size_t size_type;
/**
* Construct an empty string.
*/
String();
/**
* Copy constructor.
*
* @param original string to copy from.
*/
String(const String &original);
/**
* Create a string from a cstring.
*
* @param str text to set with.
*/
String(const char *str);
/**
* Create a String from std::string.
*
* @param string from std::string to copy from.
*/
String(std::string string);
/**
* Create a new string from a subset of another string.
*
* @param str reference of source string.
* @param offset offset to start of data in prior string.
* @param len length of our substring.
*/
String(const String &str, size_t offset, size_t len = npos);
#ifdef HAVE_SNPRINTF
/**
* Create a string from formatted text input.
*
* @param size to allocate for our new string.
* @param format of data to input.
*/
String(size_t size, const char *format, ...);
#else
/**
* Create a string of a known size, and optionally fill with
* content.
*
* @param count size to allocate for our new string.
* @param str content to put into it.
*/
String(size_t count, const char *str);
#endif
/**
* Fill a new string with character data.
*
* @param count size of new string.
* @param fill char to fill string with.
*/
String(size_t count, const char fill = ' ');
/**
* Destroy the string...
*/
virtual ~String();
/**
* Get a string pointer to string content based on an indexed
* offset. A NULL is returned if the index is outsize of range.
*
* @return string content or NULL if invalid index.
* @param index
*/
const char *getIndex(size_t index) const;
/**
* Get the text of a string.
*
* @return string content.
*/
char *getText(void) const;
/**
* Get the value of a string.
*
* @return string value as number.
*/
long getValue(long defvalue = 0l) const;
/**
* Get the bool flag of a string.
*
* @return boolean value.
*/
bool getBool(bool defbool = false) const;
/**
* Get the assigned length of string.
*
* @return string length.
*/
const size_t getLength(void) const;
/**
* Get the allocation size of the string variable.
*
* @return allocation size.
*/
const size_t getSize(void) const;
/**
* Return true if string is empty.
*
* @return true if string is empty string.
*/
bool isEmpty(void) const;
/**
* Re-allocate buffer space for string.
*
* @param size new size to use.
*/
void resize(size_t size);
/**
* Clear the contents of the entire string.
*/
void clear(void);
/**
* Return a character at a known offset.
*
* @return character at offset.
*/
char at(ssize_t offset) const;
/**
* Count the number of occurences of a specific string within
* our string.
*
* @return count of instances.
* @param s string to test.
* @param offset offset to start from.
*/
unsigned count(const String &s, size_t offset = 0) const;
/**
* Count the number of occurrences of a specific text pattern
* within our string.
*
* @return count of instances.
* @param s text pattern to find
* @param offset offset to start from.
* @param len length of text pattern if specified.
*/
unsigned count(const char *s, size_t offset = 0, size_t len = 0) const;
/**
* Extract a new string as a token from the current string.
*
* @return string containing token.
* @param delim deliminator characters.
* @param offset offset to start from.
*/
String token(const char *delim = " \t\n\r", size_t offset = 0);
/**
* Find the index to the nth instance of a substring in our string.
*
* @return index of found substring.
* @param s string to search for.
* @param offset offset to start at.
* @param instance instance to look for.
*/
size_t find(const String &s, size_t offset = 0, unsigned instance = 1) const;
/**
* Find last occurence of a substring in our string.
*
* @return index of last instance found,
* @param s string to search for.
* @param offset offset to start from.
*/
size_t rfind(const String &s, size_t offset = 0) const;
/**
* Find the index to the nth instance of text in our string.
*
* @return index of found substring.
* @param s string to search for.
* @param offset offset to start at.
* @param len size of string text.
* @param count instance to look for.
*/
size_t find(const char *s, size_t offset = 0, size_t len = 0, unsigned count = 1) const;
/**
* Find last occurence of a text in our string.
*
* @return index of last instance found,
* @param s string to search for.
* @param offset offset to start from.
* @param len size of string to look for.
*/
size_t rfind(const char *s, size_t offset = 0, size_t len = 0) const;
/**
* Trim trailing characters from a string.
*
* @param cs list of chars to trim.
*/
inline void trim(const char *cs)
{setLength(strtrim(cs, getText(), getLength()));};
/**
* Chop leading characters from a string.
*
* @param cs list of chars to chop.
*/
inline void chop(const char *cs)
{setLength(strchop(cs, getText(), getLength()));};
/**
* Strip lead and trailing characters from a string.
*
* @param cs list of chars to strip.
*/
void strip(const char *cs);
/**
* Chop n leading characters from a string.
*
* @param chars count to chop.
*/
inline void chop(size_t chars)
{erase(0, chars);};
/**
* Trim n trailing characters from a string.
*
* @param count number of bytes to trim.
*/
void trim(size_t count);
/**
* Erase a portion of string.
*
* @param start starting index to erase from.
* @param len number of characters to erase.
*/
void erase(size_t start, size_t len = npos);
/**
* Insert text into a string.
*
* @param start starting offset to insert at.
* @param text text to insert.
* @param len size of text to insert.
*/
void insert(size_t start, const char *text, size_t len = 0);
/**
* Insert other string into our string.
*
* @param start string offset to insert at.
* @param str string to insert.
*/
void insert(size_t start, const String &str);
/**
* Replace text at a specific position in the string with new
* text.
*
* @param start starting offset to replace at.
* @param len length of text to remove.
* @param text text to replace with.
* @param count size of replacement text.
*/
void replace(size_t start, size_t len, const char *text, size_t count = 0);
/**
* Replace text at a specific position in the string with new
* string,
*
* @param start starting offset to replace at.
* @param len length of text to remove.
* @param string reference to replace with.
*/
void replace(size_t start, size_t len, const String &string);
/**
* A more convenient version of find for nth occurences, by
* putting the instance first.
*
* @param instance nth instance to look for.
* @param text text to look for.
* @param offset offset to start at.
* @param len length of text.
*/
inline size_t find(unsigned instance, const char *text, size_t offset = 0, size_t len = 0) const
{return find(text, offset, len, instance);};
/**
* A more convenient version of find for nth occurences, by
* putting the instance first.
*
* @param instance nth instance to look for.
* @param string reference to look for.
* @param offset offset to start at.
*/
inline size_t find(unsigned instance, const String &string, size_t offset = 0) const
{return find(string, offset, instance);};
/**
* Return a new string that contains a specific substring of the
* current string.
*
* @return new string.
* @param start starting offset for extracted substring.
* @param len length of substring.
*/
inline String substr(size_t start, size_t len) const
{return String(*this, start, len);};
/**
* Return an indexed string based on the index, such as from a
* find. If out of range, a NULL string is returned.
*
* @return pointer to string data from our string,
* @param ind index or offset to use.
*/
inline const char *(index)(size_t ind) const
{return getIndex(ind);};
/**
* Reduce the size of the string allocation to the minimum
* needed based on the current effective length.
*/
inline void compact(void)
{resize(getLength() + 1);};
/**
* Old ANSI C++ compatible string pointer extraction.
*
* @return string data.
*/
inline char *c_str(void) const
{return getText();};
/**
* Get our string data through dereference operator.
*
* @return string data.
*/
inline operator char *() const
{return getText();};
/**
* Logical test for string empty.
*
* @return true if is empty.
*/
inline bool operator!(void) const
{return isEmpty();};
/**
* Alternate get text method.
*
* @return string data.
*/
inline char *text(void) const
{return getText();};
/**
* Alternate get text method.
*
* @return string data.
*/
inline char *data(void) const
{return getText();};
/**
* Get length as if null terminated string.
*
* @return cstring length.
*/
inline size_t length(void) const
{return strlen(getText());};
/**
* Get actual length of string data.
*
* @return actual size of string.
*/
inline size_t size(void) const
{return getLength();};
/**
* Get space allocated to hold current string.
*
* @return space of memory buffer from heap or local.
*/
inline size_t capacity(void) const
{return getSize();};
/**
* Return true if string is empty.
*/
bool empty(void) const
{return isEmpty();};
/**
* Append text to the end of the current string.
*
* @param str text to append.
* @param count size of text to append.
*/
void append(const char *str, size_t count = 0);
#ifdef HAVE_SNPRINTF
/**
* Append formatted text to the end of the current string.
*
* @param size size of text to append.
* @param format of data to append.
*/
void append(size_t size, const char *format, ...);
#endif
/**
* Append text into the current string.
*
* @param str text to append.
* @param offset offset to overlay.
* @param count size of text to append.
*/
void append(const char *str, size_t offset, size_t count);
/**
* Add a character to the end of a string.
*
* @param c char to add.
*/
void add(char c);
/**
* Append string to the end of the current string.
*
* @param str string to append.
*/
void append(const String &str);
/**
* Extract a character by array indexing.
*
* @return character code.
*/
inline const char operator[](unsigned ind) const
{return at(ind);};
/**
* Assign our string for c string.
*/
inline const char *operator =(const char *str)
{return set(str);};
/**
* Add two strings and return a temporary object.
*/
friend __EXPORT String operator+(const String &s1, const String &s2);
friend __EXPORT String operator+(const String &s1, const char *s2);
friend __EXPORT String operator+(const char *s1, const String &s2);
friend __EXPORT String operator+(const String &s1, const char c2);
friend __EXPORT String operator+(const char c1, const String &s2);
/**
* Append operator.
*/
inline String &operator+=(const String &str)
{append(str); return *this;};
/**
* Append operator.
*/
inline String &operator+=(char c)
{add(c); return *this;};
/**
* Append operator.
*/
inline String &operator+=(const char *str)
{append(str); return *this;};
/**
* Append operator.
*/
inline String &operator+=(const std::string &str)
{append(str.c_str()); return *this;};
/**
* Fetch input from a std::istream into the current string
* variable until either the string variable is filled (based on
* current length) or the deliminator is read.
*
* @param is stream to read.
* @param str string to save into.
* @param delim deliminator to use.
* @param size optional size limitor.
*/
friend __EXPORT std::istream &getline(std::istream &is, String &str, char delim = '\n', size_t size = 0);
/**
* Stream the content of our string variable directly to a C++
* streaming source.
*/
friend __EXPORT std::ostream &operator<<(std::ostream &os, const String &str);
/**
* Stream input into our variable.
*/
inline friend std::istream &operator>>(std::istream &is, String &str)
{return getline(is, str);};
#ifdef HAVE_SNPRINTF
/**
* Print values directly into a string variable.
*
* @return character count.
* @param str object reference to use.
* @param size of string required.
* @param format of data.
*/
friend __EXPORT int strprintf(String &str, size_t size, const char *format, ...);
#endif
bool operator<(const String &str) const;
bool operator<(const char *str) const;
bool operator>(const String &str) const;
bool operator>(const char *str) const;
bool operator<=(const String &str) const;
bool operator<=(const char *str) const;
bool operator>=(const String &str) const;
bool operator>=(const char *str) const;
bool operator==(const String &str) const;
bool operator==(const char *str) const;
bool operator!=(const String &str) const;
bool operator!=(const char *str) const;
#ifdef HAVE_SNPRINTF
/**
* Append operator
*/
inline String &operator+=(int i)
{append(16, "%d", i); return *this;};
inline String &operator+=(unsigned int i)
{append(16, "%u", i); return *this;};
inline String &operator+=(long l)
{append(16, "%l", l); return *this;};
inline String &operator+=(unsigned long l)
{append(16, "%ul", l); return *this;};
inline String &operator+=(float f)
{append(32, "%f", f); return *this;};
inline String &operator+=(double d)
{append(32, "%f", d); return *this;};
inline String &operator+=(short s)
{append(8, "%hd", s); return *this;};
inline String &operator+=(unsigned short s)
{append(8, "%hu", s); return *this;};
/**
* Assignment operator.
*/
inline String &operator=(int i)
{set(16, "%d", i); return *this;};
inline String &operator=(unsigned int i)
{set(16, "%u", i); return *this;};
inline String &operator=(long l)
{set(16, "%l", l); return *this;};
inline String &operator=(unsigned long l)
{set(16, "%ul", l); return *this;};
inline String &operator=(float f)
{set(32, "%f", f); return *this;};
inline String &operator=(double d)
{set(32, "%f", d); return *this;};
inline String &operator=(short s)
{set(8, "%hd", s); return *this;};
inline String &operator=(unsigned short s)
{set(8, "%hu", s); return *this;};
#endif
inline String &operator=(const String &original)
{copy(original); return *this;};
/**
* Test if string is contained in our string.
*/
bool operator*=(const String &str) const;
/**
* Test if text is contained in our string.
*/
bool operator*=(const char *str) const;
};
class __EXPORT SString : public String, protected std::streambuf, public std::ostream
{
protected:
/**
* This is the streambuf function that actually outputs the data
* to the string. Since all output should be done with the standard
* ostream operators, this function should never be called directly.
*/
int overflow(int c);
public:
/**
* Create an empty streamable string ready for input.
*/
SString();
/**
* Copy constructor
*/
SString(const SString &from);
/**
* Cancel out the object.
*/
~SString();
};
/**
* The StringObject class is used to derive subclasses that use the
* String managed memory pool for all space allocations by overriding
* new and delete operators. Due to size limits, StringObject should
* not hold very large objects.
*
* @author David Sugar <dyfet@ostel.com>
* @short Objects managed in reusable String memory pools
*/
class __EXPORT StringObject
{
public:
/**
* Create a new object in string managed space.
*/
void *operator new(size_t size) NEW_THROWS;
/**
* Delete object from string managed space.
*/
void operator delete(void *obj);
};
#ifdef CCXX_NAMESPACES
}
#endif
#endif