Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00014 #ifndef _DDC_ICONV_H
00015 #define _DDC_ICONV_H
00016
00017 #include <stdlib.h>
00018 #include <string.h>
00019 #include <errno.h>
00020 #include <string>
00021
00022 #include <iconv.h>
00023
00024 using namespace std;
00025
00027 #define DDC_ICONV_BUFLEN 256
00028
00030 #define DDC_ICONV_PTHREAD 1
00031
00032 #ifdef DDC_ICONV_PTHREAD
00033 # include <pthread.h>
00034 # define PTOP(x) x
00035 #else
00036 # define PTOP(x)
00037 #endif
00038
00040 class ddcIconv {
00041 public:
00042
00044
00045 string enc_src;
00046 string enc_dst;
00047
00048
00049 public:
00050
00052
00053 iconv_t ic;
00054
00055 char ibuf[DDC_ICONV_BUFLEN];
00056 char obuf[DDC_ICONV_BUFLEN];
00057
00058 PTOP(pthread_mutex_t mut;)
00059
00060
00061 public:
00062
00064
00065
00066 ddcIconv(const std::string &srcEncoding="", const std::string &dstEncoding="")
00067 : enc_src(""),
00068 enc_dst(""),
00069 ic((iconv_t)-1)
00070 {
00071 PTOP(pthread_mutex_init(&mut,NULL);)
00072 if (!open(srcEncoding,dstEncoding))
00073 close();
00074 };
00075
00077 ~ddcIconv(void)
00078 {
00079 close();
00080 PTOP(pthread_mutex_destroy(&mut);)
00081 };
00083
00084
00086
00087
00089 inline bool empty(void) const
00090 {
00091 return (enc_src.empty() || enc_src=="-" || enc_dst.empty() || enc_dst=="-");
00092 };
00093
00095 inline bool valid(void) const
00096 {
00097 return ic != (iconv_t)-1;
00098 };
00099
00101 inline bool good(void) const
00102 {
00103 return empty() || valid();
00104 };
00105
00110 inline bool open(const std::string &srcEncoding, const std::string dstEncoding)
00111 {
00112 close();
00113 PTOP(pthread_mutex_lock(&mut);)
00114 enc_src = srcEncoding;
00115 enc_dst = dstEncoding;
00116 if (!empty())
00117 ic = iconv_open(enc_dst.c_str(), enc_src.c_str());
00118 PTOP(pthread_mutex_unlock(&mut);)
00119 return valid();
00120 };
00121
00123 inline bool close(void) {
00124 if (!empty() && valid() && iconv_close(ic)==-1) return false;
00125 PTOP(pthread_mutex_lock(&mut);)
00126 enc_src.clear();
00127 enc_dst.clear();
00128 ic = (iconv_t)-1;
00129 PTOP(pthread_mutex_unlock(&mut);)
00130 return true;
00131 };
00132
00134 inline void reset(void) {
00135 if (!empty() && valid())
00136 iconv(ic, NULL,NULL, NULL,NULL);
00137 };
00139
00140
00142
00143
00144 inline bool convert(const string &in, string &out)
00145 {
00146 if (empty()) {
00147 out = in;
00148 return true;
00149 }
00150 const char *idata = in.data();
00151 size_t ilen=in.size();
00152 size_t itodo=ilen;
00153
00154 PTOP(pthread_mutex_lock(&mut);)
00155 out.clear();
00156 out.reserve(ilen);
00157 reset();
00158
00159 while (itodo > 0) {
00160 size_t ileft0 = itodo > DDC_ICONV_BUFLEN ? DDC_ICONV_BUFLEN : itodo;
00161 size_t oleft = DDC_ICONV_BUFLEN, ileft=ileft0;
00162 char *iptr=ibuf, *optr=obuf;
00163
00164
00165 memcpy(ibuf, idata+(ilen-itodo), ileft);
00166
00167
00168 size_t nx = iconv(ic, &iptr, &ileft, &optr, &oleft);
00169 if (nx==(size_t)-1) {
00170
00171 switch (errno) {
00172 case E2BIG:
00173 out.append(obuf,DDC_ICONV_BUFLEN-oleft);
00174 break;
00175 case EINVAL:
00176 if (itodo-ileft0) {
00177
00178 out.append(obuf,DDC_ICONV_BUFLEN-oleft);
00179 break;
00180 }
00181 case EILSEQ:
00182 out.append(obuf,DDC_ICONV_BUFLEN-oleft);
00183 if (ileft) {
00184 out.push_back(*iptr);
00185 ileft--;
00186 }
00187 reset();
00188 break;
00189 case EBADF:
00190 default:
00191 PTOP(pthread_mutex_unlock(&mut);)
00192 return false;
00193 break;
00194 }
00195 } else {
00196
00197 out.append(obuf,DDC_ICONV_BUFLEN-oleft);
00198 }
00199 itodo -= (ileft0-ileft);
00200 }
00201
00202 PTOP(pthread_mutex_unlock(&mut);)
00203 return true;
00204 };
00205
00207 inline std::string convert(const std::string &in)
00208 {
00209 std::string out("");
00210 convert(in,out);
00211 return out;
00212 };
00214
00215 };
00216
00217 #undef DDC_ICONV_BUFLEN
00218 #undef PTOP
00219
00220 #endif //_DDC_ICONV_H
00221