|
|
// 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. |