/*
* Copyright (c) 2008 Hypertriton, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Chris Torek.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef _AGAR_CORE_STRING_COMPAT_H_
#define _AGAR_CORE_STRING_COMPAT_H_
#include
#ifdef _MK_HAVE_SYS_TYPES_H
#include
#endif
#include
#include
enum ag_unicode_conv {
AG_UNICODE_FROM_USASCII, /* US-ASCII -> UCS-4 */
AG_UNICODE_FROM_UTF8, /* UTF-8 -> UCS-4 */
AG_UNICODE_TO_UTF8 /* UCS-4 -> UTF-8 */
};
__BEGIN_DECLS
extern const unsigned char agStrcasecmpMapASCII[];
size_t AG_StrlcpyUCS4(Uint32 *, const Uint32 *, size_t);
size_t AG_Strlcpy(char *, const char *, size_t)
BOUNDED_ATTRIBUTE(__string__, 1, 3);
size_t AG_StrlcatUCS4(Uint32 *, const Uint32 *, size_t);
size_t AG_Strlcat(char *, const char *, size_t)
BOUNDED_ATTRIBUTE(__string__, 1, 3);
Uint32 *AG_StrsepUCS4(Uint32 **, const Uint32 *);
char *AG_Strsep(char **, const char *);
char *AG_Strdup(const char *);
Uint32 *AG_StrdupUCS4(const Uint32 *);
Uint32 *AG_ImportUnicode(enum ag_unicode_conv, const char *, size_t);
long AG_ExportUnicode(enum ag_unicode_conv, char *, const Uint32 *, size_t)
BOUNDED_ATTRIBUTE(__string__, 2, 4);
size_t AG_CopyUnicode(enum ag_unicode_conv, const char *, Uint32 *, size_t);
/*
* Return the length of a UCS-4 string in characters, without the
* terminating NUL.
*/
static __inline__ size_t
AG_LengthUCS4(const Uint32 *ucs)
{
size_t len;
for (len = 0; *ucs != '\0'; ucs++) {
len++;
}
return (len);
}
/*
* Return the number of bytes that would be needed to encode the given
* UCS-4 character in UTF-8.
*/
static __inline__ int
AG_CharLengthUTF8FromUCS4(Uint32 ch)
{
if (ch < 0x80) { return (1); }
else if (ch < 0x800) { return (2); }
else if (ch < 0x10000) { return (3); }
else if (ch < 0x200000) { return (4); }
else if (ch < 0x4000000) { return (5); }
else if (ch <= 0x7fffffff) { return (6); }
AG_FatalError("CharLengthUTF8");
return (-1);
}
/*
* Return the number of bytes (not including the terminating NUL) that would
* be needed to encode the given UCS-4 string in UTF-8.
*/
static __inline__ size_t
AG_LengthUTF8FromUCS4(const Uint32 *ucs4)
{
size_t rv = 0;
const Uint32 *c;
for (c = &ucs4[0]; *c != '\0'; c++) {
rv += AG_CharLengthUTF8FromUCS4(*c);
}
return (rv);
}
/*
* Parse the first byte of a possible UTF-8 sequence and return the length
* of the sequence in bytes (or 1 if there is none).
*/
static __inline__ int
AG_CharLengthUTF8(unsigned char ch)
{
if ((ch >> 7) == 0) {
return (1);
} else if (((ch & 0xe0) >> 5) == 0x6) {
return (2);
} else if (((ch & 0xf0) >> 4) == 0xe) {
return (3);
} else if (((ch & 0xf8) >> 3) == 0x1e) {
return (4);
} else if (((ch & 0xfc) >> 2) == 0x3e) {
return (5);
} else if (((ch & 0xfe) >> 1) == 0x7e) {
return (6);
} else {
return (-1);
}
}
/*
* Return the number of characters in the given UTF-8 string, not counting
* the terminating NUL.
*/
static __inline__ size_t
AG_LengthUTF8(const char *s)
{
const char *c = &s[0];
size_t rv = 0;
int i, cLen;
if (s[0] == '\0') {
return (0);
}
for (;;) {
if ((cLen = AG_CharLengthUTF8((unsigned char)*c)) == -1) {
break;
}
for (i = 0; i < cLen; i++) {
if (c[i] == '\0')
return (rv);
}
rv++;
c += cLen;
}
return (rv);
}
/*
* Compare two strings ignoring case.
*/
static __inline__ int
AG_Strcasecmp(const char *s1, const char *s2)
{
const unsigned char *cm = agStrcasecmpMapASCII;
const unsigned char *us1 = (const unsigned char *)s1;
const unsigned char *us2 = (const unsigned char *)s2;
while (cm[*us1] == cm[*us2++]) {
if (*us1++ == '\0')
return (0);
}
return (cm[*us1] - cm[*--us2]);
}
/*
* Compare the first n-characters of two strings ignoring case.
*/
static __inline__ int
AG_Strncasecmp(const char *s1, const char *s2, size_t n)
{
const unsigned char *cm = agStrcasecmpMapASCII;
const unsigned char *us1 = (const unsigned char *)s1;
const unsigned char *us2 = (const unsigned char *)s2;
size_t i;
for (i = 0; i < n; i++) {
if (cm[us1[i]] != cm[us2[i]])
break;
}
return i == n ? 0 : cm[us1[i]] - cm[us2[i]];
}
/*
* Locate a substring ignoring case.
*/
static __inline__ char *
AG_Strcasestr(const char *s, const char *find)
{
char c, sc;
size_t len;
if ((c = *find++) != 0) {
c = (char)tolower((unsigned char)c);
len = strlen(find);
do {
do {
if ((sc = *s++) == 0)
return (NULL);
} while ((char)tolower((unsigned char)sc) != c);
} while (AG_Strncasecmp(s, find, len) != 0);
s--;
}
return ((char *)s);
}
__END_DECLS
#if defined(_AGAR_INTERNAL) || defined(_USE_AGAR_STD)
#define Strlcat AG_Strlcat
#define Strlcpy AG_Strlcpy
#define Strsep AG_Strsep
#define Strdup AG_Strdup
#define Strcasecmp AG_Strcasecmp
#define Strncasecmp AG_Strncasecmp
#define Strcasestr AG_Strcasestr
#define StrlcatUCS4 AG_StrlcatUCS4
#define StrlcpyUCS4 AG_StrlcpyUCS4
#define StrsepUCS4 AG_StrsepUCS4
#define StrdupUCS4 AG_StrdupUCS4
#endif
#include
#endif /* _AGAR_CORE_STRING_COMPAT_H_ */