utf.c (1317B)
1 /* Public Domain --Kris Maglione */ 2 #include "dat.h" 3 #include <errno.h> 4 #include <iconv.h> 5 #include <langinfo.h> 6 #include <string.h> 7 #include "fns.h" 8 9 char* 10 toutf8n(const char *str, size_t nstr) { 11 static iconv_t cd; 12 static bool haveiconv; 13 char *buf, *pos; 14 size_t nbuf, bsize; 15 16 if(cd == nil) { 17 cd = iconv_open("UTF-8", nl_langinfo(CODESET)); 18 if((long)cd == -1) 19 warning("Can't convert from local character encoding to UTF-8"); 20 else 21 haveiconv = true; 22 } 23 if(!haveiconv) { 24 buf = emalloc(nstr+1); 25 memcpy(buf, str, nstr); 26 buf[nstr+1] = '\0'; 27 return buf; 28 } 29 30 iconv(cd, nil, nil, nil, nil); 31 32 bsize = (nstr+1) << 1; 33 buf = emalloc(bsize); 34 pos = buf; 35 nbuf = bsize-1; 36 /* The (void*) cast is because, while the BSDs declare: 37 * size_t iconv(iconv_t, const char**, size_t*, char**, size_t*), 38 * GNU/Linux and POSIX declare: 39 * size_t iconv(iconv_t, char**, size_t*, char**, size_t*). 40 * This just happens to be safer than declaring our own 41 * prototype. 42 */ 43 while(iconv(cd, (void*)&str, &nstr, &pos, &nbuf) == -1) 44 if(errno == E2BIG) { 45 bsize <<= 1; 46 nbuf = pos - buf; 47 buf = erealloc(buf, bsize); 48 pos = buf + nbuf; 49 nbuf = bsize - nbuf - 1; 50 }else 51 break; 52 *pos++ = '\0'; 53 return erealloc(buf, pos-buf); 54 } 55 56 char* 57 toutf8(const char *str) { 58 return toutf8n(str, strlen(str)); 59 } 60