apr_ssize_t iconv_write(void *handle, const void *buf, apr_size_t insize) { #define stream ((iconv_stream *)handle) char buffer[4096]; apr_size_t outsize = sizeof(buffer), size; char *outbuf = buffer; const char *inbuf = buf; apr_size_t chars; apr_status_t status; if (!buf) insize = 0; status = apr_iconv(stream->cd, (const char **)&buf, &insize, &outbuf, &outsize, &chars); if ((int)chars < 0) return -1; stream->chars += chars; size = outbuf - buffer; if (size) { apr_ssize_t r; outbuf = buffer; while ((r = stream->method(stream->handle, outbuf, size)) < size) { if (r < 0) return -1; outbuf += r; size -= r; stream->out_bytes += r; } } size = (const char *)buf - inbuf; if (size) stream->in_bytes += size; return size; #undef stream }
int encode(int unicode, apr_pool_t *pool) { if (//(0xe000 <= unicode && unicode <= 0xf8ff) || // private use area (0xd800 <= unicode && unicode <= 0xdbff) || // high surrogate area (0xdc00 <= unicode && unicode <= 0xdfff)) { // low surrogate area return -1; } apr_size_t inbytesleft = 2; apr_size_t outbytesleft = 2; char inbuf_[2] = { (char)(unicode >> 8), (char)unicode }; char outbuf_[2]; const char *inbuf = inbuf_; char *outbuf = outbuf_; apr_iconv_t cd; if (apr_iconv_open("CP932", "UTF-16", pool, &cd) < 0) { return -1; } apr_size_t result = 0; if (apr_iconv(cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft, &result) < 0) { return -1; } if (apr_iconv_close(cd, pool) < 0) { return -1; } if (result == 0 && inbytesleft == 0) { if (outbytesleft == 1) { int cp932 = (int)(byte)outbuf_[0]; if (cp932 == 0x5f && unicode != 0x5f) { // missing char is converted to 0x5f return -1; } return cp932; } else if (outbytesleft == 0) { return ((int)(byte)outbuf_[0] << 8) | (int)(byte)outbuf_[1]; } } return -1; }