Source: ../common/misc.h


Annotated List
Files
Globals
Hierarchy
Index
// Copyright (C) 1999-2000 Open Source Telecom Corporation.
//  
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software 
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
// 
// As a special exception to the GNU General Public License, permission is 
// granted for additional uses of the text contained in its release 
// of Common C++.
// 
// The exception is that, if you link the Common C++ library with other
// files to produce an executable, this does not by itself cause the
// resulting executable to be covered by the GNU General Public License.
// Your use of that executable is in no way restricted on account of
// linking the Common C++ library code into it.
// 
// This exception does not however invalidate any other reasons why
// the executable file might be covered by the GNU General Public License.
// 
// This exception applies only to the code released under the 
// name Common C++.  If you copy code from other releases into a copy of
// Common C++, as the General Public License permits, the exception does
// not apply to the code that you add in this way.  To avoid misleading
// anyone as to the status of such modified files, you must delete
// this exception notice from them.
// 
// If you write modifications of your own for Common C++, it is your choice
// whether to permit this exception to apply to your modifications.
// If you do not wish that, delete this exception notice.  

#ifndef	__CCXX_MISC_H__
#define	__CCXX_MISC_H__

#ifndef __CCXX_THREAD_H__
#include <cc++/thread.h>
#endif

#include <fstream.h>

#define	KEYDATA_INDEX_SIZE	97
#define	KEYDATA_PAGER_SIZE	512
#define KEYDATA_PATH_SIZE	256

#pragma pack(1)

typedef struct _keyval
{
	struct _keyval *next;
	char val[1];
}	keyval_t;

typedef struct _keysym
{
	struct _keysym *next;
	struct _keyval *data;
	char **list;
	short count;
	char sym[1];
}	keysym_t;

typedef	struct
{
	char *keyword;
	char *value;
}	KEYDEF;

#pragma pack()

/**
 * The memory pager is used to allocate cumulative memory pages for
 * storing object specific "persistant" data that is presumed to persist
 * during the life of a given derived object.  When the object is
 * destroyed, all accumulated data is automatically purged.
 *
 * @author David Sugar <dyfet@ostel.com>
 * @short Accumulative object memory allocator.
 */
class __EXPORT MemPager
{
private:
	int pagesize;
	int pages;

	struct _page
	{
		struct _page *next;
		int used;
	} *page;

protected:
	/**
	 * Allocate first workspace from paged memory.  This method
	 * scans all currently allocated blocks for available space
	 * before adding new pages and hence is both slower and more
	 * efficient.
	 *
	 * @param size of memory to allocate.
	 * @return pointer to allocated memory.
	 */
	virtual void *first(size_t size);

	/**
	 * Allocate memory from either the currently active page, or
	 * allocate a new page for the object.
	 *
	 * @param size of memory to allocate.
	 * @return pointer to allocated memory.
	 */
	virtual void *alloc(size_t size);

	/**
	 * Allocate a string from the memory pager pool and copy the
	 * string into it's new memory area.  This method allocates
	 * memory by first searching for an available page, and then
	 * allocating a new page if no space is found.
	 *
	 * @param str to allocate and copy into paged memory pool.
	 * @return copy of string from allocated memory.
	 */
	char *first(char *str);

	/**
	 * Allocate a string from the memory pager pool and copy the
	 * string inti it's new memory area.  This checks only the
	 * last active page for available space before allocating a
	 * new page.
	 *
	 * @param str to allocate and copy into paged memory pool.
	 * @return copy of string from allocated memory.
	 */
	char *alloc(char *str);

	/**
	 * Create a paged memory pool for cumulative storage.  This
	 * pool allocates memory in fixed "pagesize" chunks.  Ideal
	 * performance is achived when the pool size matches the
	 * system page size.  This pool can only exist in derived
	 * objects.
	 *
	 * @param pagesize to allocate chunks.
	 */
	MemPager(int pagesize = 4096);

	/**
	 * purge the current memory pool.
	 */
	void purge(void);

	/**
	 * Delete the memory pool and all allocated memory.
	 */
	~MemPager();

public:
	/**
	 * Return the total number of pages that have been allocated
	 * for this memory pool.
	 *
	 * @return number of pages allocated.
	 */
	inline int getPages(void)
		{return pages;};
};

/**
 * The shared mempager uses a mutex to protect key access methods.
 * This class is used when a mempager will be shared by multiple
 * threads.
 *
 * @author David Sugar <dyfet@ostel.com>
 * @short mutex protected memory pager.
 */
class __EXPORT SharedMemPager : public MemPager, public Mutex
{
protected:
	/**
	 * Create a mempager mutex pool.
	 *
	 * @param pagesize for allocation.
	 */
	SharedMemPager(int pg = 4096);

	/**
	 * Purge the memory pool while locked.
 	 */
	void purge(void);

	/**
	 * Get the first memory page after locking.
	 *
	 * @return allocated memory space.
	 * @param size of request.
	 */
	void *first(int size);

	/**
	 * Get the last memory page after locking.
	 *
	 * @return allocated memory space.
	 * @param size of request.
	 */
	void *alloc(int size);
};

/**
 * Keydata objects are used to load and hold "configuration" data for
 * a given application.  Each "keydata" object holds the key pairs from
 * a [section] of a text readable config file.  The /etc directory is
 * presumed to hold the referenced file key set unless a ~ is used.
 *
 * Keydata can hold multiple values for the same key pair.  This can
 * occur either from storing a "list" of data items in a config file,
 * or when overlaying multiple config sources (such as /etc/....conf and
 * ~/.confrc segments) into a single object.  The keys are stored as
 * cumulative (read-only/replacable) config values under a hash index
 * system for quick retrieval.
 *
 * @author David Sugar <dyfet@ostel.com>
 * @short load text configuration files into keyword pairs.
 */
class __EXPORT Keydata : protected MemPager
{
private:
	static ifstream cfgFile;
	static char lastpath[KEYDATA_PATH_SIZE + 1];
	static int count, sequence;

	int link;

	keysym_t *keys[KEYDATA_INDEX_SIZE];

	/**
	 * Compute a hash key signature id for a symbol name.
	 *
	 * @return key signature index path.
	 * @param symbol name.
	 */
	unsigned getIndex(const char *sym);
protected:
	keysym_t *getSymbol(const char *sym, bool create);

	/**
	 * Load additional key values into the currrent object from
	 * the specfied config source (a config file/section pair).
	 * These values will overlay the current keywords when matches
	 * are found.  This can be used typically in a derived config
	 * object class constructor to first load a /etc section, and
	 * then load a matching user specific entry from ~/. to override
	 * default system values with user specific keyword values.
	 *
	 * @param keypath (filepath/section)
	 */ 
	void Load(const char *keypath);

	/**
	 * Load default keywords into the current object.  This only
	 * loads keyword entries which have not already been defined
	 * to reduce memory usage.  This form of Load is also commonly
	 * used in the constructor of a derived Keydata class.
	 *
	 * @param list of NULL terminated default keyword/value pairs.
	 */
	void Load(KEYDEF *pairs);
	
public:
	/**
	 * Create an empty key data object.
	 */
	Keydata();

	/**
	 * Create a new key data object and use "Load" method to load an
	 * initial config file section into it.
	 *
	 * @param keypath (filepath/section)
	 */
	Keydata(const char *keypath);

	/**
	 * Destroy the keydata object and all allocated memory.  This
	 * may also clear the "cache" file stream if no other keydata
	 * objects currently reference it.
	 */
	~Keydata();

	/**
	 * Unlink the keydata object from the cache file stream.  This
	 * should be used if you plan to keepa Keydata object after it
	 * is loaded once all keydata objects have been loaded, otherwise
	 * the cfgFile stream will remain open.  You can also use
	 * endKeydata().
	 */
	void Unlink(void);

	/**
	 * Get a count of the number of data "values" that is associated
	 * with a specific keyword.  Each value is from an accumulation of
	 * "load()" requests.
	 *
	 * @param keyword symbol name.
	 * @return count of values associated with keyword.
	 */
	int getCount(const char *sym);

	/**
	 * Get the first data value for a given keyword.  This will
	 * typically be the /etc set global default.
	 *
	 * @param keyword symbol name.
	 * @return first set value for this symbol.
	 */
	char *getFirst(const char *sym);

	/**
	 * Get the last (most recently set) value for a given keyword.
	 * This is typically the value actually used.
	 *
	 * @param keywork symbol name.
	 * @return last set value for this symbol.
	 */
	char *getLast(const char *sym);

	/**
	 * Get an index array of ALL keywords that are stored by the
	 * current keydata object.
	 *
	 * @return number of keywords found.
	 * @param data pointer of array to hold keyword strings.
	 * @param max number of entries the array can hold.
	 */
	int getIndex(char **data, int max);

	/**
	 * Set (replace) the value of a given keyword.  This new value
	 * will become the value returned from getLast(), while the
	 * prior value will still be stored and found from getList().
	 *
	 * @param keyword name to set.
	 * @param data string to store for the keyword.
	 */
	void setValue(const char *sym, const char *data);

	/**
	 * Return a list of all values set for the given keyword
	 * returned in order.
	 *
	 * @return list pointer of array holding all keyword values.
	 * @param keyword name to fetch.
	 */
	char **getList(const char *sym);

	/**
	 * Clear all values associated with a given keyword.  This does
	 * not de-allocate the keyword from memory, however.
	 *
	 * @return keyword name to clear.
	 */
	void clrValue(const char *sym);

	/**
	 * A convient notation for accessing the keydata as an associative
	 * array of keyword/value pairs through the [] operator.
	 */
	inline char *operator[](const char *keyword)
		{return getLast(keyword);};

	/**
	 * Shutdown the file stream cache.  This should be used before
	 * detaching a deamon, exec(), fork(), etc.
	 */
	friend void endKeydata(void);	
};

#endif


Generated by: dyfet@home.sys on Tue Apr 18 21:24:04 200.