/*
 * profile_helpers.c -- Helper functions for the profile library
 *
 * These functions are not part of the "core" profile library, and do
 * not require access to the internal functions and data structures of
 * the profile library.  They are mainly convenience functions for
 * programs that want to do something unusual such as obtaining the
 * list of sections or relations, or accessing multiple values from a
 * relation that is listed more than once.  This functionality can all
 * be done using the profile_iterator abstraction, but it is less
 * convenient.
 *
 * Copyright (C) 2006 by Theodore Ts'o.
 *
 * %Begin-Header%
 * This file may be redistributed under the terms of the GNU Public
 * License.
 * %End-Header%
 */

#include "config.h"
#include <stdlib.h>
#include <string.h>
#include <errno.h>

#include <et/com_err.h>
#include "profile.h"
#include "profile_helpers.h"
#include "prof_err.h"

/*
 * These functions --- init_list(), end_list(), and add_to_list() are
 * internal functions used to build up a null-terminated char ** list
 * of strings to be returned by functions like profile_get_values.
 *
 * The profile_string_list structure is used for internal booking
 * purposes to build up the list, which is returned in *ret_list by
 * the end_list() function.
 *
 * The publicly exported interface for freeing char** list is
 * profile_free_list().
 */

struct profile_string_list {
	char	**list;
	int	num;
	int	max;
};

/*
 * Initialize the string list abstraction.
 */
static errcode_t init_list(struct profile_string_list *list)
{
	list->num = 0;
	list->max = 10;
	list->list = malloc(list->max * sizeof(char *));
	if (list->list == 0)
		return ENOMEM;
	list->list[0] = 0;
	return 0;
}

/*
 * Free any memory left over in the string abstraction, returning the
 * built up list in *ret_list if it is non-null.
 */
static void end_list(struct profile_string_list *list, char ***ret_list)
{
	char	**cp;

	if (list == 0)
		return;

	if (ret_list) {
		*ret_list = list->list;
		return;
	} else {
		for (cp = list->list; *cp; cp++)
			free(*cp);
		free(list->list);
	}
	list->num = list->max = 0;
	list->list = 0;
}

/*
 * Add a string to the list.
 */
static errcode_t add_to_list(struct profile_string_list *list, char *str)
{
	char 	**newlist;
	int	newmax;

	if (list->num+1 >= list->max) {
		newmax = list->max + 10;
		newlist = realloc(list->list, newmax * sizeof(char *));
		if (newlist == 0)
			return ENOMEM;
		list->max = newmax;
		list->list = newlist;
	}

	list->list[list->num++] = str;
	list->list[list->num] = 0;
	return 0;
}

/*
 * Return TRUE if the string is already a member of the list.
 */
static int is_list_member(struct profile_string_list *list, const char *str)
{
	char **cpp;

	if (!list->list)
		return 0;

	for (cpp = list->list; *cpp; cpp++) {
		if (!strcmp(*cpp, str))
			return 1;
	}
	return 0;
}

/*
 * This function frees a null-terminated list as returned by
 * profile_get_values.
 */
void profile_free_list(char **list)
{
    char	**cp;

    if (list == 0)
	    return;

    for (cp = list; *cp; cp++)
	free(*cp);
    free(list);
}

errcode_t
profile_get_values(profile_t profile, const char *const *names,
		   char ***ret_values)
{
	errcode_t		retval;
	void			*state;
	char			*value;
	struct profile_string_list values;

	if ((retval = profile_iterator_create(profile, names,
					      PROFILE_ITER_RELATIONS_ONLY,
					      &state)))
		return retval;

	if ((retval = init_list(&values)))
		goto cleanup_iterator;

	do {
		if ((retval = profile_iterator(&state, 0, &value)))
			goto cleanup;
		if (value)
			add_to_list(&values, value);
	} while (state);

	if (values.num == 0) {
		retval = PROF_NO_RELATION;
		goto cleanup;
	}

	end_list(&values, ret_values);
	return 0;

cleanup:
	end_list(&values, 0);
cleanup_iterator:
	profile_iterator_free(&state);
	return retval;
}

/*
 * This function will return the list of the names of subsections in the
 * under the specified section name.
 */
errcode_t
profile_get_subsection_names(profile_t profile, const char **names,
			     char ***ret_names)
{
	errcode_t		retval;
	void			*state;
	char			*name;
	struct profile_string_list values;

	if ((retval = profile_iterator_create(profile, names,
		   PROFILE_ITER_LIST_SECTION | PROFILE_ITER_SECTIONS_ONLY,
		   &state)))
		return retval;

	if ((retval = init_list(&values)))
		goto cleanup_iterator;

	do {
		if ((retval = profile_iterator(&state, &name, 0)))
			goto cleanup;
		if (name)
			add_to_list(&values, name);
	} while (state);

	end_list(&values, ret_names);
	return 0;

cleanup:
	end_list(&values, 0);
cleanup_iterator:
	profile_iterator_free(&state);
	return retval;
}

/*
 * This function will return the list of the names of relations in the
 * under the specified section name.
 */
errcode_t
profile_get_relation_names(profile_t profile, const char **names,
			   char ***ret_names)
{
	errcode_t		retval;
	void			*state;
	char			*name;
	struct profile_string_list values;

	if ((retval = profile_iterator_create(profile, names,
		   PROFILE_ITER_LIST_SECTION | PROFILE_ITER_RELATIONS_ONLY,
		   &state)))
		return retval;

	if ((retval = init_list(&values)))
		goto cleanup_iterator;

	do {
		if ((retval = profile_iterator(&state, &name, 0)))
			goto cleanup;
		if (name) {
			if (is_list_member(&values, name))
				free(name);
			else
				add_to_list(&values, name);
		}
	} while (state);

	end_list(&values, ret_names);
	return 0;

cleanup:
	end_list(&values, 0);
cleanup_iterator:
	profile_iterator_free(&state);
	return retval;
}


void
profile_release_string(char *str)
{
	free(str);
}

errcode_t
profile_init_path(const char * filepath,
		  profile_t *ret_profile)
{
	int n_entries, i;
	unsigned int ent_len;
	const char *s, *t;
	char **filenames;
	errcode_t retval;

	/* count the distinct filename components */
	for(s = filepath, n_entries = 1; *s; s++) {
		if (*s == ':')
			n_entries++;
	}

	/* the array is NULL terminated */
	filenames = (char **) malloc((n_entries+1) * sizeof(char*));
	if (filenames == 0)
		return ENOMEM;

	/* measure, copy, and skip each one */
	for(s = filepath, i=0; (t = strchr(s, ':')) || (t=s+strlen(s)); s=t+1, i++) {
		ent_len = t-s;
		filenames[i] = (char*) malloc(ent_len + 1);
		if (filenames[i] == 0) {
			/* if malloc fails, free the ones that worked */
			while(--i >= 0) free(filenames[i]);
                        free(filenames);
			return ENOMEM;
		}
		strncpy(filenames[i], s, ent_len);
		filenames[i][ent_len] = 0;
		if (*t == 0) {
			i++;
			break;
		}
	}
	/* cap the array */
	filenames[i] = 0;

	retval = profile_init((const char * const *) filenames,
			      ret_profile);

	/* count back down and free the entries */
	while(--i >= 0) free(filenames[i]);
	free(filenames);

	return retval;
}
