Viewing file:
unicode.c (4.71 KB) -rw-r--r--Select action/file-type:

(
+) |

(
+) |

(
+) |
Code (
+) |
Session (
+) |

(
+) |
SDB (
+) |

(
+) |

(
+) |

(
+) |

(
+) |

(
+) |
/*
** Copyright 2000-2003 Double Precision, Inc.
** See COPYING for distribution information.
**
** $Id: unicode.c,v 1.9 2004/02/08 04:59:15 mrsam Exp $
*/
#include "unicode_config.h"
#include "unicode.h"
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <errno.h>
const char *unicode_default_chset()
{
const char *p=UNICODECHARSET;
if (unicode_find(p))
return (p);
return (unicode_ISO8859_1.chset);
}
const struct unicode_info *unicode_find(const char *chset)
{
char *p, *q;
int i;
if (!chset) /* Default character set */
return (&unicode_ISO8859_1);
p=strdup(chset);
if (!p)
return (0);
for (q=p; *q; q++)
*q=toupper(*q);
if (strcmp(unicode_ISO8859_1.chset, p) == 0)
{
free(p);
return (&unicode_ISO8859_1);
}
for (i=0; unicode_chsetlist[i].chsetname; i++)
if (strcmp(unicode_chsetlist[i].chsetname, p) == 0)
{
free(p);
return (unicode_chsetlist[i].ptr);
}
free(p);
return (0);
}
char *unicode_convert(const char *txt, const struct unicode_info *from,
const struct unicode_info *to)
{
unicode_char *uc;
char *s;
int dummy;
if (strcmp(from->chset, to->chset) == 0) /* NOOP */
return (strdup(txt));
uc=(*from->c2u)(from, txt, &dummy);
if (!uc)
{
if (dummy >= 0)
errno=EINVAL;
return (0);
}
s=(*to->u2c)(to, uc, &dummy);
free(uc);
if (dummy >= 0)
errno=EINVAL;
return (s);
}
char *unicode_convert_fromchset(const char *txt, const char *from,
const struct unicode_info *to)
{
const struct unicode_info *fromu=unicode_find(from);
if (!fromu)
{
errno=EINVAL;
return (0);
}
return (unicode_convert(txt, fromu, to));
}
/*
** Convert being character sets, except ignore errors.
*/
struct ux_buf {
char *buffer;
size_t bufsize;
} ;
static int ux_alloc(struct ux_buf *p, size_t l)
{
char *newbuf;
if (l < p->bufsize)
return (0);
l += 64;
newbuf=p->buffer ? realloc(p->buffer, l):malloc(l);
if (!newbuf)
return (-1);
p->buffer=newbuf;
p->bufsize=l;
return (0);
}
char *unicode_xconvert(const char *txt, const struct unicode_info *from,
const struct unicode_info *to)
{
unicode_char *uc;
char *s, *cur_conv;
int dummy, dummy2;
struct ux_buf dst_str;
char *orig_str=strdup(txt);
if (!orig_str)
return (0);
if (strcmp(from->chset, to->chset) == 0) /* NOOP */
return (orig_str);
dst_str.bufsize=0;
dst_str.buffer=0;
if (ux_alloc(&dst_str, strlen(txt)*2))
{
free(orig_str);
return (NULL);
}
dst_str.buffer[0]=0;
cur_conv=orig_str;
while (*cur_conv)
{
size_t l;
unicode_char *ucptr;
l=strlen(cur_conv);
if (from->flags & UNICODE_REPLACEABLE)
{
uc=(*from->c2u)(from, cur_conv, NULL);
if (!uc)
{
free(orig_str);
free(dst_str.buffer);
return NULL;
}
}
else
uc=(*from->c2u)(from, cur_conv, &dummy);
if (!uc)
{
char save_char;
if (dummy < 0)
{
free(orig_str);
free(dst_str.buffer);
return (NULL);
}
/* Error converting original text to unicode.
** Back up, and convert all the characters up until
** the error character.
*/
l=dummy;
save_char=cur_conv[dummy];
cur_conv[dummy]=0;
uc=(*from->c2u)(from, cur_conv, &dummy2);
cur_conv[dummy]=save_char;
if (!uc)
{
free(orig_str);
free(dst_str.buffer);
return (NULL);
}
}
/* Ok, now convert unicode to dest charset, using the same
** trial-and-error process.
*/
ucptr=uc;
while (*ucptr)
{
size_t cnt_done;
for (cnt_done=0; ucptr[cnt_done]; cnt_done++)
;
if (to->flags & UNICODE_REPLACEABLE)
{
s=(*to->u2c)(to, ucptr, NULL);
if (!s)
{
free(orig_str);
free(dst_str.buffer);
free(uc);
return NULL;
}
}
else
s=(*to->u2c)(to, ucptr, &dummy);
if (!s)
{
unicode_char save_char;
if (dummy < 0)
{
free(orig_str);
free(dst_str.buffer);
free(uc);
return (NULL);
}
cnt_done=dummy;
save_char=ucptr[dummy];
ucptr[dummy]=0;
s=(*to->u2c)(to, ucptr, &dummy2);
ucptr[dummy]=save_char;
if (!s)
{
free(orig_str);
free(dst_str.buffer);
free(uc);
return (NULL);
}
}
if (ux_alloc(&dst_str,
strlen(dst_str.buffer)+strlen(s)+2))
{
free(s);
free(orig_str);
free(dst_str.buffer);
free(uc);
return (NULL);
}
strcat(dst_str.buffer, s);
free(s);
ucptr += cnt_done;
if (*ucptr)
{
strcat(dst_str.buffer, ".");
++ucptr;
}
}
cur_conv += l;
if (*cur_conv)
{
char buf[2];
if (ux_alloc(&dst_str, strlen(dst_str.buffer)+1))
{
free(orig_str);
free(dst_str.buffer);
free(uc);
return (NULL);
}
buf[0]= *cur_conv++;
buf[1]=0;
strcat(dst_str.buffer, buf);
}
free(uc);
}
free(orig_str);
return (dst_str.buffer);
}