.\" $OpenBSD: OBJ_NAME_add.3,v 1.3 2022/09/10 10:22:46 jsg Exp $ .\" .\" Copyright (c) 2021 Ingo Schwarze .\" .\" Permission to use, copy, modify, and distribute this software for any .\" purpose with or without fee is hereby granted, provided that the above .\" copyright notice and this permission notice appear in all copies. .\" .\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES .\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF .\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR .\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES .\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" .Dd $Mdocdate: September 10 2022 $ .Dt OBJ_NAME_ADD 3 .Os .Sh NAME .Nm OBJ_NAME_add , .Nm OBJ_NAME_remove , .Nm OBJ_NAME_get , .Nm OBJ_NAME_new_index , .Nm OBJ_NAME_init , .Nm OBJ_NAME_cleanup , .Nm OBJ_NAME_do_all , .Nm OBJ_NAME_do_all_sorted .Nd global associative array .Sh SYNOPSIS .In openssl/objects.h .Ft int .Fo OBJ_NAME_add .Fa "const char *name" .Fa "int type" .Fa "const char *data" .Fc .Ft int .Fo OBJ_NAME_remove .Fa "const char *name" .Fa "int type" .Fc .Ft const char * .Fo OBJ_NAME_get .Fa "const char *name" .Fa "int type" .Fc .Ft int .Fo OBJ_NAME_new_index .Fa "unsigned long (*hash_func)(const char *name)" .Fa "int (*cmp_func)(const char *name1, const char *name2)" .Fa "void (*free_func)(const char *name, int type, const char *value)" .Fc .Ft int .Fn OBJ_NAME_init void .Ft void .Fn OBJ_NAME_cleanup "int type" .Bd -literal typedef struct { int type; int alias; const char *name; const char *data; } OBJ_NAME; .Ed .Pp .Ft void .Fo OBJ_NAME_do_all .Fa "int type" .Fa "void (*fn)(const OBJ_NAME *pair, void *arg)" .Fa "void *arg" .Fc .Ft void .Fo OBJ_NAME_do_all_sorted .Fa "int type" .Fa "void (*fn)(const OBJ_NAME *pair, void *arg)" .Fa "void *arg" .Fc .Sh DESCRIPTION These functions implement a single, static associative array with the following properties: .Bl -bullet .It The keys are ordered pairs consisting of a NUL-terminated string .Pq called the Fa name and an .Vt int number .Pq called the Fa type . Two types are predefined and used internally by the library: .Dv OBJ_NAME_TYPE_MD_METH and .Dv OBJ_NAME_TYPE_CIPHER_METH . Two additional types are predefined but not used internally: .Dv OBJ_NAME_TYPE_PKEY_METH and .Dv OBJ_NAME_TYPE_COMP_METH . All predefined types are greater than .Dv OBJ_NAME_TYPE_UNDEF and smaller than .Dv OBJ_NAME_TYPE_NUM . .It The values are pointers. Formally, they are of the type .Vt const char * , but in practice, pointers of other types, for example .Vt EVP_CIPHER * or .Vt EVP_MD * , are often stored as values and cast back to the correct type on retrieval. .It The array supports type-specific aliases for names. .El .Pp .Fn OBJ_NAME_add removes the key-value pair or alias with the key .Pq Fa name , type in the same way as .Fn OBJ_NAME_remove and inserts a key-value pair with the specified .Fa name , .Fa type , and .Fa value . If the bit .Dv OBJ_NAME_ALIAS is set in the .Fa type argument, that bit is cleared before using the .Fa type and the key .Pq Fa name , type becomes an alias for the key .Pq Fa value , type instead of setting a value. It is not checked whether the key .Pq Fa value , type already exists. Consequently, it is possible to define an alias before setting the associated value. .Pp .Fn OBJ_NAME_remove removes the key-value pair or alias with the key .Pq Fa name , type from the array, if it exists. Otherwise, it has no effect. If the bit .Dv OBJ_NAME_ALIAS is set in the .Fa type argument, it is ignored and cleared before using the .Fa type . If the .Fa type is an application-defined type added with .Fn OBJ_NAME_new_index and the .Fa free_func associated with the .Fa type is not a .Dv NULL pointer, it is called with the .Fa name , .Fa type , and .Fa value of the key-value pair being removed or with the .Fa name , .Fa type , and alias target name of the alias being removed. In typical usage, this function might free the .Fa name , and it might free the .Fa value in a type-specific way. .Pp .Fn OBJ_NAME_get looks up the key .Pq Fa name , type , recursively resolving up to ten aliases if needed. If the bit .Dv OBJ_NAME_ALIAS is set in the .Fa type argument, it is cleared before using the .Fa type , processing of aliases is disabled, and if .Pq Fa name , type is an alias, the target name of the alias is returned instead of a value. .Pp .Fn OBJ_NAME_new_index assigns the smallest unassigned positive integer number to represent a new, application-defined .Fa type . The three function pointers will be used, respectively, to hash a name for this type, to compare two names for this type, and to free the contents of a key-value pair holding the given .Fa name , .Fa type , and .Fa value . If the .Fa hash_func argument is a .Dv NULL pointer, .Xr lh_strhash 3 is used instead. If the .Fa cmp_func argument is a .Dv NULL pointer, .Xr strcmp 3 is used instead. If the .Fa free_func argument is a .Dv NULL pointer, the .Fa name and .Fa value pointers contained in the key-value pair are not freed, only the structure representing the pair itself is. This default behaviour is also used for the built-in types. .Pp .Fn OBJ_NAME_init initializes the array. After initialization, the array is empty. Calling .Fn OBJ_NAME_init when the array is already initialized has no effect. Application programs do not need to call this function because .Fn OBJ_NAME_add and .Fn OBJ_NAME_get automatically call it whenever needed. .Pp .Fn OBJ_NAME_cleanup removes all key-value pairs and aliases of the given .Fa type from the array by calling .Fn OBJ_NAME_remove on every such pair and alias. If the .Fa type argument is negative, it removes all key-value pairs and aliases of any type and also reverses all effects of .Fn OBJ_NAME_new_index and .Fn OBJ_NAME_init , in particular resetting the list of types to the predefined types and releasing all memory reserved by these functions. .Pp The .Vt OBJ_NAME structure represents one key-value pair or one alias with the key .Pq Fa name , type . If the .Fa alias field is 0, the .Fa data field contains the value; otherwise, it contains the alias target name. .Pp .Fn OBJ_NAME_do_all calls .Fa fn on every .Fa pair and alias in the array that has the given .Fa type , also passing the .Fa arg pointer. .Fn OBJ_NAME_do_all_sorted is similar except that it processes the pairs and aliases in lexicographic order of their names as determined by .Xr strcmp 3 , ignoring any .Fa cmp_func that may be defined for the .Fa type . .Sh RETURN VALUES .Fn OBJ_NAME_add and .Fn OBJ_NAME_init return 1 on success or 0 if memory allocation fails. .Pp .Fn OBJ_NAME_remove returns 1 if one key-value pair or alias was removed or 0 otherwise. .Pp .Fn OBJ_NAME_get returns the .Fa value associated with the key .Pq Fa name , type or .Dv NULL if .Fa name is .Dv NULL , if the array does not contain a value for this key, or if more than ten aliases are encountered before finding a value. .Pp .Fn OBJ_NAME_new_index returns a positive integer greater than or equal to .Dv OBJ_NAME_TYPE_NUM representing the new type or 0 if memory allocation fails. .Sh SEE ALSO .Xr EVP_cleanup 3 , .Xr EVP_get_cipherbyname 3 , .Xr EVP_get_digestbyname 3 , .Xr lh_new 3 , .Xr OBJ_add_sigid 3 , .Xr OBJ_create 3 , .Xr OBJ_nid2obj 3 .Sh BUGS Calling .Fn OBJ_NAME_get with the bit .Dv OBJ_NAME_ALIAS is not very useful because there is no way to tell whether the returned pointer points to a value or to a name, short of calling the function again without setting the bit and comparing the two returned pointers. .Pp The .Fa free_func has no way to tell whether its .Fa value argument is indeed of the given .Fa type or whether it is merely the target name of an alias. Consequently, to use values of a type that requires more cleanup than merely calling .Xr free 3 on it, instances of the type need to begin with a magic number or string that cannot occur at the beginning of a name. .Pp .Fn OBJ_NAME_do_all_sorted is unable to report errors. If memory allocations fails, it does nothing at all without telling the caller about the problem.