/**************************************************************************************************
	$Header: /pub/cvsroot/yencode/lib/string.c,v 1.10 2002/03/12 02:01:43 bboy Exp $

	Copyright (C) 2002  Don Moore <bboy@bboy.net>

	This program is free software; you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation; either version 2 of the License, or
	(at Your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program; if not, write to the Free Software
	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
**************************************************************************************************/

#include "misc.h"


/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
	BYTESTR
	Given a number, returns a textual, abbreviated string describing the number of bytes it
	represents.
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
char *
bytestr(u_int64_t number)
{
	char numbuf[80];

	if (number > 99999)
	{
		number = (number + 500) / 1000;
		if (number > 9999)
		{
			number = (number + 500) / 1000;
			if (number > 9999)
			{
				number = (number + 500) / 1000;
				if (number > 9999)
				{
					number = (number + 500) / 1000;
						  snprintf(numbuf, sizeof(numbuf), "%lluT", number);
				}	else snprintf(numbuf, sizeof(numbuf), "%lluG", number);
			} else snprintf(numbuf, sizeof(numbuf), "%lluM", number);
		} else snprintf(numbuf, sizeof(numbuf), "%lluk", number);
	} else snprintf(numbuf, sizeof(numbuf), "%llu", number);
	return (xstrdup(numbuf));
}
/*--- bytestr() ---------------------------------------------------------------------------------*/


/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
	Given a string such as "10MB" returns the size represented, in bytes.
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
size_t
human_file_size(const char *str)
{
	size_t numeric = 0;											/* Numeric part of `str' */
	register char *c;												/* Ptr to first nonalpha char */

	numeric = (size_t)strtoul(str, (char **)NULL, 10);

	for (c = (char *)str; *c && isdigit(*c); c++)
		/* DONOTHING */;

	if (!*c)
		return (numeric);

	/* I am using values like 1000 instead of 1024, since that's what most people expect */
	switch (tolower(*c))
	{
		case 'k': return (numeric * 1000);
		case 'm': return (numeric * 1000000);
		case 'g': return (numeric * 1000000000);
		default:	/* Silently ignore unknown quantifiers */
			break;
	}
	return (numeric);
}
/*--- human_file_size() -------------------------------------------------------------------------*/


/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
	Removes leading and trailing whitespace from a string.  Converts tabs and newlines to spaces.
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
char *
strtrim(char *str)
{
	if (!str)
		return (str);

	while (isspace(str[0]) || iscntrl(str[0]))
		memmove(str, str+1, strlen(str));

	while (isspace(str[strlen(str)-1]) || iscntrl(str[strlen(str)-1]))
		str[strlen(str)-1] = '\0';

	return (str);
}
/*--- strtrim() ---------------------------------------------------------------------------------*/


/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
	CONFTRIM
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
char *
conftrim(char *str)
{
	register char *ibuf, *obuf;

	if (!str)
		return (NULL);

	/* Strip comments */
	for (ibuf = obuf = str; *ibuf; )
	{
		if (*ibuf == '#')
		{
			if (obuf > str && obuf[-1] == '\\')
				obuf[-1] = '#';
			else
				*(obuf++) = '\0';
			ibuf++;
		}
		else
			*(obuf++) = *(ibuf++);
	}

	for (ibuf = obuf = str; *ibuf; )
	{
		while (*ibuf && (isspace(*ibuf) || iscntrl(*ibuf)))
			ibuf++;

		if (*ibuf && (obuf != str))
			*(obuf++) = ' ';

		while (*ibuf && (!isspace(*ibuf) && !iscntrl(*ibuf)))
			*(obuf++) = *(ibuf++);
	}
	*obuf = '\0';

	return (str);
}
/*--- conftrim() --------------------------------------------------------------------------------*/


/**************************************************************************************************
	COMMAFMT
	Copies the numeric value of N into buffer 'buf' of size 'bufsiz', inserting commas where
	appropriate.
**************************************************************************************************/
static size_t
commafmt(char *buf, size_t bufsiz, unsigned long N)
{
	int len = 1, posn = 1, sign = 1;
	char *ptr = buf + bufsiz - 1;

	if (2 > bufsiz)
	{
ABORT:*buf = '\0';
		return 0;
	}

	*ptr-- = '\0';
	--bufsiz;

	if (0L > N)
	{
		sign = -1;
		N = -N;
	}

	for ( ; len <= bufsiz; ++len, ++posn)
	{
		*ptr-- = (char)((N % 10L) + '0');
		if (0L == (N /= 10L))
			break;
		if (0 == (posn % 3))
		{
			*ptr-- = ',';
			++len;
		}
		if (len >= bufsiz)
			goto ABORT;
	}
	if (0 > sign)
	{
		if (0 == bufsiz)
			goto ABORT;
		*ptr-- = '-';
		++len;
	}
	strcpy(buf, ++ptr);

	return (size_t)len;
}
/*--- commafmt() --------------------------------------------------------------------------------*/


/**************************************************************************************************
	COMMA1-3
	Making printf life easy for Don at the expense of repetition and a few hundred bytes of RAM.
**************************************************************************************************/
char *comma(u_int64_t num)  { static char cbuf[81];  commafmt(cbuf, 80, num); return (cbuf); }
char *comma1(u_int64_t num) { static char cbuf[81];  commafmt(cbuf, 80, num); return (cbuf); }
char *comma2(u_int64_t num) { static char cbuf[81];  commafmt(cbuf, 80, num); return (cbuf); }
char *comma3(u_int64_t num) { static char cbuf[81];  commafmt(cbuf, 80, num); return (cbuf); }
/*--- comma1-3() --------------------------------------------------------------------------------*/


/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
	NUMERIC_WIDTH
	Given a number, returns the maximum numeric width.
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
int
numeric_width(unsigned long num)
{
	char	numbuf[80];

	snprintf(numbuf, sizeof(numbuf), "%lu", num);
	return (strlen(numbuf));
}
/*--- numeric_width() ---------------------------------------------------------------------------*/


/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
	SDPRINTF
	A dynamic sprintf; grows the buffer as it adds lines.
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
void
sdprintf(unsigned char **dest, const char *fmt, ...)
{
	char 				msg[BUFSIZ];
	va_list			ap;
	unsigned char	*d = *dest;
	register int	msglen, destlen;

	va_start(ap, fmt);
	msglen = vsnprintf(msg, sizeof(msg), fmt, ap);
	va_end(ap);

	destlen = (d) ? strlen(d) : 0;

   d = xrealloc(d, destlen + msglen + 1);

   memcpy(d + destlen, msg, msglen);
   d[destlen + msglen] = '\0';

   *dest = d;
}
/*--- sdprintf() --------------------------------------------------------------------------------*/


/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
	ESCDUMP
	For debugging, dumps a buffer with characters escaped.
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
void
escdump(const unsigned char *buf, size_t len)
{
	register size_t ct;

	for (ct = 0; ct < len; ct++)
	{
		switch (buf[ct])
		{
			case '\r':
				printf("\033[1m\\r\033[0m");
				break;
			case '\n':
				printf("\033[1m\\n\033[0m\n");
				break;
			case '\t':
				printf("\033[1m\\t\033[0m");
				break;
			default:
				if (isprint(buf[ct]))
					putc(buf[ct], stdout);
				else
					printf("\033[1m\\%03o[0m", buf[ct]);
				break;
		}
	}
	fflush(stdout);
}
/*--- escdump() ---------------------------------------------------------------------------------*/

/* vi:set ts=3: */


syntax highlighted by Code2HTML, v. 0.9.1