diff options
author | rideout <rideout@17b73243-c579-4c4c-a9d2-2d5706c11dac> | 2002-04-03 06:28:47 +0000 |
---|---|---|
committer | rideout <rideout@17b73243-c579-4c4c-a9d2-2d5706c11dac> | 2002-04-03 06:28:47 +0000 |
commit | c23ed018c1916d96720e5c2e7c21844dc1958635 (patch) | |
tree | 04d13d1df1dacec558ac7669bc55f0546d51e450 /src/util | |
parent | ca019314ea14ab5aedfe881f1e91a71eeeb9486b (diff) |
[[from Jonathan Thornburg]]
src/util/Table.c
src/include/util_Table.h
* add new functions (cf my E-mail of 30 Mar 2002)
Util_TableClone()
Util_TableItClone()
* add new functions (cf Erik Schnetter's E-mails of 5 Feb 2002)
Util_Table{Set,Get}Generic()
Util_Table{Set,Get}GenericArray()
* add tests for new functions
* fix a memory leak in Util_TableDestroy()
* fixed some assert( variable = value ) bugs (yikes!!)
* refactor some code to better modularize the implementation
* add some more const qualifiers to local vars
* reformat code to match flesh standard indentation and { } conventions
git-svn-id: http://svn.cactuscode.org/flesh/trunk@2683 17b73243-c579-4c4c-a9d2-2d5706c11dac
Diffstat (limited to 'src/util')
-rw-r--r-- | src/util/Table.c | 4225 |
1 files changed, 2527 insertions, 1698 deletions
diff --git a/src/util/Table.c b/src/util/Table.c index 2993547b..a4d8c3ef 100644 --- a/src/util/Table.c +++ b/src/util/Table.c @@ -25,6 +25,7 @@ * Prototypes for Functions Private to This File * Main Table API * Util_TableCreate + * Util_TableClone * Util_TableDestroy * Util_TableQueryFlags * Util_TableQueryNKeys @@ -35,12 +36,17 @@ * Util_TableSetFromString * Util_TableSetString * Util_TableGetString + * Util_TableSetGeneric + * Util_TableSetGenericArray + * Util_TableGetGeneric + * Util_TableGetGenericArray * Util_TableSet* * Util_TableSet*Array * Util_TableGet* * Util_TableGet*Array * Table Iterator API * Util_TableItCreate + * Util_TableItClone * Util_TableItDestroy * Util_TableItQueryIsNull * Util_TableItQueryIsNonNull @@ -54,10 +60,11 @@ * internal_set * internal_get * get_table_header_ptr - * delete_key - * free_table_entry - * bad_key + * is_bad_key * find_table_entry + * insert_table_entry + * delete_table_entry_by_key + * delete_table_entry_by_ptr * get_iterator_ptr * grow_pointer_array #ifdef UTIL_TABLE_TEST @@ -66,21 +73,22 @@ * print_table * print_all_iterators * Standalone Test Driver - * // low-level routines - * CHECK_SET_GET_{INT,REAL,COMPLEX} - * CHECK_SET_GET_{INT,REAL,COMPLEX}_ARRAY - * check_table_contents(int handle) - * // higher-level routines + * CHECK_SET_GET_{INT,GENERIC_INT,REAL,COMPLEX} + * CHECK_SET_GET_{INT,REAL,GENERIC_REAL,COMPLEX}_ARRAY * main * test_nonexistent_tables * test_table_create_destroy * test_set_get * test_set_get_array * test_iterators - * test_delete_key + * test_delete_table_entry * test_set_create_from_string * test_set_get_string - * test_table_contents + * test_clone + * check_table_contents + * check_table_contents_ij + * check_table_contents_real1 + * check_table_contents_real_e #endif */ @@ -93,7 +101,7 @@ typedef enum { false = 0, true = 1 } bool; #ifndef CCODE - #define CCODE /* signal Cactus header files that we're C, not Fortran */ + #define CCODE /* signal Cactus header files that we're C, not Fortran */ #endif #include "cctk_Types.h" @@ -136,7 +144,7 @@ typedef enum { false = 0, true = 1 } bool; * iterators. In both cases we use the same data structure: * * int N_objects; // actual number of tables/iterators - * int N_array; // actual size of growable array + * int N_elements; // actual size of growable array * void *array; // pointer to malloc-allocated growable array * // indexed by handle/ihandle * @@ -177,21 +185,21 @@ typedef enum { false = 0, true = 1 } bool; * this shouldn't be a problem. */ -struct table_entry - { - struct table_entry *next; - char *key; - int type_code; - int N_elements; - void *value; - }; - -struct table_header - { - struct table_entry *head; - int flags; - int handle; - }; +struct table_entry +{ + struct table_entry *next; + char *key; + int type_code; + int N_elements; + void *value; +}; + +struct table_header +{ + struct table_entry *head; + int flags; + int handle; +}; /* * We keep track of all tables with the following variables @@ -222,12 +230,12 @@ void **thp_array = NULL; * Note that we never modify the table through an iterator, * so all the pointers here are to const objects */ -struct iterator - { - const struct table_header *thp; /* must always be non-NULL */ - const struct table_entry *tep; /* NULL for iterator in */ - /* "null-pointer" state */ - }; +struct iterator +{ + const struct table_header *thp; /* must always be non-NULL */ + const struct table_entry *tep; /* NULL for iterator in */ + /* "null-pointer" state */ +}; /* * We keep track of all iterators with the following variables @@ -252,10 +260,7 @@ void **ip_array = NULL; /***** Misc Macros for This File **********************************************/ /******************************************************************************/ -#define then /* empty */ - #define min(x,y) ((x < y) ? (x) : (y)) -#define max(x,y) ((x > y) ? (x) : (y)) /******************************************************************************/ /***** Prototypes for Functions Private to This File **************************/ @@ -306,31 +311,36 @@ static struct table_header *get_table_header_ptr(int handle); /* - * delete a key from a table + * check if key is syntactically "bad" (eg contains '/' character) + * returns true for bad key, false for ok + */ +static + bool is_bad_key(const char *key); + +/* + * delete an entry (specified by its key) from a table * return same as Util_TableDeleteKey(), i.e. * 0 for ok (key existed before this call, and has now been deleted) * -ve for error, including * UTIL_ERROR_TABLE_NO_SUCH_KEY no such key in table */ static - int delete_key(struct table_header *thp, const char *key); - -/* free table entry and key/value it points to */ -static - void free_table_entry(struct table_entry *tep); + int delete_table_entry_by_key(struct table_header *thp, const char *key); /* - * check if key is syntactically "bad" (eg contains '/' character) - * returns true for bad key, false for ok + * delete an entry from a table, + * specifying the entry by a pointer to the entry *before* it, + * or NULL to delete the starting entry in the list */ static - bool bad_key(const char *key); + void delete_table_entry_by_ptr(struct table_header *thp, + struct table_entry *prev_tep); /* * find table entry for a given key * return pointer to it, or NULL if no such key is present in table * if prev_tep_ptr != NULL, - * then also set *prev_tep_ptr to point to table entry one *before* + * also set *prev_tep_ptr to point to table entry one *before* * the one with the given key, or to NULL if the given key is * the starting entry in the table */ @@ -339,6 +349,12 @@ static (const struct table_header *thp, const char *key, struct table_entry **prev_tep_ptr); +/* allocate a new table entry, set its fields to copies of arguments */ +static + int insert_table_entry(struct table_header *thp, + const char *key, + int type_code, int N_elements, const void *value); + /* check iterator handle for validity, return pointer to iterator */ static struct iterator *get_iterator_ptr(int ihandle); @@ -378,9 +394,14 @@ static void test_table_create_destroy(void); static void test_set_get(int handle, bool case_insensitive); static void test_set_get_array(int handle); static void test_iterators(int handle); -static void test_delete_key(int handle, bool case_insensitive); +static void test_delete_table_entry(int handle, bool case_insensitive); static int test_set_create_from_string(void); static void test_set_get_string(int handle, bool case_insensitive); +static void test_clone(int handle); +static void check_table_contents(int handle, bool order_up_flag); +static void check_table_contents_ij(int handle, int ihandle); +static void check_table_contents_real1(int handle, int ihandle); +static void check_table_contents_real_e(int handle, int ihandle); #endif /******************************************************************************/ @@ -412,71 +433,143 @@ static void test_set_get_string(int handle, bool case_insensitive); @@*/ int Util_TableCreate(int flags) { -#ifdef UTIL_TABLE_DEBUG -printf("Util_TableCreate()\n"); -#endif + #ifdef UTIL_TABLE_DEBUG + printf("Util_TableCreate()\n"); + #endif -if (flags < 0) - then return UTIL_ERROR_TABLE_BAD_FLAGS; + if (flags < 0) + return UTIL_ERROR_TABLE_BAD_FLAGS; -if (N_tables == N_thp_array) - then { - /* grow thp_array to get some room to create the new table */ - #ifdef UTIL_TABLE_DEBUG - printf(" growing thp_array[] from old size %d\n", N_thp_array); - #endif - if (grow_pointer_array(&N_thp_array, &thp_array) < 0) - then return UTIL_ERROR_NO_MEMORY; - #ifdef UTIL_TABLE_DEBUG - printf(" to new size %d\n", N_thp_array); - #endif - } + if (N_tables == N_thp_array) + { + /* grow thp_array to get some room to create the new table */ + #ifdef UTIL_TABLE_DEBUG + printf(" growing thp_array[] from old size %d\n", N_thp_array); + #endif + if (grow_pointer_array(&N_thp_array, &thp_array) < 0) + { + return UTIL_ERROR_NO_MEMORY; + } + #ifdef UTIL_TABLE_DEBUG + printf(" to new size %d\n", N_thp_array); + #endif + } -/* we should now have space to create the new table */ -assert(N_tables < N_thp_array); + /* we should now have space to create the new table */ + assert(N_tables < N_thp_array); + + /* find an unused handle */ + #ifdef UTIL_TABLE_DEBUG + printf(" searching for an unused handle (N_tables=%d N_thp_array=%d)\n", + N_tables, N_thp_array); + #endif + { + int handle; + for (handle = 0 ; handle < N_thp_array ; ++handle) + { + #ifdef UTIL_TABLE_DEBUG2 + printf(" checking handle=%d\n", handle); + #endif + if (thp_array[handle] == NULL) + { + /* we've found an unused handle ==> create the table */ + struct table_header *const thp = (struct table_header *) + malloc(sizeof(struct table_header)); + if (thp == NULL) + { + return UTIL_ERROR_NO_MEMORY; + } + + #ifdef UTIL_TABLE_DEBUG + printf(" using handle=%d\n", handle); + #endif + + thp->head = NULL; + thp->flags = flags; + thp->handle = handle; + + ++N_tables; + thp_array[handle] = (void *) thp; + + return handle; + } + } -/* find an unused handle */ -#ifdef UTIL_TABLE_DEBUG -printf(" searching for an unused handle (N_tables=%d N_thp_array=%d)\n", - N_tables, N_thp_array); -#endif + /* we should never get to here! */ + assert(false); + abort(); /* internal error (core dump) */ + /* prevent compiler warning 'function should return a value' */ + return(0); + } +} + +/******************************************************************************/ + +/*@@ + @routine Util_TableClone + @desc This function clones (makes an exact copy of) a table. + (N.b. the order in which an interator sequences through + a table may differ in the clone.) + + @var handle + @vtype int + @vdesc handle to the table to be cloned + @endvar + + @returntype int + @returndesc a handle to the clone table, or + UTIL_ERROR_NO_MEMORY unable to allocate memory + UTIL_ERROR_TABLE_BAD_FLAGS flags < 0 in the to-be-cloned + table (this should never happen) + @endreturndesc + @@*/ +int Util_TableClone(int handle) +{ + const struct table_header *const thp = get_table_header_ptr(handle); + if (thp == NULL) { -int handle; - for (handle = 0 ; handle < N_thp_array ; ++handle) - { - #ifdef UTIL_TABLE_DEBUG2 - printf(" checking handle=%d\n", handle); - #endif - if (thp_array[handle] == NULL) - then { - /* we've found an unused handle ==> create the table */ - struct table_header *const thp - = (struct table_header *) - malloc(sizeof(struct table_header)); - if (thp == NULL) - then return UTIL_ERROR_NO_MEMORY; - - #ifdef UTIL_TABLE_DEBUG - printf(" using handle=%d\n", handle); - #endif - - thp->head = NULL; - thp->flags = flags; - thp->handle = handle; - - ++N_tables; - thp_array[handle] = (void *) thp; - - return handle; - } - } + return UTIL_ERROR_BAD_HANDLE; + } + + { + const int clone_handle = Util_TableCreate(thp->flags); + if (clone_handle < 0) + { + return clone_handle; /* error creating clone table */ + } + + #ifdef UTIL_TABLE_DEBUG + printf("Util_TableClone(handle=%d) ==> clone_handle=%d\n", + handle, clone_handle); + #endif -/* we should never get to here! */ -assert(false); -abort(); /* internal error (core dump) */ -/* prevent compiler warning 'function should return a value' */ -return(0); + /* copy all the table entries */ + { + struct table_header *const clone_thp = get_table_header_ptr(clone_handle); + const struct table_entry *tep; + for (tep = thp->head ; tep != NULL ; tep = tep->next) + { + #ifdef UTIL_TABLE_DEBUG2 + printf(" copying key \"%s\"\n", tep->key); + #endif + { + /* insert_table_entry() does the actual copying */ + int status + = insert_table_entry(clone_thp, + tep->key, + tep->type_code, tep->N_elements, tep->value); + if (status < 0) + { + /* this should cleanup as much as we've done so far */ + Util_TableDestroy(clone_handle); + return status; /* error inserting table entry into clone table */ + } + } } + + return clone_handle; + } + } } /******************************************************************************/ @@ -500,32 +593,27 @@ return(0); @@*/ int Util_TableDestroy(int handle) { -struct table_header *const thp = get_table_header_ptr(handle); -if (thp == NULL) - then return UTIL_ERROR_BAD_HANDLE; + struct table_header *const thp = get_table_header_ptr(handle); + if (thp == NULL) + { + return UTIL_ERROR_BAD_HANDLE; + } -#ifdef UTIL_TABLE_DEBUG -printf("Util_TableDestroy(handle=%d)\n", handle); -#endif + #ifdef UTIL_TABLE_DEBUG + printf("Util_TableDestroy(handle=%d)\n", handle); + #endif -/* delete all the keys */ + /* delete all the keys */ + while (thp->head != NULL) { -struct table_entry *tep, *next_tep; - for (tep = thp->head ; tep != NULL ; tep = next_tep) - { - #ifdef UTIL_TABLE_DEBUG2 - printf(" deleting key \"%s\"\n", tep->key); - #endif - next_tep = tep->next; - free_table_entry(tep); - } + delete_table_entry_by_ptr(thp, NULL); + } ---N_tables; -thp_array[handle] = NULL; -free(thp); + --N_tables; + thp_array[handle] = NULL; + free(thp); -return 0; - } + return 0; } /******************************************************************************/ @@ -547,11 +635,13 @@ return 0; @@*/ int Util_TableQueryFlags(int handle) { -const struct table_header *const thp = get_table_header_ptr(handle); -if (thp == NULL) - then return UTIL_ERROR_BAD_HANDLE; + const struct table_header *const thp = get_table_header_ptr(handle); + if (thp == NULL) + { + return UTIL_ERROR_BAD_HANDLE; + } -return thp->flags; + return thp->flags; } /******************************************************************************/ @@ -574,19 +664,22 @@ return thp->flags; @@*/ int Util_TableQueryNKeys(int handle) { -const struct table_header *const thp = get_table_header_ptr(handle); -if (thp == NULL) - then return UTIL_ERROR_BAD_HANDLE; + const struct table_header *const thp = get_table_header_ptr(handle); + if (thp == NULL) + { + return UTIL_ERROR_BAD_HANDLE; + } + { + int N = 0; + const struct table_entry *tep; + for (tep = thp->head ; tep != NULL ; tep = tep->next) { -int N = 0; -const struct table_entry *tep; - for (tep = thp->head ; tep != NULL ; tep = tep->next) - { - ++N; - } -return N; + ++N; } + + return N; + } } /******************************************************************************/ @@ -608,21 +701,26 @@ return N; @@*/ int Util_TableQueryMaxKeyLength(int handle) { -const struct table_header *const thp = get_table_header_ptr(handle); -if (thp == NULL) - then return UTIL_ERROR_BAD_HANDLE; + const struct table_header *const thp = get_table_header_ptr(handle); + if (thp == NULL) + { + return UTIL_ERROR_BAD_HANDLE; + } + { + int max_length = 0; + const struct table_entry *tep; + for (tep = thp->head ; tep != NULL ; tep = tep->next) { -int max_length = 0; -const struct table_entry *tep; - for (tep = thp->head ; tep != NULL ; tep = tep->next) - { - const int length = strlen(tep->key); - if (length > max_length) - then max_length = length; - } -return max_length; + const int length = strlen(tep->key); + if (length > max_length) + { + max_length = length; + } } + + return max_length; + } } /******************************************************************************/ @@ -680,23 +778,34 @@ int Util_TableQueryValueInfo(int handle, CCTK_INT *type_code, CCTK_INT *N_elements, const char *key) { -const struct table_header *const thp = get_table_header_ptr(handle); -if (thp == NULL) - then return UTIL_ERROR_BAD_HANDLE; + const struct table_header *const thp = get_table_header_ptr(handle); + if (thp == NULL) + { + return UTIL_ERROR_BAD_HANDLE; + } -if (bad_key(key)) - then return UTIL_ERROR_TABLE_BAD_KEY; + if (is_bad_key(key)) { -const struct table_entry *const tep = find_table_entry(thp, key, NULL); -if (tep == NULL) - then return 0; /* no such key in table */ + return UTIL_ERROR_TABLE_BAD_KEY; + } -if (type_code != NULL) - then *type_code = tep->type_code; -if (N_elements != NULL) - then *N_elements = tep->N_elements; -return 1; /* key is in table */ + { + const struct table_entry *const tep = find_table_entry(thp, key, NULL); + if (tep == NULL) + { + return 0; /* no such key in table */ + } + + if (type_code != NULL) + { + *type_code = tep->type_code; } + if (N_elements != NULL) + { + *N_elements = tep->N_elements; + } + return 1; /* key is in table */ + } } /******************************************************************************/ @@ -729,14 +838,18 @@ return 1; /* key is in table */ @@*/ int Util_TableDeleteKey(int handle, const char *key) { -struct table_header *const thp = get_table_header_ptr(handle); -if (thp == NULL) - then return UTIL_ERROR_BAD_HANDLE; + struct table_header *const thp = get_table_header_ptr(handle); + if (thp == NULL) + { + return UTIL_ERROR_BAD_HANDLE; + } -if (bad_key(key)) - then return UTIL_ERROR_TABLE_BAD_KEY; + if (is_bad_key(key)) + { + return UTIL_ERROR_TABLE_BAD_KEY; + } -return delete_key(thp, key); + return delete_table_entry_by_key(thp, key); } /******************************************************************************/ @@ -770,17 +883,21 @@ return delete_key(thp, key); @@*/ int Util_TableCreateFromString(const char string[]) { -const int handle = Util_TableCreate(UTIL_TABLE_FLAGS_CASE_INSENSITIVE); -if (handle < 0) - then return handle; /* error creating table */ - + const int handle = Util_TableCreate(UTIL_TABLE_FLAGS_CASE_INSENSITIVE); + if (handle < 0) { -const int status = Util_TableSetFromString(handle, string); -if (status < 0) - then return status; /* error setting values in table */ + return handle; /* error creating table */ + } -return handle; + { + const int status = Util_TableSetFromString(handle, string); + if (status < 0) + { + return status; /* error setting values in table */ } + + return handle; + } } /******************************************************************************/ @@ -857,129 +974,133 @@ return handle; @@*/ int Util_TableSetFromString(int handle, const char string[]) { -const char *const delimiters = "; \t\n\r\f\v"; -const char *const whitespace = " \t\n\r\f\v"; -const char *const int_chars = "-+0123456789"; - -#ifdef UTIL_TABLE_DEBUG -printf("Util_TableSetFromString(handle=%d, \"%s\")\n", handle, string); -#endif - -/* make a copy of the string so we can write null characters into it */ -/* to partition it into substrings */ + const char *const delimiters = "; \t\n\r\f\v"; + const char *const whitespace = " \t\n\r\f\v"; + const char *const int_chars = "-+0123456789"; + + #ifdef UTIL_TABLE_DEBUG + printf("Util_TableSetFromString(handle=%d, \"%s\")\n", handle, string); + #endif + + /* make a copy of the string so we can write null characters into it */ + /* to partition it into substrings */ + { + char *const buffer = Util_Strdup(string); + if (buffer == NULL) { -char *const buffer = Util_Strdup(string); -if (buffer == NULL) - then return UTIL_ERROR_NO_MEMORY; + return UTIL_ERROR_NO_MEMORY; + } + { + int Set_count = 0; + char *p = buffer; + while (*p != '\0') { -int Set_count = 0; -char *p = buffer; - while (*p != '\0') + /* + * each pass through this loop processes a single key=value + * assignment starting at p, creating a table entry for it + */ + + /* skip over any leading whitespace */ + const size_t N_white = strspn(p, whitespace); + p += N_white; + #ifdef UTIL_TABLE_DEBUG2 + printf(" skipped over delimiters to p-buffer=%d\n", (int) (p-buffer)); + #endif + if (*p == '\0') + { + break; /* end of string -- nothing more to do */ + } + + { + const char *const key = p; /* key -> "key=value..." */ + char *q = strchr(p, '='); + if (q == NULL) + { + free(buffer); + return UTIL_ERROR_BAD_INPUT; /* no '=" in "key=value" string */ + } + *q++ = '\0'; /* key -> "key", q -> "value..." */ + if (strcspn(key, delimiters) != strlen(key)) + { + free(buffer); + return UTIL_ERROR_TABLE_BAD_KEY; /* key contains invalid character */ + } + { + char *const value = q; /* value -> "value..." */ + const size_t value_length = strcspn(value, delimiters); + q = value + value_length; /* q -> delimiter */ + if (*q != '\0') /* if we're already at the end of the */ + /* buffer, we don't want to advance further */ + { + *q++ = '\0'; /* value -> "value", q -> "..." */ + } + #ifdef UTIL_TABLE_DEBUG + printf(" at p-buffer=%d, got key=\"%s\" value=\"%s\"\n", + (int) (p-buffer), key, value); + #endif + + if (strspn(value, int_chars) == value_length) + { + /* value is made up solely of chars which can appear */ + /* in an integer ==> assume value is an integer */ + int value_int; + if (sscanf(value, "%d", &value_int) != 1) + { + free(buffer); + return UTIL_ERROR_BAD_INPUT; /* can't parse integer value */ + } + #ifdef UTIL_TABLE_DEBUG2 + printf(" ==> storing key=\"%s\", value_int=%d\n", + key, value_int); + #endif { - /* - * each pass through this loop processes a single key=value - * assignment starting at p, creating a table entry for it - */ - - /* skip over any leading whitespace */ - const size_t N_white = strspn(p, whitespace); - p += N_white; - #ifdef UTIL_TABLE_DEBUG2 - printf(" skipped over delimiters to p-buffer=%d\n", (int) (p-buffer)); - #endif - if (*p == '\0') - then break; /* end of string -- nothing more to do */ - - { - const char *const key = p; /* key -> "key=value..." */ - char *q = strchr(p, '='); - if (q == NULL) - then { - free(buffer); - return UTIL_ERROR_BAD_INPUT; /* no '=" in "key=value" string */ - } - *q++ = '\0'; /* key -> "key", q -> "value..." */ - if (strcspn(key, delimiters) != strlen(key)) - then { - free(buffer); - return UTIL_ERROR_TABLE_BAD_KEY; /* key contains */ - /* invalid character */ - } - { - char *const value = q; /* value -> "value..." */ - const size_t value_length = strcspn(value, delimiters); - q = value + value_length; /* q -> delimiter */ - if (*q != '\0') /* if we're already at the end of the */ - /* buffer, we don't want to advance further */ - then *q++ = '\0'; /* value -> "value", q -> "..." */ - #ifdef UTIL_TABLE_DEBUG - printf(" at p-buffer=%d, got key=\"%s\" value=\"%s\"\n", - (int) (p-buffer), key, value); - #endif - - if (strspn(value, int_chars) == value_length) - then { - /* value is made up solely of chars which can appear */ - /* in an integer ==> assume value is an integer */ - int value_int; - if (sscanf(value, "%d", &value_int) != 1) - then { - free(buffer); - return UTIL_ERROR_BAD_INPUT; - /* can't parse integer value */ - } - #ifdef UTIL_TABLE_DEBUG2 - printf(" ==> storing key=\"%s\", value_int=%d\n", - key, value_int); - #endif - { - const int status = Util_TableSetInt(handle, value_int, key); - if (status < 0) - then { - free(buffer); - return status; /* error setting key=integer in table */ - } - } - } - else { - /* value contains at least one character which can't */ - /* appear in an integer ==> assume value is a real */ - double value_double; - if (sscanf(value, "%lf", &value_double) != 1) - then { - free(buffer); - return UTIL_ERROR_BAD_INPUT; - /* can't parse real value */ - } - #ifdef UTIL_TABLE_DEBUG2 - printf(" ==> storing key=\"%s\", value_double=%g\n", - key, value_double); - #endif - { - const int status = Util_TableSetReal(handle, value_double, key); - if (status < 0) - then { - free(buffer); - return status; /* error setting key=real in table */ - } - } - } - - ++Set_count; - p = q; - #ifdef UTIL_TABLE_DEBUG2 - printf(" after key=value, advanced p to p-buffer=%d\n", - (int) (p-buffer)); - #endif - } - } + const int status = Util_TableSetInt(handle, value_int, key); + if (status < 0) + { + free(buffer); + return status; /* error setting key=integer in table */ + } } - -free(buffer); -return Set_count; - } + } + else + { + /* value contains at least one character which can't */ + /* appear in an integer ==> assume value is a real */ + double value_double; + if (sscanf(value, "%lf", &value_double) != 1) + { + free(buffer); + return UTIL_ERROR_BAD_INPUT; /* can't parse real value */ + } + #ifdef UTIL_TABLE_DEBUG2 + printf(" ==> storing key=\"%s\", value_double=%g\n", + key, value_double); + #endif + { + const int status = Util_TableSetReal(handle, value_double, key); + if (status < 0) + { + free(buffer); + return status; /* error setting key=real in table */ + } + } + } + + ++Set_count; + p = q; + #ifdef UTIL_TABLE_DEBUG2 + printf(" after key=value, advanced p to p-buffer=%d\n", + (int) (p-buffer)); + #endif + } + } } + + free(buffer); + return Set_count; + } + } } /******************************************************************************/ @@ -1035,9 +1156,9 @@ int Util_TableSetString(int handle, const char *string, const char *key) { -return internal_set(handle, - CCTK_VARIABLE_CHAR, strlen(string), (const void *) string, - key); + return internal_set(handle, + CCTK_VARIABLE_CHAR, strlen(string), (const void *) string, + key); } /******************************************************************************/ @@ -1101,7 +1222,7 @@ return internal_set(handle, buffer is non-NULL), followed by a null character to properly terminate the string in the buffer. If any other error code is returned, the user's value buffer - (pointed to by buffer if this is non-NULL) is unchanged. + (pointed to by buffer if this is non-NULL) is unchanged. @endcomment @endreturndesc @@*/ @@ -1109,30 +1230,287 @@ int Util_TableGetString(int handle, int buffer_length, char buffer[], const char *key) { -/* actual length of string, not counting terminating null character */ -int string_length = internal_get(handle, - CCTK_VARIABLE_CHAR, - buffer_length-1, (void *) buffer, - key); -if (string_length < 0) - then return string_length; /* error return from internal_get() */ - -/* explicitly add the terminating null character */ -if (buffer != NULL) - then { - assert(buffer_length >= 1); /* this should never fail: */ - /* internal_get() should return */ - /* an error if buffer != NULL */ - /* and buffer_length-1 < 0 */ - { - int null_posn = min(string_length, buffer_length-1); - buffer[null_posn] = '\0'; - } - } + /* string_length = actual length of string, not counting terminating '\0' */ + const int string_length = internal_get(handle, + CCTK_VARIABLE_CHAR, + buffer_length-1, (void *) buffer, + key); + if (string_length < 0) + { + return string_length; /* error return from internal_get() */ + } -return ((buffer != NULL) && (string_length > buffer_length-1)) - ? UTIL_ERROR_TABLE_STRING_TRUNCATED - : string_length; + /* explicitly add the terminating null character */ + if (buffer != NULL) + { + assert(buffer_length >= 1); /* this should never fail: */ + /* internal_get() should return an error */ + /* if buffer != NULL and buffer_length <= 0 */ + { + const int null_posn = min(string_length, buffer_length-1); + buffer[null_posn] = '\0'; + } + } + + return ((buffer != NULL) && (string_length > buffer_length-1)) + ? UTIL_ERROR_TABLE_STRING_TRUNCATED + : string_length; +} + +/******************************************************************************/ + +/*@@ + @routine Util_TableSetGeneric + @desc This function sets the value associated with a specified + key to be a specified value (treated as a 1-element array), + whose datatype is specified by a CCTK_VARIABLE_* type code. + + Note that this invalidates any iterators for this table. + + @var handle + @vtype int + @vdesc handle to the table + @endvar + + @var type_code + @vtype int + @vdesc one of the CCTK_VARIABLE_* constants from "cctk_Types.h", + describing the actual data type of *value_ptr + @endvar + + @var value_ptr + @vtype const void * + @vdesc a pointer to the value to be associated with the specified key + @endvar + + @var key + @vtype const char * + @vdesc pointer to the key (a C-style null-terminated string) + @endvar + + @returntype int + @returndesc 1 for key was already in table before this call + (old value was replaced) + (it doesn't matter what the old value's type_code and + N_elements were, i.e. these do *not* have to match the + new value), + 0 for key was not in table before this call, + -ve for error, including + UTIL_ERROR_BAD_HANDLE handle is invalid + UTIL_ERROR_TABLE_BAD_KEY key contains '/' character + UTIL_ERROR_NO_MEMORY unable to allocate memory + @endreturndesc + @@*/ +int Util_TableSetGeneric(int handle, + int type_code, const void *value_ptr, + const char *key) +{ + return Util_TableSetGenericArray(handle, type_code, 1, value_ptr, key); +} + +/******************************************************************************/ + +/*@@ + @routine Util_TableSetGenericArray + @desc This function sets the value associated with a specified + key to be (a copy of) a specified array, whose datatype is + specified by a CCTK_VARIABLE_* type code. + + Note that this invalidates any iterators for this table. + + @var handle + @vtype int + @vdesc handle to the table + @endvar + + @var type_code + @vtype int + @vdesc one of the CCTK_VARIABLE_* constants from "cctk_Types.h", + describing the actual data type of array[] + @endvar + + @var N_elements + @vtype int (must be >= 0) + @vdesc number of elements in array[] + @endvar + + @var array + @vtype const void * + @vdesc a pointer to the array (a copy of) which + is to be associated with the specified key + @endvar + + @var key + @vtype const char * + @vdesc pointer to the key (a C-style null-terminated string) + @endvar + + @returntype int + @returndesc 1 for key was already in table before this call + (old value was replaced) + (it doesn't matter what the old value's type_code and + N_elements were, i.e. these do *not* have to match the + new value), + 0 for key was not in table before this call, + -ve for error, including + UTIL_ERROR_BAD_HANDLE handle is invalid + UTIL_ERROR_TABLE_BAD_KEY key contains '/' character + UTIL_ERROR_BAD_INPUT N_elements < 0 + UTIL_ERROR_NO_MEMORY unable to allocate memory + @endreturndesc + @@*/ +int Util_TableSetGenericArray(int handle, + int type_code, int N_elements, const void *array, + const char *key) +{ + return internal_set(handle, + type_code, N_elements, array, + key); +} + +/******************************************************************************/ + +/*@@ + @routine Util_TableGetGeneric + @desc This function gets the value of the scalar (1-element array) + value, or more generally the first array element of the value, + associated with a specified key. The value may be of any + supported datatype; the caller specifies the expected type + by a CCTK_VARIABLE_* type code. + + @var handle + @vtype int + @vdesc handle to the table + @endvar + + @var type_code + @vtype int + @vdesc one of the CCTK_VARIABLE_* constants from "cctk_Types.h", + describing the expected data type of the table entry. + @endvar + + @var value_ptr + @vtype void * + @vdesc pointer to where this function should store + a copy of the value associated with the specified key, + or NULL pointer to skip storing this + @endvar + + @var key + @vtype const char * + @vdesc pointer to the key (a C-style null-terminated string) + @endvar + + @returntype int + @returndesc the number of elements in the value, + -ve for error, including + UTIL_ERROR_BAD_HANDLE handle is invalid + UTIL_ERROR_TABLE_BAD_KEY key contains '/' character + UTIL_ERROR_TABLE_NO_SUCH_KEY no such key in table + UTIL_ERROR_TABLE_WRONG_DATA_TYPE value has wrong data type + UTIL_ERROR_TABLE_VALUE_IS_EMPTY value is an empty + (0-element) array + @comment Note that it is *not* an error for the value to actually + be an array with > 1 elements elements; in this case only + the first element is stored. + + The rationale for this design is that the caller may + know or suspect that the value is a large array, but + may only want the first array element; in this case + this design avoids the caller having to allocate a + large buffer unnecessarily. + + In contrast, it *is* an error for the value to actually + be an empty (0-length) array, because then there is no + ``first array element'' to get. + @endcomment + @endreturndesc + @@*/ +int Util_TableGetGeneric(int handle, + int type_code, void *value_ptr, + const char *key) +{ + const int status + = Util_TableGetGenericArray(handle, type_code, 1, value_ptr, key); + return (status == 0) + ? UTIL_ERROR_TABLE_VALUE_IS_EMPTY + : status; +} + +/******************************************************************************/ + +/*@@ + @routine Util_TableGetGenericArray + @desc This is a family of functions, one for each Cactus data type, + to get a copy of the value associated with a specified key + (or at least as much of the value as will fit into the + caller's array). + + @var handle + @vtype int + @vdesc handle to the table + @endvar + + @var type_code + @vtype int + @vdesc one of the CCTK_VARIABLE_* constants from "cctk_Types.h", + describing the expected data type of the table entry. + @endvar + + @var N_elements + @vtype int (must be >= 0) + @vdesc number of elements in array[] + @endvar + + @var array + @vtype void * + @vdesc a pointer to an array into which this function should store + (at most N_elements elements of) a copy of the value + associated with the specified key, + or NULL pointer to skip storing this + @endvar + + @var key + @vtype const char * + @vdesc pointer to the key (a C-style null-terminated string) + @endvar + + @returntype int + @returndesc the number of elements in the value, + -ve for error, including + UTIL_ERROR_BAD_HANDLE handle is invalid + UTIL_ERROR_TABLE_BAD_KEY key contains '/' character + UTIL_ERROR_BAD_INPUT array != NULL and N_elements < 0 + UTIL_ERROR_TABLE_NO_SUCH_KEY no such key in table + UTIL_ERROR_TABLE_WRONG_DATA_TYPE value has wrong data type + @comment Note that it is *not* an error for the value to have + > N_elements elements; in this case only N_elements are + stored. The caller can detect this by comparing the + return value with N_elements. + + The rationale for this design is that the caller may + know or suspect that the value is a large array, but + may only want the first few array elements; in this + case this design avoids the caller having to allocate + a large buffer unnecessarily. + + It is also *not* an error for the value to have < N_elements + elements; again the caller can detect this by comparing the + return value with N_elements. + + Note also that if any error code is returned, the + caller's value buffer (pointed to by value_buffer) + is unchanged. + @endcomment + @endreturndesc + @@*/ +int Util_TableGetGenericArray(int handle, + int type_code, int N_elements, void *array, + const char *key) +{ + return internal_get(handle, + type_code, N_elements, array, + key); } /******************************************************************************/ @@ -1188,12 +1566,12 @@ return ((buffer != NULL) && (string_length > buffer_length-1)) int Util_TableSetPointer(int handle, CCTK_POINTER value, const char *key) { -return Util_TableSetPointerArray(handle, 1, &value, key); + return Util_TableSetPointerArray(handle, 1, &value, key); } int Util_TableSetFnPointer(int handle, CCTK_FN_POINTER value, const char *key) { -return Util_TableSetFnPointerArray(handle, 1, &value, key); + return Util_TableSetFnPointerArray(handle, 1, &value, key); } /**************************************/ @@ -1204,7 +1582,7 @@ return Util_TableSetFnPointerArray(handle, 1, &value, key); int Util_TableSetChar(int handle, CCTK_CHAR value, const char *key) { -return Util_TableSetCharArray(handle, 1, &value, key); + return Util_TableSetCharArray(handle, 1, &value, key); } /**************************************/ @@ -1215,27 +1593,27 @@ return Util_TableSetCharArray(handle, 1, &value, key); int Util_TableSetInt(int handle, CCTK_INT value, const char *key) { -return Util_TableSetIntArray(handle, 1, &value, key); + return Util_TableSetIntArray(handle, 1, &value, key); } #ifdef CCTK_INTEGER_PRECISION_2 int Util_TableSetInt2(int handle, CCTK_INT2 value, const char *key) { -return Util_TableSetInt2Array(handle, 1, &value, key); + return Util_TableSetInt2Array(handle, 1, &value, key); } #endif #ifdef CCTK_INTEGER_PRECISION_4 int Util_TableSetInt4(int handle, CCTK_INT4 value, const char *key) { -return Util_TableSetInt4Array(handle, 1, &value, key); + return Util_TableSetInt4Array(handle, 1, &value, key); } #endif #ifdef CCTK_INTEGER_PRECISION_8 int Util_TableSetInt8(int handle, CCTK_INT8 value, const char *key) { -return Util_TableSetInt8Array(handle, 1, &value, key); + return Util_TableSetInt8Array(handle, 1, &value, key); } #endif @@ -1247,27 +1625,27 @@ return Util_TableSetInt8Array(handle, 1, &value, key); int Util_TableSetReal(int handle, CCTK_REAL value, const char *key) { -return Util_TableSetRealArray(handle, 1, &value, key); + return Util_TableSetRealArray(handle, 1, &value, key); } #ifdef CCTK_REAL_PRECISION_4 int Util_TableSetReal4(int handle, CCTK_REAL4 value, const char *key) { -return Util_TableSetReal4Array(handle, 1, &value, key); + return Util_TableSetReal4Array(handle, 1, &value, key); } #endif #ifdef CCTK_REAL_PRECISION_8 int Util_TableSetReal8(int handle, CCTK_REAL8 value, const char *key) { -return Util_TableSetReal8Array(handle, 1, &value, key); + return Util_TableSetReal8Array(handle, 1, &value, key); } #endif #ifdef CCTK_REAL_PRECISION_16 int Util_TableSetReal16(int handle, CCTK_REAL16 value, const char *key) { -return Util_TableSetReal16Array(handle, 1, &value, key); + return Util_TableSetReal16Array(handle, 1, &value, key); } #endif @@ -1279,27 +1657,27 @@ return Util_TableSetReal16Array(handle, 1, &value, key); int Util_TableSetComplex(int handle, CCTK_COMPLEX value, const char *key) { -return Util_TableSetComplexArray(handle, 1, &value, key); + return Util_TableSetComplexArray(handle, 1, &value, key); } #ifdef CCTK_COMPLEX_PRECISION_8 int Util_TableSetComplex8(int handle, CCTK_COMPLEX8 value, const char *key) { -return Util_TableSetComplex8Array(handle, 1, &value, key); + return Util_TableSetComplex8Array(handle, 1, &value, key); } #endif #ifdef CCTK_COMPLEX_PRECISION_16 int Util_TableSetComplex16(int handle, CCTK_COMPLEX16 value, const char *key) { -return Util_TableSetComplex16Array(handle, 1, &value, key); + return Util_TableSetComplex16Array(handle, 1, &value, key); } #endif #ifdef CCTK_COMPLEX_PRECISION_32 int Util_TableSetComplex32(int handle, CCTK_COMPLEX32 value, const char *key) { -return Util_TableSetComplex32Array(handle, 1, &value, key); + return Util_TableSetComplex32Array(handle, 1, &value, key); } #endif @@ -1365,18 +1743,19 @@ int Util_TableSetPointerArray(int handle, int N_elements, const CCTK_POINTER array[], const char *key) { -return internal_set(handle, - CCTK_VARIABLE_POINTER, N_elements, (const void *) array, - key); + return internal_set(handle, + CCTK_VARIABLE_POINTER, N_elements, (const void *) array, + key); } int Util_TableSetFnPointerArray(int handle, int N_elements, const CCTK_FN_POINTER array[], const char *key) { -return internal_set(handle, - CCTK_VARIABLE_FN_POINTER, N_elements, (const void *) array, - key); + return + internal_set(handle, + CCTK_VARIABLE_FN_POINTER, N_elements, (const void *) array, + key); } /**************************************/ @@ -1389,9 +1768,9 @@ int Util_TableSetCharArray(int handle, int N_elements, const CCTK_CHAR array[], const char *key) { -return internal_set(handle, - CCTK_VARIABLE_CHAR, N_elements, (const void *) array, - key); + return internal_set(handle, + CCTK_VARIABLE_CHAR, N_elements, (const void *) array, + key); } /**************************************/ @@ -1404,9 +1783,9 @@ int Util_TableSetIntArray(int handle, int N_elements, const CCTK_INT array[], const char *key) { -return internal_set(handle, - CCTK_VARIABLE_INT, N_elements, (const void *) array, - key); + return internal_set(handle, + CCTK_VARIABLE_INT, N_elements, (const void *) array, + key); } #ifdef CCTK_INTEGER_PRECISION_2 @@ -1414,9 +1793,9 @@ int Util_TableSetInt2Array(int handle, int N_elements, const CCTK_INT2 array[], const char *key) { -return internal_set(handle, - CCTK_VARIABLE_INT2, N_elements, (const void *) array, - key); + return internal_set(handle, + CCTK_VARIABLE_INT2, N_elements, (const void *) array, + key); } #endif @@ -1425,9 +1804,9 @@ int Util_TableSetInt4Array(int handle, int N_elements, const CCTK_INT4 array[], const char *key) { -return internal_set(handle, - CCTK_VARIABLE_INT4, N_elements, (const void *) array, - key); + return internal_set(handle, + CCTK_VARIABLE_INT4, N_elements, (const void *) array, + key); } #endif @@ -1436,9 +1815,9 @@ int Util_TableSetInt8Array(int handle, int N_elements, const CCTK_INT8 array[], const char *key) { -return internal_set(handle, - CCTK_VARIABLE_INT8, N_elements, (const void *) array, - key); + return internal_set(handle, + CCTK_VARIABLE_INT8, N_elements, (const void *) array, + key); } #endif @@ -1452,10 +1831,10 @@ int Util_TableSetRealArray(int handle, int N_elements, const CCTK_REAL array[], const char *key) { -return - internal_set(handle, - CCTK_VARIABLE_REAL, N_elements, (const void *) array, - key); + return + internal_set(handle, + CCTK_VARIABLE_REAL, N_elements, (const void *) array, + key); } #ifdef CCTK_REAL_PRECISION_4 @@ -1463,9 +1842,9 @@ int Util_TableSetReal4Array(int handle, int N_elements, const CCTK_REAL4 array[], const char *key) { -return internal_set(handle, - CCTK_VARIABLE_REAL4, N_elements, (const void *) array, - key); + return internal_set(handle, + CCTK_VARIABLE_REAL4, N_elements, (const void *) array, + key); } #endif @@ -1474,9 +1853,9 @@ int Util_TableSetReal8Array(int handle, int N_elements, const CCTK_REAL8 array[], const char *key) { -return internal_set(handle, - CCTK_VARIABLE_REAL8, N_elements, (const void *) array, - key); + return internal_set(handle, + CCTK_VARIABLE_REAL8, N_elements, (const void *) array, + key); } #endif @@ -1485,9 +1864,9 @@ int Util_TableSetReal16Array(int handle, int N_elements, const CCTK_REAL16 array[], const char *key) { -return internal_set(handle, - CCTK_VARIABLE_REAL16, N_elements, (const void *) array, - key); + return internal_set(handle, + CCTK_VARIABLE_REAL16, N_elements, (const void *) array, + key); } #endif @@ -1501,9 +1880,9 @@ int Util_TableSetComplexArray(int handle, int N_elements, const CCTK_COMPLEX array[], const char *key) { -return internal_set(handle, - CCTK_VARIABLE_COMPLEX, N_elements, (const void *) array, - key); + return internal_set(handle, + CCTK_VARIABLE_COMPLEX, N_elements, (const void *) array, + key); } #ifdef CCTK_COMPLEX_PRECISION_8 @@ -1511,9 +1890,9 @@ int Util_TableSetComplex8Array(int handle, int N_elements, const CCTK_COMPLEX8 array[], const char *key) { -return internal_set(handle, - CCTK_VARIABLE_COMPLEX8, N_elements, (const void *) array, - key); + return internal_set(handle, + CCTK_VARIABLE_COMPLEX8, N_elements, (const void *) array, + key); } #endif @@ -1522,9 +1901,9 @@ int Util_TableSetComplex16Array(int handle, int N_elements, const CCTK_COMPLEX16 array[], const char *key) { -return internal_set(handle, - CCTK_VARIABLE_COMPLEX16, N_elements, (const void *) array, - key); + return internal_set(handle, + CCTK_VARIABLE_COMPLEX16, N_elements, (const void *) array, + key); } #endif @@ -1533,9 +1912,9 @@ int Util_TableSetComplex32Array(int handle, int N_elements, const CCTK_COMPLEX32 array[], const char *key) { -return internal_set(handle, - CCTK_VARIABLE_COMPLEX32, N_elements, (const void *) array, - key); + return internal_set(handle, + CCTK_VARIABLE_COMPLEX32, N_elements, (const void *) array, + key); } #endif @@ -1602,18 +1981,18 @@ return internal_set(handle, /* pointers */ int Util_TableGetPointer(int handle, CCTK_POINTER *value, const char *key) { -int status = Util_TableGetPointerArray(handle, 1, value, key); -return (status == 0) - ? UTIL_ERROR_TABLE_VALUE_IS_EMPTY - : status; + const int status = Util_TableGetPointerArray(handle, 1, value, key); + return (status == 0) + ? UTIL_ERROR_TABLE_VALUE_IS_EMPTY + : status; } int Util_TableGetFnPointer(int handle, CCTK_FN_POINTER *value, const char *key) { -int status = Util_TableGetFnPointerArray(handle, 1, value, key); -return (status == 0) - ? UTIL_ERROR_TABLE_VALUE_IS_EMPTY - : status; + const int status = Util_TableGetFnPointerArray(handle, 1, value, key); + return (status == 0) + ? UTIL_ERROR_TABLE_VALUE_IS_EMPTY + : status; } /**************************************/ @@ -1621,10 +2000,10 @@ return (status == 0) /* a single character */ int Util_TableGetChar(int handle, CCTK_CHAR *value, const char *key) { -int status = Util_TableGetCharArray(handle, 1, value, key); -return (status == 0) - ? UTIL_ERROR_TABLE_VALUE_IS_EMPTY - : status; + const int status = Util_TableGetCharArray(handle, 1, value, key); + return (status == 0) + ? UTIL_ERROR_TABLE_VALUE_IS_EMPTY + : status; } /**************************************/ @@ -1632,39 +2011,39 @@ return (status == 0) /* integers */ int Util_TableGetInt(int handle, CCTK_INT *value, const char *key) { -int status = Util_TableGetIntArray(handle, 1, value, key); -return (status == 0) - ? UTIL_ERROR_TABLE_VALUE_IS_EMPTY - : status; + const int status = Util_TableGetIntArray(handle, 1, value, key); + return (status == 0) + ? UTIL_ERROR_TABLE_VALUE_IS_EMPTY + : status; } #ifdef CCTK_INTEGER_PRECISION_2 int Util_TableGetInt2(int handle, CCTK_INT2 *value, const char *key) { -int status = Util_TableGetInt2Array(handle, 1, value, key); -return (status == 0) - ? UTIL_ERROR_TABLE_VALUE_IS_EMPTY - : status; + const int status = Util_TableGetInt2Array(handle, 1, value, key); + return (status == 0) + ? UTIL_ERROR_TABLE_VALUE_IS_EMPTY + : status; } #endif #ifdef CCTK_INTEGER_PRECISION_4 int Util_TableGetInt4(int handle, CCTK_INT4 *value, const char *key) { -int status = Util_TableGetInt4Array(handle, 1, value, key); -return (status == 0) - ? UTIL_ERROR_TABLE_VALUE_IS_EMPTY - : status; + const int status = Util_TableGetInt4Array(handle, 1, value, key); + return (status == 0) + ? UTIL_ERROR_TABLE_VALUE_IS_EMPTY + : status; } #endif #ifdef CCTK_INTEGER_PRECISION_8 int Util_TableGetInt8(int handle, CCTK_INT8 *value, const char *key) { -int status = Util_TableGetInt8Array(handle, 1, value, key); -return (status == 0) - ? UTIL_ERROR_TABLE_VALUE_IS_EMPTY - : status; + const int status = Util_TableGetInt8Array(handle, 1, value, key); + return (status == 0) + ? UTIL_ERROR_TABLE_VALUE_IS_EMPTY + : status; } #endif @@ -1673,39 +2052,39 @@ return (status == 0) /* real numbers */ int Util_TableGetReal(int handle, CCTK_REAL *value, const char *key) { -int status = Util_TableGetRealArray(handle, 1, value, key); -return (status == 0) - ? UTIL_ERROR_TABLE_VALUE_IS_EMPTY - : status; + const int status = Util_TableGetRealArray(handle, 1, value, key); + return (status == 0) + ? UTIL_ERROR_TABLE_VALUE_IS_EMPTY + : status; } #ifdef CCTK_REAL_PRECISION_4 int Util_TableGetReal4(int handle, CCTK_REAL4 *value, const char *key) { -int status = Util_TableGetReal4Array(handle, 1, value, key); -return (status == 0) - ? UTIL_ERROR_TABLE_VALUE_IS_EMPTY - : status; + const int status = Util_TableGetReal4Array(handle, 1, value, key); + return (status == 0) + ? UTIL_ERROR_TABLE_VALUE_IS_EMPTY + : status; } #endif #ifdef CCTK_REAL_PRECISION_8 int Util_TableGetReal8(int handle, CCTK_REAL8 *value, const char *key) { -int status = Util_TableGetReal8Array(handle, 1, value, key); -return (status == 0) - ? UTIL_ERROR_TABLE_VALUE_IS_EMPTY - : status; + const int status = Util_TableGetReal8Array(handle, 1, value, key); + return (status == 0) + ? UTIL_ERROR_TABLE_VALUE_IS_EMPTY + : status; } #endif #ifdef CCTK_REAL_PRECISION_16 int Util_TableGetReal16(int handle, CCTK_REAL16 *value, const char *key) { -int status = Util_TableGetReal16Array(handle, 1, value, key); -return (status == 0) - ? UTIL_ERROR_TABLE_VALUE_IS_EMPTY - : status; + const int status = Util_TableGetReal16Array(handle, 1, value, key); + return (status == 0) + ? UTIL_ERROR_TABLE_VALUE_IS_EMPTY + : status; } #endif @@ -1714,39 +2093,39 @@ return (status == 0) /* complex numbers */ int Util_TableGetComplex(int handle, CCTK_COMPLEX *value, const char *key) { -int status = Util_TableGetComplexArray(handle, 1, value, key); -return (status == 0) - ? UTIL_ERROR_TABLE_VALUE_IS_EMPTY - : status; + const int status = Util_TableGetComplexArray(handle, 1, value, key); + return (status == 0) + ? UTIL_ERROR_TABLE_VALUE_IS_EMPTY + : status; } #ifdef CCTK_COMPLEX_PRECISION_8 int Util_TableGetComplex8(int handle, CCTK_COMPLEX8 *value, const char *key) { -int status = Util_TableGetComplex8Array(handle, 1, value, key); -return (status == 0) - ? UTIL_ERROR_TABLE_VALUE_IS_EMPTY - : status; + const int status = Util_TableGetComplex8Array(handle, 1, value, key); + return (status == 0) + ? UTIL_ERROR_TABLE_VALUE_IS_EMPTY + : status; } #endif #ifdef CCTK_COMPLEX_PRECISION_16 int Util_TableGetComplex16(int handle, CCTK_COMPLEX16 *value, const char *key) { -int status = Util_TableGetComplex16Array(handle, 1, value, key); -return (status == 0) - ? UTIL_ERROR_TABLE_VALUE_IS_EMPTY - : status; + const int status = Util_TableGetComplex16Array(handle, 1, value, key); + return (status == 0) + ? UTIL_ERROR_TABLE_VALUE_IS_EMPTY + : status; } #endif #ifdef CCTK_COMPLEX_PRECISION_32 int Util_TableGetComplex32(int handle, CCTK_COMPLEX32 *value, const char *key) { -int status = Util_TableGetComplex32Array(handle, 1, value, key); -return (status == 0) - ? UTIL_ERROR_TABLE_VALUE_IS_EMPTY - : status; + const int status = Util_TableGetComplex32Array(handle, 1, value, key); + return (status == 0) + ? UTIL_ERROR_TABLE_VALUE_IS_EMPTY + : status; } #endif @@ -1764,7 +2143,7 @@ return (status == 0) @vdesc handle to the table @endvar - @var N_array + @var N_elements @vtype int (must be >= 0) @vdesc number of elements in array[] @endvar @@ -1778,7 +2157,7 @@ return (status == 0) CCTK_COMPLEX, CCTK_COMPLEX8, CCTK_COMPLEX16, CCTK_COMPLEX32 (not all of these may be supported on any given system) @vdesc an array into which this function should store - (at most N_array elements of) a copy of the value + (at most N_elements elements of) a copy of the value associated with the specified key, or NULL pointer to skip storing this @endvar @@ -1793,13 +2172,13 @@ return (status == 0) -ve for error, including UTIL_ERROR_BAD_HANDLE handle is invalid UTIL_ERROR_TABLE_BAD_KEY key contains '/' character - UTIL_ERROR_BAD_INPUT array != NULL and N_array < 0 + UTIL_ERROR_BAD_INPUT array != NULL and N_elements < 0 UTIL_ERROR_TABLE_NO_SUCH_KEY no such key in table UTIL_ERROR_TABLE_WRONG_DATA_TYPE value has wrong data type @comment Note that it is *not* an error for the value to have - > N_array elements; in this case only N_array are + > N_elements elements; in this case only N_elements are stored. The caller can detect this by comparing the - return value with N_array. + return value with N_elements. The rationale for this design is that the caller may know or suspect that the value is a large array, but @@ -1807,9 +2186,9 @@ return (status == 0) case this design avoids the caller having to allocate a large buffer unnecessarily. - It is also *not* an error for the value to have < N_array + It is also *not* an error for the value to have < N_elements elements; again the caller can detect this by comparing the - return value with N_array. + return value with N_elements. Note also that if any error code is returned, the caller's value buffer (pointed to by value_buffer) @@ -1822,77 +2201,77 @@ return (status == 0) /* arrays of pointers */ int Util_TableGetPointerArray(int handle, - int N_array, CCTK_POINTER array[], + int N_elements, CCTK_POINTER array[], const char *key) { -return internal_get(handle, - CCTK_VARIABLE_POINTER, N_array, (void *) array, - key); + return internal_get(handle, + CCTK_VARIABLE_POINTER, N_elements, (void *) array, + key); } int Util_TableGetFnPointerArray(int handle, - int N_array, CCTK_FN_POINTER array[], + int N_elements, CCTK_FN_POINTER array[], const char *key) { -return internal_get(handle, - CCTK_VARIABLE_FN_POINTER, N_array, (void *) array, - key); + return internal_get(handle, + CCTK_VARIABLE_FN_POINTER, N_elements, (void *) array, + key); } /**************************************/ /* arrays of characters (i.e. character strings) */ int Util_TableGetCharArray(int handle, - int N_array, CCTK_CHAR array[], + int N_elements, CCTK_CHAR array[], const char *key) { -return internal_get(handle, - CCTK_VARIABLE_CHAR, N_array, (void *) array, - key); + return internal_get(handle, + CCTK_VARIABLE_CHAR, N_elements, (void *) array, + key); } /**************************************/ /* integers */ int Util_TableGetIntArray(int handle, - int N_array, CCTK_INT array[], + int N_elements, CCTK_INT array[], const char *key) { -return internal_get(handle, - CCTK_VARIABLE_INT, N_array, (void *) array, - key); + return internal_get(handle, + CCTK_VARIABLE_INT, N_elements, (void *) array, + key); } #ifdef CCTK_INTEGER_PRECISION_2 int Util_TableGetInt2Array(int handle, - int N_array, CCTK_INT2 array[], + int N_elements, CCTK_INT2 array[], const char *key) { -return internal_get(handle, - CCTK_VARIABLE_INT2, N_array, (void *) array, - key); + return internal_get(handle, + CCTK_VARIABLE_INT2, N_elements, (void *) array, + key); } #endif #ifdef CCTK_INTEGER_PRECISION_4 int Util_TableGetInt4Array(int handle, - int N_array, CCTK_INT4 array[], + int N_elements, CCTK_INT4 array[], const char *key) { -return internal_get(handle, - CCTK_VARIABLE_INT4, N_array, (void *) array, - key); + return internal_get(handle, + CCTK_VARIABLE_INT4, N_elements, (void *) array, + key); } #endif #ifdef CCTK_INTEGER_PRECISION_8 int Util_TableGetInt8Array(int handle, - int N_array, CCTK_INT8 array[], + int N_elements, CCTK_INT8 array[], const char *key) { -return internal_get(handle, - CCTK_VARIABLE_INT8, N_array, (void *) array, - key); + return internal_get(handle, + CCTK_VARIABLE_INT8, N_elements, (void *) array, + key); } #endif @@ -1900,44 +2279,44 @@ return internal_get(handle, /* real numbers */ int Util_TableGetRealArray(int handle, - int N_array, CCTK_REAL array[], + int N_elements, CCTK_REAL array[], const char *key) { -return internal_get(handle, - CCTK_VARIABLE_REAL, N_array, (void *) array, - key); + return internal_get(handle, + CCTK_VARIABLE_REAL, N_elements, (void *) array, + key); } #ifdef CCTK_REAL_PRECISION_4 int Util_TableGetReal4Array(int handle, - int N_array, CCTK_REAL4 array[], + int N_elements, CCTK_REAL4 array[], const char *key) { -return internal_get(handle, - CCTK_VARIABLE_REAL4, N_array, (void *) array, - key); + return internal_get(handle, + CCTK_VARIABLE_REAL4, N_elements, (void *) array, + key); } #endif #ifdef CCTK_REAL_PRECISION_8 int Util_TableGetReal8Array(int handle, - int N_array, CCTK_REAL8 array[], + int N_elements, CCTK_REAL8 array[], const char *key) { -return internal_get(handle, - CCTK_VARIABLE_REAL8, N_array, (void *) array, - key); + return internal_get(handle, + CCTK_VARIABLE_REAL8, N_elements, (void *) array, + key); } #endif #ifdef CCTK_REAL_PRECISION_16 int Util_TableGetReal16Array(int handle, - int N_array, CCTK_REAL16 array[], + int N_elements, CCTK_REAL16 array[], const char *key) { -return internal_get(handle, - CCTK_VARIABLE_REAL16, N_array, (void *) array, - key); + return internal_get(handle, + CCTK_VARIABLE_REAL16, N_elements, (void *) array, + key); } #endif @@ -1945,44 +2324,44 @@ return internal_get(handle, /* complex numbers */ int Util_TableGetComplexArray(int handle, - int N_array, CCTK_COMPLEX array[], + int N_elements, CCTK_COMPLEX array[], const char *key) { -return internal_get(handle, - CCTK_VARIABLE_COMPLEX, N_array, (void *) array, - key); + return internal_get(handle, + CCTK_VARIABLE_COMPLEX, N_elements, (void *) array, + key); } #ifdef CCTK_COMPLEX_PRECISION_8 int Util_TableGetComplex8Array(int handle, - int N_array, CCTK_COMPLEX8 array[], + int N_elements, CCTK_COMPLEX8 array[], const char *key) { -return internal_get(handle, - CCTK_VARIABLE_COMPLEX8, N_array, (void *) array, - key); + return internal_get(handle, + CCTK_VARIABLE_COMPLEX8, N_elements, (void *) array, + key); } #endif #ifdef CCTK_COMPLEX_PRECISION_16 int Util_TableGetComplex16Array(int handle, - int N_array, CCTK_COMPLEX16 array[], + int N_elements, CCTK_COMPLEX16 array[], const char *key) { -return internal_get(handle, - CCTK_VARIABLE_COMPLEX16, N_array, (void *) array, - key); + return internal_get(handle, + CCTK_VARIABLE_COMPLEX16, N_elements, (void *) array, + key); } #endif #ifdef CCTK_COMPLEX_PRECISION_32 int Util_TableGetComplex32Array(int handle, - int N_array, CCTK_COMPLEX32 array[], + int N_elements, CCTK_COMPLEX32 array[], const char *key) { -return internal_get(handle, - CCTK_VARIABLE_COMPLEX16, N_array, (void *) array, - key); + return internal_get(handle, + CCTK_VARIABLE_COMPLEX16, N_elements, (void *) array, + key); } #endif @@ -2009,74 +2388,121 @@ return internal_get(handle, @@*/ int Util_TableItCreate(int handle) { -const struct table_header *const thp = get_table_header_ptr(handle); -if (thp == NULL) - then return UTIL_ERROR_BAD_HANDLE; - -#ifdef UTIL_TABLE_DEBUG -printf("Util_TableItCreate(handle=%d)\n", handle); -#endif - -if (N_iterators == N_ip_array) - then { - /* grow iterator_array to get some room to create the new table */ - #ifdef UTIL_TABLE_DEBUG - printf(" growing ip_array[] from old size %d\n", - N_ip_array); - #endif - if (grow_pointer_array(&N_ip_array, &ip_array) < 0) - then return UTIL_ERROR_NO_MEMORY; /* can't grow array */ - #ifdef UTIL_TABLE_DEBUG - printf(" to new size %d\n", - N_ip_array); - #endif - } + const struct table_header *const thp = get_table_header_ptr(handle); + if (thp == NULL) + { + return UTIL_ERROR_BAD_HANDLE; + } -/* we should now have space to create the new iterator */ -assert(N_iterators < N_ip_array); + #ifdef UTIL_TABLE_DEBUG + printf("Util_TableItCreate(handle=%d)\n", handle); + #endif -/* find an unused iterator handle */ -#ifdef UTIL_TABLE_DEBUG -printf(" searching for an unused iterator handle\n"); -printf(" (N_iterators=%d N_ip_array=%d\n", N_iterators, N_ip_array); -#endif + if (N_iterators == N_ip_array) { -int ihandle; - for (ihandle = 0 ; ihandle < N_ip_array ; ++ihandle) + /* grow iterator_array to get some room to create the new table */ + #ifdef UTIL_TABLE_DEBUG + printf(" growing ip_array[] from old size %d\n", + N_ip_array); + #endif + if (grow_pointer_array(&N_ip_array, &ip_array) < 0) + { + return UTIL_ERROR_NO_MEMORY; /* can't grow array */ + } + #ifdef UTIL_TABLE_DEBUG + printf(" to new size %d\n", + N_ip_array); + #endif + } + + /* we should now have space to create the new iterator */ + assert(N_iterators < N_ip_array); + + /* find an unused iterator handle */ + #ifdef UTIL_TABLE_DEBUG + printf(" searching for an unused iterator handle\n"); + printf(" (N_iterators=%d N_ip_array=%d\n", N_iterators, N_ip_array); + #endif + { + int ihandle; + for (ihandle = 0 ; ihandle < N_ip_array ; ++ihandle) + { + #ifdef UTIL_TABLE_DEBUG2 + printf(" checking ihandle=%d\n", ihandle); + #endif + if (ip_array[ihandle] == NULL) + { + /* we've found an unused ihandle ==> create the iterator */ + struct iterator *const ip = (struct iterator *) + malloc(sizeof(struct iterator)); + if (ip == NULL) { + return UTIL_ERROR_NO_MEMORY; /* can't allocate new iterator */ + } + #ifdef UTIL_TABLE_DEBUG2 - printf(" checking ihandle=%d\n", ihandle); + printf(" using ihandle=%d\n", ihandle); #endif - if (ip_array[ihandle] == NULL) - then { - /* we've found an unused ihandle ==> create the iterator */ - struct iterator *const ip - = (struct iterator *) malloc(sizeof(struct iterator)); - if (ip == NULL) - then return UTIL_ERROR_NO_MEMORY; - /* can't allocate new iterator */ - - #ifdef UTIL_TABLE_DEBUG2 - printf(" using ihandle=%d\n", ihandle); - #endif - - ip->thp = thp; - ip->tep = thp->head; /* iterator initially */ - /* -> start of table */ - - ++N_iterators; - ip_array[ihandle] = (void *) ip; - - return ihandle; - } - } -/* we should never get to here! */ -assert(false); -abort(); /* internal error (core dump) */ -/* prevent compiler warning 'function should return a value' */ -return(0); + ip->thp = thp; + ip->tep = thp->head; /* iterator initially -> start of table */ + + ++N_iterators; + ip_array[ihandle] = (void *) ip; + + return ihandle; /* NORMAL RETURN */ + } + } + + /* we should never get to here! */ + assert(false); + abort(); /* internal error (core dump) */ + /* prevent compiler warning 'function should return a value' */ + return(0); + } +} + +/******************************************************************************/ + +/*@@ + @routine Util_TableItClone + @desc This function clones (makes an exact copy of) a table + iterator. That is, it creates a new iterator which points + to the same table entry as an existing iterator. + + @var ihandle + @vtype int + @vdesc handle to the iterator to be cloned + @endvar + + @returntype int + @returndesc a handle to the newly-created iterator, + -ve for error, including + UTIL_ERROR_BAD_HANDLE iterator handle is invalid + UTIL_ERROR_NO_MEMORY unable to allocate memory + @endreturndesc + @@*/ +int Util_TableItClone(int ihandle) +{ + struct iterator *const ip = get_iterator_ptr(ihandle); + if (ip == NULL) + { + return UTIL_ERROR_BAD_HANDLE; + } + + { + const int clone_ihandle = Util_TableItCreate(ip->thp->handle); + if (clone_ihandle < 0) + { + return clone_ihandle; /* error in creating clone iterator */ } + + { + struct iterator *const clone_ip = get_iterator_ptr(clone_ihandle); + clone_ip->tep = ip->tep; + return clone_ihandle; + } + } } /******************************************************************************/ @@ -2098,19 +2524,21 @@ return(0); @@*/ int Util_TableItDestroy(int ihandle) { -struct iterator *const ip = get_iterator_ptr(ihandle); -if (ip == NULL) - then return UTIL_ERROR_BAD_HANDLE; + struct iterator *const ip = get_iterator_ptr(ihandle); + if (ip == NULL) + { + return UTIL_ERROR_BAD_HANDLE; + } -#ifdef UTIL_TABLE_DEBUG -printf("Util_TableItDestroy(ihandle=%d)\n", ihandle); -#endif + #ifdef UTIL_TABLE_DEBUG + printf("Util_TableItDestroy(ihandle=%d)\n", ihandle); + #endif ---N_iterators; -ip_array[ihandle] = NULL; -free(ip); + --N_iterators; + ip_array[ihandle] = NULL; + free(ip); -return 0; /* ok */ + return 0; /* ok */ } /******************************************************************************/ @@ -2139,13 +2567,15 @@ return 0; /* ok */ @@*/ int Util_TableItQueryIsNull(int ihandle) { -const struct iterator *const ip = get_iterator_ptr(ihandle); -if (ip == NULL) - then return UTIL_ERROR_BAD_HANDLE; + const struct iterator *const ip = get_iterator_ptr(ihandle); + if (ip == NULL) + { + return UTIL_ERROR_BAD_HANDLE; + } -return (ip->tep == NULL) - ? 1 /* iterator in "null-pointer" state */ - : 0; /* iterator -> some table entry */ + return (ip->tep == NULL) + ? 1 /* iterator in "null-pointer" state */ + : 0; /* iterator -> some table entry */ } /******************************************************************************/ @@ -2174,13 +2604,15 @@ return (ip->tep == NULL) @@*/ int Util_TableItQueryIsNonNull(int ihandle) { -const struct iterator *const ip = get_iterator_ptr(ihandle); -if (ip == NULL) - then return UTIL_ERROR_BAD_HANDLE; + const struct iterator *const ip = get_iterator_ptr(ihandle); + if (ip == NULL) + { + return UTIL_ERROR_BAD_HANDLE; + } -return (ip->tep == NULL) - ? 0 /* iterator in "null-pointer" state */ - : 1; /* iterator -> some table entry */ + return (ip->tep == NULL) + ? 0 /* iterator in "null-pointer" state */ + : 1; /* iterator -> some table entry */ } /******************************************************************************/ @@ -2207,11 +2639,13 @@ return (ip->tep == NULL) @@*/ int Util_TableItQueryTableHandle(int ihandle) { -const struct iterator *const ip = get_iterator_ptr(ihandle); -if (ip == NULL) - then return UTIL_ERROR_BAD_HANDLE; + const struct iterator *const ip = get_iterator_ptr(ihandle); + if (ip == NULL) + { + return UTIL_ERROR_BAD_HANDLE; + } -return ip->thp->handle; + return ip->thp->handle; } /******************************************************************************/ @@ -2275,7 +2709,7 @@ return ip->thp->handle; key_buffer is non-NULL), followed by a null character to properly terminate the string in the buffer. If any other error code is returned, the user's key buffer - (pointed to by key_buffer if this is non-NULL) is unchanged. + (pointed to by key_buffer if this is non-NULL) is unchanged. @endcomment @endreturndesc @@*/ @@ -2283,47 +2717,57 @@ int Util_TableItQueryKeyValueInfo(int ihandle, int key_buffer_length, char key_buffer[], CCTK_INT *type_code, CCTK_INT *N_elements) { -const struct iterator *const ip = get_iterator_ptr(ihandle); -if (ip == NULL) - then return UTIL_ERROR_BAD_HANDLE; - - { -const struct table_entry *const tep = ip->tep; -if (tep == NULL) - then return UTIL_ERROR_TABLE_ITERATOR_IS_NULL; - - { -const int actual_key_length = strlen(tep->key); - -/* store the fixed-length output arguments first, so the caller */ -/* will have them even if we hit an error trying to copy the key */ -if (type_code != NULL) - then *type_code = tep->type_code; -if (N_elements != NULL) - then *N_elements = tep->N_elements; - -if (key_buffer != NULL) - then { - const int N_key_copy = min(key_buffer_length-1, actual_key_length); - if (N_key_copy < 0) /* can only happen if key_buffer_length <= 0 */ - then { - /* - * We have to bail out now, before trying the memcpy(), - * because memcpy() takes a size_t (= unsigned) value for - * its count of how many chars to copy, and converting our - * -ve N_key_copy to size_t would give a huge +ve count :( :( - */ - return UTIL_ERROR_TABLE_STRING_TRUNCATED; - } - memcpy(key_buffer, tep->key, N_key_copy); - key_buffer[N_key_copy] = '\0'; - if (N_key_copy < actual_key_length) - then return UTIL_ERROR_TABLE_STRING_TRUNCATED; - } + const struct iterator *const ip = get_iterator_ptr(ihandle); + if (ip == NULL) + { + return UTIL_ERROR_BAD_HANDLE; + } -return actual_key_length; /* ok */ + { + const struct table_entry *const tep = ip->tep; + if (tep == NULL) + { + return UTIL_ERROR_TABLE_ITERATOR_IS_NULL; } + + { + const int actual_key_length = strlen(tep->key); + + /* store the fixed-length output arguments first, so the caller */ + /* will have them even if we hit an error trying to copy the key */ + if (type_code != NULL) + { + *type_code = tep->type_code; } + if (N_elements != NULL) + { + *N_elements = tep->N_elements; + } + + if (key_buffer != NULL) + { + const int N_key_copy = min(key_buffer_length-1, actual_key_length); + if (N_key_copy < 0) /* can only happen if key_buffer_length <= 0 */ + { + /* + * We have to bail out now, before trying the memcpy(), because + * memcpy() takes a size_t (= unsigned) value for its count of how + * many chars to copy, and converting our -ve N_key_copy to size_t + * would give a huge +ve count :( :( + */ + return UTIL_ERROR_TABLE_STRING_TRUNCATED; + } + memcpy(key_buffer, tep->key, N_key_copy); + key_buffer[N_key_copy] = '\0'; + if (N_key_copy < actual_key_length) + { + return UTIL_ERROR_TABLE_STRING_TRUNCATED; + } + } + + return actual_key_length; /* ok */ + } + } } /******************************************************************************/ @@ -2356,20 +2800,23 @@ return actual_key_length; /* ok */ @@*/ int Util_TableItAdvance(int ihandle) { -struct iterator *const ip = get_iterator_ptr(ihandle); -if (ip == NULL) - then return UTIL_ERROR_BAD_HANDLE; + struct iterator *const ip = get_iterator_ptr(ihandle); + if (ip == NULL) + { + return UTIL_ERROR_BAD_HANDLE; + } -if (ip->tep == NULL) - then return 0; /* iterator was already in */ - /* "null-pointer" state */ + if (ip->tep == NULL) + { + return 0; /* iterator was already in "null-pointer" state */ + } -ip->tep = ip->tep->next; + ip->tep = ip->tep->next; -return (ip->tep == NULL) - ? 0 /* advance past last entry */ - /* ==> iterator now in "null-pointer" state */ - : 1; /* ok */ + return (ip->tep == NULL) + ? 0 /* advance past last entry */ + /* ==> iterator now in "null-pointer" state */ + : 1; /* ok */ } /******************************************************************************/ @@ -2400,15 +2847,17 @@ return (ip->tep == NULL) @@*/ int Util_TableItResetToStart(int ihandle) { -struct iterator *const ip = get_iterator_ptr(ihandle); -if (ip == NULL) - then return UTIL_ERROR_BAD_HANDLE; + struct iterator *const ip = get_iterator_ptr(ihandle); + if (ip == NULL) + { + return UTIL_ERROR_BAD_HANDLE; + } -ip->tep = ip->thp->head; -return (ip->tep == NULL) - ? 0 /* ok, iterator is now in "null-pointer" state */ - /* (table must be empty) */ - : 1; /* ok, iterator points to some table element */ + ip->tep = ip->thp->head; + return (ip->tep == NULL) + ? 0 /* ok, iterator is now in "null-pointer" state */ + /* (table must be empty) */ + : 1; /* ok, iterator points to some table element */ } /******************************************************************************/ @@ -2435,12 +2884,14 @@ return (ip->tep == NULL) @@*/ int Util_TableItSetToNull(int ihandle) { -struct iterator *const ip = get_iterator_ptr(ihandle); -if (ip == NULL) - then return UTIL_ERROR_BAD_HANDLE; + struct iterator *const ip = get_iterator_ptr(ihandle); + if (ip == NULL) + { + return UTIL_ERROR_BAD_HANDLE; + } -ip->tep = NULL; -return 0; /* ok */ + ip->tep = NULL; + return 0; /* ok */ } /******************************************************************************/ @@ -2476,18 +2927,24 @@ return 0; /* ok */ @@*/ int Util_TableItSetToKey(int ihandle, const char *key) { -struct iterator *const ip = get_iterator_ptr(ihandle); -if (ip == NULL) - then return UTIL_ERROR_BAD_HANDLE; + struct iterator *const ip = get_iterator_ptr(ihandle); + if (ip == NULL) + { + return UTIL_ERROR_BAD_HANDLE; + } -if (bad_key(key)) - then return UTIL_ERROR_TABLE_BAD_KEY; + if (is_bad_key(key)) + { + return UTIL_ERROR_TABLE_BAD_KEY; + } -ip->tep = find_table_entry(ip->thp, key, NULL); -if (ip->tep == NULL) - then return UTIL_ERROR_TABLE_NO_SUCH_KEY; + ip->tep = find_table_entry(ip->thp, key, NULL); + if (ip->tep == NULL) + { + return UTIL_ERROR_TABLE_NO_SUCH_KEY; + } -return 0; + return 0; } /******************************************************************************/ @@ -2551,90 +3008,59 @@ static int type_code, int N_elements, const void *value, const char *key) { -struct table_header *const thp = get_table_header_ptr(handle); -if (thp == NULL) - then return UTIL_ERROR_BAD_HANDLE; - -#ifdef UTIL_TABLE_DEBUG -printf("internal_set(handle=%d, type_code=%d, N_elements=%d, key=\"%s\")\n", - handle, type_code, N_elements, key); -#endif - -if (bad_key(key)) - then return UTIL_ERROR_TABLE_BAD_KEY; -if (N_elements < 0) - then return UTIL_ERROR_BAD_INPUT; - -/* if key is already in table, delete it */ -/* ... this is a harmless no-op if it's not already in the table */ - { -int return_value; -switch (delete_key(thp, key)) - { -case 0: - return_value = 1; /* key was already in table before this call */ - /* (we've just deleted it, and we're about */ - /* to set the replacement in the table) */ - break; -case UTIL_ERROR_TABLE_NO_SUCH_KEY: - return_value = 0; /* key was not in table before this call */ - break; -default: - /* unexpected return code from delete_key() */ - /* (this should never happen!) */ - assert(false); - abort(); /* internal error (core dump) */ - } - -/* allocate a new table entry */ + struct table_header *const thp = get_table_header_ptr(handle); + if (thp == NULL) { -struct table_entry *tep - = (struct table_entry *) malloc(sizeof(struct table_entry)); -if (tep == NULL) - then return UTIL_ERROR_NO_MEMORY; /* can't allocate new table entry */ - -/* set up the new table entry */ -tep->key = Util_Strdup(key); -if (tep->key == NULL) - then { - free(tep); - return UTIL_ERROR_NO_MEMORY; /* can't allocate memory to copy key */ - } - -tep->type_code = type_code; -tep->N_elements = N_elements; + return UTIL_ERROR_BAD_HANDLE; + } + if (is_bad_key(key)) { -size_t sizeof_value = N_elements * CCTK_VarTypeSize(type_code); -#ifdef UTIL_TABLE_DEBUG2 -printf(" allocating new buffer of size sizeof_value=%d bytes\n", - (int) sizeof_value); -#endif + return UTIL_ERROR_TABLE_BAD_KEY; + } + if (N_elements < 0) { -void *buffer = malloc(sizeof_value); -if (buffer == NULL) - then { - free(tep->key); - free(tep); - return UTIL_ERROR_NO_MEMORY; /* can't allocate memory */ - /* to copy value */ - } -#ifdef UTIL_TABLE_DEBUG -printf(" copying sizeof_value=%d bytes into buffer\n", (int) sizeof_value); -#endif -memcpy(buffer, value, sizeof_value); -tep->value = buffer; + return UTIL_ERROR_BAD_INPUT; + } -/* insert the table entry into the table's linked list */ -/* (we could insert it anywhere; for simplicity we insert it at the head) */ -tep->next = thp->head; -thp->head = tep; + #ifdef UTIL_TABLE_DEBUG + printf("internal_set(handle=%d, type_code=%d, N_elements=%d, key=\"%s\")\n", + handle, type_code, N_elements, key); + #endif -return return_value; - } - } + /* if key is already in table, delete it */ + /* ... this is a harmless no-op if it's not already in the table */ + { + int return_value; + switch (delete_table_entry_by_key(thp, key)) + { + case 0: + return_value = 1; /* key was already in table before this call */ + /* (we've just deleted it, and we're about */ + /* to set the replacement in the table) */ + break; + case UTIL_ERROR_TABLE_NO_SUCH_KEY: + return_value = 0; /* key was not in table before this call */ + break; + default: + /* unexpected return code from delete_table_entry_by_key() */ + /* (this should never happen!) */ + assert(false); + abort(); /* internal error (core dump) */ } + + { + const int status = insert_table_entry(thp, + key, + type_code, N_elements, value); + if (status < 0) + { + return status; /* error inserting entry into table */ } + + return return_value; + } + } } /******************************************************************************/ @@ -2703,45 +3129,55 @@ static int type_code, int N_value_buffer, void *value_buffer, const char *key) { -const struct table_header *const thp = get_table_header_ptr(handle); -if (thp == NULL) - then return UTIL_ERROR_BAD_HANDLE; + const struct table_header *const thp = get_table_header_ptr(handle); + if (thp == NULL) + { + return UTIL_ERROR_BAD_HANDLE; + } -#ifdef UTIL_TABLE_DEBUG -printf("internal_get(handle=%d, type_code=%d, N_value_buffer=%d, key=\"%s\")\n", - handle, type_code, N_value_buffer, key); -#endif + if (is_bad_key(key)) + { + return UTIL_ERROR_TABLE_BAD_KEY; + } -if (bad_key(key)) - then return UTIL_ERROR_TABLE_BAD_KEY; + #ifdef UTIL_TABLE_DEBUG + printf( + "internal_get(handle=%d, type_code=%d, N_value_buffer=%d, key=\"%s\")\n", + handle, type_code, N_value_buffer, key); + #endif + { + const struct table_entry *const tep = find_table_entry(thp, key, NULL); + if (tep == NULL) { -const struct table_entry *const tep = find_table_entry(thp, key, NULL); -if (tep == NULL) - then return UTIL_ERROR_TABLE_NO_SUCH_KEY; /* no such key in table */ - -if (tep->type_code != type_code) - then return UTIL_ERROR_TABLE_WRONG_DATA_TYPE; /* value has wrong data type */ + return UTIL_ERROR_TABLE_NO_SUCH_KEY; /* no such key in table */ + } -if (value_buffer != NULL) - then { - if (N_value_buffer < 0) - then return UTIL_ERROR_BAD_INPUT; - { - const int N_copy = min(N_value_buffer, tep->N_elements); - const size_t sizeof_N_copy_elements - = N_copy * CCTK_VarTypeSize(type_code); - #ifdef UTIL_TABLE_DEBUG - printf( - " copying N_copy=%d elements (sizeof_N_copy_elements=%d bytes)\n", - N_copy, (int) sizeof_N_copy_elements); - #endif - memcpy(value_buffer, tep->value, sizeof_N_copy_elements); - } - } + if (tep->type_code != type_code) + { + return UTIL_ERROR_TABLE_WRONG_DATA_TYPE; /* value has wrong data type */ + } -return tep->N_elements; + if (value_buffer != NULL) + { + if (N_value_buffer < 0) + { + return UTIL_ERROR_BAD_INPUT; + } + { + const int N_copy = min(N_value_buffer, tep->N_elements); + const size_t sizeof_N_copy_elements = N_copy * CCTK_VarTypeSize(type_code); + #ifdef UTIL_TABLE_DEBUG + printf( + " copying N_copy=%d elements (sizeof_N_copy_elements=%d bytes)\n", + N_copy, (int) sizeof_N_copy_elements); + #endif + memcpy(value_buffer, tep->value, sizeof_N_copy_elements); + } } + + return tep->N_elements; + } } /******************************************************************************/ @@ -2760,64 +3196,9 @@ return tep->N_elements; static struct table_header *get_table_header_ptr(int handle) { -return ((handle >= 0) && (handle < N_thp_array)) - ? (struct table_header *) thp_array[handle] /* valid handle */ - : NULL; /* invalid handle */ -} - -/******************************************************************************/ - -/* - * This function deletes a key from a table. - * - * Results: - * The return value is the same as for Util_TableDeleteKey(), i.e. - * 0 for ok (key existed before this call, and has now been deleted) - * -ve for error, including - * UTIL_ERROR_TABLE_NO_SUCH_KEY no such key in table - */ -static - int delete_key(struct table_header *thp, const char *key) -{ -struct table_entry *prev_tep; -struct table_entry *const tep = find_table_entry(thp, key, &prev_tep); -if (tep == NULL) - then return UTIL_ERROR_TABLE_NO_SUCH_KEY; - - { -/* unlink the table entry from the list */ -struct table_entry *next_tep = tep->next; -if (prev_tep == NULL) - then thp->head = next_tep; /* it was the starting entry */ - /* in the list */ - else prev_tep->next = next_tep; /* it was somewhere in the middle */ - -free_table_entry(tep); -return 0; /* ok: key existed before this call, */ - /* and has now been deleted */ - } -} - -/******************************************************************************/ - -/* - * This function frees a table entry and the key/value it holds. - * - * Arguments: - * tep -> The table entry to be freed. - */ -static - void free_table_entry(struct table_entry *tep) -{ -assert(tep != NULL); - -assert(tep->key != NULL); -free(tep->key); - -assert(tep->value != NULL); -free(tep->value); - -free(tep); + return ((handle >= 0) && (handle < N_thp_array)) + ? (struct table_header *) thp_array[handle] /* valid handle */ + : NULL; /* invalid handle */ } /******************************************************************************/ @@ -2827,14 +3208,16 @@ free(tep); * returns true for bad key, false for ok */ static - bool bad_key(const char *key) + bool is_bad_key(const char *key) { -assert(key != NULL); + assert(key != NULL); -if (strchr(key, '/') != NULL) - then return true; + if (strchr(key, '/') != NULL) + { + return true; + } -return false; /* ok */ + return false; /* ok */ } /******************************************************************************/ @@ -2864,27 +3247,198 @@ static const char *key, struct table_entry **prev_tep_ptr) { -assert(thp != NULL); -assert(key != NULL); + assert(thp != NULL); + assert(key != NULL); + + { + const bool case_insensitive_flag + = thp->flags & UTIL_TABLE_FLAGS_CASE_INSENSITIVE; + struct table_entry *prev_tep = NULL; + struct table_entry *tep = thp->head; + for ( ; tep != NULL ; prev_tep = tep, tep = tep->next) + { + if ( case_insensitive_flag + ? (Util_StrCmpi(key, tep->key) == 0) + : ( strcmp (key, tep->key) == 0) ) + { + if (prev_tep_ptr != NULL) + { + *prev_tep_ptr = prev_tep; + } + return tep; /* key found in table */ + } + } + + return NULL; /* key not found in table */ + } +} + +/******************************************************************************/ + +/*@@ + @routine insert_table_entry + @desc This is an internal function used in implementing + Util_TableClone() and internal_set(). It allocates + a new table entry and sets the fields in it to be + copies of the arguments. + + @var thp + @vtype struct table_header * + @vdesc pointer to the table header + @endvar + + @var key + @vtype const char * + @vdesc pointer to a (C-style null-terminated) string, a copy + of which is to be the new table entry's key + @endvar + + @var type_code + @vtype int + @vdesc the value to be the new table entry's type code + (one of the CCTK_VARIABLE_* constants from "cctk_Types.h"), + @endvar + + @var N_elements + @vtype int (must be >= 0) + @vdesc number of elements in array[] + @endvar + + @var array + @vtype const T[], where T is one of + CCTK_POINTER, CCTK_FN_POINTER, + CCTK_CHAR, + CCTK_INT, CCTK_INT2, CCTK_INT4, CCTK_INT8, + CCTK_REAL, CCTK_REAL4, CCTK_REAL8, CCTK_REAL16, + CCTK_COMPLEX, CCTK_COMPLEX8, CCTK_COMPLEX16, CCTK_COMPLEX32 + (not all of these may be supported on any given system) + @vdesc (pointer to) an array, a copy of which is to be + the new table entry's value + @endvar + + @returntype int + @returndesc 0 for ok, + UTIL_ERROR_NO_MEMORY unable to allocate memory + @endreturndesc + @@*/ +static + int insert_table_entry(struct table_header *thp, + const char *key, + int type_code, int N_elements, const void *value) +{ + struct table_entry *tep = (struct table_entry *) + malloc(sizeof(struct table_entry)); + if (tep == NULL) + { + return UTIL_ERROR_NO_MEMORY; /* can't allocate new table entry */ + } + #ifdef UTIL_TABLE_DEBUG + printf("insert_table_entry(type_code=%d, N_elements=%d, key=\"%s\")...\n", + type_code, N_elements, key); + #endif + + tep->key = Util_Strdup(key); + if (tep->key == NULL) { -const int flags = thp->flags; -struct table_entry *prev_tep = NULL; -struct table_entry *tep = thp->head; - for ( ; tep != NULL ; prev_tep = tep, tep = tep->next) - { - if ( (flags & UTIL_TABLE_FLAGS_CASE_INSENSITIVE) - ? (Util_StrCmpi(key, tep->key) == 0) - : ( strcmp (key, tep->key) == 0) ) - then { - if (prev_tep_ptr != NULL) - *prev_tep_ptr = prev_tep; - return tep; /* key found in table */ - } - } + free(tep); + return UTIL_ERROR_NO_MEMORY; /* can't allocate memory to copy key */ + } -return NULL; /* key not found in table */ + tep->type_code = type_code; + tep->N_elements = N_elements; + + { + const size_t sizeof_value = N_elements * CCTK_VarTypeSize(type_code); + #ifdef UTIL_TABLE_DEBUG2 + printf(" allocating new buffer of size sizeof_value=%d bytes\n", + (int) sizeof_value); + #endif + { + void *const buffer = malloc(sizeof_value); + if (buffer == NULL) + { + free(tep->key); + free(tep); + return UTIL_ERROR_NO_MEMORY; /* can't allocate memory for copy of value */ } + #ifdef UTIL_TABLE_DEBUG + printf(" copying sizeof_value=%d bytes into buffer\n", (int) sizeof_value); + #endif + memcpy(buffer, value, sizeof_value); + tep->value = buffer; + + /* insert the table entry into the table's linked list */ + /* (we could insert it anywhere; for simplicity we insert it at the head) */ + tep->next = thp->head; + thp->head = tep; + + return 0; + } + } +} + +/******************************************************************************/ + +/* + * This function deletes an entry (specified by its key) from a table, + * freeing its table entry and the pointed-to key and value. + * + * Results: + * The return value is the same as for Util_TableDeleteKey(), i.e. + * 0 for ok (key existed before this call, and has now been deleted) + * -ve for error, including + * UTIL_ERROR_TABLE_NO_SUCH_KEY no such key in table + */ +static + int delete_table_entry_by_key(struct table_header *thp, const char *key) +{ + struct table_entry *prev_tep; + struct table_entry *const tep = find_table_entry(thp, key, &prev_tep); + if (tep == NULL) + { + return UTIL_ERROR_TABLE_NO_SUCH_KEY; + } + + delete_table_entry_by_ptr(thp, prev_tep); + return 0; /* ok: key existed before this call, */ + /* and has now been deleted */ +} + +/******************************************************************************/ + +/* + * This function deletes an entry from a table, freeing its table entry + * and the pointed-to key and value. The entry to be deleted is specified + * by a pointer to the *previous* table entry, or NULL to delete the + * starting entry in the list. + */ +static + void delete_table_entry_by_ptr(struct table_header *thp, + struct table_entry *prev_tep) +{ +/* this is the entry we want to delete */ +struct table_entry *const tep = (prev_tep == NULL) ? thp->head + : prev_tep->next; +assert(tep != NULL); + +/* unlink it from the list */ +if (prev_tep == NULL) +{ + thp->head = tep->next; +} +else +{ + prev_tep->next = tep->next; +} + +assert(tep->key != NULL); +free(tep->key); + +assert(tep->value != NULL); +free(tep->value); + +free(tep); } /******************************************************************************/ @@ -2896,16 +3450,16 @@ return NULL; /* key not found in table */ * ihandle = The iterator handle. * * Results: + * If the handle is valid, this function returns a pointer to the iterator. * If the handle is invalid (i.e. there is no such table), this function * returns NULL. - * If the handle is valid, this function returns a pointer to the iterator. */ static struct iterator *get_iterator_ptr(int ihandle) { -return ((ihandle >= 0) && (ihandle < N_ip_array)) - ? (struct iterator *) ip_array[ihandle] /* valid handle */ - : NULL; /* invalid handle */ + return ((ihandle >= 0) && (ihandle < N_ip_array)) + ? (struct iterator *) ip_array[ihandle] /* valid handle */ + : NULL; /* invalid handle */ } /******************************************************************************/ @@ -2927,25 +3481,27 @@ return ((ihandle >= 0) && (ihandle < N_ip_array)) static int grow_pointer_array(int *pN, void ***pvp_array) { -int N = *pN; -void **vp_array = *pvp_array; -int new_N = GROW(N); -void **new_vp_array = realloc(vp_array, new_N*sizeof(void *)); -if (new_vp_array == NULL) - then return UTIL_ERROR_NO_MEMORY; /* can't grow array */ +const int N = *pN; + void **vp_array = *pvp_array; + const int new_N = GROW(N); + void **new_vp_array = realloc(vp_array, new_N*sizeof(void *)); + if (new_vp_array == NULL) + { + return UTIL_ERROR_NO_MEMORY; /* can't grow array */ + } -/* initialize the new space to NULL pointers */ + /* initialize the new space to NULL pointers */ + { + int i; + for (i = N ; i < new_N ; ++i) { -int i; - for (i = N ; i < new_N ; ++i) - { - new_vp_array[i] = NULL; - } + new_vp_array[i] = NULL; } + } -*pvp_array = new_vp_array; -*pN = new_N; -return 0; /* ok */ + *pvp_array = new_vp_array; + *pN = new_N; + return 0; /* ok */ } /******************************************************************************/ @@ -2954,18 +3510,18 @@ return 0; /* ok */ #ifdef UTIL_TABLE_TEST /* - * This function prints out all the tables and their data structures. - */ +* This function prints out all the tables and their data structures. +*/ static - void print_all_tables(void) +void print_all_tables(void) { -int handle; + int handle; -printf("N_tables=%d N_thp_array=%d\n", N_tables, N_thp_array); - for (handle = 0 ; handle < N_thp_array ; ++handle) - { - print_table(handle); - } + printf("N_tables=%d N_thp_array=%d\n", N_tables, N_thp_array); + for (handle = 0 ; handle < N_thp_array ; ++handle) + { + print_table(handle); + } } #endif /* UTIL_TABLE_TEST */ @@ -2978,60 +3534,71 @@ printf("N_tables=%d N_thp_array=%d\n", N_tables, N_thp_array); static void print_table(int handle) { -printf("thp_array[%d]: ", handle); + printf("thp_array[%d]: ", handle); + { + const struct table_header *const thp = get_table_header_ptr(handle); + if (thp == NULL) + { + printf("NULL\n"); + } + else { -const struct table_header *const thp = get_table_header_ptr(handle); -if (thp == NULL) - then printf("NULL\n"); - else { - printf("flags=0x%x handle=%d\n", thp->flags, thp->handle); + printf("flags=0x%x handle=%d\n", thp->flags, thp->handle); + { + const struct table_entry *tep = thp->head; + for ( ; tep != NULL ; tep = tep->next) + { + printf(" [tep=%p]\n", (const void *) tep); + printf("\tkey=\"%s\"\n", tep->key); + printf("\ttype_code=%d N_elements=%d\n", tep->type_code, tep->N_elements); + { + int i; + switch (tep->type_code) + { + case CCTK_VARIABLE_INT: + printf("\t[int]"); + { + const CCTK_INT *const value_ptr_int = (const CCTK_INT *) tep->value; + for (i = 0 ; i < tep->N_elements ; ++i) + { + printf("\t%d", (int) value_ptr_int[i]); + } + } + break; + case CCTK_VARIABLE_REAL: + printf("\t[real]"); + { + const CCTK_REAL *const value_ptr_real + = (const CCTK_REAL *) tep->value; + for (i = 0 ; i < tep->N_elements ; ++i) { - const struct table_entry *tep = thp->head; - for ( ; tep != NULL ; tep = tep->next) - { - printf(" [tep=%p]\n", (const void *) tep); - printf("\tkey=\"%s\"\n", tep->key); - printf("\ttype_code=%d N_elements=%d\n", - tep->type_code, tep->N_elements); - { - int i; - switch (tep->type_code) - { - case CCTK_VARIABLE_INT: - printf("\t[int]"); - for (i = 0 ; i < tep->N_elements ; ++i) - { - const CCTK_INT *value_int - = (const CCTK_INT *) tep->value; - printf("\t%d", (int) value_int[i]); - } - break; - case CCTK_VARIABLE_REAL: - printf("\t[real]"); - for (i = 0 ; i < tep->N_elements ; ++i) - { - const CCTK_REAL *value_real - = (const CCTK_REAL *) tep->value; - printf("\t%g", (double) value_real[i]); - } - break; - case CCTK_VARIABLE_COMPLEX: - printf("\t[complex]"); - for (i = 0 ; i < tep->N_elements ; ++i) - { - const CCTK_COMPLEX *value_complex - = (const CCTK_COMPLEX *) tep->value; - printf("\t(%g,%g)", - (double) value_complex[i].Re, - (double) value_complex[i].Im); - } - } - printf("\n"); - } - } + printf("\t%g", (double) value_ptr_real[i]); } + } + break; + case CCTK_VARIABLE_COMPLEX: + printf("\t[complex]"); + { + const CCTK_COMPLEX *const value_ptr_complex + = (const CCTK_COMPLEX *) tep->value; + for (i = 0 ; i < tep->N_elements ; ++i) + { + printf("\t(%g,%g)", + (double) value_ptr_complex[i].Re, + (double) value_ptr_complex[i].Im); + } + } + break; + default: + printf("\t[sorry, don't know how to print this type!]"); + break; + } + printf("\n"); } + } + } } + } } #endif /* UTIL_TABLE_TEST */ @@ -3044,18 +3611,22 @@ if (thp == NULL) static void print_all_iterators(void) { -int ihandle; + int ihandle; -printf("N_iterators=%d N_ip_array=%d\n", N_iterators, N_ip_array); - for (ihandle = 0 ; ihandle < N_ip_array ; ++ihandle) - { - const struct iterator *const ip = get_iterator_ptr(ihandle); - printf("ip_array[%d]: ", ihandle); - if (ip == NULL) - then printf("NULL\n"); - else printf("thp=%p tep=%p\n", - (const void *) ip->thp, (const void *) ip->tep); - } + printf("N_iterators=%d N_ip_array=%d\n", N_iterators, N_ip_array); + for (ihandle = 0 ; ihandle < N_ip_array ; ++ihandle) + { + const struct iterator *const ip = get_iterator_ptr(ihandle); + printf("ip_array[%d]: ", ihandle); + if (ip == NULL) + { + printf("NULL\n"); + } + else + { + printf("thp=%p tep=%p\n", (const void *) ip->thp, (const void *) ip->tep); + } + } } #endif /* UTIL_TABLE_TEST */ @@ -3069,223 +3640,195 @@ printf("N_iterators=%d N_ip_array=%d\n", N_iterators, N_ip_array); * low-level macros to test set/get of scalars of various types */ -#define CHECK_SET_GET_INT(handle, type, \ - key_already_exists, case_insensitive, \ - set_fn, get_fn) \ - { \ -type x = 42; \ -assert( set_fn(handle, x, "int_x") == key_already_exists ); \ -x = 1; \ -assert( get_fn(handle, &x, "int_x") == 1 ); \ -assert( x == 42 ); \ -if (case_insensitive) \ - then { \ - x = 2; \ - assert( get_fn(handle, &x, "Int_X") == 1 ); \ - assert( x == 42 ); \ - } \ - else assert( get_fn(handle, &x, "Int_X") \ - == UTIL_ERROR_TABLE_NO_SUCH_KEY ); \ - } /* end macro */ - -/**************************************/ - -#define CHECK_SET_GET_REAL(handle, type, \ - key_already_exists, case_insensitive, \ +#define CHECK_SET_GET_INT(handle, type, \ + key_already_exists, case_insensitive, \ set_fn, get_fn) \ + { \ + type x = 42; \ + assert( set_fn(handle, x, "int_x") == key_already_exists ); \ + x = 1; \ + assert( get_fn(handle, &x, "int_x") == 1 ); \ + assert( x == 42 ); \ + if (case_insensitive) \ { \ -type y = 42.25; \ -assert( set_fn(handle, y, "REAL_y") == key_already_exists ); \ -y = 1.25; \ -assert( get_fn(handle, &y, "REAL_y") == 1 ); \ -assert( y == 42.25 ); \ -if (case_insensitive) \ - then { \ - y = 1.5; \ - assert( get_fn(handle, &y, "real_y") == 1 ); \ - assert( y == 42.25 ); \ - } \ - else assert( get_fn(handle, &y, "real_y") \ - == UTIL_ERROR_TABLE_NO_SUCH_KEY ); \ - } /* end macro */ + x = 2; \ + assert( get_fn(handle, &x, "Int_X") == 1 ); \ + assert( x == 42 ); \ + } \ + else \ + { \ + assert( get_fn(handle, &x, "Int_X") \ + == UTIL_ERROR_TABLE_NO_SUCH_KEY ); \ + } \ + } /* end macro */ /**************************************/ -#define CHECK_SET_GET_COMPLEX(handle, type, \ - key_already_exists, case_insensitive, \ - set_fn, get_fn) \ +#define CHECK_SET_GET_GENERIC_INT(handle, type_code, type, \ + key_already_exists, case_insensitive) \ + { \ + type gx = 42; \ + assert( Util_TableSetGeneric(handle, \ + type_code, (const void *) &gx, \ + "gint_x") == key_already_exists ); \ + gx = 1; \ + assert( Util_TableGetGeneric(handle, \ + type_code, (void *) &gx, \ + "gint_x") == 1 ); \ + assert( gx == 42 ); \ + if (case_insensitive) \ { \ -static type z = { 42.25, 105.5 }; \ -assert( set_fn(handle, z, "COMPlex_Z") == key_already_exists ); \ -z.Re = 1.25; z.Im = -2.78; \ -assert( get_fn(handle, &z, "COMPlex_Z") == 1 ); \ -assert( z.Re == 42.25 ); \ -assert( z.Im == 105.5 ); \ -if (case_insensitive) \ - then { \ - z.Re = 1.5; z.Im = -2.83; \ - assert( get_fn(handle, &z, "COMPLEX_Z") == 1 ); \ - assert( z.Re == 42.25 ); \ - assert( z.Im == 105.5 ); \ - } \ - else assert( get_fn(handle, &z, "COMPLEX_Z") \ - == UTIL_ERROR_TABLE_NO_SUCH_KEY ); \ - } /* end macro */ - -/******************************************************************************/ - -/* - * low-level macros to test set/get of arrays of various types - */ - -#define CHECK_SET_GET_INT_ARRAY(handle, type, key_already_exists, \ - set_fn, get_fn) \ + gx = 2; \ + assert( Util_TableGetGeneric(handle, \ + type_code, (void *) &gx, \ + "GInt_X") == 1 ); \ + assert( gx == 42 ); \ + } \ + else \ { \ -static type xx[5] = { 41, 42, 48, 45, 47 }; \ -assert( set_fn(handle, 3, xx, "xx") == key_already_exists ); \ -xx[0] = 14; xx[1] = 15; xx[2] = 16; xx[3] = 17; xx[4] = 19; \ -/* try to get 4 values, but only 3 were stored ==> only get 3 */ \ -assert( get_fn(handle, 4, xx, "xx") == 3 ); \ -assert( xx[0] == 41 ); \ -assert( xx[1] == 42 ); \ -assert( xx[2] == 48 ); \ -assert( xx[3] == 17 ); \ -assert( xx[4] == 19 ); \ - } /* end macro */ + assert( Util_TableGetGeneric(handle, \ + type_code, (void *) &gx, \ + "GInt_X") \ + == UTIL_ERROR_TABLE_NO_SUCH_KEY ); \ + } \ + } /* end macro */ /**************************************/ -#define CHECK_SET_GET_REAL_ARRAY(handle, type, key_already_exists, \ - set_fn, get_fn) \ +#define CHECK_SET_GET_REAL(handle, type, \ + key_already_exists, case_insensitive, \ + set_fn, get_fn) \ + { \ + type y = 42.25; \ + assert( set_fn(handle, y, "REAL_y") == key_already_exists ); \ + y = 1.25; \ + assert( get_fn(handle, &y, "REAL_y") == 1 ); \ + assert( y == 42.25 ); \ + if (case_insensitive) \ + { \ + y = 1.5; \ + assert( get_fn(handle, &y, "real_y") == 1 ); \ + assert( y == 42.25 ); \ + } \ + else \ { \ -static type yy[5] = { 41.25, 42.5, 48.0, 45.75, 47.125 }; \ -assert( set_fn(handle, 4, yy, "yy") == key_already_exists ); \ -yy[0] = 14.0; yy[1] = 15.5; yy[2] = 16.0; \ -yy[3] = 17.5; yy[4] = 19.5; \ -/* only get 3 of 4 stored values */ \ -assert( get_fn(handle, 3, yy, "yy") == 4 ); \ -assert( yy[0] == 41.25 ); \ -assert( yy[1] == 42.5 ); \ -assert( yy[2] == 48.0 ); \ -assert( yy[3] == 17.5 ); \ -assert( yy[4] == 19.5 ); \ - } /* end macro */ + assert( get_fn(handle, &y, "real_y") \ + == UTIL_ERROR_TABLE_NO_SUCH_KEY ); \ + } \ + } /* end macro */ /**************************************/ -#define CHECK_SET_GET_COMPLEX_ARRAY(handle, type, key_already_exists, \ - set_fn, get_fn) \ +#define CHECK_SET_GET_COMPLEX(handle, type, \ + key_already_exists, case_insensitive, \ + set_fn, get_fn) \ + { \ + static type z = { 42.25, 105.5 }; \ + assert( set_fn(handle, z, "COMPlex_Z") == key_already_exists ); \ + z.Re = 1.25; z.Im = -2.78; \ + assert( get_fn(handle, &z, "COMPlex_Z") == 1 ); \ + assert( z.Re == 42.25 ); \ + assert( z.Im == 105.5 ); \ + if (case_insensitive) \ { \ -static type zz[5] \ - = { {3.5,1.25}, {9.5,4.5}, {0.5,8.0}, {5.0,5.5}, {4.5,7.25} }; \ -assert( set_fn(handle, 4, zz, "zz") == key_already_exists ); \ -zz[0].Re = 10.25; zz[0].Im = 11.75; \ -zz[1].Re = -2.5; zz[1].Im = 3.5; \ -zz[2].Re = 14.0; zz[2].Im = -8.5; \ -zz[3].Re = 0.25; zz[3].Im = 8.875; \ -zz[4].Re = -0.25; zz[4].Im = -0.75; \ -/* only get 3 of 4 stored values */ \ -assert( get_fn(handle, 3, zz, "zz") == 4 ); \ -assert( zz[0].Re == 3.5 ); assert( zz[0].Im == 1.25 ); \ -assert( zz[1].Re == 9.5 ); assert( zz[1].Im == 4.5 ); \ -assert( zz[2].Re == 0.5 ); assert( zz[2].Im == 8.0 ); \ -assert( zz[3].Re == 0.25 ); assert( zz[3].Im == 8.875 ); \ -assert( zz[4].Re == -0.25 ); assert( zz[4].Im == -0.75 ); \ - } /* end macro */ - -#endif /* UTIL_TABLE_TEST */ + z.Re = 1.5; z.Im = -2.83; \ + assert( get_fn(handle, &z, "COMPLEX_Z") == 1 ); \ + assert( z.Re == 42.25 ); \ + assert( z.Im == 105.5 ); \ + } \ + else \ + { \ + assert( get_fn(handle, &z, "COMPLEX_Z") \ + == UTIL_ERROR_TABLE_NO_SUCH_KEY ); \ + } \ + } /* end macro */ /******************************************************************************/ -#ifdef UTIL_TABLE_TEST /* - * This function does a sequence of assert() calls to verify that - * a table contains the 3 keys - * ij = 42 - * real1 = 3.5 - * real_e = 2.75 - * inserted in that order. - * - * Bugs: - * This test is tied to the present implementation -- it assumes a - * specific ordering of table elements returned by an iterator. + * low-level macros to test set/get of arrays of various types */ -static - void check_table_contents(int handle) -{ -assert( Util_TableQueryNKeys(handle) == 3 ); -/* set up the key buffer */ - { -int max_key_length = Util_TableQueryMaxKeyLength(handle); -assert( max_key_length == (int)strlen("real_e") ); - { -const int N_key_buffer = max_key_length + 1; -char *const key_buffer = malloc(N_key_buffer); -assert( key_buffer != NULL ); +#define CHECK_SET_GET_INT_ARRAY(handle, type, key_already_exists, \ + set_fn, get_fn) \ + { \ + static type xx[5] = { 41, 42, 48, 45, 47 }; \ + assert( set_fn(handle, 3, xx, "xx") == key_already_exists ); \ + xx[0] = 14; xx[1] = 15; xx[2] = 16; xx[3] = 17; xx[4] = 19; \ + /* try to get 4 values, but only 3 were stored ==> only get 3 */ \ + assert( get_fn(handle, 4, xx, "xx") == 3 ); \ + assert( xx[0] == 41 ); \ + assert( xx[1] == 42 ); \ + assert( xx[2] == 48 ); \ + assert( xx[3] == 17 ); \ + assert( xx[4] == 19 ); \ + } /* end macro */ -/* walk through the table to verify contents {"real_e", "real1", "ij"} */ -/* n.b. implementation-dependence here for order of table elements */ - { -int ihandle = Util_TableItCreate(handle); -CCTK_INT key_length, type_code, N_elements; +/**************************************/ -/* real_e = 2.75 */ -type_code = 123456; -N_elements = 54321; -assert( Util_TableItQueryKeyValueInfo(ihandle, - N_key_buffer, key_buffer, - &type_code, &N_elements) - == (int)strlen("real_e") ); -assert( strcmp(key_buffer, "real_e") == 0 ); -assert( type_code = CCTK_VARIABLE_REAL ); -assert( N_elements == 1 ); - { -CCTK_REAL value_real; -assert( Util_TableGetReal(handle, &value_real, key_buffer) == 1 ); -assert( value_real == 2.75 ); +#define CHECK_SET_GET_REAL_ARRAY(handle, type, key_already_exists, \ + set_fn, get_fn) \ + { \ + static type yy[5] = { 41.25, 42.5, 48.0, 45.75, 47.125 }; \ + assert( set_fn(handle, 4, yy, "yy") == key_already_exists ); \ + yy[0] = 14.0; yy[1] = 15.5; yy[2] = 16.0; \ + yy[3] = 17.5; yy[4] = 19.5; \ + /* only get 3 of 4 stored values */ \ + assert( get_fn(handle, 3, yy, "yy") == 4 ); \ + assert( yy[0] == 41.25 ); \ + assert( yy[1] == 42.5 ); \ + assert( yy[2] == 48.0 ); \ + assert( yy[3] == 17.5 ); \ + assert( yy[4] == 19.5 ); \ + } /* end macro */ -/* real1 = 3.5 */ -assert( Util_TableItAdvance(ihandle) == 1 ); -type_code = 123456; -N_elements = 54321; -assert( Util_TableItQueryKeyValueInfo(ihandle, - N_key_buffer, key_buffer, - &type_code, &N_elements) - == (int)strlen("real1") ); -assert( strcmp(key_buffer, "real1") == 0 ); -assert( type_code = CCTK_VARIABLE_REAL ); -assert( N_elements == 1 ); -assert( Util_TableGetReal(handle, &value_real, key_buffer) == 1 ); -assert( value_real == 3.5 ); +/**************************************/ -/* ij = 42 */ -assert( Util_TableItAdvance(ihandle) == 1 ); -type_code = 123456; -N_elements = 54321; -assert( Util_TableItQueryKeyValueInfo(ihandle, - N_key_buffer, key_buffer, - &type_code, &N_elements) - == (int)strlen("ij") ); -assert( strcmp(key_buffer, "ij") == 0 ); -assert( type_code = CCTK_VARIABLE_REAL ); -assert( N_elements == 1 ); - { -CCTK_INT value_int; -assert( Util_TableGetInt(handle, &value_int, key_buffer) == 1 ); -assert( value_int == 42 ); +#define CHECK_SET_GET_GENERIC_REAL_ARRAY(handle, type_code, type, \ + key_already_exists) \ + { \ + static type gyy[5] = { 41.25, 42.5, 48.0, 45.75, 47.125 }; \ + assert( Util_TableSetGenericArray(handle, \ + type_code, 4, (const void *) gyy, \ + "gyy") == key_already_exists ); \ + gyy[0] = 14.0; gyy[1] = 15.5; gyy[2] = 16.0; \ + gyy[3] = 17.5; gyy[4] = 19.5; \ + /* only get 3 of 4 stored values */ \ + assert( Util_TableGetGenericArray(handle, \ + type_code, 3, gyy, \ + "gyy") == 4 ); \ + assert( gyy[0] == 41.25 ); \ + assert( gyy[1] == 42.5 ); \ + assert( gyy[2] == 48.0 ); \ + assert( gyy[3] == 17.5 ); \ + assert( gyy[4] == 19.5 ); \ + } /* end macro */ + +/**************************************/ + +#define CHECK_SET_GET_COMPLEX_ARRAY(handle, type, key_already_exists, \ + set_fn, get_fn) \ + { \ + static type zz[5] \ + = { {3.5,1.25}, {9.5,4.5}, {0.5,8.0}, {5.0,5.5}, {4.5,7.25} };\ + assert( set_fn(handle, 4, zz, "zz") == key_already_exists ); \ + zz[0].Re = 10.25; zz[0].Im = 11.75; \ + zz[1].Re = -2.5; zz[1].Im = 3.5; \ + zz[2].Re = 14.0; zz[2].Im = -8.5; \ + zz[3].Re = 0.25; zz[3].Im = 8.875; \ + zz[4].Re = -0.25; zz[4].Im = -0.75; \ + /* only get 3 of 4 stored values */ \ + assert( get_fn(handle, 3, zz, "zz") == 4 ); \ + assert( zz[0].Re == 3.5 ); assert( zz[0].Im == 1.25 ); \ + assert( zz[1].Re == 9.5 ); assert( zz[1].Im == 4.5 ); \ + assert( zz[2].Re == 0.5 ); assert( zz[2].Im == 8.0 ); \ + assert( zz[3].Re == 0.25 ); assert( zz[3].Im == 8.875 ); \ + assert( zz[4].Re == -0.25 ); assert( zz[4].Im == -0.75 ); \ + } /* end macro */ -assert( Util_TableItAdvance(ihandle) == 0 ); - } - } - } - } - } -} #endif /* UTIL_TABLE_TEST */ /******************************************************************************/ -/******************************************************************************/ #ifdef UTIL_TABLE_TEST /* @@ -3293,49 +3836,49 @@ assert( Util_TableItAdvance(ihandle) == 0 ); */ int main(void) { -test_nonexistent_tables(); -test_table_create_destroy(); - - { -int handle = Util_TableCreate(UTIL_TABLE_FLAGS_DEFAULT); -assert( handle == 0 ); -assert( Util_TableSetInt(handle, 42, "foo/") == UTIL_ERROR_TABLE_BAD_KEY ); - - { -int HANDLE = Util_TableCreate(UTIL_TABLE_FLAGS_CASE_INSENSITIVE); - -#ifdef UTIL_TABLE_DEBUG -printf("--- printing handle=%d table (should be empty)\n", handle); -print_table(handle); -printf("--- about to test set/get on handle=%d table\n", handle); -#endif -test_set_get(handle, false); -test_set_get(HANDLE, true); - -test_iterators(handle); -test_delete_key(handle, false); -test_iterators(HANDLE); -test_delete_key(HANDLE, true); - -test_set_get_array(handle); -test_set_get_array(HANDLE); - -test_set_get_string(handle, false); - - { -int HANDLE2 = test_set_create_from_string(); -test_set_get_string(HANDLE2, true); - -printf("all ok!\n" ); -return 0; - } - } - } + test_nonexistent_tables(); + test_table_create_destroy(); + + { + const int handle = Util_TableCreate(UTIL_TABLE_FLAGS_DEFAULT); + assert( handle == 0 ); + assert( Util_TableSetInt(handle, 42, "foo/") == UTIL_ERROR_TABLE_BAD_KEY ); + + { + const int HANDLE = Util_TableCreate(UTIL_TABLE_FLAGS_CASE_INSENSITIVE); + + #ifdef UTIL_TABLE_DEBUG + printf("--- printing handle=%d table (should be empty)\n", handle); + print_table(handle); + printf("--- about to test set/get on handle=%d table\n", handle); + #endif + test_set_get(handle, false); + test_set_get(HANDLE, true); + + test_iterators(handle); + test_delete_table_entry(handle, false); + test_iterators(HANDLE); + test_delete_table_entry(HANDLE, true); + + test_set_get_array(handle); + test_set_get_array(HANDLE); + + test_set_get_string(handle, false); + + { + const int HANDLE2 = test_set_create_from_string(); + test_clone(HANDLE2); + test_set_get_string(HANDLE2, true); + + printf("all ok!\n" ); + return 0; + } + } + } } #endif /* UTIL_TABLE_TEST */ /******************************************************************************/ -/******************************************************************************/ #ifdef UTIL_TABLE_TEST /* @@ -3345,25 +3888,25 @@ return 0; static void test_nonexistent_tables(void) { -assert( Util_TableDestroy(42) == UTIL_ERROR_BAD_HANDLE ); -assert( Util_TableQueryFlags(-42) == UTIL_ERROR_BAD_HANDLE ); -assert( Util_TableQueryNKeys(0) == UTIL_ERROR_BAD_HANDLE ); -assert( Util_TableDeleteKey(-1, "pickle") == UTIL_ERROR_BAD_HANDLE ); -assert( Util_TableSetInt(-1, 42, "fourty-two") == UTIL_ERROR_BAD_HANDLE ); -assert( Util_TableGetReal(-1, NULL, "something wierd") - == UTIL_ERROR_BAD_HANDLE ); - -assert( Util_TableItCreate(42) == UTIL_ERROR_BAD_HANDLE ); -assert( Util_TableItDestroy(42) == UTIL_ERROR_BAD_HANDLE ); -assert( Util_TableItQueryIsNull(42) == UTIL_ERROR_BAD_HANDLE ); -assert( Util_TableItQueryIsNonNull(42) == UTIL_ERROR_BAD_HANDLE ); -assert( Util_TableItQueryTableHandle(42) == UTIL_ERROR_BAD_HANDLE ); -assert( Util_TableItQueryKeyValueInfo(42, - 0, NULL, - NULL, NULL) == UTIL_ERROR_BAD_HANDLE ); -assert( Util_TableItAdvance(42) == UTIL_ERROR_BAD_HANDLE ); -assert( Util_TableItResetToStart(42) == UTIL_ERROR_BAD_HANDLE ); -assert( Util_TableItSetToNull(42) == UTIL_ERROR_BAD_HANDLE ); + assert( Util_TableDestroy(42) == UTIL_ERROR_BAD_HANDLE ); + assert( Util_TableQueryFlags(-42) == UTIL_ERROR_BAD_HANDLE ); + assert( Util_TableQueryNKeys(0) == UTIL_ERROR_BAD_HANDLE ); + assert( Util_TableDeleteKey(-1, "pickle") == UTIL_ERROR_BAD_HANDLE ); + assert( Util_TableSetInt(-1, 42, "fourty-two") == UTIL_ERROR_BAD_HANDLE ); + assert( Util_TableGetReal(-1, NULL, "something wierd") + == UTIL_ERROR_BAD_HANDLE ); + + assert( Util_TableItCreate(42) == UTIL_ERROR_BAD_HANDLE ); + assert( Util_TableItDestroy(42) == UTIL_ERROR_BAD_HANDLE ); + assert( Util_TableItQueryIsNull(42) == UTIL_ERROR_BAD_HANDLE ); + assert( Util_TableItQueryIsNonNull(42) == UTIL_ERROR_BAD_HANDLE ); + assert( Util_TableItQueryTableHandle(42) == UTIL_ERROR_BAD_HANDLE ); + assert( Util_TableItQueryKeyValueInfo(42, + 0, NULL, + NULL, NULL) == UTIL_ERROR_BAD_HANDLE ); + assert( Util_TableItAdvance(42) == UTIL_ERROR_BAD_HANDLE ); + assert( Util_TableItResetToStart(42) == UTIL_ERROR_BAD_HANDLE ); + assert( Util_TableItSetToNull(42) == UTIL_ERROR_BAD_HANDLE ); } #endif /* UTIL_TABLE_TEST */ @@ -3388,67 +3931,67 @@ assert( Util_TableItSetToNull(42) == UTIL_ERROR_BAD_HANDLE ); static void test_table_create_destroy(void) { -assert( N_tables == 0 ); - -assert( Util_TableCreate(UTIL_TABLE_FLAGS_DEFAULT) == 0 ); -assert( N_tables == 1 ); -assert( Util_TableCreate(UTIL_TABLE_FLAGS_CASE_INSENSITIVE) == 1 ); -assert( N_tables == 2 ); -assert( Util_TableCreate(UTIL_TABLE_FLAGS_DEFAULT) == 2 ); -assert( N_tables == 3 ); -assert( Util_TableCreate(UTIL_TABLE_FLAGS_CASE_INSENSITIVE) == 3 ); -assert( N_tables == 4 ); -assert( get_table_header_ptr(0) != NULL ); -assert( get_table_header_ptr(1) != NULL ); -assert( get_table_header_ptr(2) != NULL ); -assert( get_table_header_ptr(3) != NULL ); -assert( Util_TableQueryFlags(0) == UTIL_TABLE_FLAGS_DEFAULT ); -assert( Util_TableQueryFlags(1) == UTIL_TABLE_FLAGS_CASE_INSENSITIVE ); -assert( Util_TableQueryFlags(2) == UTIL_TABLE_FLAGS_DEFAULT ); -assert( Util_TableQueryFlags(3) == UTIL_TABLE_FLAGS_CASE_INSENSITIVE ); - -assert( Util_TableDeleteKey(3, "pickle") == UTIL_ERROR_TABLE_NO_SUCH_KEY ); -assert( Util_TableDeleteKey(3, "Pickle") == UTIL_ERROR_TABLE_NO_SUCH_KEY ); -assert( Util_TableDeleteKey(3, "PICKLE") == UTIL_ERROR_TABLE_NO_SUCH_KEY ); - -assert( Util_TableDestroy(2) == 0 ); -assert( N_tables == 3 ); -assert( get_table_header_ptr(0) != NULL ); -assert( get_table_header_ptr(1) != NULL ); -assert( get_table_header_ptr(2) == NULL ); -assert( get_table_header_ptr(3) != NULL ); - -assert( Util_TableCreate(0x43) == 2 ); -assert( N_tables == 4 ); -assert( get_table_header_ptr(0) != NULL ); -assert( get_table_header_ptr(1) != NULL ); -assert( get_table_header_ptr(2) != NULL ); -assert( Util_TableQueryFlags(2) == 0x43); -assert( get_table_header_ptr(3) != NULL ); - -assert( Util_TableDestroy(1) == 0 ); -assert( N_tables == 3 ); -assert( get_table_header_ptr(0) != NULL ); -assert( Util_TableQueryNKeys(0) == 0 ); -assert( get_table_header_ptr(1) == NULL ); -assert( Util_TableQueryMaxKeyLength(1) == UTIL_ERROR_BAD_HANDLE ); -assert( get_table_header_ptr(2) != NULL ); -assert( Util_TableQueryMaxKeyLength(2) == 0 ); -assert( get_table_header_ptr(3) != NULL ); -assert( Util_TableDeleteKey(3, "pickle") == UTIL_ERROR_TABLE_NO_SUCH_KEY ); - -assert( Util_TableDestroy(1) == UTIL_ERROR_BAD_HANDLE ); -assert( N_tables == 3 ); -assert( get_table_header_ptr(0) != NULL ); -assert( get_table_header_ptr(1) == NULL ); -assert( get_table_header_ptr(2) != NULL ); -assert( get_table_header_ptr(3) != NULL ); - -assert( Util_TableDestroy(0) == 0 ); -assert( Util_TableDestroy(2) == 0 ); -assert( Util_TableDestroy(3) == 0 ); - -assert( N_tables == 0 ); + assert( N_tables == 0 ); + + assert( Util_TableCreate(UTIL_TABLE_FLAGS_DEFAULT) == 0 ); + assert( N_tables == 1 ); + assert( Util_TableCreate(UTIL_TABLE_FLAGS_CASE_INSENSITIVE) == 1 ); + assert( N_tables == 2 ); + assert( Util_TableCreate(UTIL_TABLE_FLAGS_DEFAULT) == 2 ); + assert( N_tables == 3 ); + assert( Util_TableCreate(UTIL_TABLE_FLAGS_CASE_INSENSITIVE) == 3 ); + assert( N_tables == 4 ); + assert( get_table_header_ptr(0) != NULL ); + assert( get_table_header_ptr(1) != NULL ); + assert( get_table_header_ptr(2) != NULL ); + assert( get_table_header_ptr(3) != NULL ); + assert( Util_TableQueryFlags(0) == UTIL_TABLE_FLAGS_DEFAULT ); + assert( Util_TableQueryFlags(1) == UTIL_TABLE_FLAGS_CASE_INSENSITIVE ); + assert( Util_TableQueryFlags(2) == UTIL_TABLE_FLAGS_DEFAULT ); + assert( Util_TableQueryFlags(3) == UTIL_TABLE_FLAGS_CASE_INSENSITIVE ); + + assert( Util_TableDeleteKey(3, "pickle") == UTIL_ERROR_TABLE_NO_SUCH_KEY ); + assert( Util_TableDeleteKey(3, "Pickle") == UTIL_ERROR_TABLE_NO_SUCH_KEY ); + assert( Util_TableDeleteKey(3, "PICKLE") == UTIL_ERROR_TABLE_NO_SUCH_KEY ); + + assert( Util_TableDestroy(2) == 0 ); + assert( N_tables == 3 ); + assert( get_table_header_ptr(0) != NULL ); + assert( get_table_header_ptr(1) != NULL ); + assert( get_table_header_ptr(2) == NULL ); + assert( get_table_header_ptr(3) != NULL ); + + assert( Util_TableCreate(0x43) == 2 ); + assert( N_tables == 4 ); + assert( get_table_header_ptr(0) != NULL ); + assert( get_table_header_ptr(1) != NULL ); + assert( get_table_header_ptr(2) != NULL ); + assert( Util_TableQueryFlags(2) == 0x43); + assert( get_table_header_ptr(3) != NULL ); + + assert( Util_TableDestroy(1) == 0 ); + assert( N_tables == 3 ); + assert( get_table_header_ptr(0) != NULL ); + assert( Util_TableQueryNKeys(0) == 0 ); + assert( get_table_header_ptr(1) == NULL ); + assert( Util_TableQueryMaxKeyLength(1) == UTIL_ERROR_BAD_HANDLE ); + assert( get_table_header_ptr(2) != NULL ); + assert( Util_TableQueryMaxKeyLength(2) == 0 ); + assert( get_table_header_ptr(3) != NULL ); + assert( Util_TableDeleteKey(3, "pickle") == UTIL_ERROR_TABLE_NO_SUCH_KEY ); + + assert( Util_TableDestroy(1) == UTIL_ERROR_BAD_HANDLE ); + assert( N_tables == 3 ); + assert( get_table_header_ptr(0) != NULL ); + assert( get_table_header_ptr(1) == NULL ); + assert( get_table_header_ptr(2) != NULL ); + assert( get_table_header_ptr(3) != NULL ); + + assert( Util_TableDestroy(0) == 0 ); + assert( Util_TableDestroy(2) == 0 ); + assert( Util_TableDestroy(3) == 0 ); + + assert( N_tables == 0 ); } #endif /* UTIL_TABLE_TEST */ @@ -3465,90 +4008,114 @@ assert( N_tables == 0 ); static void test_set_get(int handle, bool case_insensitive) { -/* - * Note we put a test of a type that's guaranteed to be defined... - * - at the *beginning* of each group of tests, so we can properly - * assert whether or not the key was already in table beforehand. - * - at the *end* of each group of tests, so the final table contents - * are known independently of which types are and aren't defined. - */ - -/* integers */ -CHECK_SET_GET_INT(handle, CCTK_INT, 0, case_insensitive, - Util_TableSetInt, Util_TableGetInt); -#ifdef CCTK_INTEGER_PRECISION_2 -CHECK_SET_GET_INT(handle, CCTK_INT2, 1, case_insensitive, - Util_TableSetInt2, Util_TableGetInt2); -#endif -#ifdef CCTK_INTEGER_PRECISION_4 -CHECK_SET_GET_INT(handle, CCTK_INT4, 1, case_insensitive, - Util_TableSetInt4, Util_TableGetInt4); -#endif -#ifdef CCTK_INTEGER_PRECISION_8 -CHECK_SET_GET_INT(handle, CCTK_INT8, 1, case_insensitive, - Util_TableSetInt8, Util_TableGetInt8); -#endif -CHECK_SET_GET_INT(handle, CCTK_INT, 1, case_insensitive, - Util_TableSetInt, Util_TableGetInt); -assert( Util_TableQueryNKeys(handle) == 1 ); -assert( Util_TableQueryMaxKeyLength(handle) == (int)strlen("int_x") ); - -/* complex numbers */ -CHECK_SET_GET_COMPLEX(handle, CCTK_COMPLEX, 0, case_insensitive, - Util_TableSetComplex, Util_TableGetComplex); -#ifdef CCTK_COMPLEX_PRECISION_8 -CHECK_SET_GET_COMPLEX(handle, CCTK_COMPLEX8, 1, case_insensitive, - Util_TableSetComplex8, Util_TableGetComplex8); -#endif -#ifdef CCTK_COMPLEX_PRECISION_16 -CHECK_SET_GET_COMPLEX(handle, CCTK_COMPLEX16, 1, case_insensitive, - Util_TableSetComplex16, Util_TableGetComplex16); -#endif -#ifdef CCTK_COMPLEX_PRECISION_32 -CHECK_SET_GET_COMPLEX(handle, CCTK_COMPLEX32, 1, case_insensitive, - Util_TableSetComplex32, Util_TableGetComplex32); -#endif -CHECK_SET_GET_COMPLEX(handle, CCTK_COMPLEX, 1, case_insensitive, - Util_TableSetComplex, Util_TableGetComplex); -assert( Util_TableQueryNKeys(handle) == 2 ); -assert( Util_TableQueryMaxKeyLength(handle) == (int)strlen("COMPlex_Z") ); - -/* reals */ -CHECK_SET_GET_REAL(handle, CCTK_REAL, 0, case_insensitive, - Util_TableSetReal, Util_TableGetReal); -#ifdef CCTK_REAL_PRECISION_4 -CHECK_SET_GET_REAL(handle, CCTK_REAL4, 1, case_insensitive, - Util_TableSetReal4, Util_TableGetReal4); -#endif -#ifdef CCTK_REAL_PRECISION_8 -CHECK_SET_GET_REAL(handle, CCTK_REAL8, 1, case_insensitive, - Util_TableSetReal8, Util_TableGetReal8); -#endif -#ifdef CCTK_REAL_PRECISION_16 -CHECK_SET_GET_REAL(handle, CCTK_REAL16, 1, case_insensitive, - Util_TableSetReal16, Util_TableGetReal16); -#endif -CHECK_SET_GET_REAL(handle, CCTK_REAL, 1, case_insensitive, - Util_TableSetReal, Util_TableGetReal); -assert( Util_TableQueryNKeys(handle) == 3 ); -assert( Util_TableQueryMaxKeyLength(handle) == (int)strlen("COMPlex_Z") ); - - { -CCTK_INT type_code, N_elements; -assert( Util_TableQueryValueInfo(handle, &type_code, &N_elements, "COMPlex_Z") == 1 ); -assert( type_code == CCTK_VARIABLE_COMPLEX ); -assert( N_elements == 1 ); - -assert( Util_TableQueryValueInfo(handle, &type_code, &N_elements, "pickle") == 0 ); - -assert( Util_TableQueryValueInfo(handle, NULL, NULL, "int_x") == 1 ); -assert( Util_TableQueryValueInfo(handle, NULL, NULL, "Int_x") - == (case_insensitive ? 1 : 0) ); -assert( Util_TableQueryValueInfo(handle, NULL, NULL, "real_y") - == (case_insensitive ? 1 : 0) ); -assert( Util_TableQueryValueInfo(handle, NULL, NULL, "COMPLEX_Z") - == (case_insensitive ? 1 : 0) ); - } + /* + * Note we put a test of a type that's guaranteed to be defined... + * - at the *beginning* of each group of tests, so we can properly + * assert whether or not the key was already in table beforehand. + * - at the *end* of each group of tests, so the final table contents + * are known independently of which types are and aren't defined. + */ + + /* integers */ + CHECK_SET_GET_INT(handle, CCTK_INT, 0, case_insensitive, + Util_TableSetInt, Util_TableGetInt); + #ifdef CCTK_INTEGER_PRECISION_2 + CHECK_SET_GET_INT(handle, CCTK_INT2, 1, case_insensitive, + Util_TableSetInt2, Util_TableGetInt2); + #endif + #ifdef CCTK_INTEGER_PRECISION_4 + CHECK_SET_GET_INT(handle, CCTK_INT4, 1, case_insensitive, + Util_TableSetInt4, Util_TableGetInt4); + #endif + #ifdef CCTK_INTEGER_PRECISION_8 + CHECK_SET_GET_INT(handle, CCTK_INT8, 1, case_insensitive, + Util_TableSetInt8, Util_TableGetInt8); + #endif + CHECK_SET_GET_INT(handle, CCTK_INT, 1, case_insensitive, + Util_TableSetInt, Util_TableGetInt); + assert( Util_TableQueryNKeys(handle) == 1 ); + assert( Util_TableQueryMaxKeyLength(handle) == (int)strlen("int_x") ); + + /* generic scalars which are actually integers */ + CHECK_SET_GET_GENERIC_INT(handle, CCTK_VARIABLE_INT, CCTK_INT, + 0, case_insensitive); + #ifdef CCTK_INTEGER_PRECISION_2 + CHECK_SET_GET_GENERIC_INT(handle, CCTK_VARIABLE_INT2, CCTK_INT2, + 1, case_insensitive); + #endif + #ifdef CCTK_INTEGER_PRECISION_4 + CHECK_SET_GET_GENERIC_INT(handle, CCTK_VARIABLE_INT4, CCTK_INT4, + 1, case_insensitive); + #endif + #ifdef CCTK_INTEGER_PRECISION_8 + CHECK_SET_GET_GENERIC_INT(handle, CCTK_VARIABLE_INT8, CCTK_INT8, + 1, case_insensitive); + #endif + CHECK_SET_GET_GENERIC_INT(handle, CCTK_VARIABLE_INT, CCTK_INT, + 1, case_insensitive); + assert( Util_TableQueryNKeys(handle) == 2 ); + assert( Util_TableQueryMaxKeyLength(handle) == (int)strlen("gint_x") ); + assert( Util_TableDeleteKey(handle, "gint_x") == 0 ); + assert( Util_TableQueryNKeys(handle) == 1 ); + + /* complex numbers */ + CHECK_SET_GET_COMPLEX(handle, CCTK_COMPLEX, 0, case_insensitive, + Util_TableSetComplex, Util_TableGetComplex); + #ifdef CCTK_COMPLEX_PRECISION_8 + CHECK_SET_GET_COMPLEX(handle, CCTK_COMPLEX8, 1, case_insensitive, + Util_TableSetComplex8, Util_TableGetComplex8); + #endif + #ifdef CCTK_COMPLEX_PRECISION_16 + CHECK_SET_GET_COMPLEX(handle, CCTK_COMPLEX16, 1, case_insensitive, + Util_TableSetComplex16, Util_TableGetComplex16); + #endif + #ifdef CCTK_COMPLEX_PRECISION_32 + CHECK_SET_GET_COMPLEX(handle, CCTK_COMPLEX32, 1, case_insensitive, + Util_TableSetComplex32, Util_TableGetComplex32); + #endif + CHECK_SET_GET_COMPLEX(handle, CCTK_COMPLEX, 1, case_insensitive, + Util_TableSetComplex, Util_TableGetComplex); + assert( Util_TableQueryNKeys(handle) == 2 ); + assert( Util_TableQueryMaxKeyLength(handle) == (int)strlen("COMPlex_Z") ); + + /* reals */ + CHECK_SET_GET_REAL(handle, CCTK_REAL, 0, case_insensitive, + Util_TableSetReal, Util_TableGetReal); + #ifdef CCTK_REAL_PRECISION_4 + CHECK_SET_GET_REAL(handle, CCTK_REAL4, 1, case_insensitive, + Util_TableSetReal4, Util_TableGetReal4); + #endif + #ifdef CCTK_REAL_PRECISION_8 + CHECK_SET_GET_REAL(handle, CCTK_REAL8, 1, case_insensitive, + Util_TableSetReal8, Util_TableGetReal8); + #endif + #ifdef CCTK_REAL_PRECISION_16 + CHECK_SET_GET_REAL(handle, CCTK_REAL16, 1, case_insensitive, + Util_TableSetReal16, Util_TableGetReal16); + #endif + CHECK_SET_GET_REAL(handle, CCTK_REAL, 1, case_insensitive, + Util_TableSetReal, Util_TableGetReal); + assert( Util_TableQueryNKeys(handle) == 3 ); + assert( Util_TableQueryMaxKeyLength(handle) == (int)strlen("COMPlex_Z") ); + + { + CCTK_INT type_code, N_elements; + assert( Util_TableQueryValueInfo(handle, &type_code, &N_elements, "COMPlex_Z") + == 1 ); + assert( type_code == CCTK_VARIABLE_COMPLEX ); + assert( N_elements == 1 ); + + assert( Util_TableQueryValueInfo(handle, &type_code, &N_elements, "pickle") + == 0 ); + + assert( Util_TableQueryValueInfo(handle, NULL, NULL, "int_x") == 1 ); + assert( Util_TableQueryValueInfo(handle, NULL, NULL, "Int_x") + == (case_insensitive ? 1 : 0) ); + assert( Util_TableQueryValueInfo(handle, NULL, NULL, "real_y") + == (case_insensitive ? 1 : 0) ); + assert( Util_TableQueryValueInfo(handle, NULL, NULL, "COMPLEX_Z") + == (case_insensitive ? 1 : 0) ); + } } #endif /* UTIL_TABLE_TEST */ @@ -3564,68 +4131,82 @@ assert( Util_TableQueryValueInfo(handle, NULL, NULL, "COMPLEX_Z") static void test_set_get_array(int handle) { -/* the comments of test_set_get() about test ordering, also apply here */ - -/* integers */ -CHECK_SET_GET_INT_ARRAY(handle, CCTK_CHAR, 0, - Util_TableSetCharArray, Util_TableGetCharArray); -CHECK_SET_GET_INT_ARRAY(handle, CCTK_INT, 1, - Util_TableSetIntArray, Util_TableGetIntArray); -#ifdef CCTK_INTEGER_PRECISION_2 -CHECK_SET_GET_INT_ARRAY(handle, CCTK_INT2, 1, - Util_TableSetInt2Array, Util_TableGetInt2Array); -#endif -#ifdef CCTK_INTEGER_PRECISION_4 -CHECK_SET_GET_INT_ARRAY(handle, CCTK_INT4, 1, - Util_TableSetInt4Array, Util_TableGetInt4Array); -#endif -#ifdef CCTK_INTEGER_PRECISION_8 -CHECK_SET_GET_INT_ARRAY(handle, CCTK_INT8, 1, - Util_TableSetInt8Array, Util_TableGetInt8Array); -#endif -CHECK_SET_GET_INT_ARRAY(handle, CCTK_INT, 1, - Util_TableSetIntArray, Util_TableGetIntArray); - -/* reals */ -CHECK_SET_GET_REAL_ARRAY(handle, CCTK_REAL, 0, - Util_TableSetRealArray, Util_TableGetRealArray); -#ifdef CCTK_REAL_PRECISION_4 -CHECK_SET_GET_REAL_ARRAY(handle, CCTK_REAL4, 1, - Util_TableSetReal4Array, Util_TableGetReal4Array); -#endif -#ifdef CCTK_REAL_PRECISION_8 -CHECK_SET_GET_REAL_ARRAY(handle, CCTK_REAL8, 1, - Util_TableSetReal8Array, Util_TableGetReal8Array); -#endif -#ifdef CCTK_REAL_PRECISION_16 -CHECK_SET_GET_REAL_ARRAY(handle, CCTK_REAL16, 1, - Util_TableSetReal16Array, Util_TableGetReal16Array); -#endif -CHECK_SET_GET_REAL_ARRAY(handle, CCTK_REAL, 1, - Util_TableSetRealArray, Util_TableGetRealArray); - -/* complex numbers */ -CHECK_SET_GET_COMPLEX_ARRAY(handle, CCTK_COMPLEX, 0, - Util_TableSetComplexArray, - Util_TableGetComplexArray); -#ifdef CCTK_COMPLEX_PRECISION_8 -CHECK_SET_GET_COMPLEX_ARRAY(handle, CCTK_COMPLEX8, 1, - Util_TableSetComplex8Array, - Util_TableGetComplex8Array); -#endif -#ifdef CCTK_COMPLEX_PRECISION_16 -CHECK_SET_GET_COMPLEX_ARRAY(handle, CCTK_COMPLEX16, 1, - Util_TableSetComplex16Array, - Util_TableGetComplex16Array); -#endif -#ifdef CCTK_COMPLEX_PRECISION_32 -CHECK_SET_GET_COMPLEX_ARRAY(handle, CCTK_COMPLEX32, 1, - Util_TableSetComplex32Array, - Util_TableGetComplex32Array); -#endif -CHECK_SET_GET_COMPLEX_ARRAY(handle, CCTK_COMPLEX, 1, - Util_TableSetComplexArray, - Util_TableGetComplexArray); + /* the comments of test_set_get() about test ordering, also apply here */ + + /* integers */ + CHECK_SET_GET_INT_ARRAY(handle, CCTK_CHAR, 0, + Util_TableSetCharArray, Util_TableGetCharArray); + CHECK_SET_GET_INT_ARRAY(handle, CCTK_INT, 1, + Util_TableSetIntArray, Util_TableGetIntArray); + #ifdef CCTK_INTEGER_PRECISION_2 + CHECK_SET_GET_INT_ARRAY(handle, CCTK_INT2, 1, + Util_TableSetInt2Array, Util_TableGetInt2Array); + #endif + #ifdef CCTK_INTEGER_PRECISION_4 + CHECK_SET_GET_INT_ARRAY(handle, CCTK_INT4, 1, + Util_TableSetInt4Array, Util_TableGetInt4Array); + #endif + #ifdef CCTK_INTEGER_PRECISION_8 + CHECK_SET_GET_INT_ARRAY(handle, CCTK_INT8, 1, + Util_TableSetInt8Array, Util_TableGetInt8Array); + #endif + CHECK_SET_GET_INT_ARRAY(handle, CCTK_INT, 1, + Util_TableSetIntArray, Util_TableGetIntArray); + + /* reals */ + CHECK_SET_GET_REAL_ARRAY(handle, CCTK_REAL, 0, + Util_TableSetRealArray, Util_TableGetRealArray); + #ifdef CCTK_REAL_PRECISION_4 + CHECK_SET_GET_REAL_ARRAY(handle, CCTK_REAL4, 1, + Util_TableSetReal4Array, Util_TableGetReal4Array); + #endif + #ifdef CCTK_REAL_PRECISION_8 + CHECK_SET_GET_REAL_ARRAY(handle, CCTK_REAL8, 1, + Util_TableSetReal8Array, Util_TableGetReal8Array); + #endif + #ifdef CCTK_REAL_PRECISION_16 + CHECK_SET_GET_REAL_ARRAY(handle, CCTK_REAL16, 1, + Util_TableSetReal16Array, Util_TableGetReal16Array); + #endif + CHECK_SET_GET_REAL_ARRAY(handle, CCTK_REAL, 1, + Util_TableSetRealArray, Util_TableGetRealArray); + + /* generic arrays which are actually reals */ + CHECK_SET_GET_GENERIC_REAL_ARRAY(handle, CCTK_VARIABLE_REAL, CCTK_REAL, 0); + #ifdef CCTK_REAL_PRECISION_4 + CHECK_SET_GET_GENERIC_REAL_ARRAY(handle, CCTK_VARIABLE_REAL4, CCTK_REAL4, 1); + #endif + #ifdef CCTK_REAL_PRECISION_8 + CHECK_SET_GET_GENERIC_REAL_ARRAY(handle, CCTK_VARIABLE_REAL8, CCTK_REAL8, 1); + #endif + #ifdef CCTK_REAL_PRECISION_16 + CHECK_SET_GET_GENERIC_REAL_ARRAY(handle, + CCTK_VARIABLE_REAL16, CCTK_REAL16, 1); + #endif + CHECK_SET_GET_GENERIC_REAL_ARRAY(handle, CCTK_VARIABLE_REAL, CCTK_REAL, 1); + + /* complex numbers */ + CHECK_SET_GET_COMPLEX_ARRAY(handle, CCTK_COMPLEX, 0, + Util_TableSetComplexArray, + Util_TableGetComplexArray); + #ifdef CCTK_COMPLEX_PRECISION_8 + CHECK_SET_GET_COMPLEX_ARRAY(handle, CCTK_COMPLEX8, 1, + Util_TableSetComplex8Array, + Util_TableGetComplex8Array); + #endif + #ifdef CCTK_COMPLEX_PRECISION_16 + CHECK_SET_GET_COMPLEX_ARRAY(handle, CCTK_COMPLEX16, 1, + Util_TableSetComplex16Array, + Util_TableGetComplex16Array); + #endif + #ifdef CCTK_COMPLEX_PRECISION_32 + CHECK_SET_GET_COMPLEX_ARRAY(handle, CCTK_COMPLEX32, 1, + Util_TableSetComplex32Array, + Util_TableGetComplex32Array); + #endif + CHECK_SET_GET_COMPLEX_ARRAY(handle, CCTK_COMPLEX, 1, + Util_TableSetComplexArray, + Util_TableGetComplexArray); } #endif /* UTIL_TABLE_TEST */ @@ -3644,110 +4225,129 @@ CHECK_SET_GET_COMPLEX_ARRAY(handle, CCTK_COMPLEX, 1, static void test_iterators(int handle) { -int ihandle = Util_TableItCreate(handle); -assert( ihandle >= 0 ); -assert( Util_TableItQueryTableHandle(ihandle) == handle ); -assert( Util_TableItQueryIsNonNull(ihandle) == 1); -assert( Util_TableItQueryIsNull(ihandle) == 0); - -/* set up the key buffer */ - { -int max_key_length = Util_TableQueryMaxKeyLength(handle); -assert( max_key_length == (int)strlen("COMPlex_Z") ); - { -const int N_key_buffer = max_key_length + 1; -char *const key_buffer = malloc(N_key_buffer); -assert( key_buffer != NULL ); - -/* walk the table to verify iterator traversal */ - { -CCTK_INT type_code, N_elements; - -/* REAL_y */ -assert( Util_TableItQueryKeyValueInfo(ihandle, - N_key_buffer, key_buffer, - &type_code, &N_elements) - == (int)strlen("REAL_y") ); -assert( strcmp(key_buffer, "REAL_y") == 0 ); -assert( type_code == CCTK_VARIABLE_REAL ); -assert( N_elements == 1 ); - -/* COMPlex_Z */ -type_code = 123456; -N_elements = 54321; -assert( Util_TableItAdvance(ihandle) == 1 ); -assert( Util_TableItQueryKeyValueInfo(ihandle, - N_key_buffer, key_buffer, - &type_code, &N_elements) - == (int)strlen("COMPlex_Z") ); -assert( strcmp(key_buffer, "COMPlex_Z") == 0 ); -assert( type_code = CCTK_VARIABLE_COMPLEX ); -assert( N_elements == 1 ); - -/* int_x */ -type_code = 123456; -N_elements = 54321; -assert( Util_TableItAdvance(ihandle) == 1 ); -assert( Util_TableItQueryKeyValueInfo(ihandle, - N_key_buffer, key_buffer, - &type_code, &N_elements) - == (int)strlen("int_x") ); -assert( strcmp(key_buffer, "int_x") == 0 ); -assert( type_code = CCTK_VARIABLE_INT ); -assert( N_elements == 1 ); - -/* advance past last table entry ==> "null-pointer" state */ -assert( Util_TableItAdvance(ihandle) == 0 ); -assert( Util_TableItQueryIsNull(ihandle) == 1); -assert( Util_TableItQueryIsNonNull(ihandle) == 0); - -/* advance again ==> stays in "null-pointer" state */ -assert( Util_TableItAdvance(ihandle) == 0 ); -assert( Util_TableItQueryIsNull(ihandle) == 1); -assert( Util_TableItQueryIsNonNull(ihandle) == 0); -assert( Util_TableItQueryKeyValueInfo(ihandle, - 0, NULL, - NULL, NULL) - == UTIL_ERROR_TABLE_ITERATOR_IS_NULL ); - -/* test reset to starting point */ -assert( Util_TableItResetToStart(ihandle) == 1 ); -assert( Util_TableItQueryIsNonNull(ihandle) == 1 ); -assert( Util_TableItQueryIsNull(ihandle) == 0 ); - -/* COMPlex_Z */ -type_code = 123456; -N_elements = 54321; -assert( Util_TableItAdvance(ihandle) == 1 ); -assert( Util_TableItQueryKeyValueInfo(ihandle, - N_key_buffer, key_buffer, - &type_code, &N_elements) - == (int)strlen("COMPlex_Z") ); -assert( strcmp(key_buffer, "COMPlex_Z") == 0 ); -assert( type_code = CCTK_VARIABLE_COMPLEX ); -assert( N_elements == 1 ); - -/* test reset to "null-pointer" state */ -assert( Util_TableItSetToNull(ihandle) == 0 ); -assert( Util_TableItQueryIsNull(ihandle) == 1); -assert( Util_TableItQueryIsNonNull(ihandle) == 0); - -/* test set to key "REAL_y" */ -assert( Util_TableItSetToKey(ihandle, "REAL_y") == 0 ); -assert( Util_TableItQueryIsNonNull(ihandle) == 1); -assert( Util_TableItQueryIsNull(ihandle) == 0); -assert( Util_TableItQueryKeyValueInfo(ihandle, - N_key_buffer, key_buffer, - &type_code, &N_elements) - == (int)strlen("REAL_y") ); -assert( strcmp(key_buffer, "REAL_y") == 0 ); -assert( type_code == CCTK_VARIABLE_REAL ); -assert( N_elements == 1 ); - -free(key_buffer); - } - } - } + const int ihandle = Util_TableItCreate(handle); + assert( ihandle >= 0 ); + assert( Util_TableItQueryTableHandle(ihandle) == handle ); + assert( Util_TableItQueryIsNonNull(ihandle) == 1); + assert( Util_TableItQueryIsNull(ihandle) == 0); + + /* set up the key buffer */ + { + const int max_key_length = Util_TableQueryMaxKeyLength(handle); + assert( max_key_length == (int)strlen("COMPlex_Z") ); + { + const int N_key_buffer = max_key_length + 1; + char *const key_buffer = malloc(N_key_buffer); + assert( key_buffer != NULL ); + + /* walk the table to verify iterator traversal */ + { + CCTK_INT type_code, N_elements; + + /* REAL_y */ + assert( Util_TableItQueryKeyValueInfo(ihandle, + N_key_buffer, key_buffer, + &type_code, &N_elements) + == (int)strlen("REAL_y") ); + assert( strcmp(key_buffer, "REAL_y") == 0 ); + assert( type_code == CCTK_VARIABLE_REAL ); + assert( N_elements == 1 ); + + assert( Util_TableItAdvance(ihandle) == 1 ); + + /* COMPlex_Z */ + type_code = 123456; + N_elements = 54321; + assert( Util_TableItQueryKeyValueInfo(ihandle, + N_key_buffer, key_buffer, + &type_code, &N_elements) + == (int)strlen("COMPlex_Z") ); + assert( strcmp(key_buffer, "COMPlex_Z") == 0 ); + assert( type_code == CCTK_VARIABLE_COMPLEX ); + assert( N_elements == 1 ); + + assert( Util_TableItAdvance(ihandle) == 1 ); + + /* clone the iterator and check the clone */ + { + const int clone_ihandle = Util_TableItClone(ihandle); + type_code = 123456; + N_elements = 54321; + assert( Util_TableItQueryKeyValueInfo(clone_ihandle, + N_key_buffer, key_buffer, + &type_code, &N_elements) + == (int)strlen("int_x") ); + assert( strcmp(key_buffer, "int_x") == 0 ); + assert( type_code == CCTK_VARIABLE_INT ); + assert( N_elements == 1 ); + + /* int_x */ + type_code = 123456; + N_elements = 54321; + assert( Util_TableItQueryKeyValueInfo(ihandle, + N_key_buffer, key_buffer, + &type_code, &N_elements) + == (int)strlen("int_x") ); + assert( strcmp(key_buffer, "int_x") == 0 ); + assert( type_code == CCTK_VARIABLE_INT ); + assert( N_elements == 1 ); + + /* advance past last table entry ==> "null-pointer" state */ + assert( Util_TableItAdvance(ihandle) == 0 ); + assert( Util_TableItQueryIsNull(ihandle) == 1); + assert( Util_TableItQueryIsNonNull(ihandle) == 0); + + /* advance again ==> stays in "null-pointer" state */ + assert( Util_TableItAdvance(ihandle) == 0 ); + assert( Util_TableItQueryIsNull(ihandle) == 1); + assert( Util_TableItQueryIsNonNull(ihandle) == 0); + assert( Util_TableItQueryKeyValueInfo(ihandle, + 0, NULL, + NULL, NULL) + == UTIL_ERROR_TABLE_ITERATOR_IS_NULL ); + + /* test reset to starting point */ + assert( Util_TableItResetToStart(ihandle) == 1 ); + assert( Util_TableItQueryIsNonNull(ihandle) == 1 ); + assert( Util_TableItQueryIsNull(ihandle) == 0 ); + + /* COMPlex_Z */ + type_code = 123456; + N_elements = 54321; + assert( Util_TableItAdvance(ihandle) == 1 ); + assert( Util_TableItQueryKeyValueInfo(ihandle, + N_key_buffer, key_buffer, + &type_code, &N_elements) + == (int)strlen("COMPlex_Z") ); + assert( strcmp(key_buffer, "COMPlex_Z") == 0 ); + assert( type_code == CCTK_VARIABLE_COMPLEX ); + assert( N_elements == 1 ); + + /* test reset to "null-pointer" state */ + assert( Util_TableItSetToNull(ihandle) == 0 ); + assert( Util_TableItQueryIsNull(ihandle) == 1); + assert( Util_TableItQueryIsNonNull(ihandle) == 0); + + /* test set to key "REAL_y" */ + assert( Util_TableItSetToKey(ihandle, "REAL_y") == 0 ); + assert( Util_TableItQueryIsNonNull(ihandle) == 1); + assert( Util_TableItQueryIsNull(ihandle) == 0); + assert( Util_TableItQueryKeyValueInfo(ihandle, + N_key_buffer, key_buffer, + &type_code, &N_elements) + == (int)strlen("REAL_y") ); + assert( strcmp(key_buffer, "REAL_y") == 0 ); + assert( type_code == CCTK_VARIABLE_REAL ); + assert( N_elements == 1 ); + + assert( Util_TableItDestroy(ihandle) == 0 ); + assert( Util_TableItDestroy(clone_ihandle) == 0 ); + + free(key_buffer); + } + } + } + } } /******************************************************************************/ @@ -3762,124 +4362,124 @@ free(key_buffer); * specific ordering of table elements returned by an iterator. */ static - void test_delete_key(int handle, bool case_insensitive) + void test_delete_table_entry(int handle, bool case_insensitive) { -/* set up the key buffer */ -int max_key_length = Util_TableQueryMaxKeyLength(handle); -assert( max_key_length == (int)strlen("COMPlex_Z") ); - { -const int N_key_buffer = max_key_length + 1; -char *const key_buffer = malloc(N_key_buffer); -assert( key_buffer != NULL ); - -/* - * delete the starting table entry "REAL_y" - * (this is a special case in the implementation) - */ - -assert( Util_TableQueryNKeys(handle) == 3 ); -assert( Util_TableDeleteKey(handle, - case_insensitive ? "rEAL_y" : "REAL_y") - == 0 ); -assert( Util_TableQueryNKeys(handle) == 2 ); - -/* walk the table again to verify remaining keys {"COMPlex_Z", "int_x"} */ -assert( Util_TableQueryNKeys(handle) == 2 ); - { -int ihandle = Util_TableItCreate(handle); -assert( ihandle >= 0 ); -assert( Util_TableItQueryTableHandle(ihandle) == handle ); -assert( Util_TableItQueryIsNonNull(ihandle) == 1); -assert( Util_TableItQueryIsNull(ihandle) == 0); - -/* COMPlex_Z */ - { -CCTK_INT type_code = 123456; -CCTK_INT N_elements = 54321; -assert( Util_TableItQueryKeyValueInfo(ihandle, - N_key_buffer, key_buffer, - &type_code, &N_elements) - == (int)strlen("COMPlex_Z") ); -assert( strcmp(key_buffer, "COMPlex_Z") == 0 ); -assert( type_code = CCTK_VARIABLE_COMPLEX ); -assert( N_elements == 1 ); - -/* int_x */ -type_code = 123456; -N_elements = 54321; -assert( Util_TableItAdvance(ihandle) == 1 ); -assert( Util_TableItQueryKeyValueInfo(ihandle, - N_key_buffer, key_buffer, - &type_code, &N_elements) - == (int)strlen("int_x") ); -assert( strcmp(key_buffer, "int_x") == 0 ); -assert( type_code = CCTK_VARIABLE_INT ); -assert( N_elements == 1 ); - -/* advance past last table entry ==> "null-pointer" state */ -assert( Util_TableItAdvance(ihandle) == 0 ); -assert( Util_TableItQueryIsNull(ihandle) == 1); -assert( Util_TableItQueryIsNonNull(ihandle) == 0); - -/* delete the last key "int_x" */ -assert( Util_TableDeleteKey(handle, - case_insensitive ? "INT_X" : "int_x") - == 0 ); - -/* walk the table again to verify remaining key {"COMPlex_Z"} */ -assert( Util_TableQueryNKeys(handle) == 1 ); - { -int ihandle2 = Util_TableItCreate(handle); -assert( ihandle2 >= 0 ); -assert( Util_TableItQueryTableHandle(ihandle2) == handle ); -assert( Util_TableItQueryIsNonNull(ihandle2) == 1); -assert( Util_TableItQueryIsNull(ihandle2) == 0); - -/* COMPlex_Z */ -type_code = 123456; -N_elements = 54321; -assert( Util_TableItQueryKeyValueInfo(ihandle2, - N_key_buffer, key_buffer, - &type_code, &N_elements) - == (int)strlen("COMPlex_Z") ); -assert( strcmp(key_buffer, "COMPlex_Z") == 0 ); -assert( type_code = CCTK_VARIABLE_COMPLEX ); -assert( N_elements == 1 ); - -/* advance past last table entry ==> "null-pointer" state */ -assert( Util_TableItAdvance(ihandle2) == 0 ); -assert( Util_TableItQueryIsNull(ihandle2) == 1); -assert( Util_TableItQueryIsNonNull(ihandle2) == 0); - -/* delete the last key "COMPlex_Z" */ -assert( Util_TableQueryNKeys(handle) == 1 ); -assert( Util_TableDeleteKey(handle, - case_insensitive ? "INT_X" : "int_x") - == UTIL_ERROR_TABLE_NO_SUCH_KEY ); -assert( Util_TableQueryNKeys(handle) == 1 ); -assert( Util_TableDeleteKey(handle, - case_insensitive ? "compLEX_z" : "COMPlex_Z") - == 0 ); -assert( Util_TableQueryNKeys(handle) == 0 ); - - { -/* check that table is indeed now empty */ -int ihandle3 = Util_TableItCreate(handle); -assert( ihandle3 >= 0 ); -assert( Util_TableItQueryIsNull(ihandle3) == 1); -assert( Util_TableItQueryIsNonNull(ihandle3) == 0); - -/* clean up our iterators */ -assert( Util_TableItDestroy(ihandle2) == 0 ); -assert( Util_TableItDestroy(42) == UTIL_ERROR_BAD_HANDLE ); -assert( Util_TableItDestroy(ihandle3) == 0 ); -assert( Util_TableItDestroy(ihandle) == 0 ); -free(key_buffer); - } - } - } - } - } + /* set up the key buffer */ + const int max_key_length = Util_TableQueryMaxKeyLength(handle); + assert( max_key_length == (int)strlen("COMPlex_Z") ); + { + const int N_key_buffer = max_key_length + 1; + char *const key_buffer = malloc(N_key_buffer); + assert( key_buffer != NULL ); + + /* + * delete the starting table entry "REAL_y" + * (this is a special case in the implementation) + */ + + assert( Util_TableQueryNKeys(handle) == 3 ); + assert( Util_TableDeleteKey(handle, + case_insensitive ? "rEAL_y" : "REAL_y") + == 0 ); + assert( Util_TableQueryNKeys(handle) == 2 ); + + /* walk the table again to verify remaining keys {"COMPlex_Z", "int_x"} */ + assert( Util_TableQueryNKeys(handle) == 2 ); + { + int ihandle = Util_TableItCreate(handle); + assert( ihandle >= 0 ); + assert( Util_TableItQueryTableHandle(ihandle) == handle ); + assert( Util_TableItQueryIsNonNull(ihandle) == 1); + assert( Util_TableItQueryIsNull(ihandle) == 0); + + /* COMPlex_Z */ + { + CCTK_INT type_code = 123456; + CCTK_INT N_elements = 54321; + assert( Util_TableItQueryKeyValueInfo(ihandle, + N_key_buffer, key_buffer, + &type_code, &N_elements) + == (int)strlen("COMPlex_Z") ); + assert( strcmp(key_buffer, "COMPlex_Z") == 0 ); + assert( type_code == CCTK_VARIABLE_COMPLEX ); + assert( N_elements == 1 ); + + /* int_x */ + type_code = 123456; + N_elements = 54321; + assert( Util_TableItAdvance(ihandle) == 1 ); + assert( Util_TableItQueryKeyValueInfo(ihandle, + N_key_buffer, key_buffer, + &type_code, &N_elements) + == (int)strlen("int_x") ); + assert( strcmp(key_buffer, "int_x") == 0 ); + assert( type_code == CCTK_VARIABLE_INT ); + assert( N_elements == 1 ); + + /* advance past last table entry ==> "null-pointer" state */ + assert( Util_TableItAdvance(ihandle) == 0 ); + assert( Util_TableItQueryIsNull(ihandle) == 1); + assert( Util_TableItQueryIsNonNull(ihandle) == 0); + + /* delete the last key "int_x" */ + assert( Util_TableDeleteKey(handle, + case_insensitive ? "INT_X" : "int_x") + == 0 ); + + /* walk the table again to verify remaining key {"COMPlex_Z"} */ + assert( Util_TableQueryNKeys(handle) == 1 ); + { + int ihandle2 = Util_TableItCreate(handle); + assert( ihandle2 >= 0 ); + assert( Util_TableItQueryTableHandle(ihandle2) == handle ); + assert( Util_TableItQueryIsNonNull(ihandle2) == 1); + assert( Util_TableItQueryIsNull(ihandle2) == 0); + + /* COMPlex_Z */ + type_code = 123456; + N_elements = 54321; + assert( Util_TableItQueryKeyValueInfo(ihandle2, + N_key_buffer, key_buffer, + &type_code, &N_elements) + == (int)strlen("COMPlex_Z") ); + assert( strcmp(key_buffer, "COMPlex_Z") == 0 ); + assert( type_code == CCTK_VARIABLE_COMPLEX ); + assert( N_elements == 1 ); + + /* advance past last table entry ==> "null-pointer" state */ + assert( Util_TableItAdvance(ihandle2) == 0 ); + assert( Util_TableItQueryIsNull(ihandle2) == 1); + assert( Util_TableItQueryIsNonNull(ihandle2) == 0); + + /* delete the last key "COMPlex_Z" */ + assert( Util_TableQueryNKeys(handle) == 1 ); + assert( Util_TableDeleteKey(handle, + case_insensitive ? "INT_X" : "int_x") + == UTIL_ERROR_TABLE_NO_SUCH_KEY ); + assert( Util_TableQueryNKeys(handle) == 1 ); + assert( Util_TableDeleteKey(handle, + case_insensitive ? "compLEX_z" : "COMPlex_Z") + == 0 ); + assert( Util_TableQueryNKeys(handle) == 0 ); + + { + /* check that table is indeed now empty */ + int ihandle3 = Util_TableItCreate(handle); + assert( ihandle3 >= 0 ); + assert( Util_TableItQueryIsNull(ihandle3) == 1); + assert( Util_TableItQueryIsNonNull(ihandle3) == 0); + + /* clean up our iterators */ + assert( Util_TableItDestroy(ihandle2) == 0 ); + assert( Util_TableItDestroy(42) == UTIL_ERROR_BAD_HANDLE ); + assert( Util_TableItDestroy(ihandle3) == 0 ); + assert( Util_TableItDestroy(ihandle) == 0 ); + free(key_buffer); + } + } + } + } + } } #endif /* UTIL_TABLE_TEST */ @@ -3899,52 +4499,240 @@ free(key_buffer); static int test_set_create_from_string(void) { + /* + * Test an empty string + */ + const int handle = Util_TableCreateFromString(""); + assert( Util_TableQueryNKeys(handle) == 0 ); + + /* + * Test some error cases + */ + assert( Util_TableSetFromString(handle, "foo" ) == UTIL_ERROR_BAD_INPUT ); + assert( Util_TableSetFromString(handle, "foo/" ) == UTIL_ERROR_BAD_INPUT ); + assert( Util_TableSetFromString(handle, "foo;=12" ) + == UTIL_ERROR_TABLE_BAD_KEY ); + assert( Util_TableSetFromString(handle, "foo =12" ) + == UTIL_ERROR_TABLE_BAD_KEY ); + assert( Util_TableSetFromString(handle, "foo/=12" ) + == UTIL_ERROR_TABLE_BAD_KEY ); + assert( Util_TableSetFromString(handle, "foo= 12") == UTIL_ERROR_BAD_INPUT ); + assert( Util_TableCreateFromString("foo" ) == UTIL_ERROR_BAD_INPUT ); + assert( Util_TableCreateFromString("foo/" ) == UTIL_ERROR_BAD_INPUT ); + assert( Util_TableCreateFromString("foo/=12" ) == UTIL_ERROR_TABLE_BAD_KEY ); + assert( Util_TableCreateFromString("foo= 12") == UTIL_ERROR_BAD_INPUT ); + + /* + * Test some "good" strings + */ + { + const int handle2 + = Util_TableCreateFromString(" ij=42 real1=3.5; real_e=2.75 "); + assert( handle2 >= 0 ); + assert( Util_TableQueryFlags(handle2) == UTIL_TABLE_FLAGS_CASE_INSENSITIVE ); + assert( Util_TableQueryNKeys(handle2) == 3 ); + check_table_contents(handle2, true); + + { + const int handle3 = Util_TableCreate(UTIL_TABLE_FLAGS_DEFAULT); + assert( Util_TableSetFromString(handle3, "ij=42 real1=3.5;") == 2); + assert( Util_TableQueryNKeys(handle3) == 2 ); + assert( Util_TableSetFromString(handle3, "real_e=2.75") == 1); + assert( Util_TableQueryNKeys(handle3) == 3 ); + check_table_contents(handle3, true); + + assert( Util_TableDestroy(handle3) == 0 ); + + return handle2; + } + } +} +#endif /* UTIL_TABLE_TEST */ + +/******************************************************************************/ + +#ifdef UTIL_TABLE_TEST /* - * Test an empty string + * This function tests Util_Table{Set,Get}String() */ -int handle = Util_TableCreateFromString(""); -assert( Util_TableQueryNKeys(handle) == 0 ); +static + void test_set_get_string(int handle, bool case_insensitive) +{ + assert( Util_TableSetString(handle, "Germany", "AEI") == 0 ); + assert( Util_TableSetString(handle, "Golm", "AEI") == 1 ); + + { + CCTK_INT type_code, N_elements; + assert( Util_TableQueryValueInfo(handle, + &type_code, &N_elements, + case_insensitive ? "aei" : "AEI") == 1 ); + assert( type_code == CCTK_VARIABLE_CHAR ); + assert( N_elements == (int)strlen("Golm") ); + + { + const int N_buffer = N_elements+1; + char *const buffer = (char *) malloc(N_buffer); + assert( buffer != NULL ); + assert( Util_TableGetCharArray(handle, + N_buffer, buffer, + "AEI") == (int)strlen("Golm") ); + assert( Util_TableGetString(handle, + 0, NULL, + "AEI") == (int)strlen("Golm") ); + assert( Util_TableGetString(handle, + N_buffer, buffer, + case_insensitive ? "aEI" : "AEI") + == (int)strlen("Golm") ); + assert( strcmp(buffer, "Golm") == 0 ); + + /* check getting string longer than buffer */ + assert( Util_TableSetString(handle, "Max-Planck", "famous") == 0 ); + assert( Util_TableGetString(handle, + N_buffer, buffer, + case_insensitive ? "FAMouS" : "famous") + == UTIL_ERROR_TABLE_STRING_TRUNCATED ); + assert( strcmp(buffer, "Max-") == 0 ); + } + } +} +#endif /* UTIL_TABLE_TEST */ + +/******************************************************************************/ +#ifdef UTIL_TABLE_TEST /* - * Test some error cases + * This function tests cloning a table. We assume that on entry the + * table contains the 3 keys + * real_e = 2.75 + * real1 = 3.5 + * ij = 42 + * in that order. */ -assert( Util_TableSetFromString(handle, "foo" ) == UTIL_ERROR_BAD_INPUT ); -assert( Util_TableSetFromString(handle, "foo/" ) == UTIL_ERROR_BAD_INPUT ); -assert( Util_TableSetFromString(handle, "foo;=12" ) - == UTIL_ERROR_TABLE_BAD_KEY ); -assert( Util_TableSetFromString(handle, "foo =12" ) - == UTIL_ERROR_TABLE_BAD_KEY ); -assert( Util_TableSetFromString(handle, "foo/=12" ) - == UTIL_ERROR_TABLE_BAD_KEY ); -assert( Util_TableSetFromString(handle, "foo= 12") == UTIL_ERROR_BAD_INPUT ); -assert( Util_TableCreateFromString("foo" ) == UTIL_ERROR_BAD_INPUT ); -assert( Util_TableCreateFromString("foo/" ) == UTIL_ERROR_BAD_INPUT ); -assert( Util_TableCreateFromString("foo/=12" ) == UTIL_ERROR_TABLE_BAD_KEY ); -assert( Util_TableCreateFromString("foo= 12") == UTIL_ERROR_BAD_INPUT ); +void test_clone(int handle) +{ + check_table_contents(handle, true); /* entry assumption */ + { + const int clone_handle = Util_TableClone(handle); + + /* make sure we didn't modify the table that we cloned */ + check_table_contents(handle, true); + + /* check the clone */ + check_table_contents(clone_handle, false); + + /* + * check that the tables are now distinct by + * changing each of them and checking that the other is unchanged + */ + assert( Util_TableSetInt(handle, 105, "universal number") == 0 ); + check_table_contents(clone_handle, false); + assert( Util_TableDeleteKey(handle, "universal number") == 0 ); + + assert( Util_TableSetInt(clone_handle, 105, "universal number #2") == 0 ); + check_table_contents(handle, true); + assert( Util_TableDeleteKey(clone_handle, "universal number #2") == 0 ); + + assert( Util_TableDestroy(clone_handle) == 0 ); + } +} +#endif /* UTIL_TABLE_TEST */ +/******************************************************************************/ + +#ifdef UTIL_TABLE_TEST /* - * Test some "good" strings + * This function does a sequence of assert() calls to verify that + * a table contains the 3 keys + * real_e = 2.75 + * real1 = 3.5 + * ij = 42 + * in a specified order. + * + * Arguments: + * order_up_flag = true --> check for the order {real_e,real1,ij} + * false --> check for the order {ij,real1,real_e} + * + * Bugs: + * Having to test for a specific order is a kludge. */ +static + void check_table_contents(int handle, bool order_up_flag) +{ + assert( Util_TableQueryNKeys(handle) == 3 ); + + /* set up the key buffer */ + { + const int max_key_length = Util_TableQueryMaxKeyLength(handle); + assert( max_key_length == (int)strlen("real_e") ); + { + const int N_key_buffer = max_key_length + 1; + char *const key_buffer = malloc(N_key_buffer); + assert( key_buffer != NULL ); + + /* walk through the table to verify contents in the right order */ + { + const int ihandle = Util_TableItCreate(handle); + if (order_up_flag) { -int handle2 = Util_TableCreateFromString(" ij=42 real1=3.5; real_e=2.75 "); -assert( handle2 >= 0 ); -assert( Util_TableQueryFlags(handle2) == UTIL_TABLE_FLAGS_CASE_INSENSITIVE ); -assert( Util_TableQueryNKeys(handle2) == 3 ); -check_table_contents(handle2); - + check_table_contents_real_e(handle,ihandle); + assert( Util_TableItAdvance(ihandle) == 1 ); + check_table_contents_real1(handle,ihandle); + assert( Util_TableItAdvance(ihandle) == 1 ); + check_table_contents_ij(handle, ihandle); + } + else { -int handle3 = Util_TableCreate(UTIL_TABLE_FLAGS_DEFAULT); -assert( Util_TableSetFromString(handle3, "ij=42 real1=3.5;") == 2); -assert( Util_TableQueryNKeys(handle3) == 2 ); -assert( Util_TableSetFromString(handle3, "real_e=2.75") == 1); -assert( Util_TableQueryNKeys(handle3) == 3 ); -check_table_contents(handle3); + check_table_contents_ij(handle, ihandle); + assert( Util_TableItAdvance(ihandle) == 1 ); + check_table_contents_real1(handle,ihandle); + assert( Util_TableItAdvance(ihandle) == 1 ); + check_table_contents_real_e(handle,ihandle); + } + assert( Util_TableItAdvance(ihandle) == 0 ); + assert(Util_TableItDestroy(ihandle) == 0 ); + } + } + } +} +#endif /* UTIL_TABLE_TEST */ -assert( Util_TableDestroy(handle3) == 0 ); +/******************************************************************************/ -return handle2; - } - } +#ifdef UTIL_TABLE_TEST +/* + * This function does a sequence of assert() calls to verify that + * the longest key in a table has the length of "real_e", and that + * a table iterator points to the key ij = 42 . + */ +static + void check_table_contents_ij(int handle, int ihandle) +{ + /* set up the key buffer */ + const int max_key_length = Util_TableQueryMaxKeyLength(handle); + assert( max_key_length == (int)strlen("real_e") ); + { + const int N_key_buffer = max_key_length + 1; + char *const key_buffer = malloc(N_key_buffer); + assert( key_buffer != NULL ); + + /* check ij = 42 */ + { + int type_code = 123456; + int N_elements = 54321; + assert( Util_TableItQueryKeyValueInfo(ihandle, + N_key_buffer, key_buffer, + &type_code, &N_elements) + == (int)strlen("ij") ); + assert( strcmp(key_buffer, "ij") == 0 ); + assert( type_code == CCTK_VARIABLE_INT ); + assert( N_elements == 1 ); + { + CCTK_INT value_int; + assert( Util_TableGetInt(handle, &value_int, "ij") == 1 ); + assert( value_int == 42 ); + } + } + } } #endif /* UTIL_TABLE_TEST */ @@ -3952,53 +4740,94 @@ return handle2; #ifdef UTIL_TABLE_TEST /* - * This function tests Util_Table{Set,Get}String() + * This function does a sequence of assert() calls to verify that + * the longest key in a table has the length of "real_e", and that + * a table iterator points to the key real1 = 3.5 . (N.b. 3.5 is + * assumed to be exactly representable as a floating point number.) */ static - void test_set_get_string(int handle, bool case_insensitive) + void check_table_contents_real1(int handle, int ihandle) { -assert( Util_TableSetString(handle, "Germany", "AEI") == 0 ); -assert( Util_TableSetString(handle, "Golm", "AEI") == 1 ); - - { -CCTK_INT type_code, N_elements; -assert( Util_TableQueryValueInfo(handle, - &type_code, &N_elements, - case_insensitive ? "aei" : "AEI") == 1 ); -assert( type_code = CCTK_VARIABLE_CHAR ); -assert( N_elements = (int)strlen("Golm") ); - - { -const int N_buffer = N_elements+1; -char *const buffer = (char *) malloc(N_buffer); -assert( buffer != NULL ); -assert( Util_TableGetCharArray(handle, - N_buffer, buffer, - "AEI") == (int)strlen("Golm") ); -assert( Util_TableGetString(handle, - 0, NULL, - "AEI") == (int)strlen("Golm") ); -assert( Util_TableGetString(handle, - N_buffer, buffer, - case_insensitive ? "aEI" : "AEI") - == (int)strlen("Golm") ); -assert( strcmp(buffer, "Golm") == 0 ); - -/* check getting string longer than buffer */ -assert( Util_TableSetString(handle, "Max-Planck", "famous") == 0 ); -type_code = 123; -N_elements = 456; -assert( Util_TableQueryValueInfo(handle, - &type_code, &N_elements, - case_insensitive ? "aei" : "AEI") == 1 ); -assert( type_code = CCTK_VARIABLE_CHAR ); -assert( N_elements = (int)strlen("Max-Planck") ); -assert( Util_TableGetString(handle, - N_buffer, buffer, - case_insensitive ? "FAMouS" : "famous") - == UTIL_ERROR_TABLE_STRING_TRUNCATED ); -assert( strcmp(buffer, "Max-") == 0 ); - } - } + /* set up the key buffer */ + const int max_key_length = Util_TableQueryMaxKeyLength(handle); + assert( max_key_length == (int)strlen("real_e") ); + { + const int N_key_buffer = max_key_length + 1; + char *const key_buffer = malloc(N_key_buffer); + assert( key_buffer != NULL ); + + /* check real1 = 3.5 */ + { + int type_code = 123456; + int N_elements = 54321; + assert( Util_TableItQueryKeyValueInfo(ihandle, + N_key_buffer, key_buffer, + &type_code, &N_elements) + == (int)strlen("real1") ); + assert( strcmp(key_buffer, "real1") == 0 ); + assert( type_code == CCTK_VARIABLE_REAL ); + assert( N_elements == 1 ); + { + CCTK_REAL value_real; + assert( Util_TableGetReal(handle, &value_real, key_buffer) == 1 ); + assert( value_real == 3.5 ); + } + } + } +} +#endif /* UTIL_TABLE_TEST */ + +/******************************************************************************/ + +#ifdef UTIL_TABLE_TEST +/* + * This function does a sequence of assert() calls to verify that + * the longest key in a table has the length of "real_e", and that + * a table iterator points to the key real_e = 2.75 . (N.b. 2.75 is + * assumed to be exactly representable as a floating point number.) + */ +static + void check_table_contents_real_e(int handle, int ihandle) +{ + /* set up the key buffer */ + const int max_key_length = Util_TableQueryMaxKeyLength(handle); + assert( max_key_length == (int)strlen("real_e") ); + { + const int N_key_buffer = max_key_length + 1; + char *const key_buffer = malloc(N_key_buffer); + assert( key_buffer != NULL ); + + /* check real_e = 2.75 */ + { + int type_code = 123456; + int N_elements = 54321; + assert( Util_TableItQueryKeyValueInfo(ihandle, + N_key_buffer, key_buffer, + &type_code, &N_elements) + == (int)strlen("real_e") ); + assert( strcmp(key_buffer, "real_e") == 0 ); + assert( type_code == CCTK_VARIABLE_REAL ); + assert( N_elements == 1 ); + { + CCTK_REAL value_real; + assert( Util_TableGetReal(handle, &value_real, key_buffer) == 1 ); + assert( value_real == 2.75 ); + + value_real = 314159.271828; + assert( Util_TableGetGeneric(handle, + CCTK_VARIABLE_REAL, (void *) &value_real, + key_buffer) + == 1 ); + assert( value_real == 2.75 ); + + value_real = 314159.271828; + assert( Util_TableGetGenericArray(handle, + CCTK_VARIABLE_REAL, 1, (void *) &value_real, + key_buffer) + == 1 ); + assert( value_real == 2.75 ); + } + } + } } #endif /* UTIL_TABLE_TEST */ |