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;
}