intlconv: add intlconv_to_utf8() and use it in dvb_support.c also fixes #2319
This commit is contained in:
parent
ba8d90ff48
commit
4faa0efc87
3 changed files with 98 additions and 30 deletions
|
@ -25,12 +25,12 @@
|
|||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <iconv.h>
|
||||
|
||||
#include "tvheadend.h"
|
||||
#include "dvb.h"
|
||||
#include "dvb_charset_tables.h"
|
||||
#include "input.h"
|
||||
#include "intlconv.h"
|
||||
|
||||
static int convert_iso_8859[16] = {
|
||||
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, -1, 11, 12, 13
|
||||
|
@ -40,32 +40,14 @@ static int convert_iso_8859[16] = {
|
|||
#define convert_ucs2 16
|
||||
#define convert_gb 17
|
||||
|
||||
static inline int code_convert(const char *from_charset,const char *to_charset,char *inbuf,size_t inlen,char *outbuf,size_t *outlen)
|
||||
{
|
||||
iconv_t cd;
|
||||
|
||||
char **pin = &inbuf;
|
||||
char **pout = &outbuf;
|
||||
|
||||
cd = iconv_open(to_charset,from_charset);
|
||||
if (cd==0) return -1;
|
||||
memset(outbuf,0,*outlen);
|
||||
if (iconv(cd,pin,&inlen,pout,outlen)==-1) return -1;
|
||||
iconv_close(cd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int gb2u(char *inbuf,int inlen,char *outbuf,size_t *outlen)
|
||||
{
|
||||
return code_convert("gb2312","utf-8",inbuf,inlen,outbuf,outlen);
|
||||
}
|
||||
|
||||
static inline size_t conv_gb(const uint8_t *src, size_t srclen,
|
||||
char *dst, size_t *dstlen)
|
||||
{
|
||||
size_t len=*dstlen;
|
||||
gb2u((char *)src,srclen,dst,dstlen);
|
||||
dst+=len-*dstlen;
|
||||
ssize_t len;
|
||||
len = intlconv_to_utf8(dst, *dstlen, "gb2312", (char *)src, srclen);
|
||||
if (len < 0 || len > *dstlen)
|
||||
return -1;
|
||||
*dstlen -= len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -12,10 +12,27 @@ static RB_HEAD(,intlconv_cache) intlconv_all;
|
|||
static intlconv_cache_t *intlconv_last_ic;
|
||||
pthread_mutex_t intlconv_lock;
|
||||
|
||||
static RB_HEAD(,intlconv_cache) intlconv_src_all;
|
||||
static intlconv_cache_t *intlconv_last_src_ic;
|
||||
pthread_mutex_t intlconv_lock_src;
|
||||
|
||||
static inline size_t
|
||||
tvh_iconv(iconv_t cd, char **inbuf, size_t *inbytesleft,
|
||||
char **outbuf, size_t *outbytesleft)
|
||||
{
|
||||
#ifdef PLATFORM_FREEBSD
|
||||
return iconv(cd, (const char **)inbuf, inbytesleft,
|
||||
(const char **)outbuf, outbytesleft);
|
||||
#else
|
||||
return iconv(cd, inbuf, inbytesleft, outbuf, outbytesleft);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
intlconv_init( void )
|
||||
{
|
||||
pthread_mutex_init(&intlconv_lock, NULL);
|
||||
pthread_mutex_init(&intlconv_lock_src, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -31,6 +48,13 @@ intlconv_done( void )
|
|||
RB_REMOVE(&intlconv_all, ic, ic_link);
|
||||
free(ic);
|
||||
}
|
||||
intlconv_last_src_ic = NULL;
|
||||
while ((ic = RB_FIRST(&intlconv_src_all)) != NULL) {
|
||||
iconv_close(ic->ic_handle);
|
||||
free(ic->ic_charset_id);
|
||||
RB_REMOVE(&intlconv_src_all, ic, ic_link);
|
||||
free(ic);
|
||||
}
|
||||
pthread_mutex_unlock(&intlconv_lock);
|
||||
}
|
||||
|
||||
|
@ -121,18 +145,16 @@ intlconv_utf8( char *dst, size_t dst_size,
|
|||
ic->ic_handle = c;
|
||||
RB_INSERT_SORTED(&intlconv_all, ic, ic_link, intlconv_cmp);
|
||||
}
|
||||
intlconv_last_ic = ic;
|
||||
found:
|
||||
pthread_mutex_unlock(&intlconv_lock);
|
||||
inbuf = (char **)&src_utf8;
|
||||
inbuf_left = strlen(src_utf8);
|
||||
outbuf = &dst;
|
||||
outbuf_left = dst_size;
|
||||
res = iconv(ic->ic_handle, inbuf, &inbuf_left, outbuf, &outbuf_left);
|
||||
if (res == -1) {
|
||||
res = tvh_iconv(ic->ic_handle, inbuf, &inbuf_left, outbuf, &outbuf_left);
|
||||
if (res == -1)
|
||||
res = -errno;
|
||||
} else {
|
||||
intlconv_last_ic = ic;
|
||||
}
|
||||
pthread_mutex_unlock(&intlconv_lock);
|
||||
if (res >= 0)
|
||||
res = dst_size - outbuf_left;
|
||||
return res;
|
||||
|
@ -161,6 +183,65 @@ intlconv_utf8safestr( const char *dst_charset_id,
|
|||
return res;
|
||||
}
|
||||
|
||||
ssize_t
|
||||
intlconv_to_utf8( char *dst, size_t dst_size,
|
||||
const char *src_charset_id,
|
||||
const char *src, size_t src_size )
|
||||
{
|
||||
intlconv_cache_t templ, *ic;
|
||||
char **inbuf, **outbuf;
|
||||
size_t inbuf_left, outbuf_left;
|
||||
ssize_t res;
|
||||
|
||||
if (src_charset_id == NULL) {
|
||||
strncpy(dst, src, dst_size);
|
||||
dst[dst_size - 1] = '\0';
|
||||
return strlen(dst);
|
||||
}
|
||||
templ.ic_charset_id = (char *)src_charset_id;
|
||||
pthread_mutex_lock(&intlconv_lock_src);
|
||||
if (intlconv_last_src_ic &&
|
||||
strcmp(intlconv_last_src_ic->ic_charset_id, src_charset_id) == 0) {
|
||||
ic = intlconv_last_src_ic;
|
||||
goto found;
|
||||
}
|
||||
ic = RB_FIND(&intlconv_src_all, &templ, ic_link, intlconv_cmp);
|
||||
if (!ic) {
|
||||
iconv_t c = iconv_open("UTF-8", src_charset_id);
|
||||
if ((iconv_t)-1 == c) {
|
||||
pthread_mutex_unlock(&intlconv_lock_src);
|
||||
return -EIO;
|
||||
}
|
||||
ic = malloc(sizeof(*ic));
|
||||
if (ic == NULL) {
|
||||
pthread_mutex_unlock(&intlconv_lock_src);
|
||||
return -ENOMEM;
|
||||
}
|
||||
ic->ic_charset_id = strdup(src_charset_id);
|
||||
if (ic->ic_charset_id == NULL) {
|
||||
pthread_mutex_unlock(&intlconv_lock_src);
|
||||
free(ic);
|
||||
iconv_close(c);
|
||||
return -ENOMEM;
|
||||
}
|
||||
ic->ic_handle = c;
|
||||
RB_INSERT_SORTED(&intlconv_src_all, ic, ic_link, intlconv_cmp);
|
||||
}
|
||||
intlconv_last_src_ic = ic;
|
||||
found:
|
||||
pthread_mutex_unlock(&intlconv_lock_src);
|
||||
inbuf = (char **)&src;
|
||||
inbuf_left = src_size;
|
||||
outbuf = &dst;
|
||||
outbuf_left = dst_size;
|
||||
res = tvh_iconv(ic->ic_handle, inbuf, &inbuf_left, outbuf, &outbuf_left);
|
||||
if (res == -1)
|
||||
res = -errno;
|
||||
if (res >= 0)
|
||||
res = dst_size - outbuf_left;
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
|
|
|
@ -38,4 +38,9 @@ intlconv_utf8safestr( const char *dst_charset_id,
|
|||
const char *src_utf8,
|
||||
size_t max_size );
|
||||
|
||||
ssize_t
|
||||
intlconv_to_utf8( char *dst, size_t dst_size,
|
||||
const char *src_charset_id,
|
||||
const char *src, size_t src_size );
|
||||
|
||||
#endif /* INTLCONV_H_ */
|
||||
|
|
Loading…
Add table
Reference in a new issue