/*
 * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include <assert.h>
#include <stdarg.h>

#include <common/debug.h>
#include <plat/common/platform.h>

static void string_print(char **s, size_t n, size_t *chars_printed,
			 const char *str)
{
	while (*str != '\0') {
		if (*chars_printed < n) {
			*(*s) = *str;
			(*s)++;
		}

		(*chars_printed)++;
		str++;
	}
}

static void unsigned_num_print(char **s, size_t n, size_t *chars_printed,
			      unsigned long long int unum,
			      unsigned int radix, char padc, int padn,
			      bool capitalise)
{
	/* Just need enough space to store 64 bit decimal integer */
	char num_buf[20];
	int i = 0;
	int width;
	unsigned int rem;
	char ascii_a = capitalise ? 'A' : 'a';

	do {
		rem = unum % radix;
		if (rem < 10U) {
			num_buf[i] = '0' + rem;
		} else {
			num_buf[i] = ascii_a + (rem - 10U);
		}
		i++;
		unum /= radix;
	} while (unum > 0U);

	width = i;
	if (padn > width) {
		(*chars_printed) += (size_t)padn;
	} else {
		(*chars_printed) += (size_t)width;
	}

	if (*chars_printed < n) {

		if (padn > 0) {
			while (width < padn) {
				*(*s)++ = padc;
				padn--;
			}
		}

		while (--i >= 0) {
			*(*s)++ = num_buf[i];
		}

		if (padn < 0) {
			while (width < -padn) {
				*(*s)++ = padc;
				padn++;
			}
		}
	}
}

/*******************************************************************
 * Reduced snprintf to be used for Trusted firmware.
 * The following type specifiers are supported:
 *
 * %x (or %X) - hexadecimal format
 * %d or %i - signed decimal format
 * %s - string format
 * %u - unsigned decimal format
 * %p - pointer format
 *
 * The following padding specifiers are supported by this print
 * %0NN - Left-pad the number with 0s (NN is a decimal number)
 * %NN - Left-pad the number or string with spaces (NN is a decimal number)
 * %-NN - Right-pad the number or string with spaces (NN is a decimal number)
 *
 * The function panics on all other formats specifiers.
 *
 * It returns the number of characters that would be written if the
 * buffer was big enough. If it returns a value lower than n, the
 * whole string has been written.
 *******************************************************************/
int snprintf(char *s, size_t n, const char *fmt, ...)
{
	va_list args;
	int num;
	unsigned long long int unum;
	char *str;
	char padc;		/* Padding character */
	int padn;		/* Number of characters to pad */
	bool left;
	bool capitalise;
	size_t chars_printed = 0U;

	if (n == 0U) {
		/* There isn't space for anything. */
	} else if (n == 1U) {
		/* Buffer is too small to actually write anything else. */
		*s = '\0';
		n = 0U;
	} else {
		/* Reserve space for the terminator character. */
		n--;
	}

	va_start(args, fmt);
	while (*fmt != '\0') {
		left = false;
		padc ='\0';
		padn = 0;
		capitalise = false;

		if (*fmt == '%') {
			fmt++;
			/* Check the format specifier. */
loop:
			switch (*fmt) {
			case '0':
			case '1':
			case '2':
			case '3':
			case '4':
			case '5':
			case '6':
			case '7':
			case '8':
			case '9':
				padc = (*fmt == '0') ? '0' : ' ';
				for (padn = 0; *fmt >= '0' && *fmt <= '9'; fmt++) {
					padn = (padn * 10) + (*fmt - '0');
				}
				if (left) {
					padn = -padn;
				}
				goto loop;
			case '-':
				left = true;
				fmt++;
				goto loop;

			case 'i':
			case 'd':
				num = va_arg(args, int);

				if (num < 0) {
					if (chars_printed < n) {
						*s = '-';
						s++;
					}
					chars_printed++;

					unum = (unsigned int)-num;
				} else {
					unum = (unsigned int)num;
				}

				unsigned_num_print(&s, n, &chars_printed,
						   unum, 10, padc, padn, false);
				break;
			case 's':
				str = va_arg(args, char *);
				string_print(&s, n, &chars_printed, str);
				break;
			case 'u':
				unum = va_arg(args, unsigned int);
				unsigned_num_print(&s, n, &chars_printed,
						   unum, 10, padc, padn, false);
				break;
			case 'p':
				unum = (uintptr_t)va_arg(args, void *);
				if (unum > 0U) {
					string_print(&s, n, &chars_printed, "0x");
					padn -= 2;
				}
				unsigned_num_print(&s, n, &chars_printed,
						   unum, 16, padc, padn, false);
				break;
			case 'X':
				capitalise = true;
			case 'x':
				unum = va_arg(args, unsigned int);
				unsigned_num_print(&s, n, &chars_printed,
						   unum, 16, padc, padn,
						   capitalise);
				break;

			default:
				/* Panic on any other format specifier. */
				ERROR("snprintf: specifier with ASCII code '%d' not supported.",
				      *fmt);
				plat_panic_handler();
				assert(0); /* Unreachable */
			}
			fmt++;
			continue;
		}

		if (chars_printed < n) {
			*s = *fmt;
			s++;
		}

		fmt++;
		chars_printed++;
	}

	va_end(args);

	if (n > 0U)
		*s = '\0';

	return (int)chars_printed;
}
