mirror of
https://github.com/KolibriOS/kolibrios.git
synced 2024-12-12 18:07:06 +03:00
4f7ee97ec9
git-svn-id: svn://kolibrios.org@4680 a494cfbc-eb01-0410-851d-a64ba20cac60
266 lines
5.0 KiB
C
266 lines
5.0 KiB
C
#include "fitz.h"
|
|
|
|
int
|
|
fz_is_big_endian(void)
|
|
{
|
|
static const int one = 1;
|
|
return *(char*)&one == 0;
|
|
}
|
|
|
|
char *
|
|
fz_strsep(char **stringp, const char *delim)
|
|
{
|
|
char *ret = *stringp;
|
|
if (ret == NULL) return NULL;
|
|
if ((*stringp = strpbrk(*stringp, delim)) != NULL)
|
|
*((*stringp)++) = '\0';
|
|
return ret;
|
|
}
|
|
|
|
int
|
|
fz_strlcpy(char *dst, const char *src, int siz)
|
|
{
|
|
register char *d = dst;
|
|
register const char *s = src;
|
|
register int n = siz;
|
|
|
|
/* Copy as many bytes as will fit */
|
|
if (n != 0 && --n != 0) {
|
|
do {
|
|
if ((*d++ = *s++) == 0)
|
|
break;
|
|
} while (--n != 0);
|
|
}
|
|
|
|
/* Not enough room in dst, add NUL and traverse rest of src */
|
|
if (n == 0) {
|
|
if (siz != 0)
|
|
*d = '\0'; /* NUL-terminate dst */
|
|
while (*s++)
|
|
;
|
|
}
|
|
|
|
return(s - src - 1); /* count does not include NUL */
|
|
}
|
|
|
|
int
|
|
fz_strlcat(char *dst, const char *src, int siz)
|
|
{
|
|
register char *d = dst;
|
|
register const char *s = src;
|
|
register int n = siz;
|
|
int dlen;
|
|
|
|
/* Find the end of dst and adjust bytes left but don't go past end */
|
|
while (*d != '\0' && n-- != 0)
|
|
d++;
|
|
dlen = d - dst;
|
|
n = siz - dlen;
|
|
|
|
if (n == 0)
|
|
return dlen + strlen(s);
|
|
while (*s != '\0') {
|
|
if (n != 1) {
|
|
*d++ = *s;
|
|
n--;
|
|
}
|
|
s++;
|
|
}
|
|
*d = '\0';
|
|
|
|
return dlen + (s - src); /* count does not include NUL */
|
|
}
|
|
|
|
enum
|
|
{
|
|
UTFmax = 4, /* maximum bytes per rune */
|
|
Runesync = 0x80, /* cannot represent part of a UTF sequence (<) */
|
|
Runeself = 0x80, /* rune and UTF sequences are the same (<) */
|
|
Runeerror = 0xFFFD, /* decoding error in UTF */
|
|
Runemax = 0x10FFFF, /* maximum rune value */
|
|
};
|
|
|
|
enum
|
|
{
|
|
Bit1 = 7,
|
|
Bitx = 6,
|
|
Bit2 = 5,
|
|
Bit3 = 4,
|
|
Bit4 = 3,
|
|
Bit5 = 2,
|
|
|
|
T1 = ((1<<(Bit1+1))-1) ^ 0xFF, /* 0000 0000 */
|
|
Tx = ((1<<(Bitx+1))-1) ^ 0xFF, /* 1000 0000 */
|
|
T2 = ((1<<(Bit2+1))-1) ^ 0xFF, /* 1100 0000 */
|
|
T3 = ((1<<(Bit3+1))-1) ^ 0xFF, /* 1110 0000 */
|
|
T4 = ((1<<(Bit4+1))-1) ^ 0xFF, /* 1111 0000 */
|
|
T5 = ((1<<(Bit5+1))-1) ^ 0xFF, /* 1111 1000 */
|
|
|
|
Rune1 = (1<<(Bit1+0*Bitx))-1, /* 0000 0000 0111 1111 */
|
|
Rune2 = (1<<(Bit2+1*Bitx))-1, /* 0000 0111 1111 1111 */
|
|
Rune3 = (1<<(Bit3+2*Bitx))-1, /* 1111 1111 1111 1111 */
|
|
Rune4 = (1<<(Bit4+3*Bitx))-1, /* 0001 1111 1111 1111 1111 1111 */
|
|
|
|
Maskx = (1<<Bitx)-1, /* 0011 1111 */
|
|
Testx = Maskx ^ 0xFF, /* 1100 0000 */
|
|
|
|
Bad = Runeerror,
|
|
};
|
|
|
|
int
|
|
chartorune(int *rune, char *str)
|
|
{
|
|
int c, c1, c2, c3;
|
|
long l;
|
|
|
|
/*
|
|
* one character sequence
|
|
* 00000-0007F => T1
|
|
*/
|
|
c = *(unsigned char*)str;
|
|
if(c < Tx) {
|
|
*rune = c;
|
|
return 1;
|
|
}
|
|
|
|
/*
|
|
* two character sequence
|
|
* 0080-07FF => T2 Tx
|
|
*/
|
|
c1 = *(unsigned char*)(str+1) ^ Tx;
|
|
if(c1 & Testx)
|
|
goto bad;
|
|
if(c < T3) {
|
|
if(c < T2)
|
|
goto bad;
|
|
l = ((c << Bitx) | c1) & Rune2;
|
|
if(l <= Rune1)
|
|
goto bad;
|
|
*rune = l;
|
|
return 2;
|
|
}
|
|
|
|
/*
|
|
* three character sequence
|
|
* 0800-FFFF => T3 Tx Tx
|
|
*/
|
|
c2 = *(unsigned char*)(str+2) ^ Tx;
|
|
if(c2 & Testx)
|
|
goto bad;
|
|
if(c < T4) {
|
|
l = ((((c << Bitx) | c1) << Bitx) | c2) & Rune3;
|
|
if(l <= Rune2)
|
|
goto bad;
|
|
*rune = l;
|
|
return 3;
|
|
}
|
|
|
|
/*
|
|
* four character sequence (21-bit value)
|
|
* 10000-1FFFFF => T4 Tx Tx Tx
|
|
*/
|
|
c3 = *(unsigned char*)(str+3) ^ Tx;
|
|
if (c3 & Testx)
|
|
goto bad;
|
|
if (c < T5) {
|
|
l = ((((((c << Bitx) | c1) << Bitx) | c2) << Bitx) | c3) & Rune4;
|
|
if (l <= Rune3)
|
|
goto bad;
|
|
*rune = l;
|
|
return 4;
|
|
}
|
|
/*
|
|
* Support for 5-byte or longer UTF-8 would go here, but
|
|
* since we don't have that, we'll just fall through to bad.
|
|
*/
|
|
|
|
/*
|
|
* bad decoding
|
|
*/
|
|
bad:
|
|
*rune = Bad;
|
|
return 1;
|
|
}
|
|
|
|
int
|
|
runetochar(char *str, int *rune)
|
|
{
|
|
/* Runes are signed, so convert to unsigned for range check. */
|
|
unsigned long c;
|
|
|
|
/*
|
|
* one character sequence
|
|
* 00000-0007F => 00-7F
|
|
*/
|
|
c = *rune;
|
|
if(c <= Rune1) {
|
|
str[0] = c;
|
|
return 1;
|
|
}
|
|
|
|
/*
|
|
* two character sequence
|
|
* 0080-07FF => T2 Tx
|
|
*/
|
|
if(c <= Rune2) {
|
|
str[0] = T2 | (c >> 1*Bitx);
|
|
str[1] = Tx | (c & Maskx);
|
|
return 2;
|
|
}
|
|
|
|
/*
|
|
* If the Rune is out of range, convert it to the error rune.
|
|
* Do this test here because the error rune encodes to three bytes.
|
|
* Doing it earlier would duplicate work, since an out of range
|
|
* Rune wouldn't have fit in one or two bytes.
|
|
*/
|
|
if (c > Runemax)
|
|
c = Runeerror;
|
|
|
|
/*
|
|
* three character sequence
|
|
* 0800-FFFF => T3 Tx Tx
|
|
*/
|
|
if (c <= Rune3) {
|
|
str[0] = T3 | (c >> 2*Bitx);
|
|
str[1] = Tx | ((c >> 1*Bitx) & Maskx);
|
|
str[2] = Tx | (c & Maskx);
|
|
return 3;
|
|
}
|
|
|
|
/*
|
|
* four character sequence (21-bit value)
|
|
* 10000-1FFFFF => T4 Tx Tx Tx
|
|
*/
|
|
str[0] = T4 | (c >> 3*Bitx);
|
|
str[1] = Tx | ((c >> 2*Bitx) & Maskx);
|
|
str[2] = Tx | ((c >> 1*Bitx) & Maskx);
|
|
str[3] = Tx | (c & Maskx);
|
|
return 4;
|
|
}
|
|
|
|
int
|
|
runelen(int c)
|
|
{
|
|
char str[10];
|
|
return runetochar(str, &c);
|
|
}
|
|
|
|
float fz_atof(const char *s)
|
|
{
|
|
double d;
|
|
|
|
/* The errno voodoo here checks for us reading numbers that are too
|
|
* big to fit into a double. The checks for FLT_MAX ensure that we
|
|
* don't read a number that's OK as a double and then become invalid
|
|
* as we convert to a float. */
|
|
errno = 0;
|
|
d = strtod(s, NULL);
|
|
if (errno == ERANGE || d > FLT_MAX || d < -FLT_MAX) {
|
|
/* Return 1.0, as it's a small known value that won't cause a
|
|
* divide by 0. */
|
|
return 1.0;
|
|
}
|
|
return (float)d;
|
|
}
|