This repository has been archived on 2023-08-20. You can view files and clone it, but cannot push or open issues or pull requests.
yap-6.3/packages/PLStream/pl-string.c
2011-02-10 00:01:19 +00:00

291 lines
5.3 KiB
C

/* $Id$
Part of SWI-Prolog
Author: Jan Wielemaker
E-mail: J.Wielemaker@uva.nl
WWW: http://www.swi-prolog.org
Copyright (C): 1985-2011, University of Amsterdam
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "pl-incl.h"
#include "pl-string.h"
#include "pl-ctype.h"
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
String operations that are needed for the shared IO library.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/*******************************
* ALLOCATION *
*******************************/
#ifdef O_DEBUG
#define CHAR_INUSE 0x42
#define CHAR_FREED 0x41
char *
store_string(const char *s)
{ if ( s )
{ GET_LD
char *copy = (char *)allocHeap(strlen(s)+2);
*copy++ = CHAR_INUSE;
strcpy(copy, s);
return copy;
} else
{ return NULL;
}
}
void
remove_string(char *s)
{ if ( s )
{ GET_LD
assert(s[-1] == CHAR_INUSE);
s[-1] = CHAR_FREED;
freeHeap(s-1, strlen(s)+2);
}
}
#else /*O_DEBUG*/
char *
store_string(const char *s)
{ if ( s )
{ GET_LD
char *copy = (char *)allocHeap(strlen(s)+1);
strcpy(copy, s);
return copy;
} else
{ return NULL;
}
}
void
remove_string(char *s)
{ if ( s )
{ GET_LD
freeHeap(s, strlen(s)+1);
}
}
#endif /*O_DEBUG*/
/*******************************
* NUMBERS *
*******************************/
/* Return the character representing some digit.
** Fri Jun 10 10:45:40 1988 jan@swivax.UUCP (Jan Wielemaker) */
char
digitName(int n, int small)
{ if (n <= 9)
return n + '0';
return n + (small ? 'a' : 'A') - 10;
}
/* Return the value of a digit when transforming a number of base 'b'.
Return '-1' if it is an illegal digit.
** Fri Jun 10 10:46:40 1988 jan@swivax.UUCP (Jan Wielemaker) */
int
digitValue(int b, int c)
{ int v;
if ( b == 0 )
return c; /* 0'c */
if ( b == 1 )
return -1;
if ( b <= 10 )
{ v = c - '0';
if ( v < b )
return v;
return -1;
}
if ( c <= '9' )
return c - '0';
if (isUpper(c))
c = toLower(c);
c = c - 'a' + 10;
if ( c < b && c >= 10 )
return c;
return -1;
}
/********************************
* LESS COMMON BASIC FUNCTIONS *
*********************************/
bool
strprefix(const char *string, const char *prefix)
{ while(*prefix && *string == *prefix)
prefix++, string++;
if (*prefix == EOS )
succeed;
fail;
}
bool
strpostfix(const char *string, const char *postfix)
{ intptr_t offset = strlen(string) - strlen(postfix);
if ( offset < 0 )
fail;
return streq(&string[offset], postfix);
}
#ifndef HAVE_STRCASECMP
int
strcasecmp(const char *s1, const char *s2)
{
#ifdef HAVE_STRICMP
return stricmp(s1, s2);
#else
while(*s1 && makeLower(*s1) == makeLower(*s2))
s1++, s2++;
return makeLower(*s1) - makeLower(*s2);
#endif
}
#endif
#ifndef HAVE_STRLWR
char *
strlwr(char *s)
{ char *q;
for(q=s; *q; q++)
*q = makeLower(*q);
return s;
}
#endif
bool
stripostfix(const char *s, const char *e)
{ size_t ls = strlen(s);
size_t le = strlen(e);
if ( ls >= le )
return strcasecmp(&s[ls-le], e) == 0;
return FALSE;
}
/*******************************
* MULTIBYTE STRINGS *
*******************************/
typedef struct
{ wchar_t *wcp;
int len;
int malloced;
} wbuf;
#if !defined(HAVE_MBSCOLL) || !defined(HAVE_MBCASESCOLL)
static void
wstolower(wchar_t *w, size_t len)
{ wchar_t *e = &w[len];
for( ; w<e; w++ )
*w = towlower(*w);
}
static int
int_mbscoll(const char *s1, const char *s2, int icase)
{ size_t l1 = strlen(s1);
size_t l2 = strlen(s2);
wchar_t *w1;
wchar_t *w2;
int ml1, ml2;
mbstate_t mbs;
int rc;
if ( l1 < 1024 && (w1 = alloca(sizeof(wchar_t)*(l1+1))) )
{ ml1 = FALSE;
} else
{ w1 = PL_malloc(sizeof(wchar_t)*(l1+1));
ml1 = TRUE;
}
if ( l2 < 1024 && (w2 = alloca(sizeof(wchar_t)*(l2+1))) )
{ ml2 = FALSE;
} else
{ w2 = PL_malloc(sizeof(wchar_t)*(l2+1));
ml2 = TRUE;
}
memset(&mbs, 0, sizeof(mbs));
if ( mbsrtowcs(w1, &s1, l1+1, &mbs) == (size_t)-1 )
{ rc = -2;
goto out;
}
if ( mbsrtowcs(w2, &s2, l2+1, &mbs) == (size_t)-1 )
{ rc = 2;
goto out;
}
if ( icase )
{ wstolower(w1, l1);
wstolower(w2, l2);
}
rc = wcscoll(w1, w2);
out:
if ( ml1 ) PL_free(w1);
if ( ml2 ) PL_free(w2);
return rc;
}
#endif
#ifndef HAVE_MBSCOLL
int
mbscoll(const char *s1, const char *s2)
{ return int_mbscoll(s1, s2, FALSE);
}
#endif
#ifndef HAVE_MBSCASECOLL
int
mbscasecoll(const char *s1, const char *s2)
{ return int_mbscoll(s1, s2, TRUE);
}
#endif