📄 ssl_util_table.c
字号:
void *(*malloc_f)(size_t size), void *(*calloc_f)(size_t number, size_t size), void *(*realloc_f)(void *ptr, size_t size), void (*free_f)(void *ptr)){ table_t *table_p = NULL; unsigned int buck_n; /* allocate a table structure */ if (malloc_f != NULL) table_p = malloc_f(sizeof(table_t)); else table_p = malloc(sizeof(table_t)); if (table_p == NULL) { if (error_p != NULL) *error_p = TABLE_ERROR_ALLOC; return NULL; } if (bucket_n > 0) buck_n = bucket_n; else buck_n = DEFAULT_SIZE; /* allocate the buckets which are NULLed */ if (calloc_f != NULL) table_p->ta_buckets = (table_entry_t **)calloc_f(buck_n, sizeof(table_entry_t *)); else table_p->ta_buckets = (table_entry_t **)calloc(buck_n, sizeof(table_entry_t *)); if (table_p->ta_buckets == NULL) { if (error_p != NULL) *error_p = TABLE_ERROR_ALLOC; if (free_f != NULL) free_f(table_p); else free(table_p); return NULL; } /* initialize structure */ table_p->ta_magic = TABLE_MAGIC; table_p->ta_flags = 0; table_p->ta_bucket_n = buck_n; table_p->ta_entry_n = 0; table_p->ta_data_align = 0; table_p->ta_linear.tl_magic = 0; table_p->ta_linear.tl_bucket_c = 0; table_p->ta_linear.tl_entry_c = 0; table_p->ta_file_size = 0; table_p->ta_malloc = malloc_f != NULL ? malloc_f : malloc; table_p->ta_calloc = calloc_f != NULL ? calloc_f : calloc; table_p->ta_realloc = realloc_f != NULL ? realloc_f : realloc; table_p->ta_free = free_f != NULL ? free_f : free; if (error_p != NULL) *error_p = TABLE_ERROR_NONE; return table_p;}/* * int table_attr * * DESCRIPTION: * * Set the attributes for the table. The available attributes are * specified at the top of table.h. * * RETURNS: * * Success - TABLE_ERROR_NONE * * Failure - Table error code. * * ARGUMENTS: * * table_p - Pointer to a table structure which we will be altering. * * attr - Attribute(s) that we will be applying to the table. */int table_attr(table_t * table_p, const int attr){ if (table_p == NULL) return TABLE_ERROR_ARG_NULL; if (table_p->ta_magic != TABLE_MAGIC) return TABLE_ERROR_PNT; table_p->ta_flags = attr; return TABLE_ERROR_NONE;}/* * int table_set_data_alignment * * DESCRIPTION: * * Set the alignment for the data in the table. For data elements * sizeof(long) is recommended unless you use smaller data types * exclusively. * * WARNING: This must be done before any data gets put into the table. * * RETURNS: * * Success - TABLE_ERROR_NONE * * Failure - Table error code. * * ARGUMENTS: * * table_p - Pointer to a table structure which we will be altering. * * alignment - Alignment requested for the data. Must be a power of * 2. Set to 0 for none. */int table_set_data_alignment(table_t * table_p, const int alignment){ int val; if (table_p == NULL) return TABLE_ERROR_ARG_NULL; if (table_p->ta_magic != TABLE_MAGIC) return TABLE_ERROR_PNT; if (table_p->ta_entry_n > 0) return TABLE_ERROR_NOT_EMPTY; /* defaults */ if (alignment < 2) table_p->ta_data_align = 0; else { /* verify we have a base 2 number */ for (val = 2; val < MAX_ALIGNMENT; val *= 2) { if (val == alignment) break; } if (val >= MAX_ALIGNMENT) return TABLE_ERROR_ALIGNMENT; table_p->ta_data_align = alignment; } return TABLE_ERROR_NONE;}/* * int table_clear * * DESCRIPTION: * * Clear out and free all elements in a table structure. * * RETURNS: * * Success - TABLE_ERROR_NONE * * Failure - Table error code. * * ARGUMENTS: * * table_p - Table structure pointer that we will be clearing. */int table_clear(table_t * table_p){ table_entry_t *entry_p, *next_p; table_entry_t **bucket_p, **bounds_p; if (table_p == NULL) return TABLE_ERROR_ARG_NULL; if (table_p->ta_magic != TABLE_MAGIC) return TABLE_ERROR_PNT; /* free the table allocation and table structure */ bounds_p = table_p->ta_buckets + table_p->ta_bucket_n; for (bucket_p = table_p->ta_buckets; bucket_p < bounds_p; bucket_p++) { for (entry_p = *bucket_p; entry_p != NULL; entry_p = next_p) { /* record the next pointer before we free */ next_p = entry_p->te_next_p; table_p->ta_free(entry_p); } /* clear the bucket entry after we free its entries */ *bucket_p = NULL; } /* reset table state info */ table_p->ta_entry_n = 0; table_p->ta_linear.tl_magic = 0; table_p->ta_linear.tl_bucket_c = 0; table_p->ta_linear.tl_entry_c = 0; return TABLE_ERROR_NONE;}/* * int table_free * * DESCRIPTION: * * Deallocates a table structure. * * RETURNS: * * Success - TABLE_ERROR_NONE * * Failure - Table error code. * * ARGUMENTS: * * table_p - Table structure pointer that we will be freeing. */int table_free(table_t * table_p){ int ret; if (table_p == NULL) return TABLE_ERROR_ARG_NULL; if (table_p->ta_magic != TABLE_MAGIC) return TABLE_ERROR_PNT; ret = table_clear(table_p); if (table_p->ta_buckets != NULL) table_p->ta_free(table_p->ta_buckets); table_p->ta_magic = 0; table_p->ta_free(table_p); return ret;}/* * int table_insert_kd * * DESCRIPTION: * * Like table_insert except it passes back a pointer to the key and * the data buffers after they have been inserted into the table * structure. * * This routine adds a key/data pair both of which are made up of a * buffer of bytes and an associated size. Both the key and the data * will be copied into buffers allocated inside the table. If the key * exists already, the associated data will be replaced if the * overwrite flag is set, otherwise an error is returned. * * NOTE: be very careful changing the values since the table library * provides the pointers to its memory. The key can _never_ be * changed otherwise you will not find it again. The data can be * changed but its length can never be altered unless you delete and * re-insert it into the table. * * WARNING: The pointers to the key and data are not in any specific * alignment. Accessing the key and/or data as an short, integer, or * long pointer directly can cause problems. * * WARNING: Replacing a data cell (not inserting) will cause the table * linked list to be temporarily invalid. Care must be taken with * multiple threaded programs which are relying on the first/next * linked list to be always valid. * * RETURNS: * * Success - TABLE_ERROR_NONE * * Failure - Table error code. * * ARGUMENTS: * * table_p - Table structure pointer into which we will be inserting a * new key/data pair. * * key_buf - Buffer of bytes of the key that we are inserting. If you * are storing an (int) as the key (for example) then key_buf should * be a (int *). * * key_size - Size of the key_buf buffer. If set to < 0 then the * library will do a strlen of key_buf and add 1 for the '\0'. If you * are storing an (int) as the key (for example) then key_size should * be sizeof(int). * * data_buf - Buffer of bytes of the data that we are inserting. If * it is NULL then the library will allocate space for the data in the * table without copying in any information. If data_buf is NULL and * data_size is 0 then the library will associate a NULL data pointer * with the key. If you are storing a (long) as the data (for * example) then data_buf should be a (long *). * * data_size - Size of the data_buf buffer. If set to < 0 then the * library will do a strlen of data_buf and add 1 for the '\0'. If * you are storing an (long) as the key (for example) then key_size * should be sizeof(long). * * key_buf_p - Pointer which, if not NULL, will be set to the address * of the key storage that was allocated in the table. If you are * storing an (int) as the key (for example) then key_buf_p should be * (int **) i.e. the address of a (int *). * * data_buf_p - Pointer which, if not NULL, will be set to the address * of the data storage that was allocated in the table. If you are * storing an (long) as the data (for example) then data_buf_p should * be (long **) i.e. the address of a (long *). * * overwrite - Flag which, if set to 1, will allow the overwriting of * the data in the table with the new data if the key already exists * in the table. */int table_insert_kd(table_t * table_p, const void *key_buf, const int key_size, const void *data_buf, const int data_size, void **key_buf_p, void **data_buf_p, const char overwrite_b){ int bucket; unsigned int ksize, dsize; table_entry_t *entry_p, *last_p; void *key_copy_p, *data_copy_p; /* check the arguments */ if (table_p == NULL) return TABLE_ERROR_ARG_NULL; if (table_p->ta_magic != TABLE_MAGIC) return TABLE_ERROR_PNT; if (key_buf == NULL) return TABLE_ERROR_ARG_NULL; /* data_buf can be null but size must be >= 0, if it isn't null size != 0 */ if ((data_buf == NULL && data_size < 0) || (data_buf != NULL && data_size == 0)) return TABLE_ERROR_SIZE; /* determine sizes of key and data */ if (key_size < 0) ksize = strlen((char *) key_buf) + sizeof(char); else ksize = key_size; if (data_size < 0) dsize = strlen((char *) data_buf) + sizeof(char); else dsize = data_size; /* get the bucket number via a hash function */ bucket = hash(key_buf, ksize, 0) % table_p->ta_bucket_n; /* look for the entry in this bucket, only check keys of the same size */ last_p = NULL; for (entry_p = table_p->ta_buckets[bucket]; entry_p != NULL; last_p = entry_p, entry_p = entry_p->te_next_p) { if (entry_p->te_key_size == ksize && memcmp(ENTRY_KEY_BUF(entry_p), key_buf, ksize) == 0) break; } /* did we find it? then we are in replace mode. */ if (entry_p != NULL) { /* can we not overwrite existing data? */ if (!overwrite_b) { if (key_buf_p != NULL) *key_buf_p = ENTRY_KEY_BUF(entry_p); if (data_buf_p != NULL) { if (entry_p->te_data_size == 0) *data_buf_p = NULL; else { if (table_p->ta_data_align == 0) *data_buf_p = ENTRY_DATA_BUF(table_p, entry_p); else *data_buf_p = entry_data_buf(table_p, entry_p); } } return TABLE_ERROR_OVERWRITE; } /* re-alloc entry's data if the new size != the old */ if (dsize != entry_p->te_data_size) { /* * First we delete it from the list to keep the list whole. * This properly preserves the linked list in case we have a * thread marching through the linked list while we are * inserting. Maybe this is an unnecessary protection but it * should not harm that much. */ if (last_p == NULL) table_p->ta_buckets[bucket] = entry_p->te_next_p; else last_p->te_next_p = entry_p->te_next_p; /* * Realloc the structure which may change its pointer. NOTE: * this may change any previous data_key_p and data_copy_p * pointers. */ entry_p = (table_entry_t *) table_p->ta_realloc(entry_p, entry_size(table_p, entry_p->te_key_size, dsize)); if (entry_p == NULL) return TABLE_ERROR_ALLOC; /* add it back to the front of the list */ entry_p->te_data_size = dsize; entry_p->te_next_p = table_p->ta_buckets[bucket]; table_p->ta_buckets[bucket] = entry_p; } /* copy or replace data in storage */ if (dsize > 0) { if (table_p->ta_data_align == 0) data_copy_p = ENTRY_DATA_BUF(table_p, entry_p); else data_copy_p = entry_data_buf(table_p, entry_p); if (data_buf != NULL) memcpy(data_copy_p, data_buf, dsize); } else data_copy_p = NULL; if (key_buf_p != NULL) *key_buf_p = ENTRY_KEY_BUF(entry_p); if (data_buf_p != NULL)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -