2002-12-31 15:20:34 +03:00
|
|
|
/*
|
|
|
|
* toucs.c - convert charsets to Unicode.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "charset.h"
|
|
|
|
#include "internal.h"
|
|
|
|
|
|
|
|
struct unicode_emit_param {
|
|
|
|
wchar_t *output;
|
|
|
|
int outlen;
|
|
|
|
const wchar_t *errstr;
|
|
|
|
int errlen;
|
|
|
|
int stopped;
|
|
|
|
};
|
|
|
|
|
|
|
|
static void unicode_emit(void *ctx, long int output)
|
|
|
|
{
|
|
|
|
struct unicode_emit_param *param = (struct unicode_emit_param *)ctx;
|
|
|
|
wchar_t outval;
|
|
|
|
wchar_t const *p;
|
|
|
|
int outlen;
|
|
|
|
|
|
|
|
if (output == ERROR) {
|
|
|
|
if (param->errstr) {
|
|
|
|
p = param->errstr;
|
|
|
|
outlen = param->errlen;
|
|
|
|
} else {
|
|
|
|
outval = 0xFFFD; /* U+FFFD REPLACEMENT CHARACTER */
|
|
|
|
p = &outval;
|
|
|
|
outlen = 1;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
outval = output;
|
|
|
|
p = &outval;
|
|
|
|
outlen = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (param->outlen >= outlen) {
|
|
|
|
while (outlen > 0) {
|
|
|
|
*param->output++ = *p++;
|
|
|
|
param->outlen--;
|
|
|
|
outlen--;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
param->stopped = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-09-16 23:18:52 +04:00
|
|
|
int charset_to_unicode(const char **input, int *inlen,
|
|
|
|
wchar_t *output, int outlen,
|
2002-12-31 15:20:34 +03:00
|
|
|
int charset, charset_state *state,
|
|
|
|
const wchar_t *errstr, int errlen)
|
|
|
|
{
|
|
|
|
charset_spec const *spec = charset_find_spec(charset);
|
|
|
|
charset_state localstate;
|
|
|
|
struct unicode_emit_param param;
|
|
|
|
|
|
|
|
param.output = output;
|
|
|
|
param.outlen = outlen;
|
|
|
|
param.errstr = errstr;
|
|
|
|
param.errlen = errlen;
|
|
|
|
param.stopped = 0;
|
|
|
|
|
|
|
|
if (!state) {
|
|
|
|
localstate.s0 = 0;
|
|
|
|
} else {
|
|
|
|
localstate = *state; /* structure copy */
|
|
|
|
}
|
|
|
|
|
|
|
|
while (*inlen > 0) {
|
|
|
|
int lenbefore = param.output - output;
|
|
|
|
spec->read(spec, (unsigned char)**input, &localstate,
|
|
|
|
unicode_emit, ¶m);
|
|
|
|
if (param.stopped) {
|
|
|
|
/*
|
|
|
|
* The emit function has _tried_ to output some
|
|
|
|
* characters, but ran up against the end of the
|
|
|
|
* buffer. Leave immediately, and return what happened
|
|
|
|
* _before_ attempting to process this character.
|
|
|
|
*/
|
|
|
|
return lenbefore;
|
|
|
|
}
|
|
|
|
if (state)
|
|
|
|
*state = localstate; /* structure copy */
|
|
|
|
(*input)++;
|
|
|
|
(*inlen)--;
|
|
|
|
}
|
|
|
|
|
|
|
|
return param.output - output;
|
|
|
|
}
|