+
+char* convert_to_utf8_incremental(convert_t conv,
+ const char* input, size_t input_len)
+{
+ size_t res;
+ struct conv_buffer* outbuf = conv->outbuf;
+ struct conv_buffer* inbuf = conv->inbuf;
+ size_t outsize = outbuf->size;
+ char* wrptr = outbuf->buffer;
+ ICONV_CONST char* rdptr = (ICONV_CONST char*) inbuf->buffer;
+ char* retval = outbuf->buffer;
+
+ if (!conv || !conv->outbuf)
+ return NULL;
+
+ /* set up input buffer (concatenate to what was left previous time) */
+ /* can't use strcpy, because possible null bytes from unicode */
+ while (conv->insize + input_len > inbuf->size)
+ grow_conv_buffer(inbuf, inbuf->buffer + conv->insize);
+ memcpy(inbuf->buffer + conv->insize, input, input_len);
+ conv->insize += input_len;
+
+ /* set up output buffer (empty it) */
+ reset_conv_buffer(outbuf);
+
+ /* do the conversion */
+ res = iconv(conv->to_utf8, &rdptr, &conv->insize, &wrptr, &outsize);
+ if (res == (size_t)-1) {
+ if (errno == EILSEQ) {
+ /* restart from an empty state and return NULL */
+ retval = NULL;
+ rdptr++;
+ conv->insize--;
+ }
+ else if (errno == EINVAL) {
+ /* Do nothing, leave it to next iteration */
+ }
+ else {
+ retval = NULL;
+ }
+ }
+
+ /* then shift what is left over to the head of the input buffer */
+ memmove(inbuf->buffer, rdptr, conv->insize);
+ memset(inbuf->buffer + conv->insize, 0, inbuf->size - conv->insize);
+ return retval;
+}