yate/yateclass.h

8810 lines
270 KiB
C++

/**
* yateclass.h
* This file is part of the YATE Project http://YATE.null.ro
*
* Base classes and types, not related to the engine or telephony
*
* Yet Another Telephony Engine - a fully featured software PBX and IVR
* Copyright (C) 2004-2014 Null Team
*
* This software is distributed under multiple licenses;
* see the COPYING file in the main directory for licensing
* information for this specific distribution.
*
* This use of this software may be subject to additional restrictions.
* See the LEGAL file in the main directory for details.
*
* 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.
*/
#ifndef __YATECLASS_H
#define __YATECLASS_H
#ifndef __cplusplus
#error C++ is required
#endif
#include <limits.h>
#include <sys/types.h>
#include <stddef.h>
#include <unistd.h>
#include <errno.h>
#include <stdarg.h>
#ifndef _WORDSIZE
#if defined(__arch64__) || defined(__x86_64__) \
|| defined(__amd64__) || defined(__ia64__) \
|| defined(__alpha__) || defined(__sparcv9) || defined(__mips64)
#define _WORDSIZE 64
#else
#define _WORDSIZE 32
#endif
#endif
#ifndef _WINDOWS
#if defined(WIN32) || defined(_WIN32)
#define _WINDOWS
#endif
#endif
#ifdef _WINDOWS
#include <windows.h>
#include <io.h>
#include <direct.h>
/**
* Windows definitions for commonly used types
*/
typedef signed __int8 int8_t;
typedef unsigned __int8 u_int8_t;
typedef unsigned __int8 uint8_t;
typedef signed __int16 int16_t;
typedef unsigned __int16 u_int16_t;
typedef unsigned __int16 uint16_t;
typedef signed __int32 int32_t;
typedef unsigned __int32 u_int32_t;
typedef unsigned __int32 uint32_t;
typedef signed __int64 int64_t;
typedef unsigned __int64 u_int64_t;
typedef unsigned __int64 uint64_t;
typedef int pid_t;
typedef int socklen_t;
typedef unsigned long in_addr_t;
#ifndef strcasecmp
#define strcasecmp _stricmp
#endif
#ifndef strncasecmp
#define strncasecmp _strnicmp
#endif
#define vsnprintf _vsnprintf
#define snprintf _snprintf
#define strdup _strdup
#define strtoll _strtoi64
#define strtoull _strtoui64
#define open _open
#define dup2 _dup2
#define read _read
#define write _write
#define close _close
#define getpid _getpid
#define chdir _chdir
#define mkdir(p,m) _mkdir(p)
#define unlink _unlink
#define llabs _abs64
#define O_RDWR _O_RDWR
#define O_RDONLY _O_RDONLY
#define O_WRONLY _O_WRONLY
#define O_APPEND _O_APPEND
#define O_BINARY _O_BINARY
#define O_EXCL _O_EXCL
#define O_CREAT _O_CREAT
#define O_TRUNC _O_TRUNC
#define O_NOCTTY 0
#define S_IRUSR _S_IREAD
#define S_IWUSR _S_IWRITE
#define S_IXUSR 0
#define S_IRWXU (_S_IREAD|_S_IWRITE)
#ifdef LIBYATE_EXPORTS
#define YATE_API __declspec(dllexport)
#else
#ifndef LIBYATE_STATIC
#define YATE_API __declspec(dllimport)
#endif
#endif
#define FMT64 "%I64d"
#define FMT64U "%I64u"
#else /* _WINDOWS */
#include <sys/time.h>
#include <sys/socket.h>
#if defined(__FreeBSD__)
#include <netinet/in_systm.h>
#endif
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <netdb.h>
/**
* Non-Windows definitions for commonly used types
*/
#ifndef SOCKET
typedef int SOCKET;
#endif
#ifndef HANDLE
typedef int HANDLE;
#endif
#ifndef O_BINARY
#define O_BINARY 0
#endif
#if _WORDSIZE == 64 && !defined(__APPLE__)
#define FMT64 "%ld"
#define FMT64U "%lu"
#else
#define FMT64 "%lld"
#define FMT64U "%llu"
#endif
#endif /* ! _WINDOWS */
#ifndef LLONG_MAX
#ifdef _I64_MAX
#define LLONG_MAX _I64_MAX
#else
#define LLONG_MAX 9223372036854775807LL
#endif
#endif
#ifndef LLONG_MIN
#ifdef _I64_MIN
#define LLONG_MIN _I64_MIN
#else
#define LLONG_MIN (-LLONG_MAX - 1LL)
#endif
#endif
#ifndef ULLONG_MAX
#ifdef _UI64_MAX
#define ULLONG_MAX _UI64_MAX
#else
#define ULLONG_MAX 18446744073709551615ULL
#endif
#endif
#ifndef O_LARGEFILE
#define O_LARGEFILE 0
#endif
#ifndef IPTOS_LOWDELAY
#define IPTOS_LOWDELAY 0x10
#define IPTOS_THROUGHPUT 0x08
#define IPTOS_RELIABILITY 0x04
#endif
#ifndef IPTOS_MINCOST
#define IPTOS_MINCOST 0x02
#endif
#ifndef IPPROTO_SCTP
#define IPPROTO_SCTP 132
#endif
#ifndef YATE_API
#define YATE_API
#endif
#ifdef _WINDOWS
#undef RAND_MAX
#define RAND_MAX 2147483647
#endif
/**
* Holds all Telephony Engine related classes.
*/
namespace TelEngine {
#ifdef HAVE_GCC_FORMAT_CHECK
#define FORMAT_CHECK(f) __attribute__((format(printf,(f),(f)+1)))
#else
#define FORMAT_CHECK(f)
#endif
#define YIGNORE(v) while (v) { break; }
#ifdef HAVE_BLOCK_RETURN
#define YSTRING(s) (*({static const String str("" s);&str;}))
#define YATOM(s) (*({static const String* str(0);str ? str : String::atom(str,"" s);}))
#else
#define YSTRING(s) ("" s)
#define YATOM(s) ("" s)
#endif
#define YSTRING_INIT_HASH ((unsigned) -1)
/**
* Abort execution (and coredump if allowed) if the abort flag is set.
* This function may not return.
*/
YATE_API void abortOnBug();
/**
* Set the abort on bug flag. The default flag state is false.
* @return The old state of the flag.
*/
YATE_API bool abortOnBug(bool doAbort);
/**
* Standard debugging levels.
* The DebugFail level is special - it is always displayed and may abort
* the program if @ref abortOnBug() is set.
*/
enum DebugLevel {
DebugFail = 0,
DebugTest = 1,
DebugCrit = 2,
DebugGoOn = DebugCrit,
DebugConf = 3,
DebugStub = 4,
DebugWarn = 5,
DebugMild = 6,
DebugNote = 7,
DebugCall = 8,
DebugInfo = 9,
DebugAll = 10
};
/**
* Retrieve the current global debug level
* @return The current global debug level
*/
YATE_API int debugLevel();
/**
* Set the current global debug level.
* @param level The desired debug level
* @return The new global debug level (may be different)
*/
YATE_API int debugLevel(int level);
/**
* Check if debugging output should be generated
* @param level The global debug level we are testing
* @return True if messages should be output, false otherwise
*/
YATE_API bool debugAt(int level);
/**
* Get an ANSI string to colorize debugging output
* @param level The debug level who's color is requested.
* Negative or out of range will reset to the default color
* @return ANSI string that sets color corresponding to level
*/
YATE_API const char* debugColor(int level);
/**
* Get the name of a debugging or alarm level
* @param level The debug level
* @return Short C string describing the level
*/
YATE_API const char* debugLevelName(int level);
/**
* Holds a local debugging level that can be modified separately from the
* global debugging
* @short A holder for a debug level
*/
class YATE_API DebugEnabler
{
public:
/**
* Constructor
* @param level The initial local debug level
* @param enabled Enable debugging on this object
*/
inline DebugEnabler(int level = TelEngine::debugLevel(), bool enabled = true)
: m_level(DebugFail), m_enabled(enabled), m_chain(0), m_name(0)
{ debugLevel(level); }
inline ~DebugEnabler()
{ m_name = 0; m_chain = 0; }
/**
* Retrieve the current local debug level
* @return The current local debug level
*/
inline int debugLevel() const
{ return m_chain ? m_chain->debugLevel() : m_level; }
/**
* Set the current local debug level.
* @param level The desired debug level
* @return The new debug level (may be different)
*/
int debugLevel(int level);
/**
* Retrieve the current debug activation status
* @return True if local debugging is enabled
*/
inline bool debugEnabled() const
{ return m_chain ? m_chain->debugEnabled() : m_enabled; }
/**
* Set the current debug activation status
* @param enable The new debug activation status, true to enable
*/
inline void debugEnabled(bool enable)
{ m_enabled = enable; m_chain = 0; }
/**
* Get the current debug name
* @return Name of the debug activation if set or NULL
*/
inline const char* debugName() const
{ return m_name; }
/**
* Check if debugging output should be generated
* @param level The debug level we are testing
* @return True if messages should be output, false otherwise
*/
bool debugAt(int level) const;
/**
* Check if this enabler is chained to another one
* @return True if local debugging is chained to other enabler
*/
inline bool debugChained() const
{ return m_chain != 0; }
/**
* Chain this debug holder to a parent or detach from existing one
* @param chain Pointer to parent debug level, NULL to detach
*/
inline void debugChain(const DebugEnabler* chain = 0)
{ m_chain = (chain != this) ? chain : 0; }
/**
* Copy debug settings from another object or from engine globals
* @param original Pointer to a DebugEnabler to copy settings from
*/
void debugCopy(const DebugEnabler* original = 0);
protected:
/**
* Set the current debug name
* @param name Static debug name or NULL
*/
inline void debugName(const char* name)
{ m_name = name; }
private:
int m_level;
bool m_enabled;
const DebugEnabler* m_chain;
const char* m_name;
};
#if 0 /* for documentation generator */
/**
* Convenience macro.
* Does the same as @ref Debug if DEBUG is \#defined (compiling for debugging)
* else it does not get compiled at all.
*/
void DDebug(int level, const char* format, ...);
/**
* Convenience macro.
* Does the same as @ref Debug if DEBUG is \#defined (compiling for debugging)
* else it does not get compiled at all.
*/
void DDebug(const char* facility, int level, const char* format, ...);
/**
* Convenience macro.
* Does the same as @ref Debug if DEBUG is \#defined (compiling for debugging)
* else it does not get compiled at all.
*/
void DDebug(const DebugEnabler* local, int level, const char* format, ...);
/**
* Convenience macro.
* Does the same as @ref Debug if XDEBUG is \#defined (compiling for extra
* debugging) else it does not get compiled at all.
*/
void XDebug(int level, const char* format, ...);
/**
* Convenience macro.
* Does the same as @ref Debug if XDEBUG is \#defined (compiling for extra
* debugging) else it does not get compiled at all.
*/
void XDebug(const char* facility, int level, const char* format, ...);
/**
* Convenience macro.
* Does the same as @ref Debug if XDEBUG is \#defined (compiling for extra
* debugging) else it does not get compiled at all.
*/
void XDebug(const DebugEnabler* local, int level, const char* format, ...);
/**
* Convenience macro.
* Does the same as @ref Debug if NDEBUG is not \#defined
* else it does not get compiled at all (compiling for mature release).
*/
void NDebug(int level, const char* format, ...);
/**
* Convenience macro.
* Does the same as @ref Debug if NDEBUG is not \#defined
* else it does not get compiled at all (compiling for mature release).
*/
void NDebug(const char* facility, int level, const char* format, ...);
/**
* Convenience macro.
* Does the same as @ref Debug if NDEBUG is not \#defined
* else it does not get compiled at all (compiling for mature release).
*/
void NDebug(const DebugEnabler* local, int level, const char* format, ...);
#endif
#if defined(_DEBUG) || defined(DEBUG) || defined(XDEBUG)
#undef DEBUG
#define DEBUG 1
#endif
#ifdef DEBUG
#define DDebug Debug
#else
#ifdef _WINDOWS
#define DDebug do { break; } while
#else
#define DDebug(arg...)
#endif
#endif
#ifdef XDEBUG
#define XDebug Debug
#else
#ifdef _WINDOWS
#define XDebug do { break; } while
#else
#define XDebug(arg...)
#endif
#endif
#ifndef NDEBUG
#define NDebug Debug
#else
#ifdef _WINDOWS
#define NDebug do { break; } while
#else
#define NDebug(arg...)
#endif
#endif
/**
* Outputs a debug string.
* @param level The level of the message
* @param format A printf() style format string
*/
YATE_API void Debug(int level, const char* format, ...) FORMAT_CHECK(2);
/**
* Outputs a debug string for a specific facility.
* @param facility Facility that outputs the message
* @param level The level of the message
* @param format A printf() style format string
*/
YATE_API void Debug(const char* facility, int level, const char* format, ...) FORMAT_CHECK(3);
/**
* Outputs a debug string for a specific facility.
* @param local Pointer to a DebugEnabler holding current debugging settings
* @param level The level of the message
* @param format A printf() style format string
*/
YATE_API void Debug(const DebugEnabler* local, int level, const char* format, ...) FORMAT_CHECK(3);
/**
* Outputs a debug string and emits an alarm if a callback is installed
* @param component Component that emits the alarm
* @param level The level of the alarm
* @param format A printf() style format string
*/
YATE_API void Alarm(const char* component, int level, const char* format, ...) FORMAT_CHECK(3);
/**
* Outputs a debug string and emits an alarm if a callback is installed
* @param component Pointer to a DebugEnabler holding component name and debugging settings
* @param level The level of the alarm
* @param format A printf() style format string
*/
YATE_API void Alarm(const DebugEnabler* component, int level, const char* format, ...) FORMAT_CHECK(3);
/**
* Outputs a debug string and emits an alarm if a callback is installed
* @param component Component that emits the alarm
* @param info Extra alarm information
* @param level The level of the alarm
* @param format A printf() style format string
*/
YATE_API void Alarm(const char* component, const char* info, int level, const char* format, ...) FORMAT_CHECK(4);
/**
* Outputs a debug string and emits an alarm if a callback is installed
* @param component Pointer to a DebugEnabler holding component name and debugging settings
* @param info Extra alarm information
* @param level The level of the alarm
* @param format A printf() style format string
*/
YATE_API void Alarm(const DebugEnabler* component, const char* info, int level, const char* format, ...) FORMAT_CHECK(4);
/**
* Outputs a string to the debug console with formatting
* @param format A printf() style format string
*/
YATE_API void Output(const char* format, ...) FORMAT_CHECK(1);
/**
* Outputs a debug string with a trace ID.
* @param traceId The trace ID associated with this message
* @param level The level of the message
* @param format A printf() style format string
*/
YATE_API void TraceDebug(const char* traceId, int level, const char* format, ...) FORMAT_CHECK(3);
/**
* Outputs a debug string with a trace ID.
* @param traceId The trace ID associated with this message
* @param facility Facility that outputs the message
* @param level The level of the message
* @param format A printf() style format string
*/
YATE_API void TraceDebug(const char* traceId, const char* facility, int level,
const char* format, ...) FORMAT_CHECK(4);
/**
* Outputs a debug string with a trace ID.
* @param traceId The trace ID associated with this message
* @param local Pointer to a DebugEnabler holding current debugging settings
* @param level The level of the message
* @param format A printf() style format string
*/
YATE_API void TraceDebug(const char* traceId, const DebugEnabler* local, int level,
const char* format, ...) FORMAT_CHECK(4);
#if 0 /* for documentation generator */
/**
* Outputs a debug string with a trace ID.
* @param obj Object from where to get trace ID
* @param level The level of the message
* @param format A printf() style format string
*/
void TraceDebugObj(GenObject* obj, int level, const char* format, ...);
/**
* Outputs a debug string with a trace ID.
* @param obj Object from where to get trace ID
* @param facility Facility that outputs the message
* @param level The level of the message
* @param format A printf() style format string
*/
void TraceDebugObj(GenObject* obj, const char* facility, int level, const char* format, ...);
/**
* Outputs a debug string with a trace ID.
* @param obj Object from where to get trace ID
* @param local Pointer to a DebugEnabler holding current debugging settings
* @param level The level of the message
* @param format A printf() style format string
*/
void TraceDebugObj(GenObject* obj, const DebugEnabler* local, int level, const char* format, ...);
/**
* Outputs a debug string only if trace ID is valid.
* @param obj Object from where to get trace ID
* @param level The level of the message
* @param format A printf() style format string
*/
void Trace(GenObject* obj, int level, const char* format, ...);
/**
* Outputs a debug string only if trace ID is valid.
* @param obj Object from where to get trace ID
* @param facility Facility that outputs the message
* @param level The level of the message
* @param format A printf() style format string
*/
void Trace(GenObject* obj, const char* facility, int level, const char* format, ...);
/**
* Outputs a debug string only if trace ID is valid.
* @param obj Object from where to get trace ID
* @param local Pointer to a DebugEnabler holding current debugging settings
* @param level The level of the message
* @param format A printf() style format string
*/
void Trace(GenObject* obj, const DebugEnabler* local, int level, const char* format, ...);
/**
* Outputs a debug string only if trace ID is valid.
* @param obj Object from where to get trace ID
* @param level The level of the message
* @param format A printf() style format string
*/
void TraceObj(GenObject* obj, int level, const char* format, ...);
/**
* Outputs a debug string only if trace ID is valid.
* @param obj Object from where to get trace ID
* @param facility Facility that outputs the message
* @param level The level of the message
* @param format A printf() style format string
*/
void TraceObj(GenObject* obj, const char* facility, int level, const char* format, ...);
/**
* Outputs a debug string only if trace ID is valid.
* @param obj Object from where to get trace ID
* @param local Pointer to a DebugEnabler holding current debugging settings
* @param level The level of the message
* @param format A printf() style format string
*/
void TraceObj(GenObject* obj, const DebugEnabler* local, int level, const char* format, ...);
#endif
#define TraceDebugObj(pGenObj,...) \
TraceDebug((!!(pGenObj)) ? (pGenObj)->traceId() : "",##__VA_ARGS__)
#define Trace(traceId,...) \
do { if (!TelEngine::null(traceId)) TraceDebug(traceId,##__VA_ARGS__); } while(false)
#define TraceObj(pGenObj,...) \
do { if (!!(pGenObj) && (pGenObj)->traceId()) TraceDebug((pGenObj)->traceId(),##__VA_ARGS__); } while (false)
/**
* Outputs a debug string with trace ID and emits an alarm if a callback is installed
* @param traceId The trace ID associated with this message
* @param component Component that emits the alarm
* @param info Extra alarm information
* @param level The level of the alarm
* @param format A printf() style format string
*/
YATE_API void TraceAlarm(const char* traceId, const char* component, int level,
const char* format, ...) FORMAT_CHECK(4);
/**
* Outputs a debug string with trace ID and emits an alarm if a callback is installed
* @param traceId The trace ID associated with this message
* @param component Pointer to a DebugEnabler holding component name and debugging settings
* @param level The level of the alarm
* @param format A printf() style format string
*/
YATE_API void TraceAlarm(const char* traceId, const DebugEnabler* component,
int level, const char* format, ...) FORMAT_CHECK(4);
/**
* Outputs a debug string with trace ID and emits an alarm if a callback is installed
* @param traceId The trace ID associated with this message
* @param component Component that emits the alarm
* @param info Extra alarm information
* @param level The level of the alarm
* @param format A printf() style format string
*/
YATE_API void TraceAlarm(const char* traceId, const char* component, const char* info,
int level, const char* format, ...) FORMAT_CHECK(5);
/**
* Outputs a debug string with trace ID and emits an alarm if a callback is installed
* @param traceId The trace ID associated with this message
* @param component Pointer to a DebugEnabler holding component name and debugging settings
* @param info Extra alarm information
* @param level The level of the alarm
* @param format A printf() style format string
*/
YATE_API void TraceAlarm(const char* traceId, const DebugEnabler* component,
const char* info, int level, const char* format, ...) FORMAT_CHECK(5);
/**
* This class is used as an automatic variable that logs messages on creation
* and destruction (when the instruction block is left or function returns).
* IMPORTANT: the name is not copied so it should best be static.
* @short An object that logs messages on creation and destruction
*/
class YATE_API Debugger
{
public:
/**
* Timestamp formatting
*/
enum Formatting {
None = 0,
Relative, // from program start
Absolute, // from EPOCH (1-1-1970)
Textual, // absolute GMT in YYYYMMDDhhmmss.uuuuuu format
TextLocal, // local time in YYYYMMDDhhmmss.uuuuuu format
TextSep, // absolute GMT in YYYY-MM-DD_hh:mm:ss.uuuuuu format
TextLSep, // local time in YYYY-MM-DD_hh:mm:ss.uuuuuu format
};
/**
* The constructor prints the method entry message and indents.
* @param name Name of the function or block entered, must be static
* @param format printf() style format string
*/
explicit Debugger(const char* name, const char* format = 0, ...);
/**
* The constructor prints the method entry message and indents.
* @param level The level of the message
* @param name Name of the function or block entered, must be static
* @param format printf() style format string
*/
Debugger(int level, const char* name, const char* format = 0, ...);
/**
* The destructor prints the method leave message and deindents.
*/
~Debugger();
/**
* Set the output callback
* @param outFunc Pointer to the output function, NULL to use stderr
*/
static void setOutput(void (*outFunc)(const char*,int) = 0);
/**
* Set the interactive output callback
* @param outFunc Pointer to the output function, NULL to disable
*/
static void setIntOut(void (*outFunc)(const char*,int) = 0);
/**
* Set the alarm hook callback
* @param alarmFunc Pointer to the alarm callback function, NULL to disable
*/
static void setAlarmHook(void (*alarmFunc)(const char*,int,const char*,const char*) = 0);
/**
* Set the relay hook callback that will process all Output, Debug and Alarm
* @param relayFunc Pointer to the relay callback function, NULL to disable
*/
static void setRelayHook(void (*relayFunc)(int,const char*,const char*,const char*) = 0);
/**
* Enable or disable the debug output
* @param enable Set to true to globally enable output
* @param colorize Enable ANSI colorization of output
*/
static void enableOutput(bool enable = true, bool colorize = false);
/**
* Retrieve the start timestamp
* @return Start timestamp value in seconds
*/
static uint32_t getStartTimeSec();
/**
* Retrieve the format of timestamps
* @return The current formatting type for timestamps
*/
static Formatting getFormatting();
/**
* Set the format of timestamps on output messages and set the time start reference
* @param format Desired timestamp formatting
* @param startTimeSec Optional start timestamp (in seconds)
*/
static void setFormatting(Formatting format, uint32_t startTimeSec = 0);
/**
* Fill a buffer with a current timestamp prefix
* @param buf Buffer to fill, must be at least 28 characters long
* @param format Desired timestamp formatting
* @return Length of the prefix written in buffer excluding final NUL
*/
static unsigned int formatTime(char* buf, Formatting format = getFormatting());
/**
* Processes a preformatted string as Output, Debug or Alarm.
* This method is intended to relay messages from other processes, DO NOT USE!
* @param level The level of the debug or alarm, negative for an output
* @param buffer Preformatted text buffer, MUST HAVE SPACE for at least strlen + 2
* @param component Component that emits the alarm if applicable
* @param info Extra alarm information if applicable
*/
static void relayOutput(int level, char* buffer, const char* component = 0, const char* info = 0);
private:
const char* m_name;
int m_level;
};
/**
* A structure to build (mainly static) Token-to-ID translation tables.
* A table of such structures must end with an entry with a null token
*/
struct TokenDict {
/**
* Token to match
*/
const char* token;
/**
* Value the token translates to
*/
int value;
};
/**
* A structure to build (mainly static) Token-to-ID translation tables.
* Value is 64bit integer.
* A table of such structures must end with an entry with a null token
*/
struct TokenDict64 {
/**
* Token to match
*/
const char* token;
/**
* Value the token translates to
*/
int64_t value;
};
class String;
class DataBlock;
class Mutex;
class ObjList;
class NamedCounter;
#if 0 /* for documentation generator */
/**
* Macro to ignore the result of a function
* @param value Returned value to be ignored, must be interpretable as boolean
*/
void YIGNORE(primitive value);
/**
* Macro to create a local static String if supported by compiler, use with caution
* @param string Literal constant string
* @return A const String& if supported, literal string if not supported
*/
constant YSTRING(const char* string);
/**
* Macro to create a shared static String if supported by compiler, use with caution
* @param string Literal constant string
* @return A const String& if supported, literal string if not supported
*/
constant YATOM(const char* string);
/**
* Macro to create a GenObject class from a base class and implement @ref GenObject::getObject
* @param type Class that is declared
* @param base Base class that is inherited
*/
void YCLASS(class type,class base);
/**
* Macro to create a GenObject class from two base classes and implement @ref GenObject::getObject
* @param type Class that is declared
* @param base1 First base class that is inherited
* @param base2 Second base class that is inherited
*/
void YCLASS2(class type,class base1,class base2);
/**
* Macro to create a GenObject class from three base classes and implement @ref GenObject::getObject
* @param type Class that is declared
* @param base1 First base class that is inherited
* @param base2 Second base class that is inherited
* @param base3 Third base class that is inherited
*/
void YCLASS3(class type,class base1,class base2,class base3);
/**
* Macro to implement @ref GenObject::getObject in a derived class
* @param type Class that is declared
* @param base Base class that is inherited
*/
void YCLASSIMP(class type,class base);
/**
* Macro to implement @ref GenObject::getObject in a derived class
* @param type Class that is declared
* @param base1 First base class that is inherited
* @param base2 Second base class that is inherited
*/
void YCLASSIMP2(class type,class base1,class base2);
/**
* Macro to implement @ref GenObject::getObject in a derived class
* @param type Class that is declared
* @param base1 First base class that is inherited
* @param base2 Second base class that is inherited
* @param base3 Third base class that is inherited
*/
void YCLASSIMP3(class type,class base1,class base2,class base3);
/**
* Macro to retrieve a typed pointer to an interface from an object
* @param type Class we want to return
* @param pntr Pointer to the object we want to get the interface from
* @return Pointer to the class we want or NULL
*/
class* YOBJECT(class type,GenObject* pntr);
/**
* Macro to disable automatic copy and assignment operators
* @param type Class that is declared
*/
void YNOCOPY(class type);
#endif
#define YCLASS(type,base) \
public: virtual void* getObject(const String& name) const \
{ return (name == YATOM(#type)) ? const_cast<type*>(this) : base::getObject(name); }
#define YCLASS2(type,base1,base2) \
public: virtual void* getObject(const String& name) const \
{ if (name == YATOM(#type)) return const_cast<type*>(this); \
void* tmp = base1::getObject(name); \
return tmp ? tmp : base2::getObject(name); }
#define YCLASS3(type,base1,base2,base3) \
public: virtual void* getObject(const String& name) const \
{ if (name == YATOM(#type)) return const_cast<type*>(this); \
void* tmp = base1::getObject(name); \
if (tmp) return tmp; \
tmp = base2::getObject(name); \
return tmp ? tmp : base3::getObject(name); }
#define YCLASSIMP(type,base) \
void* type::getObject(const String& name) const \
{ return (name == YATOM(#type)) ? const_cast<type*>(this) : base::getObject(name); }
#define YCLASSIMP2(type,base1,base2) \
void* type::getObject(const String& name) const \
{ if (name == YATOM(#type)) return const_cast<type*>(this); \
void* tmp = base1::getObject(name); \
return tmp ? tmp : base2::getObject(name); }
#define YCLASSIMP3(type,base1,base2,base3) \
void* type::getObject(const String& name) const \
{ if (name == YATOM(#type)) return const_cast<type*>(this); \
void* tmp = base1::getObject(name); \
if (tmp) return tmp; \
tmp = base2::getObject(name); \
return tmp ? tmp : base3::getObject(name); }
#define YOBJECT(type,pntr) (static_cast<type*>(GenObject::getObject(YATOM(#type),pntr)))
#define YNOCOPY(type) private: \
type(const type&); \
void operator=(const type&)
/**
* Compute a hash for a 64-bit unsigned integer
* @param val Integer value to hash
* @return Hash value
*/
YATE_API inline uint32_t hashInt64(uint64_t val)
{
return (uint32_t)(((val ^ (val >> 48)) ^ (val >> 32)) ^ (val >> 16));
}
/**
* Compute a hash for a 32-bit unsigned integer
* @param val Integer value to hash
* @return Hash value
*/
YATE_API inline uint32_t hashInt32(uint32_t val)
{
return (uint32_t)((val ^ (val >> 16)) ^ (val << 16));
}
/**
* Compute a hash for a pointer
* @param val Pointer to hash
* @return Hash value
*/
YATE_API inline uint32_t hashPtr(const void* ptr)
{
#if (_WORDSIZE == 64)
return hashInt64((uintptr_t)ptr);
#else
return hashInt32((uintptr_t)ptr);
#endif
}
/**
* An object with just a public virtual destructor
*/
class YATE_API GenObject
{
YNOCOPY(GenObject); // no automatic copies please
public:
/**
* Default constructor
*/
GenObject();
/**
* Destructor.
*/
virtual ~GenObject() { setObjCounter(0); }
/**
* Check if the object is still valid and safe to access.
* Note that you should not trust this result unless the object is locked
* by other means.
* @return True if the object is still useable
*/
virtual bool alive() const;
/**
* Destroys the object, disposes the memory.
*/
virtual void destruct();
/**
* Get a string representation of this object
* @return A reference to a String representing this object
* which is either null, the object itself (for objects derived from
* String) or some form of identification
*/
virtual const String& toString() const;
/**
* Get the trace ID associated with this object
* @return The trace ID or an empty string
*/
virtual const String& traceId() const;
/**
* Get a pointer to a derived class given that class name
* @param name Name of the class we are asking for
* @return Pointer to the requested class or NULL if this object doesn't implement it
*/
virtual void* getObject(const String& name) const;
/**
* Helper method to get the pointer to a derived class
* @param name Name of the class we are asking for
* @param obj Pointer to the object to get derived class from
* @return Pointer to the requested class or NULL if this object doesn't implement it
*/
static inline void* getObject(const String& name, const GenObject* obj)
{ return obj ? obj->getObject(name) : 0; }
/**
* Get the global state of object counting
* @return True if object counting is enabled
*/
static inline bool getObjCounting()
{ return s_counting; }
/**
* Set the global state of object counting
* @param enable True to enable object counting, false to disable
*/
static inline void setObjCounting(bool enable)
{ s_counting = enable; }
/**
* Get the counter of this object
* @return Pointer to current counter object
*/
inline NamedCounter* getObjCounter() const
{ return m_counter; }
/**
* Set the counter of this object
* @param counter New counter object or NULL
* @return Pointer to old counter object
*/
NamedCounter* setObjCounter(NamedCounter* counter);
/**
* Retrieve or allocate an object counter
* @param name Name of the counter
* @param create True to create a new counter if needed
* @return Pointer to existing or new counter object
*/
static NamedCounter* getObjCounter(const String& name, bool create = true);
/**
* Access the object counters list
* @return Reference to the global object counters list
*/
static ObjList& getObjCounters();
private:
NamedCounter* m_counter;
static bool s_counting;
};
/**
* Helper function that destroys a GenObject only if the pointer is non-NULL.
* Use it instead of the delete operator.
* @param obj Pointer (rvalue) to the object to destroy
*/
inline void destruct(GenObject* obj)
{ if (obj) obj->destruct(); }
/**
* Helper template function that destroys a GenObject descendant if the pointer
* is non-NULL and also zeros out the pointer.
* Use it instead of the delete operator.
* @param obj Reference to pointer (lvalue) to the object to destroy
*/
template <class Obj> void destruct(Obj*& obj)
{ if (obj) { obj->destruct(); obj = 0; } }
/**
* A reference counted object.
* Whenever using multiple inheritance you should inherit this class virtually.
*/
class YATE_API RefObject : public GenObject
{
YNOCOPY(RefObject); // no automatic copies please
public:
/**
* The constructor initializes the reference counter to 1!
* Use deref() to destruct the object when safe
*/
RefObject();
/**
* Destructor.
*/
virtual ~RefObject();
/**
* Get a pointer to a derived class given that class name
* @param name Name of the class we are asking for
* @return Pointer to the requested class or NULL if this object doesn't implement it
*/
virtual void* getObject(const String& name) const;
/**
* Check if the object is still referenced and safe to access.
* Note that you should not trust this result unless the object is locked
* by other means.
* @return True if the object is referenced and safe to access
*/
virtual bool alive() const;
/**
* Increments the reference counter if not already zero
* @return True if the object was successfully referenced and is safe to access
*/
bool ref();
/**
* Decrements the reference counter, destroys the object if it reaches zero
* <pre>
* // Deref this object, return quickly if the object was deleted
* if (deref()) return;
* </pre>
* @return True if the object may have been deleted, false if it still exists and is safe to access
*/
bool deref();
/**
* Get the current value of the reference counter
* @return The value of the reference counter
*/
inline int refcount() const
{ return m_refcount; }
/**
* Refcounted objects should just have the counter decremented.
* That will destroy them only when the refcount reaches zero.
*/
virtual void destruct();
/**
* Check if a refcounted object is still alive
* @param obj Pointer to the object to check
* @return True if the pointer is not null and the object is referenced
*/
inline static bool alive(const RefObject* obj)
{ return obj && (obj->refcount() > 0); }
/**
* Check if reference counter manipulations are efficient on this platform.
* If platform does not support atomic operations a mutex pool is used.
* @return True if refcount uses atomic integer operations
*/
static bool efficientIncDec();
protected:
/**
* This method is called when the reference count reaches zero after
* unlocking the mutex if the call to zeroRefsTest() returned true.
* The default behaviour is to delete the object.
*/
virtual void zeroRefs();
/**
* Bring the object back alive by setting the reference counter to one.
* Note that it works only if the counter was zero previously
* @return True if the object was resurrected - its name may be Lazarus ;-)
*/
bool resurrect();
/**
* Pre-destruction notification, called just before the object is deleted.
* Unlike in the destructor it is safe to call virtual methods here.
* Reimplementing this method allows to perform any object cleanups.
*/
virtual void destroyed();
private:
int m_refcount;
Mutex* m_mutex;
};
/**
* Internal helper class providing a non-inline method to RefPointer.
* Please don't use this class directly, use @ref RefPointer instead.
* @short Internal helper class
*/
class YATE_API RefPointerBase
{
protected:
/**
* Default constructor, initialize to null pointer
*/
inline RefPointerBase()
: m_pointer(0) { }
/**
* Set a new stored pointer
* @param oldptr Pointer to the RefObject of the old stored object
* @param newptr Pointer to the RefObject of the new stored object
* @param pointer A void pointer to the derived class
*/
void assign(RefObject* oldptr, RefObject* newptr, void* pointer);
/**
* The untyped stored pointer that should be casted to a @ref RefObject derived class
*/
void* m_pointer;
};
/**
* @short Templated smart pointer class
*/
template <class Obj = RefObject> class RefPointer : public RefPointerBase
{
protected:
/**
* Retrieve the stored pointer
* @return A typed pointer
*/
inline Obj* pointer() const
{ return static_cast<Obj*>(m_pointer); }
/**
* Set a new stored pointer
* @param object Pointer to the new stored object
*/
inline void assign(Obj* object = 0)
{ RefPointerBase::assign(pointer(),object,object); }
public:
/**
* Default constructor - creates a null smart pointer
*/
inline RefPointer()
{ }
/**
* Copy constructor, references the object
* @param value Original RefPointer
*/
inline RefPointer(const RefPointer<Obj>& value)
: RefPointerBase()
{ assign(value); }
/**
* Constructs an initialized smart pointer, references the object
* @param object Pointer to object
*/
inline RefPointer(Obj* object)
{ assign(object); }
/**
* Destructs the pointer and dereferences the object
*/
inline ~RefPointer()
{ assign(); }
/**
* Assignment from smart pointer
*/
inline RefPointer<Obj>& operator=(const RefPointer<Obj>& value)
{ assign(value.pointer()); return *this; }
/**
* Assignment from regular pointer
*/
inline RefPointer<Obj>& operator=(Obj* object)
{ assign(object); return *this; }
/**
* Conversion to regular pointer operator
* @return The stored pointer
*/
inline operator Obj*() const
{ return pointer(); }
/**
* Member access operator
*/
inline Obj* operator->() const
{ return pointer(); }
/**
* Dereferencing operator
*/
inline Obj& operator*() const
{ return *pointer(); }
};
/**
* @short Templated pointer that can be inserted in a list
*/
template <class Obj = GenObject> class GenPointer : public GenObject
{
private:
/**
* The stored pointer
*/
Obj* m_pointer;
public:
/**
* Default constructor - creates a null pointer
*/
inline GenPointer()
: m_pointer(0)
{ }
/**
* Copy constructor
* @param value Original GenPointer
*/
inline GenPointer(const GenPointer<Obj>& value)
: m_pointer(value)
{ }
/**
* Constructs an initialized pointer
* @param object Pointer to object
*/
inline GenPointer(Obj* object)
: m_pointer(object)
{ }
/**
* Assignment from another GenPointer
*/
inline GenPointer<Obj>& operator=(const GenPointer<Obj>& value)
{ m_pointer = value; return *this; }
/**
* Assignment from regular pointer
*/
inline GenPointer<Obj>& operator=(Obj* object)
{ m_pointer = object; return *this; }
/**
* Conversion to regular pointer operator
* @return The stored pointer
*/
inline operator Obj*() const
{ return m_pointer; }
/**
* Member access operator
*/
inline Obj* operator->() const
{ return m_pointer; }
/**
* Dereferencing operator
*/
inline Obj& operator*() const
{ return *m_pointer; }
};
/**
* A simple single-linked object list handling class
* @short An object list class
*/
class YATE_API ObjList : public GenObject
{
YNOCOPY(ObjList); // no automatic copies please
public:
/**
* Creates a new, empty list.
*/
ObjList();
/**
* Destroys the list and everything in it.
*/
virtual ~ObjList();
/**
* Get a pointer to a derived class given that class name
* @param name Name of the class we are asking for
* @return Pointer to the requested class or NULL if this object doesn't implement it
*/
virtual void* getObject(const String& name) const;
/**
* Get the number of elements in the list
* @return Count of items
*/
unsigned int length() const;
/**
* Get the number of non-null objects in the list
* @return Count of items
*/
unsigned int count() const;
/**
* Get the object associated to this list item
* @return Pointer to the object or NULL
*/
inline GenObject* get() const
{ return m_obj; }
/**
* Set the object associated to this list item
* @param obj Pointer to the new object to set
* @param delold True to delete the old object (default)
* @return Pointer to the old object if not destroyed
*/
GenObject* set(const GenObject* obj, bool delold = true);
/**
* Get the next item in the list
* @return Pointer to the next item in list or NULL
*/
inline ObjList* next() const
{ return m_next; }
/**
* Get the last item in the list
* @return Pointer to the last item in list
*/
ObjList* last() const;
/**
* Skip over NULL holding items in the list
* @return Pointer to the first non NULL holding item in list or NULL
*/
ObjList* skipNull() const;
/**
* Advance in the list skipping over NULL holding items
* @return Pointer to the next non NULL holding item in list or NULL
*/
ObjList* skipNext() const;
/**
* Get the object at a specific index in list
* @param index Index of the object to retrieve
* @return Pointer to the object or NULL
*/
GenObject* at(int index) const;
/**
* Pointer-like indexing operator
* @param index Index of the list item to retrieve
* @return Pointer to the list item or NULL
*/
ObjList* operator+(int index) const;
/**
* Array-like indexing operator with signed parameter
* @param index Index of the object to retrieve
* @return Pointer to the object or NULL
*/
inline GenObject* operator[](signed int index) const
{ return at(index); }
/**
* Array-like indexing operator with unsigned parameter
* @param index Index of the object to retrieve
* @return Pointer to the object or NULL
*/
inline GenObject* operator[](unsigned int index) const
{ return at(index); }
/**
* Array-like indexing operator
* @param str String value of the object to locate
* @return Pointer to the object or NULL
*/
GenObject* operator[](const String& str) const;
/**
* Get the item in the list that holds an object
* @param obj Pointer to the object to search for
* @return Pointer to the found item or NULL
*/
ObjList* find(const GenObject* obj) const;
/**
* Get the item in the list that holds an object by String value
* @param str String value (toString) of the object to search for
* @return Pointer to the found item or NULL
*/
ObjList* find(const String& str) const;
/**
* Get the position in list of a GenObject by a pointer to it
* @param obj Pointer to the object to search for
* @return Index of object in list, -1 if not found
*/
int index(const GenObject* obj) const;
/**
* Get the position in list of the first GenObject with a given value
* @param str String value (toString) of the object to search for
* @return Index of object in list, -1 if not found
*/
int index(const String& str) const;
/**
* Insert an object at this point
* @param obj Pointer to the object to insert
* @param compact True to replace NULL values in list if possible
* @return A pointer to the inserted list item
*/
ObjList* insert(const GenObject* obj, bool compact = true);
/**
* Append an object to the end of the list
* @param obj Pointer to the object to append
* @param compact True to replace NULL values in list if possible
* @return A pointer to the inserted list item
*/
ObjList* append(const GenObject* obj, bool compact = true);
/**
* Set unique entry in this list. If not found, append it to the list
* @param obj Pointer to the object to uniquely set in the list
* @param compact True to replace NULL values in list if possible
* @return A pointer to the set list item
*/
ObjList* setUnique(const GenObject* obj, bool compact = true);
/**
* Delete this list item
* @param delobj True to delete the object (default)
* @return Pointer to the object if not destroyed
*/
GenObject* remove(bool delobj = true);
/**
* Delete the list item that holds a given object
* @param obj Object to search in the list
* @param delobj True to delete the object (default)
* @return Pointer to the object if not destroyed
*/
GenObject* remove(GenObject* obj, bool delobj = true);
/**
* Delete the first list item that holds an object with a iven value
* @param str String value (toString) of the object to remove
* @param delobj True to delete the object (default)
* @return Pointer to the object if not destroyed
*/
GenObject* remove(const String& str, bool delobj = true);
/**
* Clear the list and optionally delete all contained objects
*/
void clear();
/**
* Remove all empty objects in the list
*/
void compact();
/**
* Get the automatic delete flag
* @return True if will delete on destruct, false otherwise
*/
inline bool autoDelete()
{ return m_delete; }
/**
* Set the automatic delete flag
* @param autodelete True to delete on destruct, false otherwise
*/
inline void setDelete(bool autodelete)
{ m_delete = autodelete; }
/**
* A static empty object list
* @return Reference to a static empty list
*/
static const ObjList& empty();
/**
* Sort this list
* @param callbackCompare pointer to a callback function that should compare two objects.
* <pre>
* obj1 First object of the comparation
* obj2 Second object of the comparation
* context Data context
* return 0 if the objects are equal; positive value if obj2 > obj1; negative value if obj1 > obj2
* Note: the function should expect receiving null pointers
* </pre>
* @param context Context data.
*/
void sort(int (*callbackCompare)(GenObject* obj1, GenObject* obj2, void* context), void* context = 0);
private:
ObjList* m_next;
GenObject* m_obj;
bool m_delete;
};
/**
* Simple vector class that holds objects derived from GenObject
* @short A vector holding GenObjects
*/
class YATE_API ObjVector : public GenObject
{
YNOCOPY(ObjVector); // no automatic copies please
public:
/**
* Constructor of a zero capacity vector
* @param autodelete True to delete objects on destruct, false otherwise
*/
inline explicit ObjVector(bool autodelete = true)
: m_length(0), m_objects(0), m_delete(autodelete)
{ }
/**
* Constructor of an empty vector
* @param maxLen Maximum number of objects the vector can hold
* @param autodelete True to delete objects on destruct, false otherwise
*/
ObjVector(unsigned int maxLen, bool autodelete = true);
/**
* Constructor from an object list
* @param list List of objects to store in vector
* @param move True to move elements from list, false to just copy the pointer
* @param maxLen Maximum number of objects to put in vector, zero to put all
* @param autodelete True to delete objects on destruct, false otherwise
*/
ObjVector(ObjList& list, bool move = true, unsigned int maxLen = 0, bool autodelete = true);
/**
* Destroys the vector and the objects if automatic delete is set
*/
virtual ~ObjVector();
/**
* Get a pointer to a derived class given that class name
* @param name Name of the class we are asking for
* @return Pointer to the requested class or NULL if this object doesn't implement it
*/
virtual void* getObject(const String& name) const;
/**
* Get the capacity of the vector
* @return Number of items the vector can hold
*/
inline unsigned int length() const
{ return m_length; }
/**
* Get the number of non-null objects in the vector
* @return Count of items
*/
unsigned int count() const;
/**
* Check if the vector is empty
* @return True if the vector contains no objects
*/
bool null() const;
/**
* Get the object at a specific index in vector
* @param index Index of the object to retrieve
* @return Pointer to the object or NULL
*/
inline GenObject* at(int index) const
{ return (index >= 0 && index < (int)m_length) ? m_objects[index] : 0; }
/**
* Indexing operator with signed parameter
* @param index Index of the object to retrieve
* @return Pointer to the object or NULL
*/
inline GenObject* operator[](signed int index) const
{ return at(index); }
/**
* Indexing operator with unsigned parameter
* @param index Index of the object to retrieve
* @return Pointer to the object or NULL
*/
inline GenObject* operator[](unsigned int index) const
{ return at(index); }
/**
* Clear the vector and assign objects from a list
* @param list List of objects to store in vector
* @param move True to move elements from list, false to just copy the pointer
* @param maxLen Maximum number of objects to put in vector, zero to put all
* @return Capacity of the vector
*/
unsigned int assign(ObjList& list, bool move = true, unsigned int maxLen = 0);
/**
* Retrieve and remove an object from the vector
* @param index Index of the object to retrieve
* @return Pointer to the stored object, NULL for out of bound index
*/
GenObject* take(unsigned int index);
/**
* Store an object in the vector
* @param obj Object to store in vector
* @param index Index of the object to store
* @return True for success, false if index was out of bounds
*/
bool set(GenObject* obj, unsigned int index);
/**
* Get the position in vector of a GenObject by a pointer to it
* @param obj Pointer to the object to search for
* @return Index of object in vector, -1 if not found
*/
int index(const GenObject* obj) const;
/**
* Get the position in vector of the first GenObject with a given value
* @param str String value (toString) of the object to search for
* @return Index of object in vector, -1 if not found
*/
int index(const String& str) const;
/**
* Clear the vector and optionally delete all contained objects
*/
void clear();
/**
* Get the automatic delete flag
* @return True if will delete objects on destruct, false otherwise
*/
inline bool autoDelete()
{ return m_delete; }
/**
* Set the automatic delete flag
* @param autodelete True to delete objects on destruct, false otherwise
*/
inline void setDelete(bool autodelete)
{ m_delete = autodelete; }
private:
unsigned int m_length;
GenObject** m_objects;
bool m_delete;
};
/**
* A simple Array class derivated from RefObject
* It uses one ObjList to keep the pointers to other ObjList's.
* Data is organized in columns - the main ObjList holds pointers to one
* ObjList for each column.
* This class has been written by Diana
* @short A list based Array
*/
class YATE_API Array : public RefObject
{
public:
/**
* Creates a new empty array.
* @param columns Initial number of columns
* @param rows Initial number of rows
*/
explicit Array(int columns = 0, int rows = 0);
/**
* Destructor. Destructs all objects in the array
*/
virtual ~Array();
/**
* Get a pointer to a derived class given that class name
* @param name Name of the class we are asking for
* @return Pointer to the requested class or NULL if this object doesn't implement it
*/
virtual void* getObject(const String& name) const;
/**
* Insert a row of objects
* @param row List of objects to insert or NULL
* @param index Number of the row to insert before, negative to append
* @return True for success, false if index was larger than the array
*/
bool addRow(ObjList* row = 0, int index = -1);
/**
* Insert a column of objects
* @param column List of objects to insert or NULL
* @param index Number of the column to insert before, negative to append
* @return True for success, false if index was larger than the array
*/
bool addColumn(ObjList* column = 0, int index = -1);
/**
* Delete an entire row of objects
* @param index Number of the row to delete
* @return True for success, false if index was out of bounds
*/
bool delRow(int index);
/**
* Delete an entire column of objects
* @param index Number of the column to delete
* @return True for success, false if index was out of bounds
*/
bool delColumn(int index);
/**
* Retrieve an object from the array
* @param column Number of the column in the array
* @param row Number of the row in the array
* @return Pointer to the stored object, NULL for out of bound indexes
*/
GenObject* get(int column, int row) const;
/**
* Retrieve and remove an object from the array
* @param column Number of the column in the array
* @param row Number of the row in the array
* @return Pointer to the stored object, NULL for out of bound indexes
*/
GenObject* take(int column, int row);
/**
* Store an object in the array
* @param obj Object to store in the array
* @param column Number of the column in the array
* @param row Number of the row in the array
* @return True for success, false if indexes were out of bounds
*/
bool set(GenObject* obj, int column, int row);
/**
* Get the number of rows in the array
* @return Total number of rows
*/
inline int getRows() const
{ return m_rows; }
/**
* Get the number of columns in the array
* @return Total number of columns
*/
inline int getColumns() const
{ return m_columns; }
/**
* Retrieve a column.
* Note: Use the returned list only to get or set data.
* List items must not be removed or appended
* @param column Column to retrieve
* @return Pointer to column list, NULL for out of bound indexes
*/
inline ObjList* getColumn(int column) const {
if (column >= 0 || column < m_columns)
return static_cast<ObjList*>(m_obj[column]);
return 0;
}
private:
int m_rows;
int m_columns;
ObjList m_obj;
};
class Regexp;
class StringMatchPrivate;
/**
* A simple class to hold a single Unicode character and convert it to / from UTF-8
* @short A single Unicode character
*/
class YATE_API UChar
{
public:
enum Endianness {
LE = 0,
BE = 1,
Native = 2,
};
/**
* Constructor from unsigned numeric code
* @param code Code of the Unicode character
*/
inline explicit UChar(uint32_t code = 0)
: m_chr(code)
{ encode(); }
/**
* Constructor from signed numeric code
* @param code Code of the Unicode character
*/
inline explicit UChar(int32_t code)
: m_chr((code < 0) ? 0 : code)
{ encode(); }
/**
* Constructor from signed character
* @param code Character to construct from
*/
inline explicit UChar(signed char code)
: m_chr((unsigned char)code)
{ encode(); }
/**
* Constructor from unsigned character
* @param code Character to construct from
*/
inline explicit UChar(unsigned char code)
: m_chr(code)
{ encode(); }
/**
* Assignment operator from a character code
* @param code Character code to assign
* @return Reference to this object
*/
inline UChar& operator=(uint32_t code)
{ m_chr = code; encode(); return *this; }
/**
* Assignment operator from a character
* @param code Character to assign
* @return Reference to this object
*/
inline UChar& operator=(char code)
{ m_chr = (unsigned char)code; encode(); return *this; }
/**
* Get the Unicode value of the character
* @return Code of the character as defined by Unicode
*/
inline uint32_t code() const
{ return m_chr; }
/**
* Get the value of the character as UTF-8 string.
* @return The character as UTF-8 C string
*/
inline const char* c_str() const
{ return m_str; }
/**
* Conversion to "const char *" operator.
* @return Pointer to the internally stored UTF-8 string
*/
inline operator const char*() const
{ return m_str; };
/**
* Decode the first Unicode character from an UTF-8 C string
* @param str String to extract from, will be advanced past the character
* @param maxChar Maximum accepted Unicode character code
* @param overlong Accept overlong UTF-8 sequences (dangerous!)
* @return True if an Unicode character was decoded from string
*/
bool decode(const char*& str, uint32_t maxChar = 0x10ffff, bool overlong = false);
/**
* Decode the first Unicode character from an UTF-16 string
* @param buff Input buffer, advanced if decoding succeeds
* @param len Length of input buffer, updated if decoding succeeds
* @param order Endianness to use for decoding the character
* @param maxChar Maximum accepted Unicode character code
* @return True if decoding succeeded, false otherwise
*/
bool decode(uint16_t*& buff, unsigned int& len, Endianness order, uint32_t maxChar = 0x10ffff);
/**
* Decode the first Unicode character from an UTF-16 string
* @param buff Input buffer from which to decode the character
* @param order Endianness to use for decoding the character
* @param maxChar Maximum accepted Unicode character code
* @return True if decoding succeeded, false otherwise
*/
bool decode(DataBlock& buff, Endianness order, uint32_t maxChar = 0x10ffff);
/**
* Encode the Unicode character to UTF-16 into a given buffer
* @param buff Buffer where to put encoded character, advanced after encoding
* @param len Available space in given buffer, updated after encoding
* @param order Endianness to use for encoding the character
* @return True if decoding succeeded, false otherwise
*/
bool encode(uint16_t*& buff, unsigned int& len, Endianness order);
/**
* Encode the Unicode character to UTF-16 into a DataBlock
* @param buff DataBlock to which the encoded character is to be appended
* @param order Endianness to use for encoding the character
* @return True if decoding succeeded, false otherwise
*/
bool encode(DataBlock& buff, Endianness order);
/**
* Decode a UTF-16 encoded string
* @param out String to append the decoded characters to
* @param buff Input buffer to decode, advanced as decoding occurs
* @param len Length of input buffer, decremented as decoding occurs
* @param order Endianness to use for decoding
* @param checkBOM Check for presence of BOM and interpret accordingly if present
* @param maxChar Maximum accepted Unicode character code
* @return True if decoding succeeded, false otherwise
*/
static bool decode(String& out, uint16_t*& buff, unsigned int& len, Endianness order, bool checkBOM = false, uint32_t maxChar = 0x10ffff);
/**
* Encode a string to UTF-16
* @param out DataBlock to which encoded data is to be appended
* @param str String to be encoded
* @param order Endianness to use for encoding the character
* @param addBOM True to add BOM to the resulting encoding
* @return True if encoding succeeded, false otherwise
*/
static bool encode(DataBlock& out, const char*& str, Endianness order, bool addBOM = false);
/**
* Encode a string to UTF-16 into a given buffer
* @param buff Buffer where to put encoded character, advanced after encoding
* @param len Available space in given buffer, updated after encoding
* @param str String to be encoded
* @param order Endianness to use for encoding the character
* @param addBOM True to add BOM to the resulting encoding
* @return True if encoding succeeded, false otherwise
*/
static bool encode(uint16_t*& buff, unsigned int& len, const char*& str, Endianness order, bool addBOM = false);
private:
void encode();
uint32_t m_chr;
char m_str[8];
};
/**
* A simple string handling class for C style (one byte) strings.
* For simplicity and read speed no copy-on-write is performed.
* Strings have hash capabilities and comparations are using the hash
* for fast inequality check.
* @short A C-style string handling class
*/
class YATE_API String : public GenObject
{
public:
enum Align {
Left = 0,
Center,
Right
};
/**
* Creates a new, empty string.
*/
String();
/**
* Creates a new initialized string.
* @param value Initial value of the string
* @param len Length of the data to copy, -1 for full string
*/
String(const char* value, int len = -1);
/**
* Creates a new initialized string.
* @param value Character to fill the string
* @param repeat How many copies of the character to use
*/
explicit String(char value, unsigned int repeat = 1);
/**
* Creates a new initialized string from a 32 bit integer.
* @param value Value to convert to string
*/
explicit String(int32_t value);
/**
* Creates a new initialized string from a 32 bit unsigned int.
* @param value Value to convert to string
*/
explicit String(uint32_t value);
/**
* Creates a new initialized string from a 64 bit integer.
* @param value Value to convert to string
*/
explicit String(int64_t value);
/**
* Creates a new initialized string from a 64 bit unsigned int.
* @param value Value to convert to string
*/
explicit String(uint64_t value);
/**
* Creates a new initialized string from a boolean.
* @param value Value to convert to string
*/
explicit String(bool value);
/**
* Creates a new initialized string from a double value.
* @param value Value to convert to string
*/
explicit String(double value);
/**
* Copy constructor.
* @param value Initial value of the string
*/
String(const String& value);
/**
* Constructor from String pointer.
* @param value Initial value of the string
*/
String(const String* value);
/**
* Destroys the string, disposes the memory.
*/
virtual ~String();
/**
* Get a pointer to a derived class given that class name
* @param name Name of the class we are asking for
* @return Pointer to the requested class or NULL if this object doesn't implement it
*/
virtual void* getObject(const String& name) const;
/**
* A static null String
* @return Reference to a static empty String
*/
static const String& empty();
/**
* A standard text representation of boolean values
* @param value Boolean value to convert
* @return Pointer to a text representation of the value
*/
inline static const char* boolText(bool value)
{ return value ? "true" : "false"; }
/**
* Get the value of the stored string.
* @return The stored C string which may be NULL.
*/
inline const char* c_str() const
{ return m_string; }
/**
* Get a valid non-NULL C string.
* @return The stored C string or a static "".
*/
inline const char* safe() const
{ return m_string ? m_string : ""; }
/**
* Get a valid non-NULL C string with a provided default.
* @param defStr Default C string to return if stored is NULL
* @return The stored C string, the default or a static "".
*/
inline const char* safe(const char* defStr) const
{ return m_string ? m_string : (defStr ? defStr : ""); }
/**
* Get the length of the stored string.
* @return The length of the stored string, zero for NULL.
*/
inline unsigned int length() const
{ return m_length; }
/**
* Checks if the string holds a NULL pointer.
* @return True if the string holds NULL, false otherwise.
*/
inline bool null() const
{ return !m_string; }
/**
* Get the number of characters in a string assuming UTF-8 encoding
* @param value C string to compute Unicode length
* @param maxChar Maximum accepted Unicode character code
* @param overlong Accept overlong UTF-8 sequences (dangerous!)
* @return Count of Unicode characters, -1 if not valid UTF-8
*/
static int lenUtf8(const char* value, uint32_t maxChar = 0x10ffff, bool overlong = false);
/**
* Get the number of characters in the string assuming UTF-8 encoding
* @param maxChar Maximum accepted Unicode character code
* @param overlong Accept overlong UTF-8 sequences (dangerous!)
* @return Count of Unicode characters, -1 if not valid UTF-8
*/
inline int lenUtf8(uint32_t maxChar = 0x10ffff, bool overlong = false) const
{ return lenUtf8(m_string,maxChar,overlong); }
/**
* Fix an UTF-8 encoded string by replacing invalid sequences
* @param replace String to replace invalid sequences, use U+FFFD if null
* @param maxChar Maximum accepted Unicode character code
* @param overlong Accept overlong UTF-8 sequences (dangerous!)
* @return Count of invalid UTF-8 sequences that were replaced
*/
int fixUtf8(const char* replace = 0, uint32_t maxChar = 0x10ffff, bool overlong = false);
/**
* Encode flags from dictionary values
* @param tokens The dictionary containing the flags
* @return Encoded flags
*/
unsigned int encodeFlags(const TokenDict* tokens) const;
/**
* Encode flags from dictionary values
* @param tokens The dictionary containing the flags
* @return Encoded flags
*/
uint64_t encodeFlags(const TokenDict64* tokens) const;
/**
* Decodoe flags from dictionary values
* @param flags The flags
* @param tokens The dictionary containing the flags
* @param unknownflag True (default) to add unknown flags
* @return Decoded flags
*/
const String& decodeFlags(unsigned int flags, const TokenDict* tokens, bool unknownflag = true);
/**
* Decode flags from dictionary values
* @param flags The flags
* @param tokens The dictionary containing the flags
* @param unknownflag True (default) to add unknown flags
* @return Decoded flags
*/
const String& decodeFlags(uint64_t flags, const TokenDict64* tokens, bool unknownflag = true);
/**
* Check if a string starts with UTF-8 Byte Order Mark
* @param str String to check for BOM
* @return True if the string starts with UTF-8 BOM
*/
inline static bool checkBOM(const char* str)
{ return str && (str[0] == '\357') && (str[1] == '\273') && (str[2] == '\277'); }
/**
* Check if this string starts with UTF-8 Byte Order Mark
* @return True if the string starts with UTF-8 BOM
*/
inline bool checkBOM() const
{ return checkBOM(c_str()); }
/**
* Advance a const string past an UTF-8 Byte Order Mark
* @param str String to check for and strip BOM
* @return True if the string started with UTF-8 BOM
*/
inline static bool stripBOM(const char*& str)
{ return checkBOM(str) && (str += 3); }
/**
* Advance a string past an UTF-8 Byte Order Mark
* @param str String to check for and strip BOM
* @return True if the string started with UTF-8 BOM
*/
inline static bool stripBOM(char*& str)
{ return checkBOM(str) && (str += 3); }
/**
* Strip an UTF-8 Byte Order Mark from the start of this string
* @return True if the string started with UTF-8 BOM
*/
inline bool stripBOM()
{ return checkBOM(c_str()) && &(*this = c_str() + 3); }
/**
* Get the hash of the contained string.
* @return The hash of the string.
*/
inline unsigned int hash() const
{
if (m_hash == YSTRING_INIT_HASH)
m_hash = hash(m_string);
return m_hash;
}
/**
* Get the hash of an arbitrary string.
* @param value C string to hash
* @param h Old hash value for incremental hashing
* @return The hash of the string.
*/
static unsigned int hash(const char* value, unsigned int h = 0);
/**
* Clear the string and free the memory
*/
void clear();
/**
* Extract the caracter at a given index
* @param index Index of character in string
* @return Character at given index or 0 if out of range
*/
char at(int index) const;
/**
* Substring extraction
* @param offs Offset of the substring, negative to count from end
* @param len Length of the substring, -1 for everything possible
* @return A copy of the requested substring
*/
String substr(int offs, int len = -1) const;
/**
* Strip off leading and trailing blank characters
*/
String& trimBlanks();
/**
* Strip off leading and trailing whitespace characters
* (blank, tabs, form-feed, newlines)
*/
String& trimSpaces();
/**
* Override GenObject's method to return this String
* @return A reference to this String
*/
virtual const String& toString() const;
/**
* Convert the string to an integer value.
* @param defvalue Default to return if the string is not a number
* @param base Numeration base, 0 to autodetect
* @param minvalue Minimum value allowed
* @param maxvalue Maximum value allowed
* @param clamp Control the out of bound values: true to adjust to the nearest
* bound, false to return the default value
* @return The integer interpretation or defvalue.
*/
int toInteger(int defvalue = 0, int base = 0, int minvalue = INT_MIN,
int maxvalue = INT_MAX, bool clamp = true) const;
/**
* Convert the string to an integer value looking up first a token table.
* @param tokens Pointer to an array of tokens to lookup first
* @param defvalue Default to return if the string is not a token or number
* @param base Numeration base, 0 to autodetect
* @return The integer interpretation or defvalue.
*/
int toInteger(const TokenDict* tokens, int defvalue = 0, int base = 0) const;
/**
* Convert the string to an long integer value.
* @param defvalue Default to return if the string is not a number
* @param base Numeration base, 0 to autodetect
* @param minvalue Minimum value allowed
* @param maxvalue Maximum value allowed
* @param clamp Control the out of bound values: true to adjust to the nearest
* bound, false to return the default value
* @return The long integer interpretation or defvalue.
*/
long int toLong(long int defvalue = 0, int base = 0, long int minvalue = LONG_MIN,
long int maxvalue = LONG_MAX, bool clamp = true) const;
/**
* Convert the string to an 64 bit integer value.
* @param defvalue Default to return if the string is not a number
* @param base Numeration base, 0 to autodetect
* @param minvalue Minimum value allowed
* @param maxvalue Maximum value allowed
* @param clamp Control the out of bound values: true to adjust to the nearest
* bound, false to return the default value
* @return The 64 bit integer interpretation or defvalue.
*/
int64_t toInt64(int64_t defvalue = 0, int base = 0, int64_t minvalue = LLONG_MIN,
int64_t maxvalue = LLONG_MAX, bool clamp = true) const;
/**
* Convert the string to an unsigned 64 bit integer value.
* @param defvalue Default to return if the string is not a number
* @param base Numeration base, 0 to autodetect
* @param minvalue Minimum value allowed
* @param maxvalue Maximum value allowed
* @param clamp Control the out of bound values: true to adjust to the nearest
* bound, false to return the default value
* @return The unsigned 64 bit integer interpretation or defvalue.
*/
uint64_t toUInt64(uint64_t defvalue = 0, int base = 0, uint64_t minvalue = 0,
uint64_t maxvalue = ULLONG_MAX, bool clamp = true) const;
/**
* Convert the string to a floating point value.
* @param defvalue Default to return if the string is not a number
* @return The floating-point interpretation or defvalue.
*/
double toDouble(double defvalue = 0.0) const;
/**
* Convert the string to a boolean value.
* @param defvalue Default to return if the string is not a bool
* @return The boolean interpretation or defvalue.
*/
bool toBoolean(bool defvalue = false) const;
/**
* Check if the string can be converted to a boolean value.
* @return True if the string is a valid boolean.
*/
bool isBoolean() const;
/**
* Turn the string to an all-uppercase string
* @return A reference to this String
*/
String& toUpper();
/**
* Turn the string to an all-lowercase string
* @return A reference to this String
*/
String& toLower();
/**
* Indexing operator with signed int
* @param index Index of character in string
* @return Character at given index or 0 if out of range
*/
inline char operator[](signed int index) const
{ return at(index); }
/**
* Indexing operator with unsigned int
* @param index Index of character in string
* @return Character at given index or 0 if out of range
*/
inline char operator[](unsigned int index) const
{ return at(index); }
/**
* Conversion to "const char *" operator.
* @return Pointer to the internally stored string
*/
inline operator const char*() const
{ return m_string; };
/**
* Assigns a new value to the string from a character block.
* @param value New value of the string
* @param len Length of the data to copy, -1 for full string
* @return Reference to the String
*/
String& assign(const char* value, int len = -1);
/**
* Assigns a new value by filling with a repeated character
* @param value Character to fill the string
* @param repeat How many copies of the character to use
* @return Reference to the String
*/
String& assign(char value, unsigned int repeat = 1);
/**
* Build a hexadecimal representation of a buffer of data
* @param data Pointer to data to dump
* @param len Length of the data buffer
* @param sep Separator character to use between octets
* @param upCase Set to true to use upper case characters in hexa
* @return Reference to the String
*/
String& hexify(void* data, unsigned int len, char sep = 0, bool upCase = false);
/**
* Assignment operator.
* @param value Value to assign to the string
*/
inline String& operator=(const String& value)
{ return operator=(value.c_str()); }
/**
* Assignment from String* operator.
* @param value Value to assign to the string
* @see TelEngine::strcpy
*/
inline String& operator=(const String* value)
{ return operator=(value ? value->c_str() : ""); }
/**
* Assignment from char* operator.
* @param value Value to assign to the string
* @see TelEngine::strcpy
*/
String& operator=(const char* value);
/**
* Assignment operator for single characters.
* @param value Value to assign to the string
*/
String& operator=(char value);
/**
* Assignment operator for 32 bit integers.
* @param value Value to assign to the string
*/
String& operator=(int32_t value);
/**
* Assignment operator for 32 bit unsigned integers.
* @param value Value to assign to the string
*/
String& operator=(uint32_t value);
/**
* Assignment operator for 64 bit integers.
* @param value Value to assign to the string
*/
String& operator=(int64_t value);
/**
* Assignment operator for 64 bit unsigned integers.
* @param value Value to assign to the string
*/
String& operator=(uint64_t value);
/**
* Assignment operator for booleans.
* @param value Value to assign to the string
*/
inline String& operator=(bool value)
{ return operator=(boolText(value)); }
/**
* Assignment operator for double.
* @param value Value to assign to the string
*/
String& operator=(double value);
/**
* Appending operator for strings.
* @param value Value to assign to the string
* @see TelEngine::strcat
*/
inline String& operator+=(const char* value)
{ return append(value,-1); }
/**
* Appending operator for single characters.
* @param value Value to append to the string
*/
String& operator+=(char value);
/**
* Appending operator for 32 bit integers.
* @param value Value to append to the string
*/
String& operator+=(int32_t value);
/**
* Appending operator for 32 bit unsigned integers.
* @param value Value to append to the string
*/
String& operator+=(uint32_t value);
/**
* Appending operator for 64 bit integers.
* @param value Value to append to the string
*/
String& operator+=(int64_t value);
/**
* Appending operator for 64 bit unsigned integers.
* @param value Value to append to the string
*/
String& operator+=(uint64_t value);
/**
* Appending operator for booleans.
* @param value Value to append to the string
*/
inline String& operator+=(bool value)
{ return operator+=(boolText(value)); }
/**
* Appending operator for double.
* @param value Value to append to the string
*/
String& operator+=(double value);
/**
* Equality operator.
*/
bool operator==(const char* value) const;
/**
* Inequality operator.
*/
bool operator!=(const char* value) const;
/**
* Fast equality operator.
*/
inline bool operator==(const String& value) const
{ return (this == &value) || ((hash() == value.hash()) && operator==(value.c_str())); }
/**
* Fast inequality operator.
*/
inline bool operator!=(const String& value) const
{ return (this != &value) && ((hash() != value.hash()) || operator!=(value.c_str())); }
/**
* Case-insensitive equality operator.
*/
bool operator&=(const char* value) const;
/**
* Case-insensitive inequality operator.
*/
bool operator|=(const char* value) const;
/**
* Stream style appending operator for C strings
*/
inline String& operator<<(const char* value)
{ return operator+=(value); }
/**
* Stream style appending operator for single characters
*/
inline String& operator<<(char value)
{ return operator+=(value); }
/**
* Stream style appending operator for 32 bit integers
*/
inline String& operator<<(int32_t value)
{ return operator+=(value); }
/**
* Stream style appending operator for 32 bit unsigned integers
*/
inline String& operator<<(uint32_t value)
{ return operator+=(value); }
/**
* Stream style appending operator for 64 bit integers
*/
inline String& operator<<(int64_t value)
{ return operator+=(value); }
/**
* Stream style appending operator for 64 bit unsigned integers
*/
inline String& operator<<(uint64_t value)
{ return operator+=(value); }
/**
* Stream style appending operator for booleans
*/
inline String& operator<<(bool value)
{ return operator+=(value); }
/**
* Stream style appending operator for double
*/
inline String& operator<<(double value)
{ return operator+=(value); }
/**
* Stream style substring skipping operator.
* It eats all characters up to and including the skip string
*/
String& operator>>(const char* skip);
/**
* Stream style extraction operator for single characters
*/
String& operator>>(char& store);
/**
* Stream style extraction operator for single Unicode characters
*/
String& operator>>(UChar& store);
/**
* Stream style extraction operator for integers
*/
String& operator>>(int& store);
/**
* Stream style extraction operator for unsigned integers
*/
String& operator>>(unsigned int& store);
/**
* Stream style extraction operator for booleans
*/
String& operator>>(bool& store);
/**
* Append a string to the current string
* @param value String from which to append
* @param len Length of the data to copy, -1 for full string
* @return Reference to the String
*/
String& append(const char* value, int len);
/**
* Conditional appending with a separator
* @param value String to append
* @param separator Separator to insert before the value
* @param force True to allow appending empty strings
*/
String& append(const char* value, const char* separator = 0, bool force = false);
/**
* List members appending with a separator
* @param list Pointer to ObjList whose @ref GenObject::toString() of the items will be appended
* @param separator Separator to insert before each item in list
* @param force True to allow appending empty strings
*/
String& append(const ObjList* list, const char* separator = 0, bool force = false);
/**
* List members appending with a separator
* @param list Reference of ObjList whose @ref GenObject::toString() of the items will be appended
* @param separator Separator to insert before each item in list
* @param force True to allow appending empty strings
*/
inline String& append(const ObjList& list, const char* separator = 0, bool force = false)
{ return append(&list,separator,force); }
/**
* Explicit double append
* @param value Value to append
* @param decimals Number of decimals
*/
String& append(double value, unsigned int decimals = 3);
/**
* Insert a string into current string
* @param pos Position to insert. String will be appended if position is greater than curent length
* @param value String to insert
* @param len Length of the data to copy, -1 for full string
* @return Reference to the String
*/
String& insert(unsigned int pos, const char* value, int len = -1);
/**
* Insert a character into current string
* @param pos Position to insert. The character will be appended if position is greater than curent length
* @param value Character to insert. NUL character will be ignored
* @return Reference to the String
*/
inline String& insert(unsigned int pos, char value) {
if (!value)
return *this;
char s[] = {value};
return insert(pos,s,1);
}
/**
* Build a String in a printf style.
* @param format The output format.
* NOTE: The length of the resulting string will be at most 128 + length of format
*/
String& printf(const char* format, ...) FORMAT_CHECK(2);
/**
* Build a String in a printf style.
* @param length maximum length of the resulting string
* @param format The output format.
*/
String& printf(unsigned int length, const char* format, ...) FORMAT_CHECK(3);
/**
* Build a fixed aligned string from str and append it.
* @param fixedLength The fixed length in which the 'str' will be aligned.
* @param str The string to align
* @param len The number of characters to use from str.
* @param fill Character to fill the empty space.
* @param align The alignment mode.
*/
String& appendFixed(unsigned int fixedLength, const char* str, unsigned int len = -1, char fill = ' ', int align = Left);
/**
* Build a fixed aligned string from str and append it.
* @param fixedLength The fixed length in which the 'str' will be aligned.
* @param str The string to align
* @param fill Character to fill the empty space.
* @param align The alignment mode.
*/
inline String& appendFixed(unsigned int fixedLength, const String& str, char fill = ' ', int align = Left)
{ return appendFixed(fixedLength,str.c_str(),str.length(),fill,align); }
/**
* Locate the first instance of a character in the string
* @param what Character to search for
* @param offs Offset in string to start searching from
* @return Offset of character or -1 if not found
*/
int find(char what, unsigned int offs = 0) const;
/**
* Locate the first instance of a substring in the string
* @param what Substring to search for
* @param offs Offset in string to start searching from
* @return Offset of substring or -1 if not found
*/
int find(const char* what, unsigned int offs = 0) const;
/**
* Locate the last instance of a character in the string
* @param what Character to search for
* @return Offset of character or -1 if not found
*/
int rfind(char what) const;
/**
* Locate the last instance of a substring in the string
* @param what Substring to search for
* @return Offset of substring or -1 if not found
*/
int rfind(const char* what) const;
/**
* Checks if the string starts with a substring
* @param what Substring to search for
* @param wordBreak Check if a word boundary follows the substring
* @param caseInsensitive Compare case-insensitive if set
* @return True if the substring occurs at the beginning of the string
*/
bool startsWith(const char* what, bool wordBreak = false, bool caseInsensitive = false) const;
/**
* Checks if the string ends with a substring
* @param what Substring to search for
* @param wordBreak Check if a word boundary precedes the substring
* @param caseInsensitive Compare case-insensitive if set
* @return True if the substring occurs at the end of the string
*/
bool endsWith(const char* what, bool wordBreak = false, bool caseInsensitive = false) const;
/**
* Checks if the string starts with a substring and removes it
* @param what Substring to search for
* @param wordBreak Check if a word boundary follows the substring;
* this parameter defaults to True because the intended use of this
* method is to separate commands from their parameters
* @param caseInsensitive Compare case-insensitive if set
* @return True if the substring occurs at the beginning of the string
* and also removes the substring; if wordBreak is True any word
* breaking characters are also removed
*/
bool startSkip(const char* what, bool wordBreak = true, bool caseInsensitive = false);
/**
* Extract a substring up to a separator
* @param sep Separator string to match after extracted fragment
* @param store Reference to String variable to store extracted fragment
* @return Reference to this string
*/
String& extractTo(const char* sep, String& store);
/**
* Extract a boolean substring up to a separator
* @param sep Separator string to match after extracted fragment
* @param store Reference to boolean variable to store extracted fragment
* @return Reference to this string
*/
String& extractTo(const char* sep, bool& store);
/**
* Extract an integer value substring up to a separator
* @param sep Separator string to match after extracted fragment
* @param store Reference to integer variable to store extracted fragment
* @param base Numeration base, 0 to autodetect
* @return Reference to this string
*/
String& extractTo(const char* sep, int& store, int base = 0);
/**
* Extract an integer or token value substring up to a separator
* @param sep Separator string to match after extracted fragment
* @param store Reference to integer variable to store extracted fragment
* @param tokens Pointer to an array of tokens to lookup first
* @param base Numeration base, 0 to autodetect
* @return Reference to this string
*/
String& extractTo(const char* sep, int& store, const TokenDict* tokens, int base = 0);
/**
* Extract a double value substring up to a separator
* @param sep Separator string to match after extracted fragment
* @param store Reference to double variable to store extracted fragment
* @return Reference to this string
*/
String& extractTo(const char* sep, double& store);
/**
* Checks if matches another string
* @param value String to check for match
* @return True if matches, false otherwise
*/
virtual bool matches(const String& value) const
{ return operator==(value); }
/**
* Checks if matches a regular expression and fill the match substrings
* @param rexp Regular expression to check for match
* @return True if matches, false otherwise
*/
bool matches(const Regexp& rexp);
/**
* Get the offset of the last match
* @param index Index of the submatch to return, 0 for full match
* @return Offset of the last match, -1 if no match or not in range
*/
int matchOffset(int index = 0) const;
/**
* Get the length of the last match
* @param index Index of the submatch to return, 0 for full match
* @return Length of the last match, 0 if no match or out of range
*/
int matchLength(int index = 0) const;
/**
* Get a copy of a matched (sub)string
* @param index Index of the submatch to return, 0 for full match
* @return Copy of the matched substring
*/
inline String matchString(int index = 0) const
{ return substr(matchOffset(index),matchLength(index)); }
/**
* Create a string by replacing matched strings in a template
* @param templ Template of the string to generate
* @return Copy of template with "\0" - "\9" replaced with submatches
*/
String replaceMatches(const String& templ) const;
/**
* Get the total number of submatches from the last match, 0 if no match
* @return Number of matching subexpressions
*/
int matchCount() const;
/**
* Splits the string at a delimiter character
* @param separator Character where to split the string
* @param emptyOK True if empty strings should be inserted in list
* @return A newly allocated list of strings, must be deleted after use
*/
ObjList* split(char separator, bool emptyOK = true) const;
/**
* Splits the string at Regexp delimiter
* @param reg Regexp describing the delimiter
* @param emptyOK True if empty strings should be inserted in list
* @return A newly allocated list of strings, must be deleted after use
*/
ObjList* split(const Regexp& reg, bool emptyOK = true) const;
/**
* Create an escaped string suitable for use in messages
* @param str String to convert to escaped format
* @param extraEsc Character to escape other than the default ones
* @return The string with special characters escaped
*/
static String msgEscape(const char* str, char extraEsc = 0);
/**
* Create an escaped string suitable for use in messages
* @param extraEsc Character to escape other than the default ones
* @return The string with special characters escaped
*/
inline String msgEscape(char extraEsc = 0) const
{ return msgEscape(c_str(),extraEsc); }
/**
* Decode an escaped string back to its raw form
* @param str String to convert to unescaped format
* @param errptr Pointer to an integer to receive the place of 1st error
* @param extraEsc Character to unescape other than the default ones
* @return The string with special characters unescaped
*/
static String msgUnescape(const char* str, int* errptr = 0, char extraEsc = 0);
/**
* Decode an escaped string back to its raw form
* @param errptr Pointer to an integer to receive the place of 1st error
* @param extraEsc Character to unescape other than the default ones
* @return The string with special characters unescaped
*/
inline String msgUnescape(int* errptr = 0, char extraEsc = 0) const
{ return msgUnescape(c_str(),errptr,extraEsc); }
/**
* Create an escaped string suitable for use in SQL queries
* @param str String to convert to escaped format
* @param extraEsc Character to escape other than the default ones
* @return The string with special characters escaped
*/
static String sqlEscape(const char* str, char extraEsc = 0);
/**
* Create an escaped string suitable for use in SQL queries
* @param extraEsc Character to escape other than the default ones
* @return The string with special characters escaped
*/
inline String sqlEscape(char extraEsc = 0) const
{ return sqlEscape(c_str(),extraEsc); }
/**
* Create an escaped string suitable for use in URIs
* @param str String to convert to escaped format
* @param extraEsc Character to escape other than the default ones
* @param noEsc Optional pointer to string of characters that shouldn't be escaped
* @return The string with special characters escaped
*/
static String uriEscape(const char* str, char extraEsc = 0, const char* noEsc = 0);
/**
* Create an escaped string suitable for use in URIs
* @param str String to convert to escaped format
* @param extraEsc Pointer to string of characters to escape other than the defaults
* @param noEsc Optional pointer to string of characters that shouldn't be escaped
* @return The string with special characters escaped
*/
static String uriEscape(const char* str, const char* extraEsc, const char* noEsc = 0);
/**
* Create an escaped string suitable for use in URI
* @param extraEsc Character to escape other than the default ones
* @param noEsc Optional pointer to string of characters that shouldn't be escaped
* @return The string with special characters escaped
*/
inline String uriEscape(char extraEsc = 0, const char* noEsc = 0) const
{ return uriEscape(c_str(),extraEsc,noEsc); }
/**
* Decode an URI escaped string back to its raw form
* @param str String to convert to unescaped format
* @param errptr Pointer to an integer to receive the place of 1st error
* @return The string with special characters unescaped
*/
static String uriUnescape(const char* str, int* errptr = 0);
/**
* Decode an URI escaped string back to its raw form
* @param errptr Pointer to an integer to receive the place of 1st error
* @return The string with special characters unescaped
*/
inline String uriUnescape(int* errptr = 0) const
{ return uriUnescape(c_str(),errptr); }
/**
* Atom string support helper
* @param str Reference to variable to hold the atom string
* @param val String value to allocate to the atom
* @return Pointer to shared atom string
*/
static const String* atom(const String*& str, const char* val);
protected:
/**
* Called whenever the value changed (except in constructors).
*/
virtual void changed();
private:
void clearMatches();
char* m_string;
unsigned int m_length;
// I hope every C++ compiler now knows about mutable...
mutable unsigned int m_hash;
StringMatchPrivate* m_matches;
};
/**
* Utility function to retrieve a C string from a possibly NULL String pointer
* @param str Pointer to a String that may be NULL
* @return String data pointer or NULL
*/
inline const char* c_str(const String* str)
{ return str ? str->c_str() : (const char*)0; }
/**
* Utility function to replace NULL C string pointers with an empty C string
* @param str Pointer to a C string that may be NULL
* @return Original pointer or pointer to an empty C string
*/
inline const char* c_safe(const char* str)
{ return str ? str : ""; }
/**
* Utility function to replace NULL String pointers with an empty C string
* @param str Pointer to a String that may be NULL
* @return String data pointer or pointer to an empty C string
*/