#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifndef PHP_WIN32
#include <php_config.h>
#else
#include <config.w32.h>
#include <stdlib.h>
#endif
static const char rcsid[] = "#(@) $Id$";
#include <errno.h>
#include <string.h>
#ifdef HAVE_GICONV_H
#include <giconv.h>
#else
#include <iconv.h>
#endif
#include "encodings.h"
#ifndef ICONV_CSNMAXLEN
#define ICONV_CSNMAXLEN 64
#endif
static char* convert(const char* src, int src_len, int *new_len, const char* from_enc, const char* to_enc) {
char* outbuf = 0;
if(src && src_len && from_enc && to_enc) {
size_t outlenleft = src_len;
size_t inlenleft = src_len;
int outlen = src_len;
iconv_t ic;
char* out_ptr = 0;
if(strlen(to_enc) >= ICONV_CSNMAXLEN || strlen(from_enc) >= ICONV_CSNMAXLEN) {
return NULL;
}
ic = iconv_open(to_enc, from_enc);
if(ic != (iconv_t)-1) {
size_t st;
outbuf = (char*)malloc(outlen + 1);
if(outbuf) {
out_ptr = (char*)outbuf;
while(inlenleft) {
st = iconv(ic, (char**)&src, &inlenleft, &out_ptr, &outlenleft);
if(st == -1) {
if(errno == E2BIG) {
int diff = out_ptr - outbuf;
outlen += inlenleft;
outlenleft += inlenleft;
outbuf = (char*)realloc(outbuf, outlen + 1);
if(!outbuf) {
break;
}
out_ptr = outbuf + diff;
}
else {
free(outbuf);
outbuf = 0;
break;
}
}
}
}
iconv_close(ic);
}
outlen -= outlenleft;
if(new_len) {
*new_len = outbuf ? outlen : 0;
}
if(outbuf) {
outbuf[outlen] = 0;
}
}
return outbuf;
}
char* utf8_encode(const char *s, int len, int *newlen, const char* encoding)
{
return convert(s, len, newlen, encoding, "UTF-8");
}
char* utf8_decode(const char *s, int len, int *newlen, const char* encoding)
{
return convert(s, len, newlen, "UTF-8", encoding);
}