mirror of
https://gitlab.gnome.org/GNOME/libxml2.git
synced 2024-12-25 23:21:26 +03:00
269 lines
6.5 KiB
C
269 lines
6.5 KiB
C
/**
|
|
*** Transcoding support and wrappers.
|
|
***
|
|
*** See Copyright for the status of this software.
|
|
***
|
|
*** Author: Patrick Monnerat <pm@datasphere.ch>, DATASPHERE S.A.
|
|
**/
|
|
|
|
#define IN_LIBXML
|
|
#include "libxml.h"
|
|
|
|
#include <sys/types.h>
|
|
#include <iconv.h>
|
|
#include "libxml/xmlmemory.h"
|
|
#include "libxml/dict.h"
|
|
#include "transcode.h"
|
|
|
|
|
|
/**
|
|
*** Destroy a dictionary and mark as destroyed.
|
|
**/
|
|
|
|
void
|
|
xmlZapDict(xmlDictPtr * dict)
|
|
|
|
{
|
|
if (dict && *dict) {
|
|
xmlDictFree(*dict);
|
|
*dict = (xmlDictPtr) NULL;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
*** Support for inline conversion from/to UTF-8.
|
|
*** This is targetted to function parameter encoding conversion.
|
|
*** Method is:
|
|
*** - Convert string from/to UTF-8.
|
|
*** - Keep it in a dictionary.
|
|
*** - Free original string if a release procedure is provided.
|
|
*** Can also be called without dictionary to convert a string from/to UTF-8
|
|
*** into xmlMalloc'ed dynamic storage.
|
|
**/
|
|
|
|
const char *
|
|
xmlTranscodeResult(const xmlChar * s, const char * encoding,
|
|
xmlDictPtr * dict, void (*freeproc)(const void *))
|
|
|
|
{
|
|
size_t l;
|
|
iconv_t cd;
|
|
char * srcp;
|
|
char * dstp;
|
|
size_t srcc;
|
|
size_t dstc;
|
|
char * ts;
|
|
const char * ret;
|
|
int err;
|
|
static const int nullstring[] = { 0 };
|
|
|
|
/* Convert from UTF-8. */
|
|
|
|
if (!s)
|
|
return (const char *) NULL;
|
|
|
|
ret = (const char *) NULL;
|
|
ts = (char *) NULL;
|
|
err = 0;
|
|
l = xmlStrlen(s);
|
|
|
|
if (!l && dict)
|
|
ret = (const char *) nullstring;
|
|
else {
|
|
if (dict && !*dict)
|
|
err = !(*dict = xmlDictCreate());
|
|
|
|
if (!err)
|
|
err = !(ts = xmlMalloc(4 * l + 4));
|
|
|
|
dstp = ts;
|
|
dstc = 4 * l;
|
|
|
|
if (!err && l) {
|
|
if (!encoding)
|
|
encoding = "ibm-0"; /* Job's encoding. */
|
|
|
|
cd = iconv_open(encoding, "UTF-8");
|
|
|
|
if (cd == (iconv_t) -1)
|
|
err = 1;
|
|
else {
|
|
srcp = (char *) s;
|
|
srcc = l;
|
|
srcc = iconv(cd, &srcp, &srcc, &dstp, &dstc);
|
|
iconv_close(cd);
|
|
err = srcc == (size_t) -1;
|
|
}
|
|
}
|
|
|
|
if (!err) {
|
|
dstp[0] = dstp[1] = dstp[2] = dstp[3] = '\0';
|
|
|
|
if (!dict) {
|
|
if (dstc)
|
|
ts = xmlRealloc(ts, (dstp - ts) + 4);
|
|
|
|
ret = (const char *) ts;
|
|
ts = (char *) NULL;
|
|
}
|
|
else
|
|
ret = (char *) xmlDictLookup(*dict,
|
|
(xmlChar *) ts, dstp - ts + 1);
|
|
}
|
|
}
|
|
|
|
if (ts)
|
|
xmlFree(ts);
|
|
|
|
if (freeproc)
|
|
(*freeproc)(s);
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
/**
|
|
*** Support for inline conversion to UTF-8.
|
|
*** Method is:
|
|
*** - Convert string to UTF-8.
|
|
*** - Keep it in a dictionary.
|
|
*** Can also be called without dictionary to convert a string to UTF-8 into
|
|
*** xmlMalloc'ed dynamic storage.
|
|
**/
|
|
|
|
static const xmlChar *
|
|
inTranscode(const char * s, size_t l, const char * encoding, xmlDictPtr * dict)
|
|
|
|
{
|
|
iconv_t cd;
|
|
char * srcp;
|
|
char * dstp;
|
|
size_t srcc;
|
|
size_t dstc;
|
|
xmlChar * ts;
|
|
const xmlChar * ret;
|
|
static const xmlChar nullstring[] = { 0 };
|
|
|
|
if (!l && dict)
|
|
return nullstring;
|
|
|
|
if (dict && !*dict)
|
|
if (!(*dict = xmlDictCreate()))
|
|
return (const xmlChar *) NULL;
|
|
|
|
ts = (xmlChar *) xmlMalloc(6 * l + 1);
|
|
|
|
if (!ts)
|
|
return (const xmlChar *) NULL;
|
|
|
|
dstp = (char *) ts;
|
|
dstc = 6 * l;
|
|
|
|
if (l) {
|
|
if (!encoding)
|
|
encoding = "ibm-0"; /* Use job's encoding. */
|
|
|
|
cd = iconv_open("UTF-8", encoding);
|
|
|
|
if (cd == (iconv_t) -1) {
|
|
xmlFree((char *) ts);
|
|
return (const xmlChar *) NULL;
|
|
}
|
|
|
|
srcp = (char *) s;
|
|
srcc = l;
|
|
srcc = iconv(cd, &srcp, &srcc, &dstp, &dstc);
|
|
iconv_close(cd);
|
|
|
|
if (srcc == (size_t) -1) {
|
|
xmlFree((char *) ts);
|
|
return (const xmlChar *) NULL;
|
|
}
|
|
}
|
|
|
|
*dstp = '\0';
|
|
|
|
if (!dict) {
|
|
if (dstc)
|
|
ts = xmlRealloc(ts, (dstp - ts) + 1);
|
|
|
|
return ts;
|
|
}
|
|
|
|
ret = xmlDictLookup(*dict, ts, dstp - ts + 1);
|
|
xmlFree((char *) ts);
|
|
return ret;
|
|
}
|
|
|
|
|
|
/**
|
|
*** Input 8-bit character string parameter.
|
|
**/
|
|
|
|
const xmlChar *
|
|
xmlTranscodeString(const char * s, const char * encoding, xmlDictPtr * dict)
|
|
|
|
{
|
|
if (!s)
|
|
return (const xmlChar *) NULL;
|
|
|
|
return inTranscode(s, xmlStrlen(s), encoding, dict);
|
|
}
|
|
|
|
|
|
/**
|
|
*** Input 16-bit character string parameter.
|
|
**/
|
|
|
|
const xmlChar *
|
|
xmlTranscodeWString(const char * s, const char * encoding, xmlDictPtr * dict)
|
|
|
|
{
|
|
size_t i;
|
|
|
|
if (!s)
|
|
return (const xmlChar *) NULL;
|
|
|
|
for (i = 0; s[i] && s[i + 1]; i += 2)
|
|
;
|
|
|
|
return inTranscode(s, i, encoding, dict);
|
|
}
|
|
|
|
|
|
/**
|
|
*** Input 32-bit character string parameter.
|
|
**/
|
|
|
|
const xmlChar *
|
|
xmlTranscodeHString(const char * s, const char * encoding, xmlDictPtr * dict)
|
|
|
|
{
|
|
size_t i;
|
|
|
|
if (!s)
|
|
return (const xmlChar *) NULL;
|
|
|
|
for (i = 0; s[i] && s[i + 1] && s[i + 2] && s[i + 3]; i += 4)
|
|
;
|
|
|
|
return inTranscode(s, i, encoding, dict);
|
|
}
|
|
|
|
|
|
/**
|
|
*** vasprintf() implementation with result transcoding.
|
|
**/
|
|
|
|
const char *
|
|
xmlVasprintf(xmlDictPtr * dict, const char * encoding,
|
|
const xmlChar * fmt, va_list args)
|
|
|
|
{
|
|
char * s = NULL;
|
|
|
|
vasprintf(&s, fmt, args);
|
|
return xmlTranscodeResult((const xmlChar *) s, encoding, dict, free);
|
|
}
|