// 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 APE.
//
// The exception is that, if you link the APE 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 APE 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 APE. If you copy code from other releases into a copy of
// APE, 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 APE, 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 __APE_MISC_H__
#define __APE_MISC_H__
#ifndef __APE_THREAD_H__
#include <APE/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;
char data[0];
} *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.
*/
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.
*/
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;};
};
/**
* 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 : private 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 Mar 7 09:18:03 200. |