blob: 2761bd11e739c1fdb7c259ea567265f36ad0a05f (
plain) (
tree)
|
|
/* See LICENSE file for copyright and license details. */
#include "common.h"
/**
* List all recognised adjustment method
*
* SIGCHLD must not be ignored or blocked
*
* @return A `NULL`-terminated list of names. You should only free
* the outer pointer, inner pointers are subpointers of the
* outer pointer and cannot be freed. `NULL` on error.
*/
char **
libcoopgamma_get_methods(void)
{
char num[5]; /* The size is base on the fact that we have limited `n` in the loop below */
char **methods = NULL;
char *method;
char **rc;
char *buffer;
size_t n = 0;
size_t size = 0;
void *new;
methods = malloc(4U * sizeof(*methods));
if (!methods)
goto fail;
for (n = 0; n < 10000 /* just to be safe */; n++) {
if (n >= 4 && (n & (~n + 1U)) == n) {
new = realloc(methods, (n << 1) * sizeof(*methods));
if (!new)
goto fail;
methods = new;
}
sprintf(num, "%zu", n);
if (libcoopgamma_get_method_and_site(num, NULL, &method, NULL))
goto fail;
if (!strcmp(method, num)) {
free(method);
break;
}
methods[n] = method;
size += strlen(method) + 1U;
}
rc = malloc((n + 1U) * sizeof(char *) + size);
if (!rc)
goto fail;
buffer = (char *)&rc[n + 1U];
rc[n] = NULL;
while (n--) {
rc[n] = buffer;
buffer = &stpcpy(buffer, methods[n])[1U];
free(methods[n]);
}
free(methods);
return rc;
fail:
while (n--)
free(methods[n]);
free(methods);
return NULL;
}
|