summaryrefslogtreecommitdiffstats
path: root/src/libuemf/uemf_utf.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libuemf/uemf_utf.c')
-rw-r--r--src/libuemf/uemf_utf.c376
1 files changed, 272 insertions, 104 deletions
diff --git a/src/libuemf/uemf_utf.c b/src/libuemf/uemf_utf.c
index 48d2510f0..5c6507818 100644
--- a/src/libuemf/uemf_utf.c
+++ b/src/libuemf/uemf_utf.c
@@ -1,5 +1,7 @@
/**
- @file uemf_utf.c Functions for manipulating UTF and various types of text.
+ @file uemf_utf.c
+
+ @brief Functions for manipulating UTF and various types of text.
Compile with "U_VALGRIND" defined defined to enable code which lets valgrind check each record for
@@ -10,11 +12,11 @@
/*
File: uemf_utf.c
-Version: 0.0.4
-Date: 19-MAR-2013
+Version: 0.0.5
+Date: 29-JAN-2014
Author: David Mathog, Biology Division, Caltech
email: mathog@caltech.edu
-Copyright: 2013 David Mathog and California Institute of Technology (Caltech)
+Copyright: 2014 David Mathog and California Institute of Technology (Caltech)
*/
#ifdef __cplusplus
@@ -32,10 +34,12 @@ extern "C" {
#include <math.h> // for U_ROUND()
#include "uemf_utf.h"
+//! \cond
/* Prototypes for functions used here and defined in uemf_endian.c, but which are not supposed
to be used in end user code. */
void U_swap2(void *ul, unsigned int count);
+//! \endcond
/* ******************************************************************************************** */
@@ -45,11 +49,14 @@ void U_swap2(void *ul, unsigned int count);
on another funky system this code may need to be modified, or define ICONV_CAST
on the compile line(but it may be tricky).
*/
+#if _LIBICONV_VERSION == 0x0109
+# define ICONV_CAST (const char **)
+#endif // _LIBICONV_VERSION 0x0109
#ifdef SOL8
-#define ICONV_CAST (const char **)
+# define ICONV_CAST (const char **)
#endif //SOL8
#if !defined(ICONV_CAST)
-#define ICONV_CAST (char **)
+# define ICONV_CAST (char **)
#endif //ICONV_CAST
/** \endcond */
@@ -64,9 +71,14 @@ These functions are used for development and debugging and should be be includie
void wchar8show(
const char *src
){
- printf("char show\n");
- size_t srclen = 0;
- while(*src){ printf("%d %d %x\n",(int) srclen,*src,*src); srclen++; src++; }
+ if(!src){
+ printf("char show <NULL>\n");
+ }
+ else {
+ printf("char show\n");
+ size_t srclen = 0;
+ while(*src){ printf("%d %d %x\n",(int) srclen,*src,*src); srclen++; src++; }
+ }
}
/**
@@ -76,9 +88,14 @@ void wchar8show(
void wchar16show(
const uint16_t *src
){
- printf("uint16_t show\n");
- size_t srclen = 0;
- while(*src){ printf("%d %d %x\n",(int) srclen,*src,*src); srclen++; src++; }
+ if(!src){
+ printf("uint16_t show <NULL>\n");
+ }
+ else {
+ printf("uint16_t show\n");
+ size_t srclen = 0;
+ while(*src){ printf("%d %d %x\n",(int) srclen,*src,*src); srclen++; src++; }
+ }
}
/**
@@ -87,9 +104,14 @@ void wchar16show(
void wchar32show(
const uint32_t *src
){
- printf("uint32_t show\n");
- size_t srclen = 0;
- while(*src){ printf("%d %d %x\n",(int) srclen,*src,*src); srclen++; src++; }
+ if(!src){
+ printf("uint32_t show <NULL>\n");
+ }
+ else {
+ printf("uint32_t show\n");
+ size_t srclen = 0;
+ while(*src){ printf("%d %d %x\n",(int) srclen,*src,*src); srclen++; src++; }
+ }
}
/**
@@ -100,13 +122,19 @@ void wchartshow(
const wchar_t *src
){
uint32_t val;
- printf("wchar_t show\n");
- size_t srclen = 0;
- while(*src){
- val = *src; // because *src is wchar_t is not strictly an integer type, can cause warnings on next line
- printf("%d %d %x\n",(int) srclen,val,val);
- srclen++;
- src++;
+ if(!src){
+ printf("wchar_t show <NULL>\n");
+ }
+ else {
+ printf("wchar_t show\n");
+ size_t srclen = 0;
+ if(!src)return;
+ while(*src){
+ val = *src; // because *src is wchar_t is not strictly an integer type, can cause warnings on next line
+ printf("%d %d %x\n",(int) srclen,val,val);
+ srclen++;
+ src++;
+ }
}
}
@@ -123,7 +151,9 @@ size_t wchar16len(
const uint16_t *src
){
size_t srclen = 0;
- while(*src){ srclen++; src++; }
+ if(src){
+ while(*src){ srclen++; src++; }
+ }
return(srclen);
}
@@ -135,7 +165,9 @@ size_t wchar32len(
const uint32_t *src
){
size_t srclen = 0;
- while(*src){ srclen++; src++; }
+ if(src){
+ while(*src){ srclen++; src++; }
+ }
return(srclen);
}
@@ -150,9 +182,11 @@ void wchar16strncpy(
const uint16_t *src,
size_t nchars
){
- for(;nchars;nchars--,dst++,src++){
- *dst = *src;
- if(!*src)break;
+ if(src){
+ for(;nchars;nchars--,dst++,src++){
+ *dst = *src;
+ if(!*src)break;
+ }
}
}
@@ -168,8 +202,10 @@ void wchar16strncpypad(
const uint16_t *src,
size_t nchars
){
- for(;*src && nchars;nchars--,dst++,src++){ *dst = *src; }
- for(;nchars;nchars--,dst++){ *dst = 0; } // Pad the remainder
+ if(src){
+ for(;*src && nchars;nchars--,dst++,src++){ *dst = *src; }
+ for(;nchars;nchars--,dst++){ *dst = 0; } // Pad the remainder
+ }
}
/* For the following converstion functions, remember that iconv() modifies ALL of its parameters,
@@ -191,19 +227,33 @@ uint16_t *U_Utf32leToUtf16le(
size_t *len
){
char *dst,*dst2;
+ char *src2 = (char *) src;
size_t srclen,dstlen,status;
+ if(!src)return(NULL);
if(max){ srclen = 4*max; }
else { srclen = 4 + 4*wchar32len(src); } //include terminator, length in BYTES
dstlen = 2 + srclen; // this will always work, but may waste space
dst2 = dst = calloc(dstlen,1); // so there will be at least one terminator
- if(!dst)return(NULL);
- iconv_t conv = iconv_open("UTF-16LE", "UTF-32LE");
- status = iconv(conv, ICONV_CAST &src, &srclen, &dst, &dstlen);
- iconv_close(conv);
- if(status == (size_t) -1)return(NULL);
- if(len)*len=wchar16len((uint16_t *)dst2);
+ if(dst){
+ iconv_t conv = iconv_open("UTF-16LE", "UTF-32LE");
+ if ( conv == (iconv_t) -1){
+ free(dst2);
+ dst2=NULL;
+ }
+ else {
+ status = iconv(conv, ICONV_CAST &src2, &srclen, &dst, &dstlen);
+ iconv_close(conv);
+ if(status == (size_t) -1){
+ free(dst2);
+ dst2 = NULL;
+ }
+ else if(len){
+ *len=wchar16len((uint16_t *)dst2);
+ }
+ }
+ }
return((uint16_t *)dst2);
}
@@ -222,17 +272,30 @@ uint32_t *U_Utf16leToUtf32le(
char *dst,*dst2;
char *src2 = (char *) src;
size_t srclen,dstlen,status;
+
+ if(!src)return(NULL);
if(max){ srclen = 2*max; }
else { srclen = 2*wchar16len(src)+2; } // include terminator, length in BYTES
dstlen = 2*(2 + srclen); // This should always work
dst2 = dst = calloc(dstlen,1);
- if(!dst)return(NULL);
- iconv_t conv = iconv_open("UTF-32LE", "UTF-16LE");
- if ( conv == (iconv_t)-1)return(NULL);
- status = iconv(conv, ICONV_CAST &src2, &srclen, &dst, &dstlen);
- iconv_close(conv);
- if(status == (size_t) -1)return(NULL);
- if(len)*len=wchar32len((uint32_t *)dst2);
+ if(dst){
+ iconv_t conv = iconv_open("UTF-32LE", "UTF-16LE");
+ if ( conv == (iconv_t) -1){
+ free(dst2);
+ dst2=NULL;
+ }
+ else {
+ status = iconv(conv, ICONV_CAST &src2, &srclen, &dst, &dstlen);
+ iconv_close(conv);
+ if(status == (size_t) -1){
+ free(dst2);
+ dst2 = NULL;
+ }
+ else if(len){
+ *len=wchar32len((uint32_t *)dst2);
+ }
+ }
+ }
return((uint32_t *) dst2);
}
@@ -257,17 +320,30 @@ uint32_t *U_Latin1ToUtf32le(
char *dst,*dst2;
char *src2 = (char *) src;
size_t srclen,dstlen,status;
+
+ if(!src)return(NULL);
if(max){ srclen = max; }
else { srclen = strlen(src)+1; } // include terminator, length in BYTES
dstlen = sizeof(uint32_t)*(1 + srclen); // This should always work but might waste some space
dst2 = dst = calloc(dstlen,1);
- if(!dst)return(NULL);
- iconv_t conv = iconv_open("UTF-32LE", "LATIN1");
- if ( conv == (iconv_t) -1)return(NULL);
- status = iconv(conv, ICONV_CAST &src2, &srclen, &dst, &dstlen);
- iconv_close(conv);
- if(status == (size_t) -1)return(NULL);
- if(len)*len=wchar32len((uint32_t *)dst2);
+ if(dst){
+ iconv_t conv = iconv_open("UTF-32LE", "LATIN1");
+ if ( conv == (iconv_t) -1){
+ free(dst2);
+ dst2=NULL;
+ }
+ else {
+ status = iconv(conv, ICONV_CAST &src2, &srclen, &dst, &dstlen);
+ iconv_close(conv);
+ if(status == (size_t) -1){
+ free(dst2);
+ dst2 = NULL;
+ }
+ else if(len){
+ *len=wchar32len((uint32_t *)dst2);
+ }
+ }
+ }
return((uint32_t *) dst2);
}
@@ -286,17 +362,30 @@ uint32_t *U_Utf8ToUtf32le(
char *dst,*dst2;
char *src2 = (char *) src;
size_t srclen,dstlen,status;
+
+ if(!src)return(NULL);
if(max){ srclen = max; }
else { srclen = strlen(src)+1; } // include terminator, length in BYTES
dstlen = sizeof(uint32_t)*(1 + srclen); // This should always work but might waste some space
dst2 = dst = calloc(dstlen,1);
- if(!dst)return(NULL);
- iconv_t conv = iconv_open("UTF-32LE", "UTF-8");
- if ( conv == (iconv_t) -1)return(NULL);
- status = iconv(conv, ICONV_CAST &src2, &srclen, &dst, &dstlen);
- iconv_close(conv);
- if(status == (size_t) -1)return(NULL);
- if(len)*len=wchar32len((uint32_t *)dst2);
+ if(dst){
+ iconv_t conv = iconv_open("UTF-32LE", "UTF-8");
+ if ( conv == (iconv_t) -1){
+ free(dst2);
+ dst2=NULL;
+ }
+ else {
+ status = iconv(conv, ICONV_CAST &src2, &srclen, &dst, &dstlen);
+ iconv_close(conv);
+ if(status == (size_t) -1){
+ free(dst2);
+ dst2 = NULL;
+ }
+ else if(len){
+ *len=wchar32len((uint32_t *)dst2);
+ }
+ }
+ }
return((uint32_t *) dst2);
}
@@ -315,17 +404,30 @@ char *U_Utf32leToUtf8(
char *dst,*dst2;
char *src2 = (char *) src;
size_t srclen,dstlen,status;
+
+ if(!src)return(NULL);
if(max){ srclen = 4*max; }
else { srclen = 4*(1 + wchar32len(src)); } //include terminator, length in BYTES
dstlen = 1 + srclen; // This should always work but might waste some space
dst2 = dst = calloc(dstlen,1);
- if(!dst)return(NULL);
- iconv_t conv = iconv_open("UTF-8", "UTF-32LE");
- if ( conv == (iconv_t)-1)return(NULL);
- status = iconv(conv, ICONV_CAST &src2, &srclen, &dst, &dstlen);
- iconv_close(conv);
- if(status == (size_t) -1)return(NULL);
- if(len)*len=strlen(dst2);
+ if(dst){
+ iconv_t conv = iconv_open("UTF-8", "UTF-32LE");
+ if ( conv == (iconv_t) -1){
+ free(dst2);
+ dst2=NULL;
+ }
+ else {
+ status = iconv(conv, ICONV_CAST &src2, &srclen, &dst, &dstlen);
+ iconv_close(conv);
+ if(status == (size_t) -1){
+ free(dst2);
+ dst2 = NULL;
+ }
+ else if(len){
+ *len=strlen(dst2);
+ }
+ }
+ }
return(dst2);
}
@@ -342,20 +444,32 @@ uint16_t *U_Utf8ToUtf16le(
size_t *len
){
char *dst,*dst2;
+ char *src2 = (char *) src;
size_t srclen,dstlen,status;
- iconv_t conv;
+ if(!src)return(NULL);
if(max){ srclen = max; }
else { srclen = strlen(src)+1; } // include terminator, length in BYTES
dstlen = 2 * (1 + srclen); // this will always work, but may waste space
dst2 = dst =calloc(dstlen,1); // so there will always be a terminator
- if(!dst)return(NULL);
- conv = iconv_open("UTF-16LE", "UTF-8");
- if (conv == (iconv_t) -1)return(NULL);
- status = iconv(conv, ICONV_CAST &src, &srclen, &dst, &dstlen);
- iconv_close(conv);
- if(status == (size_t) -1)return(NULL);
- if(len)*len=wchar16len((uint16_t *)dst2);
+ if(dst){
+ iconv_t conv = iconv_open("UTF-16LE", "UTF-8");
+ if ( conv == (iconv_t) -1){
+ free(dst2);
+ dst2=NULL;
+ }
+ else {
+ status = iconv(conv, ICONV_CAST &src2, &srclen, &dst, &dstlen);
+ iconv_close(conv);
+ if(status == (size_t) -1){
+ free(dst2);
+ dst2 = NULL;
+ }
+ else if(len){
+ *len=wchar16len((uint16_t *)dst2);
+ }
+ }
+ }
return((uint16_t *)dst2);
}
@@ -372,23 +486,37 @@ char *U_Utf16leToUtf8(
size_t *len
){
char *dst, *dst2;
- char *ret=NULL;
+ char *src2 = (char *) src;
size_t srclen,dstlen,status;
+
+ if(!src)return(NULL);
if(max){ srclen = 2*max; }
else { srclen = 2*(1 +wchar16len(src)); } //include terminator, length in BYTES
dstlen = 1 + 2*srclen; // this will always work, but may waste space
// worst case is all glyphs (==max) need 4 UTF-8 encoded bytes + terminator.
dst2 = dst = (char *) calloc(dstlen,1);
- if(!dst)return(NULL);
- iconv_t conv = iconv_open("UTF-8", "UTF-16LE");
- status = iconv(conv, ICONV_CAST &src, &srclen, &dst, &dstlen);
- iconv_close(conv);
- if(status != (size_t) -1){
- if(len)*len=strlen(dst2);
- ret=U_strdup(dst2); // make a string of exactly the right size
+ if(dst){
+ iconv_t conv = iconv_open("UTF-8", "UTF-16LE");
+ if ( conv == (iconv_t) -1){
+ free(dst2);
+ dst2=NULL;
+ }
+ else {
+ status = iconv(conv, ICONV_CAST &src2, &srclen, &dst, &dstlen);
+ iconv_close(conv);
+ if(status == (size_t) -1){
+ free(dst2);
+ dst2 = NULL;
+ }
+ else if(len){
+ *len=strlen(dst2);
+ dst = dst2;
+ dst2 = U_strdup(dst); // make a string of exactly the right size
+ free(dst); // free the one which was probably too big
+ }
+ }
}
- free(dst2); // free the one which was probably too big
- return(ret);
+ return(dst2);
}
/**
@@ -404,20 +532,36 @@ char *U_Utf16leToLatin1(
size_t *len
){
char *dst, *dst2;
- char *ret=NULL;
+ char *src2 = (char *) src;
size_t srclen,dstlen,status;
+
+ if(!src)return(NULL);
if(max){ srclen = 2*max; }
else { srclen = 2*(1 +wchar16len(src)); } //include terminator, length in BYTES
dstlen = 1 + srclen; // this will always work as latin1 is always 1 byte/character
- ret = dst2 = dst = (char *) calloc(dstlen,1);
- if(!dst)return(NULL);
- iconv_t conv = iconv_open("LATIN1//TRANSLIT", "UTF-16LE"); // translate what can be, fill in with something close for the rest
- status = iconv(conv, ICONV_CAST &src, &srclen, &dst, &dstlen);
- iconv_close(conv);
- if(status != (size_t) -1){
- if(len)*len=strlen(dst2);
+ dst2 = dst = (char *) calloc(dstlen,1);
+ if(dst){
+ iconv_t conv = iconv_open("LATIN1//TRANSLIT", "UTF-16LE");
+ if ( conv == (iconv_t) -1){
+ free(dst2);
+ dst2=NULL;
+ }
+ else {
+ status = iconv(conv, ICONV_CAST &src2, &srclen, &dst, &dstlen);
+ iconv_close(conv);
+ if(status == (size_t) -1){
+ free(dst2);
+ dst2 = NULL;
+ }
+ else if(len){
+ *len=strlen(dst2);
+ dst = dst2;
+ dst2 = U_strdup(dst); // make a string of exactly the right size
+ free(dst); // free the one which was probably too big
+ }
+ }
}
- return(ret);
+ return(dst2);
}
/**
\brief Put a single 16 bit character into UTF-16LE form.
@@ -454,18 +598,30 @@ char *U_Utf8ToLatin1(
size_t *len
){
char *dst,*dst2;
+ char *src2 = (char *) src;
size_t srclen,dstlen,status;
if(max){ srclen = max; }
else { srclen = strlen(src)+1; } // include terminator, length in BYTES
dstlen = (1 + srclen); // This should always work but might waste some space
dst2 = dst = calloc(dstlen,1);
- if(!dst)return(NULL);
- iconv_t conv = iconv_open("LATIN1//TRANSLIT", "UTF-8"); // translate what can be, fill in with something close for the rest
- if ( conv == (iconv_t) -1)return(NULL);
- status = iconv(conv, ICONV_CAST &src, &srclen, &dst, &dstlen);
- iconv_close(conv);
- if(status == (size_t) -1)return(NULL);
- if(len)*len=strlen(dst2);
+ if(dst){
+ iconv_t conv = iconv_open("LATIN1//TRANSLIT", "UTF-8"); // translate what can be, fill in with something close for the rest
+ if ( conv == (iconv_t) -1){
+ free(dst2);
+ dst2=NULL;
+ }
+ else {
+ status = iconv(conv, ICONV_CAST &src2, &srclen, &dst, &dstlen);
+ iconv_close(conv);
+ if(status == (size_t) -1){
+ free(dst2);
+ dst2 = NULL;
+ }
+ else if(len){
+ *len=strlen(dst2);
+ }
+ }
+ }
return((char *) dst2);
}
@@ -486,18 +642,30 @@ char *U_Latin1ToUtf8(
size_t *len
){
char *dst,*dst2;
+ char *src2 = (char *) src;
size_t srclen,dstlen,status;
if(max){ srclen = max; }
else { srclen = strlen(src)+1; } // include terminator, will waste some space
dstlen = (1 + 2*srclen); // This should always work because all latin1 convert to 1 or 2 byte UTF8, it might waste some space
dst2 = dst = calloc(dstlen,1);
- if(!dst)return(NULL);
- iconv_t conv = iconv_open("UTF-8", "LATIN1"); // everything should translate
- if ( conv == (iconv_t) -1)return(NULL);
- status = iconv(conv, ICONV_CAST &src, &srclen, &dst, &dstlen);
- iconv_close(conv);
- if(status == (size_t) -1)return(NULL);
- if(len)*len=strlen(dst2);
+ if(dst){
+ iconv_t conv = iconv_open("UTF-8", "LATIN1"); // everything should translate
+ if ( conv == (iconv_t) -1){
+ free(dst2);
+ dst2=NULL;
+ }
+ else {
+ status = iconv(conv, ICONV_CAST &src2, &srclen, &dst, &dstlen);
+ iconv_close(conv);
+ if(status == (size_t) -1){
+ free(dst2);
+ dst2 = NULL;
+ }
+ else if(len){
+ *len=strlen(dst2);
+ }
+ }
+ }
return((char *) dst2);
}