/*
 * (C) Copyright 2012
 * Joe Hershberger, National Instruments, joe.hershberger@ni.com
 *
 * SPDX-License-Identifier:	GPL-2.0+
 */

#ifdef USE_HOSTCC /* Eliminate "ANSI does not permit..." warnings */
#include <stdint.h>
#include <stdio.h>
#include <linux/linux_string.h>
#else
#include <common.h>
#endif

#include <env_attr.h>
#include <errno.h>
#include <linux/string.h>
#include <malloc.h>

/*
 * Iterate through the whole list calling the callback for each found element.
 * "attr_list" takes the form:
 *	attributes = [^,:\s]*
 *	entry = name[:attributes]
 *	list = entry[,list]
 */
int env_attr_walk(const char *attr_list,
	int (*callback)(const char *name, const char *attributes))
{
	const char *entry, *entry_end;
	char *name, *attributes;

	if (!attr_list)
		/* list not found */
		return 1;

	entry = attr_list;
	do {
		char *entry_cpy = NULL;

		entry_end = strchr(entry, ENV_ATTR_LIST_DELIM);
		/* check if this is the last entry in the list */
		if (entry_end == NULL) {
			int entry_len = strlen(entry);

			if (entry_len) {
				/*
				 * allocate memory to copy the entry into since
				 * we will need to inject '\0' chars and squash
				 * white-space before calling the callback
				 */
				entry_cpy = malloc(entry_len + 1);
				if (entry_cpy)
					/* copy the rest of the list */
					strcpy(entry_cpy, entry);
				else
					return -ENOMEM;
			}
		} else {
			int entry_len = entry_end - entry;

			if (entry_len) {
				/*
				 * allocate memory to copy the entry into since
				 * we will need to inject '\0' chars and squash
				 * white-space before calling the callback
				 */
				entry_cpy = malloc(entry_len + 1);
				if (entry_cpy) {
					/* copy just this entry and null term */
					strncpy(entry_cpy, entry, entry_len);
					entry_cpy[entry_len] = '\0';
				} else
					return -ENOMEM;
			}
		}

		/* check if there is anything to process (e.g. not ",,,") */
		if (entry_cpy != NULL) {
			attributes = strchr(entry_cpy, ENV_ATTR_SEP);
			/* check if there is a ':' */
			if (attributes != NULL) {
				/* replace the ':' with '\0' to term name */
				*attributes++ = '\0';
				/* remove white-space from attributes */
				attributes = strim(attributes);
			}
			/* remove white-space from name */
			name = strim(entry_cpy);

			/* only call the callback if there is a name */
			if (strlen(name) != 0) {
				int retval = 0;

				retval = callback(name, attributes);
				if (retval) {
					free(entry_cpy);
					return retval;
				}
			}
		}

		free(entry_cpy);
		entry = entry_end + 1;
	} while (entry_end != NULL);

	return 0;
}

/*
 * Search for the last matching string in another string with the option to
 * start looking at a certain point (i.e. ignore anything beyond that point).
 */
static char *reverse_strstr(const char *searched, const char *search_for,
	const char *searched_start)
{
	char *result = NULL;

	if (*search_for == '\0')
		return (char *)searched;

	for (;;) {
		char *match = strstr(searched, search_for);

		/*
		 * Stop looking if no new match is found or looking past the
		 * searched_start pointer
		 */
		if (match == NULL || (searched_start != NULL &&
		    match + strlen(search_for) > searched_start))
			break;

		result = match;
		searched = match + 1;
	}

	return result;
}

/*
 * Retrieve the attributes string associated with a single name in the list
 * There is no protection on attributes being too small for the value
 */
int env_attr_lookup(const char *attr_list, const char *name, char *attributes)
{
	const char *entry = NULL;

	if (!attributes)
		/* bad parameter */
		return -1;
	if (!attr_list)
		/* list not found */
		return 1;

	entry = reverse_strstr(attr_list, name, NULL);
	while (entry != NULL) {
		const char *prevch = entry - 1;
		const char *nextch = entry + strlen(name);

		/* Skip spaces */
		while (*prevch == ' ')
			prevch--;
		while (*nextch == ' ')
			nextch++;

		/* check for an exact match */
		if ((entry == attr_list ||
		     *prevch == ENV_ATTR_LIST_DELIM) &&
		    (*nextch == ENV_ATTR_SEP ||
		     *nextch == ENV_ATTR_LIST_DELIM ||
		     *nextch == '\0'))
			break;

		entry = reverse_strstr(attr_list, name, entry);
	}
	if (entry != NULL) {
		int len;

		/* skip the name */
		entry += strlen(name);
		/* skip spaces */
		while (*entry == ' ')
			entry++;
		if (*entry != ENV_ATTR_SEP)
			len = 0;
		else {
			const char *delim;
			static const char delims[] = {
				ENV_ATTR_LIST_DELIM, ' ', '\0'};

			/* skip the attr sep */
			entry += 1;
			/* skip spaces */
			while (*entry == ' ')
				entry++;

			delim = strpbrk(entry, delims);
			if (delim == NULL)
				len = strlen(entry);
			else
				len = delim - entry;
			memcpy(attributes, entry, len);
		}
		attributes[len] = '\0';

		/* success */
		return 0;
	}

	/* not found in list */
	return 2;
}
