/* * METADATA - Common set of routines for handling data according to * flexible definitions. * * Author: * Emile van Bergen, emile@evbergen.xs4all.nl * * Permission to redistribute an original or modified version of this program * in source, intermediate or object code form is hereby granted exclusively * under the terms of the GNU General Public License, version 2. Please see the * file COPYING for details, or refer to http://www.gnu.org/copyleft/gpl.html. * * History: * 2000/12/12 - EvB - Created * 2000/12/27 - EvB - Added the meta_add_ functions * Added the META_VND type * 2001/01/18 - EvB - Added the out_ fields in the fixed field and attribute * types * 2001/02/06 - EvB - Removed them again - will first write the thing * without the whole canonicalisation of A/V list idea. * 2001/02/11 - EvB - Removed separate tag meta definitions; will use separate * types instead. * - Renamed all members to according to how they're written * in the dictionary. * 2001/03/17 - EvB - Unified the attribute and fixed field types * - Changed numeric references to pointers for speed * - Moved all higher-level things, including a dictionary * reader and encoding / decoding functions to another * file. * 2001/04/17 - EvB - Added META_VAL type, to define names for numeric values * 2001/07/10 - EvB - Added meta_getitembyspec here as we need that in more * places than just the compiler. * 2001/09/13 - EvB - Added nodec and noenc item options that affect * meta_decode (only follow subspaces, ignore data) and * meta_buildtree/meta_encode (ignore), resp. This * obsoletes the MT_IGNORE data type. * 2002/12/12 - EvB - Fixed incorrect behaviour of meta_getitemby*, which used * META_ORD_ERR as a wildcard for vendor numbers; introduced * META_VND_WILD for that purpose instead. * 2004/07/15 - EvB - Made signed chars explicitly signed as they should be * 2005/06/15 - EvB - Added 'max_size' to specify maximum value size before * splitting (used by buildtree) * 2005/12/05 - EvB - Changed META_ORD to unsigned. Signed arithmetic is the * exception in the code and behaviour files, not the rule. */ #ifndef __METADATA_H #define __METADATA_H 1 /* * INCLUDES & DEFINES */ #include /* For XXX_MAX */ /* * TYPES */ /* Because of performance requirements, all fields described by the meta definitions below must fit in a natural datatype for the host, so that those fields can be handled as a normal ordinal, which greatly facilitates common operations like searching etc. This type defines that host type. */ typedef unsigned long META_ORD; /* Some semaphore values - use these only in the contexts they're defined for, * that is, vendor- or attribute/item numbers. When META_ORD represents user * or network input, these values are not allowed to get specific treatment! */ #define META_ORD_ERR ((-LONG_MAX)-1) /* eq. of -128 resp. -32768 */ #define META_VND_WILD (-LONG_MAX) /* eq. of -127, specifies a search disregarding vendor */ #define META_VND_ANY META_ORD_ERR /* search for attributes specifically allowed for any vendor; attributes having vendor=x end up here. */ /* Another fixed definition: names. They have a fixed length, so that data structures containing them can be allocated with one operation. Any assignment or comparison can be done assuming a standard ASCIIZ format case-sensitive string. */ #define META_NAME_LEN 64 typedef char META_NAME[META_NAME_LEN]; #define META_SPEC_LEN (3 * META_NAME_LEN + 2) typedef char META_SPEC[META_SPEC_LEN]; /* Forward declarations of structures */ typedef struct meta_spc META_SPC; typedef struct meta_vnd META_VND; typedef struct meta_item META_ITEM; typedef struct meta_val META_VAL; /* Definition applying to a particular a/v data space. This describes the attribute field of all attributes in this space. Because _the_ identifier of an attribute within a space is this value, all attributes within a space must agree upon its definition. A space that cannot define its attribute fields isn't worth much. */ struct meta_spc { META_SPC *next; META_ORD nr; META_NAME name; char atr_ofs, atr_size, resv0, resv1; /* Describes attribute field */ char vnd_ofs, vnd_size, resv2; /* Describes vendor field */ char single; /* Single attribute flag */ META_ITEM *enc_items; /* Encapsulating items */ META_ITEM *items; /* List of items within space. There MUST at least be a default item within this list, nr. META_ORD_ERR */ }; /* Definition mapping a vendor's number to its name and vice-versa. a vendor defines no attribute properties by itself. This structure exists only to be able to associate a particular vendor name with its IANA-registered number. Note that the space isn't part of the primary key, so vendor names and numbers are to be unique among all (protocol) spaces. */ struct meta_vnd { META_VND *next; META_ORD nr; META_NAME name; }; /* Definition that applies to a particular data item (fixed field or attribute/value style) */ struct meta_item { META_ITEM *next; META_ORD nr; META_ORD vnd; /* Vendor, only for AV items */ META_NAME name; signed char len_ofs, len_size, len_adj, resv0; signed char val_ofs, val_size, val_type, resv1; char nodec, noenc, keeprej, keepacct; /* flags */ META_ORD max_size; /* limit to val_size before we split. Calculated in meta_additem if not given */ META_SPC *spc; /* The space this is part of */ META_SPC *subspace; /* The space inside this item */ META_VAL *values; /* List of defined constant values for this item. Only for convenience, just like vendor names .*/ }; /* Definition for a possible value of a particular item. */ struct meta_val { META_VAL *next; META_ORD nr; META_NAME name; }; /* The lists to search in. This is not very efficient; e.g. a separate attribute list per space or even vendor could be a lot faster, or perhaps even an avl tree based on the attribute ordinal. We should experiment with this. */ typedef struct meta { META_SPC *spaces; /* The list of spaces */ META_VND *vendors; /* There SHOULD at least be a default vendor in this list with nr. META_ORD_ERR */ } META; /* I'm not defining any actual data types for values here, because a. they primarily have to do with the meaning of values, not how they should be handled at these lower layers, b. because the only place where type definitions really matter is where the values are constructed (in parsers), compared or printed, and none of that is done here. */ /* * PROTOTYPES */ /* CREATION / DELETION */ META *meta_new(); void meta_del(META *m); /* LOW LEVEL UTILITY FUNCTIONS */ /* These two functions handle arbitrarily aligned ordinal values of arbitrary size up to sizeof(META_ORD), in network order. */ META_ORD getord(char *data, int size); void putord(char *data, int size, META_ORD ord); /* This function initializes a META_NAME pointed to by 'name' with the ASCIIZ string at 's', while doing proper bounds checking and zero termination. */ void setname(char *name, char *s); void setname_n(char *name, char *s, int slen); void setspec_n(char *spec, char *s, int slen); /* HANDLING SPACES */ META_SPC *meta_addspc(META *m, META_ORD nr, char *name, char atr_ofs, char atr_size, char vnd_ofs, char vnd_size, char single); META_SPC *meta_getspcbynr(META *m, META_ORD nr); META_SPC *meta_getspcbyname(META *m, char *name); /* HANDLING VENDORS */ META_VND *meta_addvnd(META *m, META_ORD nr, char *name); META_VND *meta_getvndbynr(META *m, META_ORD nr); META_VND *meta_getvndbyname(META *m, char *name); /* HANDLING DATA ITEMS */ META_ITEM *meta_additem(META *m, META_SPC *s, META_ORD nr, META_ORD vnd, char *name, char len_ofs, char len_size, char len_adj, char val_ofs, char val_size, char val_type, META_SPC *subspace, char nodec, char noenc, char keeprej, char keepacct); META_ITEM *meta_getitembynr(META *m, META_SPC *s, META_ORD nr, META_ORD vnd); META_ITEM *meta_getitembyname(META *m, META_SPC *s, char *name, META_ORD vnd); META_ITEM *meta_getitembyspec(META *m, char *spec); /* HANDLING VALUES */ META_VAL *meta_addval(META *m, META_ITEM *i, META_ORD nr, char *name); META_VAL *meta_getvalbynr(META *m, META_ITEM *i, META_ORD nr); META_VAL *meta_getvalbyname(META *m, META_ITEM *i, char *name); #endif