//	Zinc Application Framework - Z_INT.CPP
//	COPYRIGHT (C) 1990-1999.  All Rights Reserved.
//	Zinc Software Incorporated.  Pleasant Grove, Utah  USA

#include <z_int.hpp>
#include <z_ctype.hpp>
#include <z_stdlib.hpp>
#include <z_stdarg.hpp>
#include <z_string.hpp>
#define ZAF_INTEGER_DATA_INFO
#include "gbl_def.cpp"

// ----- ZafIntegerData -----------------------------------------------------

ZafIntegerData::ZafIntegerData(void) :
	ZafFormatData(), value(0)
{
	// Check the printf binding.
	Bind();
}

ZafIntegerData::ZafIntegerData(long zValue) :
	ZafFormatData(), value(zValue)
{
	// Check the printf binding.
	Bind();
}

ZafIntegerData::ZafIntegerData(const ZafIChar *string, const ZafIChar *format) :
	ZafFormatData()
{
	// Check the printf binding.
	Bind();
	Sscanf(string, (format && format[0]) ? format : zafLocale->integerStringInputFormat);
}

ZafIntegerData::ZafIntegerData(const ZafIntegerData &copy) :
	ZafFormatData(copy), value(copy.value)
{
	// Check the printf binding.
	Bind();
}

ZafIntegerData::~ZafIntegerData(void)
{
}

void ZafIntegerData::Bind(void)
{
	// Bind in the sprintf characters.
#if defined(ZAF_INDEPENDENT)
#	define bound zafIntegerData_bound
	extern bool bound;
#else
	static bool bound = false;
#endif
	if (!bound)
	{
		// Check for a valid locale.
		if (!zafLocale)
			ZafI18nData::I18nAllocate();

		// Set the lookup characters.
		bound = true;
/* START BLOCK COMMENT
**			ZafStandardArg::SetSprintf('d', ZafIntegerData::Format);
**			ZafStandardArg::SetSprintf('i', ZafIntegerData::Format);
**			ZafStandardArg::SetSprintf('o', ZafIntegerData::Format);
**			ZafStandardArg::SetSprintf('u', ZafIntegerData::Format);
**			ZafStandardArg::SetSprintf('x', ZafIntegerData::Format);
**			ZafStandardArg::SetSprintf('X', ZafIntegerData::Format);
**			ZafStandardArg::SetSscanf('d', ZafIntegerData::Parse);
**			ZafStandardArg::SetSscanf('D', ZafIntegerData::Parse);
**			ZafStandardArg::SetSscanf('i', ZafIntegerData::Parse);
**			ZafStandardArg::SetSscanf('o', ZafIntegerData::Parse);
**			ZafStandardArg::SetSscanf('O', ZafIntegerData::Parse);
**			ZafStandardArg::SetSscanf('u', ZafIntegerData::Parse);
**			ZafStandardArg::SetSscanf('x', ZafIntegerData::Parse);
**			ZafStandardArg::SetSscanf('X', ZafIntegerData::Parse);
END BLOCK COMMENT */
		ZafFormatData::SetSprintf('d', ZafIntegerData::Format);
		ZafFormatData::SetSprintf('i', ZafIntegerData::Format);
		ZafFormatData::SetSprintf('o', ZafIntegerData::Format);
		ZafFormatData::SetSprintf('u', ZafIntegerData::Format);
		ZafFormatData::SetSprintf('x', ZafIntegerData::Format);
		ZafFormatData::SetSprintf('X', ZafIntegerData::Format);
		ZafFormatData::SetSscanf('d', ZafIntegerData::Parse);
		ZafFormatData::SetSscanf('D', ZafIntegerData::Parse);
		ZafFormatData::SetSscanf('i', ZafIntegerData::Parse);
		ZafFormatData::SetSscanf('o', ZafIntegerData::Parse);
		ZafFormatData::SetSscanf('O', ZafIntegerData::Parse);
		ZafFormatData::SetSscanf('u', ZafIntegerData::Parse);
		ZafFormatData::SetSscanf('x', ZafIntegerData::Parse);
		ZafFormatData::SetSscanf('X', ZafIntegerData::Parse);
	}
}

void ZafIntegerData::Clear(void)
{
	// Reset the value.
	PushLevel();
	value = 0;
	SetError(ZAF_ERROR_NONE);
	PopLevel();
}

ZafData *ZafIntegerData::Duplicate(void)
{
	return (new ZafIntegerData(*this));
}

int ZafIntegerData::FormattedText(ZafIChar *buffer, int maxLength, const ZafIChar *format) const
{
	// Format the text.
	return (Sprintf(buffer, maxLength, format ? format : zafLocale->integerStringOutputFormat));
}

bool ZafIntegerData::IsA(ZafClassID compareID) const
{
	return ((compareID == classID) ? true : ZafFormatData::IsA(compareID));
}

bool ZafIntegerData::IsA(ZafClassName compareName) const
{
	return (!strcmp(compareName, className) ? true : ZafFormatData::IsA(compareName));
}

ZafError ZafIntegerData::SetInteger(long tValue)
{
	// Reset the value.
	PushLevel();
	value = tValue;
	PopLevel();

	// Return success.
	return (ZAF_ERROR_NONE);
}

ZafError ZafIntegerData::SetInteger(const ZafIChar *buffer, const ZafIChar *format)
{
	// Reset the value.
	PushLevel();
	if (!buffer || !buffer[0])
		Clear();
	else if (!Sscanf(buffer, (format && format[0]) ? format : zafLocale->integerStringInputFormat))
		SetError(ZAF_ERROR_INVALID);
	else
		SetError(ZAF_ERROR_NONE);
	PopLevel();

	// Return the error status.
	return (Error());
}

ZafError ZafIntegerData::SetInteger(const ZafIntegerData &number)
{
	// Reset the value.
	PushLevel();
	value = number.value;
	PopLevel();

	// Return success.
	return (ZAF_ERROR_NONE);
}

// ----- Operators ----------------------------------------------------------

ZafIntegerData ZafIntegerData::operator++(void)
{
	// Reset the value.
	PushLevel();
	*this += 1;
	PopLevel();

	// Return a reference pointer.
	return *this;
}

ZafIntegerData ZafIntegerData::operator++(int)
{
	// Reset the value.
	PushLevel();
	ZafIntegerData tmp = *this;
	*this += 1;
	PopLevel();

	// Return a temporary reference pointer.
	return tmp;
}

ZafIntegerData ZafIntegerData::operator--(void)
{
	// Reset the value.
	PushLevel();
	*this -= 1;
	PopLevel();

	// Return a reference pointer.
	return *this;
}

ZafIntegerData ZafIntegerData::operator--(int)
{
	// Reset the value.
	PushLevel();
	ZafIntegerData tmp = *this;
	*this -= 1;
	PopLevel();

	// Return a temporary reference pointer.
	return tmp;
}

ZafIntegerData &ZafIntegerData::operator=(ZafIntegerData &tValue)
{
	// Reset the value.
	PushLevel();
	value = tValue.value;
	PopLevel();

	// Return a reference pointer.
	return (*this);
}

ZafIntegerData &ZafIntegerData::operator=(long tValue)
{
	// Reset the value.
	PushLevel();
	value = tValue;
	PopLevel();

	// Return a reference pointer.
	return (*this);
}

ZafIntegerData &ZafIntegerData::operator+=(long tValue)
{
	// Reset the value.
	PushLevel();
	value += tValue;
	PopLevel();

	// Return a reference pointer.
	return (*this);
}

ZafIntegerData &ZafIntegerData::operator-=(long tValue)
{
	// Reset the value.
	PushLevel();
	value -= tValue;
	PopLevel();

	// Return a reference pointer.
	return (*this);
}

ZafIntegerData &ZafIntegerData::operator*=(long tValue)
{
	// Reset the value.
	PushLevel();
	value *= tValue;
	PopLevel();

	// Return a reference pointer.
	return (*this);
}

ZafIntegerData &ZafIntegerData::operator/=(long tValue)
{
	// Reset the value.
	PushLevel();
	value /= tValue;
	PopLevel();

	// Return a reference pointer.
	return (*this);
}

ZafIntegerData &ZafIntegerData::operator%=(long tValue)
{
	// Reset the value.
	PushLevel();
	value %= tValue;
	PopLevel();

	// Return a reference pointer.
	return (*this);
}

// ----- sprintf/sscanf functions -------------------------------------------

//	The rest of this file is modified from a version of vfprintf.c obtained
//	from the Berkeley Source Tree administered by The Regents of the
//	University of California (the "Regents")
//
//	Modifications made by Zinc are:
//	  COPYRIGHT (C) 1994-1999.  All Rights Reserved.
//	  Zinc Software Incorporated.  Pleasant Grove, Utah  USA
//
//	Permission from the Regents is conditioned on inclusion of the following
//	notice from the Regents which applies only to vfprintf.c:
//
//	  Copyright (c) 1990 The Regents of the University of California.
//	  All rights reserved.
//
//	  This code is derived from software contributed to Berkeley by
//	  Chris Torek.
//
//	  Redistribution and use in source and binary forms, with or without
//	  modification, are permitted provided that the following conditions
//	  are met:
//	  1. Redistributions of source code must retain the above copyright
//	     notice, this list of conditions and the following disclaimer.
//	  2. Redistributions in binary form must reproduce the above copyright
//	     notice, this list of conditions and the following disclaimer in the
//	     documentation and/or other materials provided with the distribution.
//	  3. All advertising materials mentioning features or use of this software
//	     must display the following acknowledgement:
//	       This product includes software developed by the University of
//	       California, Berkeley and its contributors.
//	  4. Neither the name of the University nor the names of its contributors
//	     may be used to endorse or promote products derived from this software
//	     without specific prior written permission.
//
//	  THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
//	  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
//	  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
//	  ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
//	  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
//	  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
//	  OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
//	  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
//	  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
//	  OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
//	  SUCH DAMAGE.

//-----------------------------------------------------------------------------
#define LENGTHOF(x)	((int)(sizeof(x)/sizeof((x)[0])))
static unsigned long ZAF_FARDATA POT[] =
{
	10L,
	100L,
	1000L,
	10000L,
	100000L,
	1000000L,
	10000000L,
	100000000L,
	1000000000L,
};
// For Octal numbers (always in Arabic numerals)
#define to_char(n)	((n) + '0')

/*
 * To extend shorts properly, we need both signed and unsigned
 * argument extraction methods.
 */
#define	SARG() \
	(flags&ZAF_LONGINT ? va_arg(*argList, long) : \
	    flags&ZAF_SHORTINT ? (long)(short)va_arg(*argList, int) : \
	    (long)va_arg(*argList, int))
#define	UARG() \
	(flags&ZAF_LONGINT ? va_arg(*argList, unsigned long) : \
	    flags&ZAF_SHORTINT ? (unsigned long)(unsigned short)va_arg(*argList, int) : \
	    (unsigned long)va_arg(*argList, int))
#define	BUF		40
#define	PRINT(ptr, len) strncpy(buffer, ptr, (size_t)len), buffer += len;
#define	PAD(howmany, with) { \
	n = (howmany); \
	while (n > 0) { \
		*(buffer)++ = with; \
		n--; \
	} \
}

typedef unsigned long U_QUAD_T;
typedef long QUAD_T;
static ZafIChar _intSpaceString[] 	= { ' ', 0 };
static ZafIChar _intBlankString[] 	= { 0 };

void ZafIntegerData::Format(va_list *argList, ZafIChar **ptrBuffer,
	ZafIChar fmtch, int flags, int width, int prec)
{
	ZafIChar *buffer = *ptrBuffer;
	ZafIChar buf[BUF];
	ZafIChar *cp = buf;
	*cp = '\0';
	char *xdigs = ZAF_NULLP(char); // digits for [xX] conversion
	enum { OCT, DEC, HEX } base = DEC; // base for [diouxX] conversion
	if (fmtch == 'D')
	{
		flags |= ZAF_LONGINT;
		fmtch = 'd';
	}
	else if (fmtch == 'O')
	{
		flags |= ZAF_LONGINT;
		fmtch = 'o';
	}	
	else if (fmtch == 'U')
	{
		flags |= ZAF_LONGINT;
		fmtch = 'u';
	}
	U_QUAD_T _uquad = 0; // integer arguments %[diouxX]
	if (flags & ZAF_OBJ)
	{
		ZafIntegerData *tmp = va_arg(*argList, ZafIntegerData *);
		_uquad = (U_QUAD_T)tmp->value;
	}
	bool sign = false;
	switch (fmtch)
	{
	case 'd':
	case 'i':
		if (!(flags & ZAF_OBJ))
			_uquad = (U_QUAD_T)SARG();
		if ((QUAD_T)_uquad < 0)
		{
			_uquad = (U_QUAD_T)(-(QUAD_T)_uquad);
			sign = true;
		}
		base = DEC;
		break;
	case 'o':
		if (!(flags & ZAF_OBJ))
			_uquad = UARG();
		base = OCT;
		break;
	case 'u':
		if (!(flags & ZAF_OBJ))
			_uquad = UARG();
		base = DEC;
		break;
	case 'X':
		if (!(flags & ZAF_OBJ))
			_uquad = UARG();
		base = HEX;
		xdigs = "0123456789ABCDEFX";
		if (flags & ZAF_ALT && _uquad != 0)
			flags |= ZAF_HEXPREFIX;
		break;
	case 'x':
		if (!(flags & ZAF_OBJ))
			_uquad = UARG();
		base = HEX;
		xdigs = "0123456789abcdefx";
		/* leading 0x/X only if non-zero */
		if (flags & ZAF_ALT && _uquad != 0)
			flags |= ZAF_HEXPREFIX;
		break;
	}
	const ZafIChar *ps1, *pc, *ps, *ps2;
	const ZafIChar *ss2, *ss, *sc, *ss1;
	const ZafIChar *t;
	//*** const ZafIChar *cm;
	//*** const char *gp; int oldgp;
	ps1 = pc = ps = ps2 = ss1 = sc = ss = ss2 = _intBlankString;
	if (flags & ZAF_CURRENCYx)
	{
		//*** cm = zafLocale->data.monThousandsSeparator;
		//*** gp = zafLocale->data.monGrouping;
		if (sign)
		{
			if (zafLocale->negCurrencyPrecedes)
			{
				pc = zafLocale->currencySymbol;
				if (zafLocale->negSpaceSeparation)
					ps = _intSpaceString;
			}
			else
			{
				sc = zafLocale->currencySymbol;
				if (zafLocale->negSpaceSeparation)
					ss = _intSpaceString;
			}
		}
		else
		{
			if (zafLocale->posCurrencyPrecedes)
			{
				pc = zafLocale->currencySymbol;
				if (zafLocale->posSpaceSeparation)
					ps = _intSpaceString;
			}
			else
			{
				sc = zafLocale->currencySymbol;
				if (zafLocale->posSpaceSeparation)
					ss = _intSpaceString;
			}
		}
	}
	else
	{
		//*** cm = zafLocale->thousandsSeparator;
		//*** gp = zafLocale->grouping;
	}
	/*
	 * ``... diouXx conversions ... if a precision is
	 * specified, the 0 flag will be ignored.''
	 *	-- ANSI X3J11
	 */
	int dprec;
	if ((dprec = prec) >= 0)
		flags &= ~ZAF_ZEROPAD;
	/*
	 * ``The result of converting a zero value with an
	 * explicit precision of zero is no characters.''
	 *	-- ANSI X3J11
	 */
	cp = buf + BUF;
	if (_uquad != 0 || prec != 0) {
		/*
		 * Unsigned mod is hard, and unsigned mod
		 * by a constant is easier than that by
		 * a variable; hence this switch.
		 */
		switch (base) {
		case OCT:
			do {
				*--cp = (char)to_char(_uquad & 7);
				_uquad >>= 3;
			} while (_uquad);
			/* handle octal leading 0 */
			if (flags & ZAF_ALT && *cp != '0')
				*--cp = '0';
			break;
		case DEC:
			{
			ZafIChar *useDigits = (flags & ZAF_ALT_DIGITS ? zafLocale->altDigits : zafLocale->defDigits);
			if (_uquad == 0)
			{
				*--cp = useDigits[0];
				break;
			}
			bool dontUsePOT = false;
			int i = 0;
			for (; i < LENGTHOF(POT); i++)
				if (useDigits[10+i] == 0)
				{
					dontUsePOT = (bool)(POT[i] <= _uquad);
					break;
				}
			i = 10;
			do {
				int tmp = (int)(_uquad % 10);
				if (dontUsePOT || (tmp != 0 && !(tmp == 1 && i == 12 && (_uquad / 10 == 0))))
					*--cp = useDigits[tmp];
				_uquad /= 10;
				if (!dontUsePOT && (_uquad % 10))
					*--cp = useDigits[i];
				i++;
			} while (_uquad);
			}
			break;
		case HEX:
			do {
				*--cp = xdigs[(int)(_uquad & 15)];
				_uquad >>= 4;
			} while (_uquad);
			break;
		}
	}
	int size = BUF - (int)(cp - buf);
	int fieldsz = size;
	int i;
	if (sign)
	{
		i = zafLocale->negSignPrecedes;
		t = zafLocale->negativeSign;
		if (flags & ZAF_CREDIT)
			i = 0;
	}
	else
	{
		i = zafLocale->posSignPrecedes;
		if (flags & ZAF_PLUS)
			t = zafLocale->positiveSign;
		else
			t = _intBlankString;
	}
	switch (i)
	{
	case 0:
		if (sign)
		{
			ps1 = zafLocale->creditLeftParen;
			ss1 = zafLocale->creditRightParen;
		}
		else
		{
			ps1 = ps2 = _intSpaceString;
		}
		break;
	case 1:
		ps1 = t;
		break;
	case 2:
		ps2 = t;
		break;
	case 3:
		ss2 = t;
		break;
	case 4:
		ss1 = t;
		break;
	}
	fieldsz = (int)(fieldsz + strlen(ps1) + strlen(ps2) + strlen(ss1) + strlen(ss2));
	if (flags & ZAF_HEXPREFIX)
		fieldsz += 2;
	int n;	// Scratch for PAD();
	/* right-adjusting blank padding */
	if ((flags & (ZAF_LADJUST | ZAF_ZEROPAD)) == 0)
		PAD(width - ((dprec > fieldsz) ? dprec : fieldsz), ' ');
	// prefix
	PRINT(ps1, strlen(ps1));
	PRINT(pc, strlen(pc));
	PRINT(ps, strlen(ps));
	PRINT(ps2, strlen(ps2));
	if (flags & ZAF_HEXPREFIX)
	{
		PAD(1, '0');
		PAD(1, xdigs[16]);
	}
	/* right-adjusting zero padding */
	if ((flags & (ZAF_LADJUST | ZAF_ZEROPAD)) == ZAF_ZEROPAD)
		PAD(width - fieldsz, '0');
	/* leading zeroes from decimal precision */
	PAD(dprec - fieldsz, '0');
	/* the string or number proper */
	PRINT(cp, size);
	/* left-adjusting padding (always blank) */
	if (flags & ZAF_LADJUST)
		PAD(width - fieldsz, ' ');
	// suffix
	PRINT(ss2, strlen(ss2));
	PRINT(ss, strlen(ss));
	PRINT(sc, strlen(sc));
	PRINT(ss1, strlen(ss1));
	*buffer = 0;
	*ptrBuffer = buffer;
}

#if defined(_SUNOS4) && !defined(ZAF_UNICODE)
unsigned long strtoul(const ZafIChar *str, ZafIChar **ptr, int base)
{
	return (unsigned long)strtol(str, ptr, base);
}
#endif

int ZafIntegerData::Parse(va_list *argList, ZafIChar **ptrBuffer,
	ZafIChar fmtch, int flags, int width, const ZafIChar **fmt)
{
	/* `basefix' is used to avoid `if' tests in the integer scanner */
	static short basefix[17] =
		{ 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
	int base = 10;		// base argument to strtol/strtoul

	ZafIChar *buffer = *ptrBuffer;
	ZafIChar buf[BUF];
	/* scan an integer as if by strtol/strtoul */
	if (width == 0 || width > LENGTHOF(buf) - 1)
		width = LENGTHOF(buf) - 1;

//???	width++;
	// conversion function (strtol/strtoul)
	bool useStrtol = false;
	bool useStrtoul = false;
	if (isupper(fmtch))
		flags |= ZAF_LONGVAL;
	switch (fmtch)
	{
	case 'D':
	case 'd':
		useStrtol = true;
		base = 10;
		break;
	case 'u':
		useStrtoul = true;
		base = 10;
		break;
	case 'i':
		useStrtol = true;
		base = 0;
		break;
	case 'O':
	case 'o':
		useStrtoul = true;
		base = 8;
		break;
	case 'X':
	case 'x':
		flags |= ZAF_PFXOK;
		useStrtoul = true;
		base = 16;
		break;
	}
	if ((flags & ZAF_NOSKIP) == 0)
		while (isspace(*buffer))
			buffer++;
	bool sign = false;
	bool paren = false;
	if (*buffer == '(')
	{
		sign = true;
		paren = true;
		buffer++;
	}
	flags |= ZAF_SIGNOK | ZAF_NDIGITS | ZAF_NZDIGITS;
	ZafIChar *p;
	for (p = buf; width; width--)
	{
		ZafIChar c = *buffer++;
		/*
		 * Switch on the character; `goto ok'
		 * if we accept it as a part of number.
		 */
		switch (c)
		{
		/*
		 * The digit 0 is always legal, but is
		 * special.  For %i conversions, if no
		 * digits (zero or nonzero) have been
		 * scanned (only signs), we will have
		 * base==0.  In that case, we should set
		 * it to 8 and enable 0x prefixing.
		 * Also, if we have not scanned zero digits
		 * before this, do not turn off prefixing
		 * (someone else will turn it off if we
		 * have scanned any nonzero digits).
		 */
		case '0':
			if (base == 0)
			{
				base = 8;
				flags |= ZAF_PFXOK;
			}
			if (flags & ZAF_NZDIGITS)
				flags &= ~(ZAF_SIGNOK | ZAF_NZDIGITS | ZAF_NDIGITS);
			else
				flags &= ~(ZAF_SIGNOK | ZAF_PFXOK | ZAF_NDIGITS);
			goto ok;

		/* 1 through 7 always legal */
		case '1': case '2': case '3':
		case '4': case '5': case '6': case '7':
			base = basefix[base];
			flags &= ~(ZAF_SIGNOK | ZAF_PFXOK | ZAF_NDIGITS);
			goto ok;
			/* digits 8 and 9 ok iff decimal or hex */
		case '8': case '9':
			base = basefix[base];
			if (base <= 8)
				break;	/* not legal here */
			flags &= ~(ZAF_SIGNOK | ZAF_PFXOK | ZAF_NDIGITS);
			goto ok;
			/* letters ok iff hex */
		case 'A': case 'B': case 'C':
		case 'D': case 'E': case 'F':
		case 'a': case 'b': case 'c':
		case 'd': case 'e': case 'f':
			/* no need to fix base here */
			if (base <= 10)
				break;	/* not legal here */
			flags &= ~(ZAF_SIGNOK | ZAF_PFXOK | ZAF_NDIGITS);
			goto ok;
			/* sign ok only as first character */
		case '+': case '-': 
			if (flags & ZAF_SIGNOK)
			{
				flags &= ~ZAF_SIGNOK;
				goto ok;
			}
			break;
			/* x ok if flag still set & 2nd char */
		case 'x': case 'X':
			if (flags & ZAF_PFXOK && p == buf + 1)
			{
				base = 16;	/* if %i */
				flags &= ~ZAF_PFXOK;
				goto ok;
			}
			break;
			default:
				buffer--; //Unrecognized character.
		}
		/*
		 * If we got here, c is not a legal character
		 * for a number.  Stop accumulating digits.
		 */
		if (!c || isspace(c) || c == **fmt)
			break;
		else if (c == ')' && paren)
		{
			buffer++;
			break;
		}
		else
			return (-1);
ok:
		/*
		 * c is legal: store it and look at the next.
		 */
		*p++ = c;
	}
	/*
	 * If we had only a sign, it is no good; push
	 * back the sign.  If the number ends in `x',
	 * it was [sign] '0' 'x', so push back the x
	 * and treat it as [sign] '0'.
	 */
	if (flags & ZAF_NDIGITS)
	{
		if (p > buf)
			*--buffer = *--p;
		*ptrBuffer = buffer;
		return -1;
	}
	ZafIChar c = ((ZafIChar *)p)[-1];
	if (c == 'x' || c == 'X')
	{
		--p;
		*--buffer = c;
	}
	if ((flags & ZAF_SUPPRESS) == 0)
	{
		unsigned long res = 0;
		*p = 0;
		// Compensate for bug in strtol and strtoul.
		if (buf[0] == '-' && buf[1]== '0')
		{
			p = &buf[2];
			while (*p == '0')
				p++;
			if (*p == '\0')
				useStrtol = useStrtoul = false;
		}
		if (useStrtol)
		{
			res = (unsigned long)strtol(buf, ZAF_NULLP(ZafIChar *), (int)base);
		}
		if (useStrtoul)
			res = strtoul(buf, ZAF_NULLP(ZafIChar *), base);
		if (sign)
			res = (unsigned long)(-(long)res);
		if (flags & ZAF_OBJ)
		{
			ZafIntegerData *tmp = va_arg(*argList, ZafIntegerData *);
			tmp->value = (long)res;
		}
		else if (flags & ZAF_POINTER)
			*va_arg(*argList, void **) = (void *)res;
		else if (flags & ZAF_SHORTVAL)
			*va_arg(*argList, short *) = (short)res;
		else if (flags & ZAF_LONGVAL)
			*va_arg(*argList, long *) = (long)res;
		else
			*va_arg(*argList, int *) = (int)res;
		*ptrBuffer = buffer;
		return 1;
	}
	*ptrBuffer = buffer;
	return 0;
}

// ----- Persistent functions -----------------------------------------------
#if defined(USE_ZAF_PERSISTENCE)
ZafIntegerData::ZafIntegerData(const ZafIChar *name, ZafDataPersistence &persist) :
	ZafFormatData(name, persist.PushLevel(className, classID, ZAF_PERSIST_FILE))
{
	Bind();

	// Read the data.
	if (persist.Error() == ZAF_ERROR_NONE)
		ZafIntegerData::ReadData(persist);

	persist.PopLevel();
	if (persist.Error() != ZAF_ERROR_NONE)
		SetError(persist.Error());
}

ZafElement *ZafIntegerData::Read(const ZafIChar *name, ZafDataPersistence &persist)
{
	return (new ZafIntegerData(name, persist));
}

void ZafIntegerData::ReadData(ZafDataPersistence &persist)
{
	// Read the data.
	ZafInt32 tValue;
	ZafFile *file = persist.CurrentFile();
	*file >> tValue;
	value = tValue;
}

void ZafIntegerData::Write(ZafDataPersistence &persist)
{
	// Write the object.
	ZafFormatData::Write(persist.PushLevel(className, classID, ZAF_PERSIST_FILE));
	if (persist.Error() == ZAF_ERROR_NONE)
		ZafIntegerData::WriteData(persist);
	persist.PopLevel();
	if (persist.Error() != ZAF_ERROR_NONE)
		SetError(persist.Error());
}

void ZafIntegerData::WriteData(ZafDataPersistence &persist)
{
	// Write the data.
	ZafInt32 tValue = value;
	ZafFile *file = persist.CurrentFile();
	*file << tValue;
}
#endif
