Logo Search packages:      
Sourcecode: yate version File versions  Download package

telengine.h

/**
 * telengine.h
 * This file is part of the YATE Project http://YATE.null.ro
 *
 * Yet Another Telephony Engine - a fully featured software PBX and IVR
 * Copyright (C) 2004 Null Team
 *
 * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#ifndef __TELENGINE_H
#define __TELENGINE_H

#ifndef __cplusplus
#error C++ is required
#endif

#include <stddef.h>

struct timeval;
      
/**
 * 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

/**
 * Abort execution (and coredump if allowed) if the abort flag is set.
 * This function may not return.
 */
void abortOnBug();

/**
 * Set the abort on bug flag. The default flag state is false.
 * @return The old state of the flag.
 */
bool abortOnBug(bool doAbort);

/**
 * Enable timestamping of output messages and set the time start reference
 */
void setDebugTimestamp();

/**
 * Standard debugging levels.
 * The DebugFail level is special - it is always displayed and may abort
 *  the program if @ref abortOnBug() is set.
 */
00067 enum DebugLevel {
    DebugFail = 0,
    DebugGoOn = 2,
    DebugWarn = 5,
    DebugMild = 7,
    DebugInfo = 9,
    DebugAll = 10
};

/**
 * Retrive the current debug level
 * @return The current debug level
 */
int debugLevel();

/**
 * Set the current debug level.
 * @param level The desired debug level
 * @return The new debug level (may be different)
 */
int debugLevel(int level);

/**
 * Check if debugging output should be generated
 * @param level The desired debug level
 * @return True if messages should be output, false otherwise
 */
bool debugAt(int level);

#if 0
/**
 * Convenience macro.
 * Does the same as @ref Debug if DEBUG is #defined (compiling for debugging)
 *  else it does not get compiled at all.
 */
bool 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.
 */
bool DDebug(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.
 */
bool 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.
 */
bool XDebug(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).
 */
bool 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).
 */
bool NDebug(const char *facility, int level, const char *format, ...);
#endif

#ifdef XDEBUG
#undef DEBUG
#define DEBUG
#endif

#ifdef DEBUG
#define DDebug(arg...) Debug(arg)
#else
#define DDebug(arg...)
#endif

#ifdef XDEBUG
#define XDebug(arg...) Debug(arg)
#else
#define XDebug(arg...)
#endif

#ifndef NDEBUG
#define NDebug(arg...) Debug(arg)
#else
#define NDebug(arg...)
#endif

/**
 * Outputs a debug string.
 * @param level The level of the message
 * @param format A printf() style format string
 * @return True if message was output, false otherwise
 */
bool 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
 * @return True if message was output, false otherwise
 */
bool Debug(const char *facility, int level, const char *format, ...) FORMAT_CHECK(3);

/**
 * Outputs a string to the debug console with formatting
 * @param facility Facility that outputs the message
 * @param format A printf() style format string
 */
void Output(const char *format, ...) FORMAT_CHECK(1);

/**
 * This class is used as an automatic variable that logs messages on creation
 *  and destruction (when the instruction block is left or function returns)
 * @short An object that logs messages on creation and destruction
 */
00192 class Debugger
{
public:
    /**
     * 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
     */
    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 *) = 0);

    /**
     * Set the interactive output callback
     * @param outFunc Pointer to the output function, NULL to disable
     */
    static void setIntOut(void (*outFunc)(const char *) = 0);

    /**
     * Enable or disable the debug output
     */
    static void enableOutput(bool enable = true);

private:
    const char *m_name;
};

/**
 * 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
 */
00240 struct TokenDict {
    const char *token;
    int value;
};

class String;

/**
 * An object with just a public virtual destructor
 */
00250 class GenObject
{
public:
    /**
     * Destructor.
     */
00256     virtual ~GenObject() { }

    /**
     * Destroys the object, disposes the memory.
     */
00261     virtual void destruct()
      { delete this; }

    /**
     * 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;
};

/**
 * A reference counted object.
 * Whenever using multiple inheritance you should inherit this class virtually.
 */
00277 class RefObject : public GenObject
{
public:
    /**
     * The constructor initializes the reference counter to 1!
     * Use deref() to destruct the object when safe
     */
00284     RefObject()
      : m_refcount(1) { }

    /**
     * Destructor.
     */
    virtual ~RefObject();

    /**
     * Increments the reference counter
     * @return The new reference count
     */
    int 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 was deleted, false if it still exists
     */
    bool deref();

    /**
     * Get the current value of the reference counter
     * @return The value of the reference counter
     */
00312     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.
     */
00319     virtual void destruct()
      { deref(); }

private:
    int m_refcount;
};

/**
 * A simple single-linked object list handling class
 * @short An object list class
 */
00330 class ObjList : public GenObject
{
public:
    /**
     * Creates a new, empty list.
     */
    ObjList();

    /**
     * Destroys the list and everything in it.
     */
    virtual ~ObjList();

    /**
     * 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
     */
00359     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
     */
00374     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;

    /**
     * Indexing operator
     * @param index Index of the item to retrive
     * @return Pointer to the item or NULL
     */
    ObjList *operator[](int index) 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;

    /**
     * Insert an object at this point
     * @param obj Pointer to the object to insert
     * @return A pointer to the inserted list item
     */
    ObjList *insert(const GenObject *obj);

    /**
     * Append an object to the end of the list
     * @param obj Pointer to the object to append
     * @return A pointer to the inserted list item
     */
    ObjList *append(const GenObject *obj);

    /**
     * Delete this list item
     * @param delold 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);

    /**
     * Clear the list and optionally delete all contained objects
     */
    void clear();

    /**
     * Get the automatic delete flag
     * @return True if will delete on destruct, false otherwise
     */
00442     inline bool autoDelete()
      { return m_delete; }

    /**
     * Set the automatic delete flag
     * @param autodelete True to delete on destruct, false otherwise
     */
00449     inline void setDelete(bool autodelete)
      { m_delete = autodelete; }

private:
    ObjList *m_next;
    GenObject *m_obj;
    bool m_delete;
};

class Regexp;
class StringMatchPrivate;

/**
 * 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
 */
00468 class String : public GenObject
{
public:
    /**
     * 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
     */
    String(char value, unsigned int repeat = 1);

    /**
     * Creates a new initialized string from an integer.
     * @param value Value to convert to string
     */
    String(int value);

    /**
     * Creates a new initialized string from an unsigned int.
     * @param value Value to convert to string
     */
    String(unsigned int value);

    /**
     * Creates a new initialized string from a boolean.
     * @param value Value to convert to string
     */
    String(bool 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();

    /**
     * A static null String
     */
    static const String &empty();

    /**
     * Get the value of the stored string.
     * @return The stored C string which may be NULL.
     */
00534     inline const char *c_str() const
      { return m_string; }

    /**
     * Get a valid non-NULL C string.
     * @return The stored C string or "".
     */
00541     inline const char *safe() const
      { return m_string ? m_string : ""; }

    /**
     * Get the length of the stored string.
     * @return The length of the stored string, zero for NULL.
     */
00548     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.
     */
00555     inline bool null() const
      { return !m_string; }

    /**
     * Get the hash of the contained string.
     * @return The hash of the string.
     */
    unsigned int hash() const;

    /**
     * Get the hash of an arbitrary string.
     * @return The hash of the string.
     */
    static unsigned int hash(const char *value);

    /**
     * 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();

    /**
     * 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
     * @return The integer interpretation or defvalue.
     */
    int toInteger(int defvalue = 0, int base = 0) 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 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;

    /**
     * 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
     * @param index Index of character in string
     * @return Character at given index or 0 if out of range
     */
00642     inline char operator[](int index) const
      { return at(index); }

    /**
     * Conversion to "const char *" operator.
     */
00648     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
     */
    String& assign(const char *value, int len = -1);

    /**
     * Assignment operator.
     */
00661     inline String& operator=(const String &value)
      { return operator=(value.c_str()); }

    /**
     * Assignment from String* operator.
     * @see TelEngine::strcpy
     */
00668     inline String& operator=(const String *value)
      { return operator=(value ? value->c_str() : ""); }

    /**
     * Assignment from char* operator.
     * @see TelEngine::strcpy
     */
    String& operator=(const char *value);

    /**
     * Assignment operator for single characters.
     */
    String& operator=(char value);

    /**
     * Assignment operator for integers.
     */
    String& operator=(int value);

    /**
     * Assignment operator for unsigned integers.
     */
    String& operator=(unsigned int value);

    /**
     * Assignment operator for booleans.
     */
00695     inline String& operator=(bool value)
      { return operator=(value ? "true" : "false"); }

    /**
     * Appending operator for strings.
     * @see TelEngine::strcat
     */
    String& operator+=(const char *value);

    /**
     * Appending operator for single characters.
     */
    String& operator+=(char value);

    /**
     * Appending operator for integers.
     */
    String& operator+=(int value);

    /**
     * Appending operator for unsigned integers.
     */
    String& operator+=(unsigned int value);

    /**
     * Appending operator for booleans.
     */
00722     inline String& operator+=(bool value)
      { return operator+=(value ? "true" : "false"); }

    /**
     * Equality operator.
     */
    bool operator==(const char *value) const;

    /**
     * Inequality operator.
     */
    bool operator!=(const char *value) const;

    /**
     * Fast equality operator.
     */
    bool operator==(const String &value) const;

    /**
     * Fast inequality operator.
     */
    bool operator!=(const String &value) const;

    /**
     * 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
     */
00758     inline String& operator<<(const char *value)
      { return operator+=(value); }

    /**
     * Stream style appending operator for single characters
     */
00764     inline String& operator<<(char value)
      { return operator+=(value); }

    /**
     * Stream style appending operator for integers
     */
00770     inline String& operator<<(int value)
      { return operator+=(value); }

    /**
     * Stream style appending operator for unsigned integers
     */
00776     inline String& operator<<(unsigned int value)
      { return operator+=(value); }

    /**
     * Stream style appending operator for booleans
     */
00782     inline String& operator<<(bool 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 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);

    /**
     * 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;

    /**
     * Checks if the string starts with a substring
     * @param what Substring to search for
     * @param wordBreak Check if a word boundary follows the substring
     * @return True if the substring occurs at the beginning of the string
     */
    bool startsWith(const char *what, bool wordBreak = 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
     * @return True if the substring occurs at the end of the string
     */
    bool endsWith(const char *what, bool wordBreak = 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
     * @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);

    /**
     * Checks if matches another string
     * @param value String to check for match
     * @return True if matches, false otherwise
     */
00867     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(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
     */
00896     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;

    /**
     * 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
     */
00933     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
     */
00951     inline String msgUnescape(int *errptr = 0, char extraEsc = 0) const
      { return msgUnescape(c_str(),errptr,extraEsc); }

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 replace NULL string pointers with an empty string
 * @param str Pointer to a C string that may be NULL
 * @return Original pointer or pointer to an empty string
 */
00974 inline const char *c_safe(const char *str)
    { return str ? str : ""; }

/**
 * Concatenation operator for strings.
 */
String operator+(const String &s1, const String &s2);

/**
 * Concatenation operator for strings.
 */
String operator+(const String &s1, const char *s2);

/**
 * Concatenation operator for strings.
 */
String operator+(const char *s1, const String &s2);

/**
 * Prevent careless programmers from overwriting the string
 * @see TelEngine::String::operator=
 */
00996 inline char *strcpy(String &dest, const char *src)
    { dest = src; return (char *)dest.c_str(); }

/**
 * Prevent careless programmers from overwriting the string
 * @see TelEngine::String::operator+=
 */
01003 inline char *strcat(String &dest, const char *src)
    { dest += src; return (char *)dest.c_str(); }

/**
 * Utility function to look up a string in a token table,
 * interpret as number if it fails
 * @param str String to look up
 * @param tokens Pointer to the token table
 * @param defvalue Value to return if lookup and conversion fail
 * @param base Default base to use to convert to number
 */
int lookup(const char *str, const TokenDict *tokens, int defvalue = 0, int base = 0);

/**
 * Utility function to look up a number in a token table
 * @param value Value to search for
 * @param tokens Pointer to the token table
 * @param defvalue Value to return if lookup fails
 */
const char *lookup(int value, const TokenDict *tokens, const char *defvalue = 0);


/**
 * A regular expression matching class.
 * @short A regexp matching class
 */
01029 class Regexp : public String
{
    friend class String;
public:
    /**
     * Creates a new, empty regexp.
     */
    Regexp();

    /**
     * Creates a new initialized regexp.
     * @param value Initial value of the regexp.
     * @param extended True to use POSIX Extended Regular Expression syntax
     * @param insensitive True to not differentiate case
     */
    Regexp(const char *value, bool extended = false, bool insensitive = false);

    /**
     * Copy constructor.
     * @param value Initial value of the regexp.
     */
    Regexp(const Regexp &value);

    /**
     * Destroys the regexp, disposes the memory.
     */
    virtual ~Regexp();

    /**
     * Assignment from char* operator.
     */
01060     inline Regexp& operator=(const char *value)
      { String::operator=(value); return *this; }

    /**
     * Makes sure the regular expression is compiled
     * @return True if successfully compiled, false on error
     */
    bool compile();

    /**
     * Checks if the pattern matches a given value
     * @param value String to check for match
     * @return True if matches, false otherwise
     */
    bool matches(const char *value);

    /**
     * Checks if the pattern matches a string
     * @param value String to check for match
     * @return True if matches, false otherwise
     */
01081     virtual bool matches(const String &value) const
      { return matches(value.safe()); }

    /**
     * Change the expression matching flags
     * @param extended True to use POSIX Extended Regular Expression syntax
     * @param insensitive True to not differentiate case
     */
    void setFlags(bool extended, bool insensitive);

    /**
     * Return the POSIX Extended syntax flag
     * @return True if using POSIX Extended Regular Expression syntax
     */
    bool isExtended() const;

    /**
     * Return the Case Insensitive flag
     * @return True if not differentiating case
     */
    bool isCaseInsensitive() const;

protected:
    /**
     * Called whenever the value changed (except in constructors) to recompile.
     */
    virtual void changed();

private:
    void cleanup();
    bool matches(const char *value, StringMatchPrivate *matches);
    void *m_regexp;
    int m_flags;
};

/**
 * A string class with a hashed string name
 * @short A named string class.
 */
01120 class NamedString : public String
{
public:
    /**
     * Creates a new named string.
     * @param name Name of this string
     * @param value Initial value of the string.
     */
    NamedString(const char *name, const char *value = 0);

    /**
     * Retrive the name of this string.
     * @return A hashed string with the name of the string
     */
01134     inline const String& name() const
      { return m_name; }

    /**
     * Get a string representation of this object
     * @return A reference to the name of this object
     */
    virtual const String& toString() const;

    /**
     * Value assignment operator
     */
01146     inline NamedString& operator=(const char *value)
      { String::operator=(value); return *this; }

private:
    NamedString(); // no default constructor please
    String m_name;
};

/**
 * The Time class holds a time moment with microsecond accuracy
 * @short A time holding class
 */
01158 class Time
{
public:
    /**
     * Constructs a Time object from the current time
     */
01164     inline Time()
      : m_time(now())
      { }

    /**
     * Constructs a Time object from a given time
     * @param usec Time in microseconds
     */
01172     inline Time(unsigned long long usec)
      : m_time(usec)
      { }

    /**
     * Constructs a Time object from a timeval structure
     * @param tv Pointer to the timeval structure
     */
01180     inline Time(struct timeval *tv)
      : m_time(fromTimeval(tv))
      { }

    /**
     * Do-nothing destructor that keeps the compiler from complaining
     *  about inlining derivates or members of Time type
     */
01188     inline ~Time()
      { }

    /**
     * Get time in seconds
     * @return Time in seconds since the Epoch
     */
01195     inline unsigned long sec() const
      { return (m_time+500000) / 1000000; }

    /**
     * Get time in milliseconds
     * @return Time in milliseconds since the Epoch
     */
01202     inline unsigned long long msec() const
      { return (m_time+500) / 1000; }

    /**
     * Get time in microseconds
     * @return Time in microseconds since the Epoch
     */
01209     inline unsigned long long usec() const
      { return m_time; }

    /**
     * Conversion to microseconds operator
     */
01215     inline operator unsigned long long() const
      { return m_time; }

    /**
     * Assignment operator.
     */
01221     inline Time& operator=(unsigned long long usec)
      { m_time = usec; return *this; }

    /**
     * Offsetting operator.
     */
01227     inline Time& operator+=(long long delta)
      { m_time += delta; return *this; }

    /**
     * Offsetting operator.
     */
01233     inline Time& operator-=(long long delta)
      { m_time -= delta; return *this; }

    /**
     * Fill in a timeval struct from a value in microseconds
     * @param tv Pointer to the timeval structure
     */
01240     inline void toTimeval(struct timeval *tv) const
      { toTimeval(tv, m_time); }

    /**
     * Fill in a timeval struct from a value in microseconds
     * @param tv Pointer to the timeval structure
     * @param usec Time to convert to timeval
     */
    static void toTimeval(struct timeval *tv, unsigned long long usec);

    /**
     * Convert time in a timeval struct to microseconds
     * @param tv Pointer to the timeval structure
     * @return Corresponding time in microseconds or zero if tv is NULL
     */
    static unsigned long long fromTimeval(struct timeval *tv);

    /**
     * Get the current system time in microseconds
     * @return Time in microseconds since the Epoch
     */
    static unsigned long long now();

private:
    unsigned long long m_time;
};

/**
 * A class to compute and check MD5 digests
 * @short A standard MD5 digest calculator
 */
01271 class MD5
{
public:
    /**
     * Construct a fresh initialized instance
     */
    MD5();

    /**
     * Copy constructor
     * @param original MD5 instance to copy
     */
    MD5(const MD5& original);

    /**
     * Construct a digest from a buffer of data
     * @param buf Pointer to the data to be included in digest
     * @param len Length of data in the buffer
     */
    MD5(const void* buf, unsigned int len);

    /**
     * Construct a digest from a String
     * @param str String to be included in digest
     */
    MD5(const String& str);

    /**
     * Destroy the instance, free allocated memory
     */
    ~MD5();

    /**
     * Assignment operator.
     */
    MD5& operator=(const MD5 &original);

    /**
     * Clear the digest and prepare for reuse
     */
    void clear();

    /**
     * Finalize the digest computation, make result ready.
     * Subsequent calls to @ref update() will fail
     */
    void finalize();

    /**
     * Update the digest from a buffer of data
     * @param buf Pointer to the data to be included in digest
     * @param len Length of data in the buffer
     * @return True if success, false if @ref finalize() was already called
     */
    bool update(const void* buf, unsigned int len);

    /**
     * Update the digest from the content of a String
     * @param str String to be included in digest
     * @return True if success, false if @ref finalize() was already called
     */
01332     inline bool update(const String& str)
      { return update(str.c_str(), str.length()); }

    /**
     * Returns a pointer to the raw 16-byte binary value of the message digest.
     * The digest is finalized if if wasn't already
     * @return Pointer to the raw digest data or NULL if some error occured
     */
    const unsigned char* rawDigest();

    /**
     * Returns the standard hexadecimal representation of the message digest.
     * The digest is finalized if if wasn't already
     * @return A String which holds the hex digest or a null one if some error occured
     */
    const String& hexDigest();

private:
    void init();
    void* m_private;
    String m_hex;
    unsigned char m_bin[16];
};

/**
 * This class holds a named list of named strings
 * @short A named string container class
 */
01360 class NamedList : public String
{
public:
    /**
     * Creates a new named list.
     * @param name Name of the list - must not be NULL or empty
     */
    NamedList(const char *name);

    /**
     * Get the number of parameters
     * @return Count of named strings
     */
01373     inline unsigned int length() const
      { return m_params.length(); }

    /**
     * Get the number of non-null parameters
     * @return Count of existing named strings
     */
01380     inline unsigned int count() const
      { return m_params.count(); }

    /**
     * Add a named string to the parameter list.
     * @param param Parameter to add
     */
    NamedList &addParam(NamedString *param);

    /**
     * Add a named string to the parameter list.
     * @param name Name of the new string
     * @param value Value of the new string
     */
    NamedList &addParam(const char *name, const char *value);

    /**
     * Set a named string in the parameter list.
     * @param param Parameter to set or add
     */
    NamedList &setParam(NamedString *param);

    /**
     * Set a named string in the parameter list.
     * @param name Name of the string
     * @param value Value of the string
     */
    NamedList &setParam(const char *name, const char *value);

    /**
     * Clars all instances of a named string in the parameter list.
     * @param name Name of the string to remove
     */
    NamedList &clearParam(const String &name);

    /**
     * Locate a named string in the parameter list.
     * @param name Name of parameter to locate
     * @return A pointer to the named string or NULL.
     */
    NamedString *getParam(const String &name) const;

    /**
     * Locate a named string in the parameter list.
     * @param index Index of the parameter to locate
     * @return A pointer to the named string or NULL.
     */
    NamedString *getParam(unsigned int index) const;

    /**
     * Retrive the value of a named parameter.
     * @param name Name of parameter to locate
     * @param defvalue Default value to return if not found
     * @return The string contained in the named parameter or the default
     */
    const char *getValue(const String &name, const char *defvalue = 0) const;

private:
    NamedList(); // no default constructor please
    NamedList(const NamedList &value); // no copy constructor
    NamedList& operator=(const NamedList &value); // no assignment please
    ObjList m_params;
};

/**
 * A class for parsing and quickly accessing INI style configuration files
 * @short Configuration file handling
 */
01448 class Configuration : public String
{
public:
    /**
     * Create an empty configuration
     */
    Configuration();

    /**
     * Create a configuration from a file
     * @param filename Name of file to initialize from
     */
    Configuration(const char *filename);

    /**
     * Assignment from string operator
     */
01465     inline Configuration& operator=(const String &value)
      { String::operator=(value); return *this; }

    /**
     * Get the number of sections
     * @return Count of sections
     */
01472     inline unsigned int sections() const
      { return m_sections.length(); }

    /**
     * Retrive an entire section
     * @param index Index of the section
     * @return The section's content or NULL if no such section
     */
    NamedList *getSection(unsigned int index) const;

    /**
     * Retrive an entire section
     * @param sect Name of the section
     * @return The section's content or NULL if no such section
     */
    NamedList *getSection(const String &sect) const;

    /**
     * Locate a key/value pair in the section.
     * @param sect Name of the section
     * @param key Name of the key in section
     * @return A pointer to the key/value pair or NULL.
     */
    NamedString *getKey(const String &sect, const String &key) const;

    /**
     * Retrive the value of a key in a section.
     * @param sect Name of the section
     * @param key Name of the key in section
     * @param defvalue Default value to return if not found
     * @return The string contained in the key or the default
     */
    const char *getValue(const String &sect, const String &key, const char *defvalue = 0) const;

    /**
     * Retrive the numeric value of a key in a section.
     * @param sect Name of the section
     * @param key Name of the key in section
     * @param defvalue Default value to return if not found
     * @return The number contained in the key or the default
     */
    int getIntValue(const String &sect, const String &key, int defvalue = 0) const;

    /**
     * Retrive the numeric value of a key in a section trying first a table lookup.
     * @param sect Name of the section
     * @param key Name of the key in section
     * @param tokens A pointer to an array of tokens to try to lookup
     * @param defvalue Default value to return if not found
     * @return The number contained in the key or the default
     */
    int getIntValue(const String &sect, const String &key, const TokenDict *tokens, int defvalue = 0) const;

    /**
     * Retrive the boolean value of a key in a section.
     * @param sect Name of the section
     * @param key Name of the key in section
     * @param defvalue Default value to return if not found
     * @return The boolean value contained in the key or the default
     */
    bool getBoolValue(const String &sect, const String &key, bool defvalue = false) const;

    /**
     * Deletes an entire section
     * @param sect Name of section to delete, NULL to delete all
     */
    void clearSection(const char *sect = 0);

    /**
     * Deletes a key/value pair
     * @param sect Name of section
     * @param key Name of the key to delete
     */
    void clearKey(const String &sect, const String &key);

    /**
     * Add the value of a key in a section.
     * @param sect Name of the section, will be created if missing
     * @param key Name of the key to add in the section
     * @param value Value to set in the key
     */
    void addValue(const String &sect, const char *key, const char *value = 0);

    /**
     * Set the value of a key in a section.
     * @param sect Name of the section, will be created if missing
     * @param key Name of the key in section, will be created if missing
     * @param value Value to set in the key
     */
    void setValue(const String &sect, const char *key, const char *value = 0);

    /**
     * Set the numeric value of a key in a section.
     * @param sect Name of the section, will be created if missing
     * @param key Name of the key in section, will be created if missing
     * @param value Value to set in the key
     */
    void setValue(const String &sect, const char *key, int value);

    /**
     * Set the boolean value of a key in a section.
     * @param sect Name of the section, will be created if missing
     * @param key Name of the key in section, will be created if missing
     * @param value Value to set in the key
     */
    void setValue(const String &sect, const char *key, bool value);

    /**
     * Load the configuration from file
     * @return True if successfull, false for failure
     */
    bool load();

    /**
     * Save the configuration to file
     * @return True if successfull, false for failure
     */
    bool save() const;

private:
    Configuration(const Configuration &value); // no copy constructor
    Configuration& operator=(const Configuration &value); // no assignment please
    ObjList *getSectHolder(const String &sect) const;
    ObjList *makeSectHolder(const String &sect);
    ObjList m_sections;
};

class MessageDispatcher;

/**
 * This class holds the messages that are moved around in the engine.
 * @short A message container class
 */
01605 class Message : public NamedList
{
    friend class MessageDispatcher;
public:
    /**
     * Creates a new message.
     *
     * @param name Name of the message - must not be NULL or empty
     * @param retval Default return value
     */
    Message(const char *name, const char *retval = 0);

    /**
     * Retrive a reference to the value returned by the message.
     * @return A reference to the value the message will return
     */
01621     inline String &retValue()
      { return m_return; }

    /**
     * Retrive the obscure data associated with the message
     * @return Pointer to arbitrary user data
     */
01628     inline void *userData() const
      { return m_data; }

    /**
     * Set obscure data associated with the message
     * @param _data Pointer to arbitrary user data
     */
01635     inline void userData(void *_data)
      { m_data = _data; }

    /**
     * Retrive a reference to the creation time of the message.
     * @return A reference to the Time when the message was created
     */
01642     inline Time &msgTime()
      { return m_time; }

    /**
     * Name assignment operator
     */
01648     inline Message& operator=(const char *value)
      { String::operator=(value); return *this; }

    /**
     * Encode the message into a string adequate for sending for processing
     * to an external communication interface
     * @param id Unique identifier to add to the string
     */
    String encode(const char *id) const;

    /**
     * Encode the message into a string adequate for sending as answer
     * to an external communication interface
     * @param received True if message was processed locally
     * @param id Unique identifier to add to the string
     */
    String encode(bool received, const char *id) const;

    /**
     * Decode a string from an external communication interface for processing
     * in the engine. The message is modified accordingly.
     * @param str String to decode
     * @param id A String object in which the identifier is stored
     * @return -2 for success, -1 if the string was not a text form of a
     * message, index of first erroneous character if failed
     */
    int decode(const char *str, String &id);

    /**
     * Decode a string from an external communication interface that is an
     * answer to a specific external processing request.
     * @param str String to decode
     * @param received Pointer to variable to store the dispatch return value
     * @param id The identifier expected
     * @return -2 for success, -1 if the string was not the expected answer,
     * index of first erroneous character if failed
     */
    int decode(const char *str, bool &received, const char *id);

protected:
    /**
     * Notify the message it has been dispatched
     */
01691     virtual void dispatched(bool accepted)
      { }

private:
    Message(); // no default constructor please
    Message(const Message &value); // no copy constructor
    Message& operator=(const Message &value); // no assignment please
    String m_return;
    Time m_time;
    void *m_data;
    void commonEncode(String &str) const;
    int commonDecode(const char *str, int offs);
};

/**
 * The purpose of this class is to hold a message received method that is
 *  called for matching messages. It holds as well the matching criteria
 *  and priority among other handlers.
 * @short A message handler
 */
01711 class MessageHandler : public String
{
    friend class MessageDispatcher;
public:
    /**
     * Creates a new message handler.
     * @param name Name of the handled message - may be NULL
     * @param priority Priority of the handler, 0 = top
     */
    MessageHandler(const char *name, unsigned priority = 100);

    /**
     * Handler destructor.
     */
    virtual ~MessageHandler();

    /**
     * This method is called whenever the registered name matches the message.
     * @param msg The received message
     * @return True to stop processing, false to try other handlers
     */
    virtual bool received(Message &msg) = 0;

    /**
     * Find out the priority of the handler
     * @return Stored priority of the handler, 0 = top
     */
01738     inline unsigned priority() const
      { return m_priority; }

private:
    unsigned m_priority;
    MessageDispatcher *m_dispatcher;
};

/**
 * A multiple message receiver to be invoked by a message relay
 * @short A multiple message receiver
 */
01750 class MessageReceiver : public GenObject
{
public:
    /**
     * This method is called from the message relay.
     * @param msg The received message
     * @param id The identifier with which the relay was created
     * @return True to stop processing, false to try other handlers
     */
    virtual bool received(Message &msg, int id) = 0;
};

/**
 * A message handler that allows to relay several messages to a single receiver
 * @short A message handler relay
 */
01766 class MessageRelay : public MessageHandler
{
public:
    /**
     * Creates a new message relay.
     * @param name Name of the handled message - may be NULL
     * @param receiver Receiver of th relayed messages
     * @param id Numeric identifier to pass to receiver
     * @param priority Priority of the handler, 0 = top
     */
01776     MessageRelay(const char *name, MessageReceiver *receiver, int id, int priority = 100)
      : MessageHandler(name,priority), m_receiver(receiver), m_id(id) { }

    /**
     * This method is called whenever the registered name matches the message.
     * @param msg The received message
     * @return True to stop processing, false to try other handlers
     */
01784     virtual bool received(Message &msg)
      { return m_receiver ? m_receiver->received(msg,m_id) : false; }

private:
    MessageReceiver *m_receiver;
    int m_id;
};

class MutexPrivate;
class ThreadPrivate;

/**
 * A simple mutual exclusion for locking access between threads
 * @short Mutex support
 */
01799 class Mutex
{
    friend class MutexPrivate;
public:
    /**
     * Construct a new unlocked fast mutex
     */
    Mutex();

    /**
     * Construct a new unlocked mutex
     * @param recursive True if the mutex has to be recursive (reentrant),
     *  false for a normal fast mutex
     */
    Mutex(bool recursive);

    /**
     * Copt constructor creates a shared mutex
     * @param original Reference of the mutex to share
     */
    Mutex(const Mutex &orginal);

    /**
     * Destroy the mutex
     */
    ~Mutex();

    /**
     * Assignment operator makes the mutex shared with the original
     * @param original Reference of the mutex to share
     */
    Mutex& operator=(const Mutex &original);

    /**
     * Attempt to lock the mutex and eventually wait for it
     * @param maxait Time in microseconds to wait for the mutex, -1 wait forever
     * @return True if successfully locked, false on failure
     */
    bool lock(long long int maxwait = -1);

    /**
     * Unlock the mutex, does never wait
     */
    void unlock();

    /**
     * Check if the mutex is currently locked - as it's asynchronous it
     *  guarantees nothing if other thread changes the mutex's status
     * @return True if the mutex was locked when the function was called
     */
    bool locked() const;

    /**
     * Check if the mutex is unlocked (try to lock and unlock the mutex)
     * @param maxait Time in microseconds to wait for the mutex, -1 wait forever
     * @return True if successfully locked and unlocked, false on failure
     */
    bool check(long long int maxwait = -1);

    /**
     * Check if this mutex is recursive or not
     * @return True if this is a recursive mutex
     */
    bool recursive() const;

    /**
     * Get the number of mutexes counting the shared ones only once
     * @return Count of individual mutexes
     */
    static int count();

    /**
     * Get the number of currently locked mutexes
     * @return Count of locked mutexes, should be zero at program exit
     */
    static int locks();

private:
    MutexPrivate *privDataCopy() const;
    MutexPrivate *m_private;
};

/**
 * A lock is a stack allocated (automatic) object that locks a mutex on
 *  creation and unlocks it on destruction - typically when exiting a block
 * @short Ephemeral mutex locking object
 */
01886 class Lock
{
public:
    /**
     * Create the lock, try to lock the mutex
     * @param mutex Reference to the mutex to lock
     * @param maxait Time in microseconds to wait for the mutex, -1 wait forever
     */
01894     inline Lock(Mutex &mutex, long long int maxwait = -1)
      { m_mutex = mutex.lock(maxwait) ? &mutex : 0; }

    /**
     * Create the lock, try to lock the mutex
     * @param mutex Pointer to the mutex to lock
     * @param maxait Time in microseconds to wait for the mutex, -1 wait forever
     */
01902     inline Lock(Mutex *mutex, long long int maxwait = -1)
      { m_mutex = (mutex && mutex->lock(maxwait)) ? mutex : 0; }

    /**
     * Destroy the lock, unlock the mutex if it was locked
     */
01908     inline ~Lock()
      { if (m_mutex) m_mutex->unlock(); }

    /**
     * Return a pointer to the mutex this lock holds
     * @return A mutex pointer or NULL if locking failed
     */
01915     inline Mutex *mutex() const
      { return m_mutex; }

    /**
     * Unlock the mutex if it was locked and drop the reference to it
     */
01921     inline void drop()
      { if (m_mutex) m_mutex->unlock(); m_mutex = 0; }

private:
    Mutex *m_mutex;

    /** Make sure no Lock is ever created on heap */
    inline void* operator new(size_t);

    /** Never allocate an array of this class */
    inline void* operator new[](size_t);

    /** No copy constructor */
    inline Lock(const Lock&);
};

/**
 * This class holds the action to execute a certain task, usually in a
 *  different execution thread.
 * @short Encapsulates a runnable task
 */
01942 class Runnable
{
public:
    /**
     * This method is called in another thread to do the actual job.
     * When it returns the job or thread terminates.
     */
    virtual void run() = 0;
};

/**
 * A thread is a separate execution context that exists in the same address
 *  space. Threads make better use of multiple processor machines and allow
 *  blocking one execution thread while allowing other to run.
 * @short Thread support class
 */
01958 class Thread : public Runnable
{
    friend class ThreadPrivate;
public:
    /**
     * This method is called when the current thread terminates.
     */
    virtual void cleanup();

    /**
     * Actually starts running the new thread which lingers after creation
     * @return True if an error occured, false if started ok
     */
    bool startup();

    /**
     * Check if the thread creation failed
     * @return True if an error occured, false if created ok
     */
    bool error() const;

    /**
     * Check if the thread is running or not
     * @return True if running, false if it has terminated or no startup called
     */
    bool running() const;

    /**
     * Give up the currently running timeslice
     */
    static void yield();

    /**
     * Get a pointer to the currently running thread
     * @return A pointer to the current thread or NULL for main thread
     */
    static Thread *current();

    /**
     * Get the number of threads
     * @return Count of threads except the main one
     */
    static int count();

    /**
     * Terminates the current thread.
     */
    static void exit();

    /**
     * Terminates the specified thread.
     */
    void cancel();

    /**
     * Kills all other running threads. Ouch!
     * Must be called from the main thread or it does nothing.
     */
    static void killall();

    /**
     * On some platforms this method kills all other running threads.
     * Must be called after fork() but before any exec*() call.
     */
    static void preExec();

protected:
    /**
     * Creates and starts a new thread
     * @param name Static name of the thread (for debugging purpose only)
     */
    Thread(const char *name = 0);

    /**
     * The destructor is called when the thread terminates
     */
    virtual ~Thread();

private:
    ThreadPrivate *m_private;
};

/**
 * The dispatcher class is a hub that holds a list of handlers to be called
 *  for the messages that pass trough the hub. It can also handle a queue of
 *  messages that are typically dispatched by a separate thread.
 * @short A message dispatching hub
 */
02046 class MessageDispatcher : public GenObject
{
public:
    /**
     * Creates a new message dispatcher.
     */
    MessageDispatcher();

    /**
     * Destroys the dispatcher and the installed handlers.
     */
    ~MessageDispatcher();

    /**
     * Installs a handler in the dispatcher.
     * @param handler A pointer to the handler to install
     * @return True on success, false on failure
     */
    bool install(MessageHandler *handler);

    /**
     * Uninstalls a handler from the dispatcher.
     * @param handler A pointer to the handler to uninstall
     * @return True on success, false on failure
     */
    bool uninstall(MessageHandler *handler);

    /**
     * Dispatch a message to the installed handlers
     * @param msg The message to dispatch
     * @return True if one handler accepted it, false if all ignored
     */
    bool dispatch(Message &msg);

    /**
     * Get the number of messages waiting in the queue
     * @return Count of messages in the queue
     */
02084     inline unsigned int queueLength() const
      { return m_messages.count(); }

    /**
     * Put a message in the waiting queue
     * @param msg The message to enqueue, will be destroyed after dispatching
     * @return True if successfully queued, false otherwise
     */
    bool enqueue(Message *msg);

    /**
     * Dispatch all messages from the waiting queue
     */
    void dequeue();

    /**
     * Dispatch one message from the waiting queue
     * @return True if success, false if the queue is empty
     */
    bool dequeueOne();

    /**
     * Clear all the message handlers
     */
02108     inline void clear()
      { m_handlers.clear(); }

    /**
     * Install or remove a hook to catch messages after being dispatched
     * @param hookFunc Pointer to a callback function
     */
02115     inline void setHook(void (*hookFunc)(Message &, bool) = 0)
      { m_hook = hookFunc; }

private:
    ObjList m_handlers;
    ObjList m_messages;
    Mutex m_mutex;
    unsigned int m_changes;
    void (*m_hook)(Message &, bool);
};

/**
 * Initialization and information about plugins.
 * Plugins are located in @em shared libraries that are loaded at runtime.
 *
 *<pre>
 * // Create static Plugin object by using the provided macro
 * INIT_PLUGIN(Plugin);
 *</pre>
 * @short Plugin support
 */
02136 class Plugin : public GenObject
{
public:
    /**
     * Creates a new Plugin container.
     * @param name the undecorated name of the library that contains the plugin
     */
    Plugin(const char *name);

    /**
     * Creates a new Plugin container.
     * Alternate constructor which is also the default.
     */
    Plugin();

    /**
     * Destroys the plugin.
     * The destructor must never be called directly - the Loader will do it when @ref refCount() reaches zero.
     */
    virtual ~Plugin();

    /**
     * Initialize the plugin after it was loaded and registered.
     */
    virtual void initialize() = 0;

    /**
     * Check if the module is actively used.
     * @return True if the plugin is in use, false if should be ok to restart
     */
02166     virtual bool isBusy() const
      { return false; }
};

/**
 * Macro to create static instance of the plugin
 * @param pclass Class of the plugin to create
 */
#define INIT_PLUGIN(pclass) static pclass __plugin

/**
 * This class holds global information about the engine.
 * Note: this is a singleton class.
 *
 * @short Engine globals
 */
02182 class Engine
{
    friend class EnginePrivate;
public:
    /**
     * Main entry point to be called directly from a wrapper program
     * @param argc Argument count
     * @param argv Argument array
     * @param environ Environment variables
     * @return Program exit code
     */
    static int main(int argc, const char **argv, const char **environ);

    /**
     * Run the engine.
     * @return Error code, 0 for success
     */
    int run();

    /**
     * Get a pointer to the unique instance.
     * @return A pointer to the singleton instance of the engine
     */
    static Engine *self();

    /**
     * Register or unregister a plugin to the engine.
     * @param plugin A pointer to the plugin to (un)register
     * @param reg True to register (default), false to unregister
     * @return True on success, false on failure
     */
    static bool Register(const Plugin *plugin, bool reg = true);

    /**
     * The configuration directory path
     */
02218     inline static String configFile(const char *name)
      { return s_cfgpath+"/"+name+s_cfgsuffix; }

    /**
     * The configuration directory path
     */
02224     inline static String &configPath()
      { return s_cfgpath; }

    /**
     * The module loading path
     */
02230     inline static String &modulePath()
      { return s_modpath; }

    /**
     * The module suffix
     */
02236     inline static String &moduleSuffix()
      { return s_modsuffix; }

    /**
     * Reinitialize the plugins
     */
    static void init();

    /**
     * Stop the engine and the entire program
     * @param code Return code of the program
     */
    static void halt(unsigned int code);

    /**
     * Check if the engine is currently exiting
     * @return True if exiting, false in normal operation
     */
02254     static bool exiting()
      { return (s_haltcode != -1); }

    /**
     * Installs a handler in the dispatcher.
     * @param handler A pointer to the handler to install
     * @return True on success, false on failure
     */
    static bool install(MessageHandler *handler);

    /**
     * Uninstalls a handler drom the dispatcher.
     * @param handler A pointer to the handler to uninstall
     * @return True on success, false on failure
     */
    static bool uninstall(MessageHandler *handler);

    /**
     * Enqueue a message in the message queue
     * @param msg The message to enqueue, will be destroyed after dispatching
     * @return True if enqueued, false on error (already queued)
     */
    static bool enqueue(Message *msg);

    /**
     * Convenience function.
     * Enqueue a new parameterless message in the message queue
     * @param name Name of the parameterless message to put in queue
     * @return True if enqueued, false on error (already queued)
     */
02284     inline static bool enqueue(const char *name)
      { return (name && *name) ? enqueue(new Message(name)) : false; }

    /**
     * Dispatch a message to the registered handlers
     * @param msg Pointer to the message to dispatch
     * @return True if one handler accepted it, false if all ignored
     */
    static bool dispatch(Message *msg);

    /**
     * Dispatch a message to the registered handlers
     * @param msg The message to dispatch
     * @return True if one handler accepted it, false if all ignored
     */
    static bool dispatch(Message &msg);

    /**
     * Convenience function.
     * Dispatch a parameterless message to the registered handlers
     * @param name The name of the message to create and dispatch
     * @return True if one handler accepted it, false if all ignored
     */
    static bool dispatch(const char *name);

    /**
     * Install or remove a hook to catch messages after being dispatched
     * @param hookFunc Pointer to a callback function
     */
02313     inline void setHook(void (*hookFunc)(Message &, bool) = 0)
      { m_dispatcher.setHook(hookFunc); }

    /**
     * Get a count of plugins that are actively in use
     * @return Count of plugins in use
     */
    int usedPlugins();

protected:
    /**
     * Destroys the engine and everything. You must not call it directly,
     * @ref run() will do it for you.
     */
    ~Engine();

    /**
     * Loads one plugin from a shared object file
     * @return True if success, false on failure
     */
    bool loadPlugin(const char *file);

    /**
     * Loads the plugins from the plugins directory
     */
    void loadPlugins();

    /**
     * Initialize all registered plugins
     */
    void initPlugins();

private:
    Engine();
    ObjList m_libs;
    MessageDispatcher m_dispatcher;
    static Engine *s_self;
    static String s_cfgpath;
    static String s_cfgsuffix;
    static String s_modpath;
    static String s_modsuffix;
    static int s_haltcode;
    static int s_maxworkers;
    static bool s_init;
    static bool s_dynplugin;
};

}; // namespace TelEngine

#endif /* __TELENGINE_H */

Generated by  Doxygen 1.6.0   Back to index