/*
** Copyright 2000-2002 Double Precision, Inc.
** See COPYING for distribution information.
**
** $Id: utf8.c,v 1.4 2002/11/18 00:54:22 mrsam Exp $
*/
#include "unicode.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
unicode_char *unicode_utf8_tou(const char *cp, int *ip)
{
size_t l;
size_t n=1;
unicode_char *p, uc;
for (l=0; cp[l]; ++n)
{
if ((cp[l] & 0x80) == 0)
{
++l;
continue;
}
if ((cp[l] & 0xE0) == 0xC0)
{
if ((cp[l+1] & 0xC0) == 0x80)
{
l += 2;
continue;
}
}
if ((cp[l] & 0xF0) == 0xE0)
{
if ((cp[l+1] & 0xC0) == 0x80 &&
(cp[l+2] & 0xC0) == 0x80)
{
l += 3;
continue;
}
}
if ((cp[l] & 0xF8) == 0xF0)
{
if ((cp[l+1] & 0xC0) == 0x80 &&
(cp[l+2] & 0xC0) == 0x80 &&
(cp[l+3] & 0xC0) == 0x80)
{
l += 4;
continue;
}
}
if ((cp[l] & 0xFC) == 0xF8)
{
if ((cp[l+1] & 0xC0) == 0x80 &&
(cp[l+2] & 0xC0) == 0x80 &&
(cp[l+3] & 0xC0) == 0x80 &&
(cp[l+4] & 0xC0) == 0x80)
{
l += 5;
continue;
}
}
if ((cp[l] & 0xFE) == 0xFC)
{
if ((cp[l+1] & 0xC0) == 0x80 &&
(cp[l+2] & 0xC0) == 0x80 &&
(cp[l+3] & 0xC0) == 0x80 &&
(cp[l+4] & 0xC0) == 0x80 &&
(cp[l+5] & 0xC0) == 0x80)
{
l += 6;
continue;
}
}
if (ip)
{
*ip= l;
return (0);
}
++l;
}
if (ip)
*ip = -1;
if ((p=malloc(n*sizeof(unicode_char))) == 0)
return (0);
n=0;
for (l=0; cp[l]; p[n++]=uc)
{
if ((cp[l] & 0x80) == 0)
{
uc=cp[l];
++l;
continue;
}
if ((cp[l] & 0xE0) == 0xC0)
{
if ((cp[l+1] & 0xC0) == 0x80)
{
uc=cp[l] & 0x1F;
uc <<= 6; uc |= cp[l+1] & 0x3F;
l += 2;
continue;
}
}
if ((cp[l] & 0xF0) == 0xE0)
{
if ((cp[l+1] & 0xC0) == 0x80 &&
(cp[l+2] & 0xC0) == 0x80)
{
uc=cp[l] & 0x0F;
uc <<= 6; uc |= cp[l+1] & 0x3F;
uc <<= 6; uc |= cp[l+2] & 0x3F;
l += 3;
continue;
}
}
if ((cp[l] & 0xF8) == 0xF0)
{
if ((cp[l+1] & 0xC0) == 0x80 &&
(cp[l+2] & 0xC0) == 0x80 &&
(cp[l+3] & 0xC0) == 0x80)
{
uc=cp[l] & 0x07;
uc <<= 6; uc |= cp[l+1] & 0x3F;
uc <<= 6; uc |= cp[l+2] & 0x3F;
uc <<= 6; uc |= cp[l+3] & 0x3F;
l += 4;
continue;
}
}
if ((cp[l] & 0xFC) == 0xF8)
{
if ((cp[l+1] & 0xC0) == 0x80 &&
(cp[l+2] & 0xC0) == 0x80 &&
(cp[l+3] & 0xC0) == 0x80 &&
(cp[l+4] & 0xC0) == 0x80)
{
uc=cp[l] & 0x03;
uc <<= 6; uc |= cp[l+1] & 0x3F;
uc <<= 6; uc |= cp[l+2] & 0x3F;
uc <<= 6; uc |= cp[l+3] & 0x3F;
uc <<= 6; uc |= cp[l+4] & 0x3F;
l += 5;
continue;
}
}
if ((cp[l] & 0xFE) == 0xFC)
{
if ((cp[l+1] & 0xC0) == 0x80 &&
(cp[l+2] & 0xC0) == 0x80 &&
(cp[l+3] & 0xC0) == 0x80 &&
(cp[l+4] & 0xC0) == 0x80 &&
(cp[l+5] & 0xC0) == 0x80)
{
uc=cp[l] & 0x01;
uc <<= 6; uc |= cp[l+1] & 0x3F;
uc <<= 6; uc |= cp[l+2] & 0x3F;
uc <<= 6; uc |= cp[l+3] & 0x3F;
uc <<= 6; uc |= cp[l+4] & 0x3F;
uc <<= 6; uc |= cp[l+5] & 0x3F;
l += 6;
continue;
}
}
uc=cp[l];
++l;
}
p[n]=0;
return (p);
}
char *unicode_utf8_fromu(const unicode_char *cp, int *ip)
{
char *p=0;
int pass;
size_t l=0;
for (pass=0; pass<2; pass++)
{
if (pass)
{
p=malloc(l+1);
if (!p)
{
if (ip) *ip= -1;
return (0);
}
}
l=unicode_utf8_fromu_pass(cp, p);
if (pass)
p[l]=0;
}
return (p);
}
size_t unicode_utf8_fromu_pass(const unicode_char *cp, char *p)
{
size_t l=0;
unicode_char uc;
l=0;
while (cp && *cp)
{
uc= *cp++;
if ((unicode_char)uc ==
(unicode_char)(uc & 0x007F))
{
if (p)
{
p[l]= (char)uc;
}
++l;
continue;
}
if ((unicode_char)uc ==
(unicode_char)(uc & 0x07FF))
{
if (p)
{
p[l+1]=(char)(uc & 0x3F) | 0x80;
uc >>= 6;
p[l]= (char)(uc & 0x1F) | 0xC0;
}
l += 2;
continue;
}
if ((unicode_char)uc ==
(unicode_char)(uc & 0x00FFFF))
{
if (p)
{
p[l+2]=(char)(uc & 0x3F) | 0x80;
uc >>= 6;
p[l+1]=(char)(uc & 0x3F) | 0x80;
uc >>= 6;
p[l]= (char)(uc & 0x0F) | 0xE0;
}
l += 3;
continue;
}
if ((unicode_char)uc ==
(unicode_char)(uc & 0x001FFFFF))
{
if (p)
{
p[l+3]=(char)(uc & 0x3F) | 0x80;
uc >>= 6;
p[l+2]=(char)(uc & 0x3F) | 0x80;
uc >>= 6;
p[l+1]=(char)(uc & 0x3F) | 0x80;
uc >>= 6;
p[l]= (char)(uc & 0x07) | 0xF0;
}
l += 4;
continue;
}
if ((unicode_char)uc ==
(unicode_char)(uc & 0x03FFFFFF))
{
if (p)
{
p[l+4]=(char)(uc & 0x3F) | 0x80;
uc >>= 6;
p[l+3]=(char)(uc & 0x3F) | 0x80;
uc >>= 6;
p[l+2]=(char)(uc & 0x3F) | 0x80;
uc >>= 6;
p[l+1]=(char)(uc & 0x3F) | 0x80;
uc >>= 6;
p[l]= (char)(uc & 0x03) | 0xF8;
}
l += 5;
continue;
}
if (p)
{
p[l+5]=(char)(uc & 0x3F) | 0x80;
uc >>= 6;
p[l+4]=(char)(uc & 0x3F) | 0x80;
uc >>= 6;
p[l+3]=(char)(uc & 0x3F) | 0x80;
uc >>= 6;
p[l+2]=(char)(uc & 0x3F) | 0x80;
uc >>= 6;
p[l+1]=(char)(uc & 0x3F) | 0x80;
uc >>= 6;
p[l]= (char)(uc & 0x01) | 0xFC;
}
l += 6;
}
return l;
}
syntax highlighted by Code2HTML, v. 0.9.1