301 lines
5.8 KiB
C
301 lines
5.8 KiB
C
|
/* tmbstr.c -- Tidy string utility functions
|
||
|
|
||
|
(c) 1998-2006 (W3C) MIT, ERCIM, Keio University
|
||
|
See tidy.h for the copyright notice.
|
||
|
|
||
|
*/
|
||
|
|
||
|
#include "forward.h"
|
||
|
#include "tmbstr.h"
|
||
|
#include "lexer.h"
|
||
|
|
||
|
/* like strdup but using an allocator */
|
||
|
tmbstr TY_(tmbstrdup)( TidyAllocator *allocator, ctmbstr str )
|
||
|
{
|
||
|
tmbstr s = NULL;
|
||
|
if ( str )
|
||
|
{
|
||
|
uint len = TY_(tmbstrlen)( str );
|
||
|
tmbstr cp = s = (tmbstr) TidyAlloc( allocator, 1+len );
|
||
|
while ( 0 != (*cp++ = *str++) )
|
||
|
/**/;
|
||
|
}
|
||
|
return s;
|
||
|
}
|
||
|
|
||
|
/* like strndup but using an allocator */
|
||
|
tmbstr TY_(tmbstrndup)( TidyAllocator *allocator, ctmbstr str, uint len )
|
||
|
{
|
||
|
tmbstr s = NULL;
|
||
|
if ( str && len > 0 )
|
||
|
{
|
||
|
tmbstr cp = s = (tmbstr) TidyAlloc( allocator, 1+len );
|
||
|
while ( len-- > 0 && (*cp++ = *str++) )
|
||
|
/**/;
|
||
|
*cp = 0;
|
||
|
}
|
||
|
return s;
|
||
|
}
|
||
|
|
||
|
/* exactly same as strncpy */
|
||
|
uint TY_(tmbstrncpy)( tmbstr s1, ctmbstr s2, uint size )
|
||
|
{
|
||
|
if ( s1 != NULL && s2 != NULL )
|
||
|
{
|
||
|
tmbstr cp = s1;
|
||
|
while ( *s2 && --size ) /* Predecrement: reserve byte */
|
||
|
*cp++ = *s2++; /* for NULL terminator. */
|
||
|
*cp = 0;
|
||
|
}
|
||
|
return size;
|
||
|
}
|
||
|
|
||
|
/* Allows expressions like: cp += tmbstrcpy( cp, "joebob" );
|
||
|
*/
|
||
|
uint TY_(tmbstrcpy)( tmbstr s1, ctmbstr s2 )
|
||
|
{
|
||
|
uint ncpy = 0;
|
||
|
while (0 != (*s1++ = *s2++) )
|
||
|
++ncpy;
|
||
|
return ncpy;
|
||
|
}
|
||
|
|
||
|
/* Allows expressions like: cp += tmbstrcat( cp, "joebob" );
|
||
|
*/
|
||
|
uint TY_(tmbstrcat)( tmbstr s1, ctmbstr s2 )
|
||
|
{
|
||
|
uint ncpy = 0;
|
||
|
while ( *s1 )
|
||
|
++s1;
|
||
|
|
||
|
while (0 != (*s1++ = *s2++) )
|
||
|
++ncpy;
|
||
|
return ncpy;
|
||
|
}
|
||
|
|
||
|
/* exactly same as strcmp */
|
||
|
int TY_(tmbstrcmp)( ctmbstr s1, ctmbstr s2 )
|
||
|
{
|
||
|
int c;
|
||
|
while ((c = *s1) == *s2)
|
||
|
{
|
||
|
if (c == '\0')
|
||
|
return 0;
|
||
|
|
||
|
++s1;
|
||
|
++s2;
|
||
|
}
|
||
|
|
||
|
return (*s1 > *s2 ? 1 : -1);
|
||
|
}
|
||
|
|
||
|
/* returns byte count, not char count */
|
||
|
uint TY_(tmbstrlen)( ctmbstr str )
|
||
|
{
|
||
|
uint len = 0;
|
||
|
if ( str )
|
||
|
{
|
||
|
while ( *str++ )
|
||
|
++len;
|
||
|
}
|
||
|
return len;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
MS C 4.2 doesn't include strcasecmp.
|
||
|
Note that tolower and toupper won't
|
||
|
work on chars > 127.
|
||
|
|
||
|
Neither does ToLower()!
|
||
|
*/
|
||
|
int TY_(tmbstrcasecmp)( ctmbstr s1, ctmbstr s2 )
|
||
|
{
|
||
|
uint c;
|
||
|
|
||
|
while (c = (uint)(*s1), TY_(ToLower)(c) == TY_(ToLower)((uint)(*s2)))
|
||
|
{
|
||
|
if (c == '\0')
|
||
|
return 0;
|
||
|
|
||
|
++s1;
|
||
|
++s2;
|
||
|
}
|
||
|
|
||
|
return (*s1 > *s2 ? 1 : -1);
|
||
|
}
|
||
|
|
||
|
int TY_(tmbstrncmp)( ctmbstr s1, ctmbstr s2, uint n )
|
||
|
{
|
||
|
uint c;
|
||
|
|
||
|
while ((c = (byte)*s1) == (byte)*s2)
|
||
|
{
|
||
|
if (c == '\0')
|
||
|
return 0;
|
||
|
|
||
|
if (n == 0)
|
||
|
return 0;
|
||
|
|
||
|
++s1;
|
||
|
++s2;
|
||
|
--n;
|
||
|
}
|
||
|
|
||
|
if (n == 0)
|
||
|
return 0;
|
||
|
|
||
|
return (*s1 > *s2 ? 1 : -1);
|
||
|
}
|
||
|
|
||
|
int TY_(tmbstrncasecmp)( ctmbstr s1, ctmbstr s2, uint n )
|
||
|
{
|
||
|
uint c;
|
||
|
|
||
|
while (c = (uint)(*s1), TY_(ToLower)(c) == TY_(ToLower)((uint)(*s2)))
|
||
|
{
|
||
|
if (c == '\0')
|
||
|
return 0;
|
||
|
|
||
|
if (n == 0)
|
||
|
return 0;
|
||
|
|
||
|
++s1;
|
||
|
++s2;
|
||
|
--n;
|
||
|
}
|
||
|
|
||
|
if (n == 0)
|
||
|
return 0;
|
||
|
|
||
|
return (*s1 > *s2 ? 1 : -1);
|
||
|
}
|
||
|
|
||
|
#if 0
|
||
|
/* return offset of cc from beginning of s1,
|
||
|
** -1 if not found.
|
||
|
*/
|
||
|
int TY_(tmbstrnchr)( ctmbstr s1, uint maxlen, tmbchar cc )
|
||
|
{
|
||
|
int i;
|
||
|
ctmbstr cp = s1;
|
||
|
|
||
|
for ( i = 0; (uint)i < maxlen; ++i, ++cp )
|
||
|
{
|
||
|
if ( *cp == cc )
|
||
|
return i;
|
||
|
}
|
||
|
|
||
|
return -1;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
ctmbstr TY_(tmbsubstrn)( ctmbstr s1, uint len1, ctmbstr s2 )
|
||
|
{
|
||
|
uint len2 = TY_(tmbstrlen)(s2);
|
||
|
int ix, diff = len1 - len2;
|
||
|
|
||
|
for ( ix = 0; ix <= diff; ++ix )
|
||
|
{
|
||
|
if ( TY_(tmbstrncmp)(s1+ix, s2, len2) == 0 )
|
||
|
return (ctmbstr) s1+ix;
|
||
|
}
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
#if 0
|
||
|
ctmbstr TY_(tmbsubstrncase)( ctmbstr s1, uint len1, ctmbstr s2 )
|
||
|
{
|
||
|
uint len2 = TY_(tmbstrlen)(s2);
|
||
|
int ix, diff = len1 - len2;
|
||
|
|
||
|
for ( ix = 0; ix <= diff; ++ix )
|
||
|
{
|
||
|
if ( TY_(tmbstrncasecmp)(s1+ix, s2, len2) == 0 )
|
||
|
return (ctmbstr) s1+ix;
|
||
|
}
|
||
|
return NULL;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
ctmbstr TY_(tmbsubstr)( ctmbstr s1, ctmbstr s2 )
|
||
|
{
|
||
|
uint len1 = TY_(tmbstrlen)(s1), len2 = TY_(tmbstrlen)(s2);
|
||
|
int ix, diff = len1 - len2;
|
||
|
|
||
|
for ( ix = 0; ix <= diff; ++ix )
|
||
|
{
|
||
|
if ( TY_(tmbstrncasecmp)(s1+ix, s2, len2) == 0 )
|
||
|
return (ctmbstr) s1+ix;
|
||
|
}
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
/* Transform ASCII chars in string to lower case */
|
||
|
tmbstr TY_(tmbstrtolower)( tmbstr s )
|
||
|
{
|
||
|
tmbstr cp;
|
||
|
for ( cp=s; *cp; ++cp )
|
||
|
*cp = (tmbchar) TY_(ToLower)( *cp );
|
||
|
return s;
|
||
|
}
|
||
|
|
||
|
/* Transform ASCII chars in string to upper case */
|
||
|
tmbstr TY_(tmbstrtoupper)(tmbstr s)
|
||
|
{
|
||
|
tmbstr cp;
|
||
|
|
||
|
for (cp = s; *cp; ++cp)
|
||
|
*cp = (tmbchar)TY_(ToUpper)(*cp);
|
||
|
|
||
|
return s;
|
||
|
}
|
||
|
|
||
|
#if 0
|
||
|
Bool TY_(tmbsamefile)( ctmbstr filename1, ctmbstr filename2 )
|
||
|
{
|
||
|
#if FILENAMES_CASE_SENSITIVE
|
||
|
return ( TY_(tmbstrcmp)( filename1, filename2 ) == 0 );
|
||
|
#else
|
||
|
return ( TY_(tmbstrcasecmp)( filename1, filename2 ) == 0 );
|
||
|
#endif
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
int TY_(tmbvsnprintf)(tmbstr buffer, size_t count, ctmbstr format, va_list args)
|
||
|
{
|
||
|
int retval;
|
||
|
#if HAS_VSNPRINTF
|
||
|
retval = vsnprintf(buffer, count - 1, format, args);
|
||
|
/* todo: conditionally null-terminate the string? */
|
||
|
buffer[count - 1] = 0;
|
||
|
#else
|
||
|
retval = vsprintf(buffer, format, args);
|
||
|
#endif /* HAS_VSNPRINTF */
|
||
|
return retval;
|
||
|
}
|
||
|
|
||
|
int TY_(tmbsnprintf)(tmbstr buffer, size_t count, ctmbstr format, ...)
|
||
|
{
|
||
|
int retval;
|
||
|
va_list args;
|
||
|
va_start(args, format);
|
||
|
#if HAS_VSNPRINTF
|
||
|
retval = vsnprintf(buffer, count - 1, format, args);
|
||
|
/* todo: conditionally null-terminate the string? */
|
||
|
buffer[count - 1] = 0;
|
||
|
#else
|
||
|
retval = vsprintf(buffer, format, args);
|
||
|
#endif /* HAS_VSNPRINTF */
|
||
|
va_end(args);
|
||
|
return retval;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* local variables:
|
||
|
* mode: c
|
||
|
* indent-tabs-mode: nil
|
||
|
* c-basic-offset: 4
|
||
|
* eval: (c-set-offset 'substatement-open 0)
|
||
|
* end:
|
||
|
*/
|