shithub: 9ficl

ref: 7d02e382d314d5bdde7978ccb7a64ea9201d03db
dir: 9ficl/utility.c

View raw version
#include <ctype.h>

#include "ficl.h"


/**************************************************************************
                        a l i g n P t r
** Aligns the given pointer to FICL_ALIGN address units.
** Returns the aligned pointer value.
**************************************************************************/
void *ficlAlignPointer(void *ptr)
{
#if FICL_PLATFORM_ALIGNMENT > 1
	intptr_t p = (intptr_t)ptr;
	if (p & (FICL_PLATFORM_ALIGNMENT - 1))
		ptr = (void *)((p & ~(FICL_PLATFORM_ALIGNMENT - 1)) + FICL_PLATFORM_ALIGNMENT);
#endif
    return ptr;
}


/**************************************************************************
                        s t r r e v
** 
**************************************************************************/
char *ficlStringReverse( char *string )    
{                               /* reverse a string in-place */
    int i = strlen(string);
    char *p1 = string;          /* first char of string */
    char *p2 = string + i - 1;  /* last non-NULL char of string */
    char c;

    if (i > 1)
    {
        while (p1 < p2)
        {
            c = *p2;
            *p2 = *p1;
            *p1 = c;
            p1++; p2--;
        }
    }
        
    return string;
}


/**************************************************************************
                        d i g i t _ t o _ c h a r
** 
**************************************************************************/
static char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";

char ficlDigitToCharacter(int value)
{
    return digits[value];
}


/**************************************************************************
                        i s P o w e r O f T w o
** Tests whether supplied argument is an integer power of 2 (2**n)
** where 32 > n > 1, and returns n if so. Otherwise returns zero.
**************************************************************************/
int ficlIsPowerOfTwo(ficlUnsigned u)
{
    int i = 1;
    ficlUnsigned t = 2;

    for (; ((t <= u) && (t != 0)); i++, t <<= 1)
    {
        if (u == t)
            return i;
    }

    return 0;
}


/**************************************************************************
                        l t o a
** 
**************************************************************************/
char *ficlLtoa( ficlInteger value, char *string, int radix )
{                               /* convert long to string, any base */
    char *cp = string;
    int sign = ((radix == 10) && (value < 0));
    int pwr;

    FICL_ASSERT(NULL, radix > 1);
    FICL_ASSERT(NULL, radix < 37);
    FICL_ASSERT(NULL, string);

    pwr = ficlIsPowerOfTwo((ficlUnsigned)radix);

    if (sign)
        value = -value;

    if (value == 0)
        *cp++ = '0';
    else if (pwr != 0)
    {
        ficlUnsigned v = (ficlUnsigned) value;
        ficlUnsigned mask = (ficlUnsigned) ~(-1 << pwr);
        while (v)
        {
            *cp++ = digits[v & mask];
            v >>= pwr;
        }
    }
    else
    {
        ficl2UnsignedQR result;
        ficl2Unsigned v;
		FICL_UNSIGNED_TO_2UNSIGNED((ficlUnsigned)value, v);
        while (FICL_2UNSIGNED_NOT_ZERO(v))
        {
            result = ficl2UnsignedDivide(v, (ficlUnsigned)radix);
            *cp++ = digits[result.remainder];
			v = result.quotient;
        }
    }

    if (sign)
        *cp++ = '-';

    *cp++ = '\0';

    return ficlStringReverse(string);
}


/**************************************************************************
                        u l t o a
** 
**************************************************************************/
char *ficlUltoa(ficlUnsigned value, char *string, int radix )
{                               /* convert long to string, any base */
    char *cp = string;
    ficl2Unsigned ud;
    ficl2UnsignedQR result;

    FICL_ASSERT(NULL, radix > 1);
    FICL_ASSERT(NULL, radix < 37);
    FICL_ASSERT(NULL, string);

    if (value == 0)
        *cp++ = '0';
    else
    {
		FICL_UNSIGNED_TO_2UNSIGNED(value, ud);
        while (FICL_2UNSIGNED_NOT_ZERO(ud))
        {
            result = ficl2UnsignedDivide(ud, (ficlUnsigned)radix);
			ud = result.quotient;
            *cp++ = digits[result.remainder];
        }
    }

    *cp++ = '\0';

    return ficlStringReverse(string);
}


/**************************************************************************
                        c a s e F o l d
** Case folds a NULL terminated string in place. All characters
** get converted to lower case.
**************************************************************************/
char *ficlStringCaseFold(char *cp)
{
    char *oldCp = cp;

    while (*cp)
    {
        if (isupper((unsigned char)*cp))
            *cp = (char)tolower((unsigned char)*cp);
        cp++;
    }

    return oldCp;
}


/**************************************************************************
                        s t r i n c m p
** (jws) simplified the code a bit in hopes of appeasing Purify
**************************************************************************/
int ficlStrincmp(char *cp1, char *cp2, ficlUnsigned count)
{
    int i = 0;

    for (; 0 < count; ++cp1, ++cp2, --count)
    {
        i = tolower((unsigned char)*cp1) - tolower((unsigned char)*cp2);
        if (i != 0)
            return i;
        else if (*cp1 == '\0')
            return 0;
    }
    return 0;
}

/**************************************************************************
                        s k i p S p a c e
** Given a string pointer, returns a pointer to the first non-space
** char of the string, or to the NULL terminator if no such char found.
** If the pointer reaches "end" first, stop there. Pass NULL to 
** suppress this behavior.
**************************************************************************/
char *ficlStringSkipSpace(char *cp, char *end)
{
    FICL_ASSERT(NULL, cp);

    while ((cp != end) && isspace((unsigned char)*cp))
        cp++;

    return cp;
}





void ficlCompatibilityTextOutCallback(ficlCallback *callback, char *text, ficlCompatibilityOutputFunction outputFunction)
{
	char buffer[256];
	char *bufferStop = buffer + sizeof(buffer) - 1;

	if (text == NULL)
	{
		outputFunction(callback->vm, NULL, 0 /* false */);
		return;
	}

	while (*text)
	{
		int newline = 0 /* false */;
		char *trace = buffer;
		while ((*text) && (trace < bufferStop))
		{
			switch (*text)
			{
				/* throw away \r */
				case '\r':
					text++;
					continue;
				case '\n':
					text++;
					newline = !0 /* true */;
					break;
				default:
					*trace++ = *text++;
					break;
			}
		}
		
		*trace = 0;
		(outputFunction)(callback->vm, buffer, newline);
	}
}