You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

399 lines
8.6 KiB

/*
* jit-string.c - String handling routines.
*
* Copyright (C) 2004 Southern Storm Software, Pty Ltd.
*
* 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 "jit-internal.h"
#include <config.h>
#ifdef HAVE_STRING_H
#include <string.h>
#elif defined(HAVE_STRINGS_H)
#include <strings.h>
#endif
#include <stdio.h>
#ifdef HAVE_STDARG_H
#include <stdarg.h>
#elif HAVE_VARARGS_H
#include <varargs.h>
#endif
/*@
* @section String operations
* @cindex String operations
*
* The following functions are provided to manipulate NULL-terminated
* strings. It is highly recommended that you use these functions in
* preference to system functions, because the corresponding system
* functions are extremely non-portable.
@*/
/*@
* @deftypefun {unsigned int} jit_strlen ({const char *} str)
* Returns the length of @code{str}.
* @end deftypefun
@*/
unsigned int jit_strlen(const char *str)
{
#ifdef HAVE_STRLEN
return (unsigned int)(strlen(str));
#else
unsigned int len = 0;
while(*str++ != '\0')
{
++len;
}
return len;
#endif
}
/*@
* @deftypefun {char *} jit_strcpy ({char *} dest, {const char *} src)
* Copy the string at @code{src} to @code{dest}. Returns @code{dest}.
* @end deftypefun
@*/
char *jit_strcpy(char *dest, const char *src)
{
#ifdef HAVE_STRCPY
return strcpy(dest, src);
#else
char ch;
char *d = dest;
while((ch = *src++) != '\0')
{
*d++ = ch;
}
*d = '\0';
return dest;
#endif
}
/*@
* @deftypefun {char *} jit_strcat ({char *} dest, {const char *} src)
* Copy the string at @code{src} to the end of the string at @code{dest}.
* Returns @code{dest}.
* @end deftypefun
@*/
char *jit_strcat(char *dest, const char *src)
{
#ifdef HAVE_STRCAT
return strcat(dest, src);
#else
char ch;
char *d = dest + jit_strlen(dest);
while((ch = *src++) != '\0')
{
*d++ = ch;
}
*d = '\0';
return dest;
#endif
}
/*@
* @deftypefun {char *} jit_strncpy ({char *} dest, {const char *} src, {unsigned int} len)
* Copy at most @code{len} characters from the string at @code{src} to
* @code{dest}. Returns @code{dest}.
* @end deftypefun
@*/
char *jit_strncpy(char *dest, const char *src, unsigned int len)
{
#ifdef HAVE_STRNCPY
return strncpy(dest, src, len);
#else
char ch;
char *d = dest;
while(len > 0 && (ch = *src++) != '\0')
{
*d++ = ch;
--len;
}
while(len > 0)
{
*d++ = '\0';
--len;
}
return dest;
#endif
}
/*@
* @deftypefun {char *} jit_strdup ({const char *} str)
* Allocate a block of memory using @code{jit_malloc} and copy
* @code{str} into it. Returns NULL if @code{str} is NULL or there
* is insufficient memory to perform the @code{jit_malloc} operation.
* @end deftypefun
@*/
char *jit_strdup(const char *str)
{
char *new_str;
if(!str)
{
return 0;
}
new_str = jit_malloc(strlen(str) + 1);
if(!new_str)
{
return 0;
}
strcpy(new_str, str);
return new_str;
}
/*@
* @deftypefun {char *} jit_strndup ({const char *} str, unsigned int len)
* Allocate a block of memory using @code{jit_malloc} and copy at most
* @code{len} characters of @code{str} into it. The copied string is then
* NULL-terminated. Returns NULL if @code{str} is NULL or there
* is insufficient memory to perform the @code{jit_malloc} operation.
* @end deftypefun
@*/
char *jit_strndup(const char *str, unsigned int len)
{
char *new_str;
if(!str)
{
return 0;
}
new_str = jit_malloc(len + 1);
if(!new_str)
{
return 0;
}
jit_memcpy(new_str, str, len);
new_str[len] = '\0';
return new_str;
}
/*@
* @deftypefun int jit_strcmp ({const char *} str1, {const char *} str2)
* Compare the two strings @code{str1} and @code{str2}, returning
* a negative, zero, or positive value depending upon their relationship.
* @end deftypefun
@*/
int jit_strcmp(const char *str1, const char *str2)
{
#ifdef HAVE_STRCMP
return strcmp(str1, str2);
#else
int ch1, ch2;
for(;;)
{
ch1 = *str1++;
ch2 = *str2++;
if(ch1 != ch2 || !ch1 || !ch2)
{
break;
}
}
return (ch1 - ch2);
#endif
}
/*@
* @deftypefun int jit_strncmp ({const char *} str1, {const char *} str2, {unsigned int} len)
* Compare the two strings @code{str1} and @code{str2}, returning
* a negative, zero, or positive value depending upon their relationship.
* At most @code{len} characters are compared.
* @end deftypefun
@*/
int jit_strncmp(const char *str1, const char *str2, unsigned int len)
{
#ifdef HAVE_STRNCMP
return strncmp(str1, str2, len);
#else
int ch1, ch2;
while(len > 0)
{
ch1 = *str1++;
ch2 = *str2++;
if(ch1 != ch2 || !ch1 || !ch2)
{
return (ch1 - ch2);
}
--len;
}
return 0;
#endif
}
/*@
* @deftypefun int jit_stricmp ({const char *} str1, {const char *} str2)
* Compare the two strings @code{str1} and @code{str2}, returning
* a negative, zero, or positive value depending upon their relationship.
* Instances of the English letters A to Z are converted into their
* lower case counterparts before comparison.
*
* Note: this function is guaranteed to use English case comparison rules,
* no matter what the current locale is set to, making it suitable for
* comparing token tags and simple programming language identifiers.
*
* Locale-sensitive string comparison is complicated and usually specific
* to the front end language or its supporting runtime library. We
* deliberately chose not to handle this in @code{libjit}.
* @end deftypefun
@*/
int jit_stricmp(const char *str1, const char *str2)
{
int ch1, ch2;
for(;;)
{
ch1 = *str1++;
ch2 = *str2++;
if(ch1 >= 'A' && ch1 <= 'Z')
{
ch1 = ch1 - 'A' + 'a';
}
if(ch2 >= 'A' && ch2 <= 'Z')
{
ch2 = ch2 - 'A' + 'a';
}
if(ch1 != ch2 || !ch1 || !ch2)
{
break;
}
}
return (ch1 - ch2);
}
/*@
* @deftypefun int jit_strnicmp ({const char *} str1, {const char *} str2, {unsigned int} len)
* Compare the two strings @code{str1} and @code{str2}, returning
* a negative, zero, or positive value depending upon their relationship.
* At most @code{len} characters are compared. Instances of the English
* letters A to Z are converted into their lower case counterparts
* before comparison.
* @end deftypefun
@*/
int jit_strnicmp(const char *str1, const char *str2, unsigned int len)
{
int ch1, ch2;
while(len > 0)
{
ch1 = *str1++;
ch2 = *str2++;
if(ch1 >= 'A' && ch1 <= 'Z')
{
ch1 = ch1 - 'A' + 'a';
}
if(ch2 >= 'A' && ch2 <= 'Z')
{
ch2 = ch2 - 'A' + 'a';
}
if(ch1 != ch2 || !ch1 || !ch2)
{
return (ch1 - ch2);
}
--len;
}
return 0;
}
/*@
* @deftypefun {char *} jit_strchr ({const char *} str, int ch)
* Search @code{str} for the first occurrence of @code{ch}. Returns
* the address where @code{ch} was found, or NULL if not found.
* @end deftypefun
@*/
char *jit_strchr(const char *str, int ch)
{
#ifdef HAVE_STRCHR
return strchr(str, ch);
#else
char *s = (char *)str;
for(;;)
{
if(*s == (char)ch)
{
return s;
}
else if(*s == '\0')
{
break;
}
++s;
}
return 0;
#endif
}
/*@
* @deftypefun {char *} jit_strrchr ({const char *} str, int ch)
* Search @code{str} for the first occurrence of @code{ch}, starting
* at the end of the string. Returns the address where @code{ch}
* was found, or NULL if not found.
* @end deftypefun
@*/
char *jit_strrchr(const char *str, int ch)
{
#ifdef HAVE_STRRCHR
return strrchr(str, ch);
#else
unsigned int len = jit_strlen(str);
char *s = (char *)(str + len);
while(len > 0)
{
--s;
if(*s == (char)ch)
{
return s;
}
--len;
}
return 0;
#endif
}
int jit_sprintf(char *str, const char *format, ...)
{
va_list va;
int result;
#ifdef HAVE_STDARG_H
va_start(va, format);
#else
va_start(va);
#endif
#ifdef VSPRINTF
result = vsprintf(str, format, va);
#else
*str = '\0';
result = 0;
#endif
va_end(va);
return result;
}
int jit_snprintf(char *str, unsigned int len, const char *format, ...)
{
va_list va;
int result;
#ifdef HAVE_STDARG_H
va_start(va, format);
#else
va_start(va);
#endif
#if defined(HAVE_VSNPRINTF)
result = vsnprintf(str, len, format, va);
#elif defined(HAVE__VSNPRINTF)
result = _vsnprintf(str, len, format, va);
#else
*str = '\0';
result = 0;
#endif
va_end(va);
return result;
}