mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-26 12:53:13 +00:00
Minor performance tweak: Do not allocate any heap memory for hash_table_t until an element is inserted. That way, hash tables that never contain any data will not cause a call to malloc()
darcs-hash:20051026144823-ac50b-570dfe169a2ce693458c493e8f103884de3c5078.gz
This commit is contained in:
parent
5ba0affdd7
commit
c8bc79005c
3 changed files with 110 additions and 36 deletions
12
expand.c
12
expand.c
|
@ -88,11 +88,11 @@ parameter expansion.
|
||||||
#define UNCLEAN L"$*?\\\"'({})"
|
#define UNCLEAN L"$*?\\\"'({})"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Test if the specified argument is clean, i.e. it does not contin
|
Test if the specified argument is clean, i.e. it does not contain
|
||||||
any tokens which are expanded. Clean strings can be passed through
|
any tokens which need to be expanded or otherwise altered. Clean
|
||||||
expand_string and expand_one without changing them. About 90% of
|
strings can be passed through expand_string and expand_one without
|
||||||
all strings are clean, so skipping expantion on them actually does
|
changing them. About 90% of all strings are clean, so skipping
|
||||||
save a small amount of time.
|
expantion on them actually does save a small amount of time.
|
||||||
*/
|
*/
|
||||||
static int is_clean( const wchar_t *in )
|
static int is_clean( const wchar_t *in )
|
||||||
{
|
{
|
||||||
|
@ -114,7 +114,7 @@ static int is_clean( const wchar_t *in )
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Return the environment variable value for the string starting at in
|
Return the environment variable value for the string starting at \c in.
|
||||||
*/
|
*/
|
||||||
static wchar_t *expand_var( wchar_t *in )
|
static wchar_t *expand_var( wchar_t *in )
|
||||||
{
|
{
|
||||||
|
|
49
util.c
49
util.c
|
@ -27,11 +27,16 @@
|
||||||
#include "wutil.h"
|
#include "wutil.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Minimum allocated size for data structures. Used to avoid excessive
|
Minimum allocated size for data structures. Used to avoid excessive
|
||||||
memory allocations for lists, hash tables, etc, which are nearly
|
memory allocations for lists, hash tables, etc, which are nearly
|
||||||
empty.
|
empty.
|
||||||
*/
|
*/
|
||||||
#define MIN_SIZE 128
|
#define MIN_SIZE 32
|
||||||
|
|
||||||
|
/**
|
||||||
|
Minimum size for hash tables
|
||||||
|
*/
|
||||||
|
#define HASH_MIN_SIZE 7
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Maximum number of characters that can be inserted using a single
|
Maximum number of characters that can be inserted using a single
|
||||||
|
@ -191,7 +196,11 @@ void hash_init( hash_table_t *h,
|
||||||
int (*hash_func)(const void *key),
|
int (*hash_func)(const void *key),
|
||||||
int (*compare_func)(const void *key1, const void *key2) )
|
int (*compare_func)(const void *key1, const void *key2) )
|
||||||
{
|
{
|
||||||
hash_init2( h, hash_func, compare_func, 31 );
|
h->arr = 0;
|
||||||
|
h->size = 0;
|
||||||
|
h->count=0;
|
||||||
|
h->hash_func = hash_func;
|
||||||
|
h->compare_func = compare_func;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -207,8 +216,11 @@ void hash_destroy( hash_table_t *h )
|
||||||
static int hash_search( hash_table_t *h,
|
static int hash_search( hash_table_t *h,
|
||||||
const void *key )
|
const void *key )
|
||||||
{
|
{
|
||||||
int hv = h->hash_func( key );
|
int hv;
|
||||||
int pos = abs(hv) % h->size;
|
int pos;
|
||||||
|
|
||||||
|
hv = h->hash_func( key );
|
||||||
|
pos = abs(hv) % h->size;
|
||||||
while(1)
|
while(1)
|
||||||
{
|
{
|
||||||
if( (h->arr[pos].key == 0 ) ||
|
if( (h->arr[pos].key == 0 ) ||
|
||||||
|
@ -229,9 +241,9 @@ static int hash_realloc( hash_table_t *h,
|
||||||
{
|
{
|
||||||
|
|
||||||
/* Avoid reallocating when using pathetically small tables */
|
/* Avoid reallocating when using pathetically small tables */
|
||||||
if( ( sz < h->size ) && (h->size < MIN_SIZE))
|
if( ( sz < h->size ) && (h->size < HASH_MIN_SIZE))
|
||||||
return 1;
|
return 1;
|
||||||
sz = maxi( sz, MIN_SIZE );
|
sz = maxi( sz, HASH_MIN_SIZE );
|
||||||
|
|
||||||
hash_struct_t *old_arr = h->arr;
|
hash_struct_t *old_arr = h->arr;
|
||||||
int old_size = h->size;
|
int old_size = h->size;
|
||||||
|
@ -294,6 +306,9 @@ int hash_put( hash_table_t *h,
|
||||||
const void *hash_get( hash_table_t *h,
|
const void *hash_get( hash_table_t *h,
|
||||||
const void *key )
|
const void *key )
|
||||||
{
|
{
|
||||||
|
if( !h->count )
|
||||||
|
return 0;
|
||||||
|
|
||||||
int pos = hash_search( h, key );
|
int pos = hash_search( h, key );
|
||||||
if( h->arr[pos].key == 0 )
|
if( h->arr[pos].key == 0 )
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -304,6 +319,9 @@ const void *hash_get( hash_table_t *h,
|
||||||
const void *hash_get_key( hash_table_t *h,
|
const void *hash_get_key( hash_table_t *h,
|
||||||
const void *key )
|
const void *key )
|
||||||
{
|
{
|
||||||
|
if( !h->count )
|
||||||
|
return 0;
|
||||||
|
|
||||||
int pos = hash_search( h, key );
|
int pos = hash_search( h, key );
|
||||||
if( h->arr[pos].key == 0 )
|
if( h->arr[pos].key == 0 )
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -321,6 +339,16 @@ void hash_remove( hash_table_t *h,
|
||||||
const void **old_key,
|
const void **old_key,
|
||||||
const void **old_val )
|
const void **old_val )
|
||||||
{
|
{
|
||||||
|
if( !h->count )
|
||||||
|
{
|
||||||
|
|
||||||
|
if( old_key != 0 )
|
||||||
|
*old_key = 0;
|
||||||
|
if( old_val != 0 )
|
||||||
|
*old_val = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int pos = hash_search( h, key );
|
int pos = hash_search( h, key );
|
||||||
int next_pos;
|
int next_pos;
|
||||||
|
|
||||||
|
@ -377,6 +405,9 @@ void hash_remove( hash_table_t *h,
|
||||||
int hash_contains( hash_table_t *h,
|
int hash_contains( hash_table_t *h,
|
||||||
const void *key )
|
const void *key )
|
||||||
{
|
{
|
||||||
|
if( !h->count )
|
||||||
|
return 0;
|
||||||
|
|
||||||
int pos = hash_search( h, key );
|
int pos = hash_search( h, key );
|
||||||
return h->arr[pos].key != 0;
|
return h->arr[pos].key != 0;
|
||||||
}
|
}
|
||||||
|
|
75
util.h
75
util.h
|
@ -136,14 +136,17 @@ typedef buffer_t string_buffer_t;
|
||||||
Returns the larger of two ints
|
Returns the larger of two ints
|
||||||
*/
|
*/
|
||||||
int maxi( int a, int b );
|
int maxi( int a, int b );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Returns the smaller of two ints
|
Returns the smaller of two ints
|
||||||
*/
|
*/
|
||||||
int mini( int a, int b );
|
int mini( int a, int b );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Returns the larger of two floats
|
Returns the larger of two floats
|
||||||
*/
|
*/
|
||||||
float maxf( float a, float b );
|
float maxf( float a, float b );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Returns the smaller of two floats
|
Returns the smaller of two floats
|
||||||
*/
|
*/
|
||||||
|
@ -161,14 +164,19 @@ float minf( float a, float b );
|
||||||
returned.
|
returned.
|
||||||
*/
|
*/
|
||||||
void q_init( dyn_queue_t *q );
|
void q_init( dyn_queue_t *q );
|
||||||
|
|
||||||
/** Destroy the queue */
|
/** Destroy the queue */
|
||||||
void q_destroy( dyn_queue_t *q );
|
void q_destroy( dyn_queue_t *q );
|
||||||
|
|
||||||
/** Insert element into queue */
|
/** Insert element into queue */
|
||||||
int q_put( dyn_queue_t *q, void *e );
|
int q_put( dyn_queue_t *q, void *e );
|
||||||
|
|
||||||
/** Remove and return next element from queue */
|
/** Remove and return next element from queue */
|
||||||
void *q_get( dyn_queue_t *q);
|
void *q_get( dyn_queue_t *q);
|
||||||
|
|
||||||
/** Return next element from queue without removing it */
|
/** Return next element from queue without removing it */
|
||||||
void *q_peek( dyn_queue_t *q);
|
void *q_peek( dyn_queue_t *q);
|
||||||
|
|
||||||
/** Returns 1 if the queue is empty, 0 otherwise */
|
/** Returns 1 if the queue is empty, 0 otherwise */
|
||||||
int q_empty( dyn_queue_t *q );
|
int q_empty( dyn_queue_t *q );
|
||||||
|
|
||||||
|
@ -224,6 +232,7 @@ void hash_remove( hash_table_t *h,
|
||||||
const void *key,
|
const void *key,
|
||||||
const void **old_key,
|
const void **old_key,
|
||||||
const void **old_data );
|
const void **old_data );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Checks whether the specified key is in the hash table
|
Checks whether the specified key is in the hash table
|
||||||
*/
|
*/
|
||||||
|
@ -235,16 +244,23 @@ int hash_contains( hash_table_t *h,
|
||||||
*/
|
*/
|
||||||
void hash_get_keys( hash_table_t *h,
|
void hash_get_keys( hash_table_t *h,
|
||||||
array_list_t *arr );
|
array_list_t *arr );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Appends all data elements in the table to the specified list
|
Appends all data elements in the table to the specified list
|
||||||
*/
|
*/
|
||||||
void hash_get_data( hash_table_t *h,
|
void hash_get_data( hash_table_t *h,
|
||||||
array_list_t *arr );
|
array_list_t *arr );
|
||||||
/** Call the function func for each key/data pair in the table*/
|
|
||||||
|
/**
|
||||||
|
Call the function func for each key/data pair in the table
|
||||||
|
*/
|
||||||
void hash_foreach( hash_table_t *h,
|
void hash_foreach( hash_table_t *h,
|
||||||
void (*func)( const void *, const void * ) );
|
void (*func)( const void *, const void * ) );
|
||||||
/** Same as hash_foreach, but the function func takes an additional
|
|
||||||
* argument, which is provided by the caller in the variable aux */
|
/**
|
||||||
|
Same as hash_foreach, but the function func takes an additional
|
||||||
|
argument, which is provided by the caller in the variable aux
|
||||||
|
*/
|
||||||
void hash_foreach2( hash_table_t *h, void (*func)( const void *,
|
void hash_foreach2( hash_table_t *h, void (*func)( const void *,
|
||||||
const void *,
|
const void *,
|
||||||
void *),
|
void *),
|
||||||
|
@ -269,10 +285,11 @@ int hash_wcs_func( const void *data );
|
||||||
*/
|
*/
|
||||||
int hash_wcs_cmp( const void *a, const void *b );
|
int hash_wcs_cmp( const void *a, const void *b );
|
||||||
|
|
||||||
/** Initialize the priority queue
|
/**
|
||||||
|
Initialize the priority queue
|
||||||
|
|
||||||
\param q the queue to initialize
|
\param q the queue to initialize
|
||||||
\param compare a comparison function that can compare two entries in the queue
|
\param compare a comparison function that can compare two entries in the queue
|
||||||
*/
|
*/
|
||||||
void pq_init( priority_queue_t *q,
|
void pq_init( priority_queue_t *q,
|
||||||
int (*compare)(void *e1, void *e2) );
|
int (*compare)(void *e1, void *e2) );
|
||||||
|
@ -289,6 +306,7 @@ int pq_put( priority_queue_t *q,
|
||||||
Removes and returns the last entry in the priority queue
|
Removes and returns the last entry in the priority queue
|
||||||
*/
|
*/
|
||||||
void *pq_get( priority_queue_t *q );
|
void *pq_get( priority_queue_t *q );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Returns the last entry in the priority queue witout removing it.
|
Returns the last entry in the priority queue witout removing it.
|
||||||
*/
|
*/
|
||||||
|
@ -314,10 +332,16 @@ void pq_destroy( priority_queue_t *q );
|
||||||
*/
|
*/
|
||||||
array_list_t *al_new();
|
array_list_t *al_new();
|
||||||
|
|
||||||
/** Initialize the list. */
|
/**
|
||||||
|
Initialize the list.
|
||||||
|
*/
|
||||||
void al_init( array_list_t *l );
|
void al_init( array_list_t *l );
|
||||||
/** Destroy the list and free memory used by it.*/
|
|
||||||
|
/**
|
||||||
|
Destroy the list and free memory used by it.
|
||||||
|
*/
|
||||||
void al_destroy( array_list_t *l );
|
void al_destroy( array_list_t *l );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Append element to list
|
Append element to list
|
||||||
|
|
||||||
|
@ -327,6 +351,7 @@ void al_destroy( array_list_t *l );
|
||||||
\return 1 if succesfull, 0 otherwise
|
\return 1 if succesfull, 0 otherwise
|
||||||
*/
|
*/
|
||||||
int al_push( array_list_t *l, const void *o );
|
int al_push( array_list_t *l, const void *o );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Append all elements of a list to another
|
Append all elements of a list to another
|
||||||
|
|
||||||
|
@ -335,6 +360,7 @@ int al_push( array_list_t *l, const void *o );
|
||||||
\return 1 if succesfull, 0 otherwise
|
\return 1 if succesfull, 0 otherwise
|
||||||
*/
|
*/
|
||||||
int al_push_all( array_list_t *a, array_list_t *b );
|
int al_push_all( array_list_t *a, array_list_t *b );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Sets the element at the specified index
|
Sets the element at the specified index
|
||||||
|
|
||||||
|
@ -343,6 +369,7 @@ int al_push_all( array_list_t *a, array_list_t *b );
|
||||||
\param o The element
|
\param o The element
|
||||||
*/
|
*/
|
||||||
int al_set( array_list_t *l, int pos, const void *o );
|
int al_set( array_list_t *l, int pos, const void *o );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Returns the element at the specified index
|
Returns the element at the specified index
|
||||||
|
|
||||||
|
@ -351,26 +378,37 @@ int al_set( array_list_t *l, int pos, const void *o );
|
||||||
\return The element
|
\return The element
|
||||||
*/
|
*/
|
||||||
const void *al_get( array_list_t *l, int pos );
|
const void *al_get( array_list_t *l, int pos );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Truncates the list to new_sz items.
|
Truncates the list to new_sz items.
|
||||||
*/
|
*/
|
||||||
void al_truncate( array_list_t *l, int new_sz );
|
void al_truncate( array_list_t *l, int new_sz );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Removes and returns the last entry in the list
|
Removes and returns the last entry in the list
|
||||||
*/
|
*/
|
||||||
const void *al_pop( array_list_t *l );
|
const void *al_pop( array_list_t *l );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Returns the number of elements in the list
|
Returns the number of elements in the list
|
||||||
*/
|
*/
|
||||||
int al_get_count( array_list_t *l );
|
int al_get_count( array_list_t *l );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Returns the last entry in the list witout removing it.
|
Returns the last entry in the list witout removing it.
|
||||||
*/
|
*/
|
||||||
const void *al_peek( array_list_t *l );
|
const void *al_peek( array_list_t *l );
|
||||||
/** Returns 1 if the list is empty, 0 otherwise*/
|
|
||||||
|
/**
|
||||||
|
Returns 1 if the list is empty, 0 otherwise
|
||||||
|
*/
|
||||||
int al_empty( array_list_t *l);
|
int al_empty( array_list_t *l);
|
||||||
/** Call the function func for each entry in the list*/
|
|
||||||
|
/**
|
||||||
|
Call the function func for each entry in the list
|
||||||
|
*/
|
||||||
void al_foreach( array_list_t *l, void (*func)(const void * ));
|
void al_foreach( array_list_t *l, void (*func)(const void * ));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Same as al_foreach, but the function func takes an additional
|
Same as al_foreach, but the function func takes an additional
|
||||||
argument, which is provided by the caller in the variable aux
|
argument, which is provided by the caller in the variable aux
|
||||||
|
@ -400,7 +438,9 @@ void al_foreach2( array_list_t *l, void (*func)(const void *, void *), void *aux
|
||||||
|
|
||||||
Which most people would find more intuitive.
|
Which most people would find more intuitive.
|
||||||
|
|
||||||
The system breaks down if the user is using numbers of a base larger than 10.
|
This won't return the optimum results for numbers in bases higher
|
||||||
|
than ten, such as hexadecimal, but at least a stable sort order
|
||||||
|
will result.
|
||||||
*/
|
*/
|
||||||
int wcsfilecmp( const wchar_t *a, const wchar_t *b );
|
int wcsfilecmp( const wchar_t *a, const wchar_t *b );
|
||||||
|
|
||||||
|
@ -432,19 +472,21 @@ void sb_append_char( string_buffer_t *, wchar_t );
|
||||||
Append a null terminated list of strings to the buffer.
|
Append a null terminated list of strings to the buffer.
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
sb_append2( my_buff, L"foo", L"bar", 0 );
|
sb_append2( my_buff, L"foo", L"bar", (void *)0 );
|
||||||
|
|
||||||
|
Do not forget to cast the last 0 to (void *), or you might encounter errors on 64-bit platforms!
|
||||||
*/
|
*/
|
||||||
void sb_append2( string_buffer_t *, ... );
|
void sb_append2( string_buffer_t *, ... );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Append formated string data to the buffer. This function internally
|
Append formated string data to the buffer. This function internally
|
||||||
relies on \c vswprintf, so any filter options supported by that
|
relies on \c vswprintf, so any filter options supported by that
|
||||||
function is also supported by this function
|
function is also supported by this function.
|
||||||
*/
|
*/
|
||||||
int sb_printf( string_buffer_t *buffer, const wchar_t *format, ... );
|
int sb_printf( string_buffer_t *buffer, const wchar_t *format, ... );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Vararg version of sb_printf
|
Vararg version of sb_printf.
|
||||||
*/
|
*/
|
||||||
int sb_vprintf( string_buffer_t *buffer, const wchar_t *format, va_list va_orig );
|
int sb_vprintf( string_buffer_t *buffer, const wchar_t *format, va_list va_orig );
|
||||||
|
|
||||||
|
@ -454,15 +496,16 @@ int sb_vprintf( string_buffer_t *buffer, const wchar_t *format, va_list va_orig
|
||||||
void sb_destroy( string_buffer_t * );
|
void sb_destroy( string_buffer_t * );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Truncate the buffer.
|
Truncate the buffer. This will not deallocate the memory used, it will only set the contents of the string to L"\0".
|
||||||
*/
|
*/
|
||||||
void sb_clear( string_buffer_t * );
|
void sb_clear( string_buffer_t * );
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Initialize the specified buffer_t
|
Initialize the specified buffer_t
|
||||||
*/
|
*/
|
||||||
void b_init( buffer_t *b);
|
void b_init( buffer_t *b);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Destroy the specified buffer_t
|
Destroy the specified buffer_t
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in a new issue