ref: 67757267d0b9c6b15a0f9a87abab74ab152d9b09
dir: /utility.c/
#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);
}
}