Logo Search packages:      
Sourcecode: wvstreams version File versions

uniconfgen.h

/* -*- Mode: C++ -*-
 * Worldvisions Weaver Software:
 *   Copyright (C) 2002 Net Integration Technologies, Inc.
 * 
 * An abstract data container that backs a UniConf tree.
 */
#ifndef __UNICONFGEN_H
#define __UNICONFGEN_H
 
#include "wvxplc.h"
#include "uniconfkey.h"
#include "wvcallback.h"
#include "wvlinklist.h"
#include "uniconfpair.h"

class UniConfGen;

/**
 * The callback type for signalling key changes from a UniConfGen.
 * 
 * Generators that wrap other generators should catch notifications
 * and reissue them using themselves as the "gen" parameter and their
 * userdata as the "userdata parameter".  This can be done effectively by
 * invoking the delta() function on receipt of a notification from a
 * wrapped generator.  See UniFilterGen.
 * 
 * Parameters: gen, key, userdata
 *   gen - the externally visible generator whose key has changed
 *   key - the key that has changed
 *   userdata - the userdata supplied during setcallback
 */
typedef WvCallback<void, const UniConfKey &, WvStringParm, void *> 
    UniConfGenCallback;

/**
 * An abstract data container that backs a UniConf tree.
 *
 * This is intended to be implemented to provide support for fetching
 * and storing keys and values using different access methods.
 */
00041 class IUniConfGen : public IObject
{
public:
    virtual ~IUniConfGen();
    
    /***** Notification API *****/
    
    /** Sets the callback for change notification. */
    virtual void setcallback(const UniConfGenCallback &callback,
                       void *userdata) = 0;
    

    /***** Status API *****/
    
    /**
     * Determines if the generator is usable and working properly.
     * The default implementation always returns true.
     */
    virtual bool isok() = 0;

    
    /***** Key Persistence API *****/
    
    /** Commits any changes. The default implementation does nothing. */
    virtual void commit() = 0;
    
    /**
     * Refreshes information about a key recursively.
     * May discard uncommitted data.
     *
     * The default implementation always returns true.
     */
    virtual bool refresh() = 0;

    /** 
     * Flushes any commitment/notification buffers . 
     *
     * The default implementation always returns true.
     *  NOTE: This method should be 'protected'
     */
    virtual void flush_buffers() = 0;

    /***** Key Retrieval API *****/
    
    /**
     * Indicate that we will eventually be interested in doing get(),
     * haschildren(), or other "get-like" operations on a particular key
     * or tree of keys.  The generator may be able to speed up these
     * operations by, say, caching them in advance.
     * 
     * This function is not allowed to do blocking operations.  It is allowed
     * to do nothing at all, however, and then get() might block later.
     */
    virtual void prefetch(const UniConfKey &key, bool recursive) = 0;
    
    /**
     * Fetches a string value for a key from the registry.  If the key doesn't
     * exist, the return value has .isnull() == true.
     */
    virtual WvString get(const UniConfKey &key) = 0;
    
    /**
     * Without fetching its value, returns true if a key exists.
     *
     * This is provided because it is often more efficient to
     * test existance than to actually retrieve the value.
     *
     * The default implementation returns !get(key).isnull().
     */
    virtual bool exists(const UniConfKey &key) = 0;


    /**
     * Converts a string to an integer.  If the string is null or not
     * recognized, return defvalue. 
     *
     * This is here to support the common str2int(get(key)).
     *
     * The default implementation recognizes the booleans 'true', 'yes', 'on'
     * and 'enabled' as 1, and 'false', 'no', 'off' and 'disabled' as 0.
     */
    virtual int str2int(WvStringParm s, int defvalue) const = 0;

    
    /***** Key Storage API *****/
    
    /**
     * Stores a string value for a key into the registry.  If the value is
     * WvString::null, the key is deleted.
     * 
     * Returns true on success.
     */
    virtual void set(const UniConfKey &key, WvStringParm value) = 0;


    /***** Key Enumeration API *****/
    
    /**
     * Returns true if a key has children.
     *
     * This is provided because it is often more efficient to
     * test existance than to actually retrieve the keys.
     * 
     * The default implementation uses the iterator returned by iterator()
     * to test whether the child has any keys.
     * Subclasses are strongly encouraged to provide a better implementation.
     */
    virtual bool haschildren(const UniConfKey &key) = 0;

    /** The abstract iterator type (see below) */
    class Iter;

    /** A concrete null iterator type (see below) */
    class NullIter;
    
    /** An iterator over a constant list of keys (see below) */
    class ListIter;

    /**
     * Returns an iterator over the children of the specified key.
     * May return NULL or an empty iterator if the key has no children.
     *
     * The caller takes ownership of the returned iterator and is responsible
     * for deleting it when finished.
     */
    virtual Iter *iterator(const UniConfKey &key) = 0;
    
    /**
     * Like iterator(), but the returned iterator is recursive, that is,
     * it will return children of the immediate children, not just the
     * immediate children themselves.
     * 
     * May return NULL if the key has no immediate children (since that means
     * there are also no indirect children).
     * 
     * Note that UniConfGen::recursiveiterator() is a default
     * implementation that just calls iterator() recursively, so it'll work
     * in any derived class without you overriding this function.  However,
     * you might want to do it anyway if it would be more efficient in your
     * particular case.
     */
    virtual Iter *recursiveiterator(const UniConfKey &key) = 0;
};

DEFINE_IID(IUniConfGen, {0x7ca76e98, 0xb694, 0x43ca,
    {0xb0, 0x56, 0x8b, 0x9d, 0xde, 0x9a, 0xbe, 0x9f}});


/**
 * A default implementation of IUniConfGen, providing various handy features
 * that save trouble when implementing typical generators.
 */
00193 class UniConfGen : public IUniConfGen
{
    IMPLEMENT_IOBJECT(UniConfGen);

    // These fields are deliberately hidden to encourage use of the
    // special notification members

00200     UniConfGenCallback cb; //!< gets called whenever a key changes its value.
    void *cbdata;
    int hold_nesting;
    UniConfPairList deltas;
    
protected:
    /** Creates a UniConfGen object. */
    UniConfGen();

public:
    /** Destroys the UniConfGen and may discard uncommitted data. */
    virtual ~UniConfGen();

    /***** Notification API *****/
    
    /**
     * Sets the callback for change notification.
     * Must not be reimplemented by subclasses.
     */
    void setcallback(const UniConfGenCallback &callback, void *userdata);
    
    /**
     * Immediately sends notification that a key has possibly changed.
     * Takes care of the details of invoking the callback.
     *
     * Note: You probably want to be using delta() instead.
     */
    void dispatch_delta(const UniConfKey &key, WvStringParm value);

    /**
     * Pauses notifications until matched with a call to unhold_delta().
     * 
     * While paused, notification events are placed into a pending list.
     * Redundant notifications may be discarded.
     *
     * Use this to safeguard non-reentrant code.
     */
    void hold_delta();

    /**
     * Resumes notifications when each hold_delta() has been matched.
     * 
     * On resumption, dispatches all pending notifications except
     * those that were destined to watches that were removed.
     * 
     * Use this to safeguard non-reentrant code.
     */
    void unhold_delta();

    /**
     * Clears the list of pending notifications without sending them.
     * Does not affect the hold nesting count.
     */
    void clear_delta();

    /**
     * Flushes the list of pending notifications by sending them.
     * Does not affect the hold nesting count.
     */
    void flush_delta();

    /**
     * Call this when a key's value or children have possibly changed.
     * 
     * If the hold nesting count is 0, the notification is sent immediately.
     * Otherwise it is added to a pending list for later.
     */
    void delta(const UniConfKey &key, WvStringParm value);   
    
    /***** Status API *****/
    virtual bool isok();
    
    /***** Key Persistence API *****/
00273     virtual void commit() { }
00274     virtual bool refresh() { return true; }
00275     virtual void prefetch(const UniConfKey &key, bool recursive) { }
    virtual WvString get(const UniConfKey &key) = 0;
    virtual bool exists(const UniConfKey &key);
    virtual int str2int(WvStringParm s, int defvalue) const;

    /***** Key Storage API *****/
    virtual void set(const UniConfKey &key, WvStringParm value) = 0;

    virtual void flush_buffers() = 0;

    /***** Key Enumeration API *****/
    virtual bool haschildren(const UniConfKey &key);
    virtual Iter *iterator(const UniConfKey &key) = 0;
    
    // a helpful default that just calls iterator() recursively
    virtual Iter *recursiveiterator(const UniConfKey &key);
};

DeclareWvList(IUniConfGen);
DeclareWvList2(UniConfGenList, IUniConfGen);


/**
 * An abstract iterator over keys and values in a generator.
 *
 * Unlike other WvStreams iterators, this one declares virtual methods so
 * that UniConfGen implementations can supply the right behaviour
 * through a common interface that does not depend on static typing.
 *
 * The precise traversal sequence is defined by the iterator implementation.
 *
 * The iterator need not support concurrent modifications of the underlying
 * data structures.
 * 
 * TODO: Consider changing this rule depending on observed usage patterns.
 */
00311 class UniConfGen::Iter
{
public:
    /** Destroys the iterator. */
00315     virtual ~Iter() { }

    /**
     * Rewinds the iterator.
     * Must be called prior to the first invocation of next().
     */
    virtual void rewind() = 0;

    /**
     * Seeks to the next element in the sequence.
     * Returns true if that element exists.
     * Must be called prior to the first invocation of key().
     */
    virtual bool next() = 0;

    /** Returns the current key. */
    virtual UniConfKey key() const = 0;
    
    /** 
     * Returns the value of the current key.  You could just do a get(),
     * but maybe your generator has a more efficient way.
     */
    virtual WvString value() const = 0;
};


/**
 * An iterator that's always empty.
 * This is handy if you don't have anything good to iterate over.
 */
00345 class UniConfGen::NullIter : public UniConfGen::Iter
{
public:
    /***** Overridden members *****/
    
00350     virtual void rewind() { }
00351     virtual bool next() { return false; }
00352     virtual UniConfKey key() const { return UniConfKey::EMPTY; }
00353     virtual WvString value() const { return WvString(); }
};


/**
 * An iterator that iterates through a constant list of keys.  This is
 * handy if you know the list of keys is relatively short, and you don't
 * want to write your own iterator and/or you know your own object state
 * might change during iteration, so you would have to pregenerate the list
 * of keys anyway.
 * 
 * The creator of the iter is responsible for filling the 'keys' and 'values'
 * lists.  If the 'values' list runs out of values before 'keys', the
 * remaining values will be retrieved from the given generator instead.
 */
00368 class UniConfGen::ListIter : public UniConfGen::Iter
{
public:
    IUniConfGen *gen;
    WvList<WvString> keys, values;
    WvList<WvString>::Iter ki, vi;
    
    ListIter(IUniConfGen *_gen);

    /***** Overridden members *****/
    virtual void rewind();
    virtual bool next();
    virtual UniConfKey key() const;
    virtual WvString value() const;
};

#endif // __UNICONFGEN_H

Generated by  Doxygen 1.6.0   Back to index