// Copyright (C) 1999-2005 Open Source Telecom Corporation. // // 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 #endif #ifndef CCXX_STRCHAR_H_ #include #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 * @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 * @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