#ifndef MAPPING_H__ #define MAPPING_H__ 1 #include "driver.h" #include "typedefs.h" #include "svalue.h" /* --- Types --- */ /* --- struct mapping: the mapping datatypes --- */ /* The main structure of a mapping */ struct mapping_s { p_int ref; /* Number of references */ struct hash_mapping *hash; /* 'dirty' part of the mapping */ struct condensed_mapping *condensed; /* 'clean' part of the mapping. If this pointer is NULL, the mapping * is pending for final deallocation. */ wiz_list_t *user; /* Save who made the mapping */ p_int num_values; /* Number of values per key */ }; /* The 'dirty' part of a mapping. * * It is allocated big enough for chains[] to hold all (.mask+1) chain * heads. The number of chains is chosen, and if necessary increased, * so that the average length of a chain is less or equal two entries. */ struct hash_mapping { p_int mask; /* Index mask for chains[], converting the raw hash value into * the valid index number using a bit-and operation. * Incremented by one, it's the number of chains. */ p_int used; /* Number of entries in the hash */ p_int condensed_deleted; /* Number of entries deleted from the condensed part */ p_int ref; /* Refcount if this mapping is part of a T_PROTECTOR_MAPPING svalue. * The value is <= the mappings main refcount. */ struct map_chain *deleted; /* Protector mappings only: list of deleted entries, which are kept * pending because the they may still be used as destination for * a lvalue. */ mapping_t *next_dirty; /* Next dirty mapping in the list */ struct map_chain *chains[ 1 /* +.mask */ ]; /* The hash chain heads ('hash buckets') */ }; /* One 'dirty' entry in a mapping. * It is allocated big enough for data[] to hold all values. */ struct map_chain { struct map_chain *next; /* next dirty entry in hash_mapping chain */ svalue_t key; /* the key value */ svalue_t data[1]; /* the data values */ /* &data == &key+1 is used in some places, like in copy_mapping() * or resize_mapping() */ }; /* The 'clean' part of a mapping. * * The memory layout is a bit complicated... */ struct condensed_mapping { /* svalue_t m_values[ ... ]; * * The values associated with the following misc (non-string) keys. * The association is (with num values per key): * * misc[x] -> m_values[num * x .. num * x + num - 1] * * svalue_t misc[ ... ] * * The misc keys and their associated values. * Invalid keys have the svalue-type T_INVALID, the associated * values are (usually) all svalue-0; and both are always located at * the end of the array. */ p_int misc_size; /* Total size of the misc key values in byte(!) */ p_int string_size; /* Total size of the string key pointers in byte(!) */ /* Using the size in Byte for these two values allows a faster setup * for the search when indexing */ /* char *string[ ... ]; * * Pointer to the key strings. Uneven pointer values denote * deleted/invalidated keys and no longer point to valid * memory, the associated values are (usually) all svalue-0. * * svalue_t s_values[ ... ]; * * The values associated with the preceeding string keys. * The association is (with num values per key): * * string[x] -> s_values[num * x .. num * x + num - 1] */ }; /* --- Macros --- */ #define CM_MISC(m) ((svalue_t *)(m)) /* For condensed_mapping <m>, return a pointer to the svalue * after the last misc key in that mapping. */ #define CM_STRING(m) ((char **) ((m)+1)) /* For condensed_mapping <m>, return a pointer to the first * string key in that mapping. */ #define MAP_CHAIN_SIZE(n) (\ (sizeof(struct map_chain) - sizeof(svalue_t) ) +\ sizeof(svalue_t)*(n) ) /* Size of a map_chain structure for <n> values */ #define MAP_SIZE(m) (\ (m)->condensed->string_size / sizeof(char *) + \ (m)->condensed->misc_size / sizeof(svalue_t) + \ ((m)->hash ? (m)->hash->used - (m)->hash->condensed_deleted : 0) \ ) /* Size of a given mapping <m>. */ /* mapping_t *ref_mapping(mapping_t *m) * Add another ref to mapping <m> and return the mapping <m>. */ #define ref_mapping(m) ((m)->ref++, (m)) /* void free_mapping(mapping_t *m) * Subtract one ref from mapping <m>, and free the mapping fully if * the refcount reaches zero. */ #define free_mapping(m) MACRO( if (--((m)->ref) <= 0) _free_mapping(m); ) /* p_int deref_mapping(mapping_t *m) * Subtract one ref from mapping <m>, but don't check if it needs to * be freed. Result is the number of refs left. */ #define deref_mapping(m) (--(m)->ref) /* --- Variables --- */ extern mp_int num_mappings; extern mp_int num_dirty_mappings; /* --- Prototypes --- */ extern mapping_t *allocate_mapping(mp_int size, mp_int num_values); extern void _free_mapping(mapping_t *m); extern void free_empty_mapping(mapping_t *m); extern void free_protector_mapping(mapping_t *m); extern svalue_t *_get_map_lvalue(mapping_t *m, svalue_t *map_index, Bool need_lvalue, Bool check_size); #define get_map_value(m,x) _get_map_lvalue(m,x,MY_FALSE, MY_TRUE) #define get_map_lvalue(m,x) _get_map_lvalue(m,x,MY_TRUE, MY_TRUE) #define get_map_lvalue_unchecked(m,x) _get_map_lvalue(m,x,MY_TRUE, MY_FALSE) extern void check_map_for_destr(mapping_t *m); extern void remove_mapping(mapping_t *m, svalue_t *map_index); extern mapping_t *copy_mapping(mapping_t *m); extern mapping_t *resize_mapping(mapping_t *m, mp_int new_width); extern mapping_t *add_mapping(mapping_t *m1, mapping_t *m2); extern void walk_mapping(mapping_t *m, void (*func)(svalue_t *key, svalue_t *val, void *extra), void *extra); extern void compact_mappings(mp_int num); extern mp_int total_mapping_size(void); extern void set_mapping_user(mapping_t *m, object_t *owner); extern vector_t *m_indices(mapping_t *m); extern void sub_from_mapping_filter(svalue_t *key, svalue_t *data, void *extra); extern void add_to_mapping(mapping_t *m1, mapping_t *m2); extern mapping_t *subtract_mapping(mapping_t *minuend, mapping_t *subtrahend); extern svalue_t *x_filter_mapping(svalue_t *sp, int num_arg, Bool bFull); extern svalue_t *f_filter_indices (svalue_t *sp, int num_arg); extern svalue_t *x_map_mapping(svalue_t *sp, int num_arg, Bool bFull); extern svalue_t *f_map_indices (svalue_t *sp, int num_arg); extern svalue_t *f_walk_mapping(svalue_t *sp, int num_arg); extern svalue_t *f_m_reallocate (svalue_t *sp); #ifdef DEBUG extern void check_dirty_mapping_list(void); #endif #ifdef GC_SUPPORT extern void count_ref_in_mapping(mapping_t *m); extern void clean_stale_mappings(void); extern void clear_mapping_size (void); extern void count_mapping_size (mapping_t *m); #endif #endif /* MAPPING_H__ */