summaryrefslogtreecommitdiff
path: root/iconv/loop.c
diff options
context:
space:
mode:
Diffstat (limited to 'iconv/loop.c')
-rw-r--r--iconv/loop.c39
1 files changed, 32 insertions, 7 deletions
diff --git a/iconv/loop.c b/iconv/loop.c
index c8f893406a..9c5dbfca77 100644
--- a/iconv/loop.c
+++ b/iconv/loop.c
@@ -307,10 +307,10 @@ SINGLE(LOOPFCT) (const unsigned char **inptrp, const unsigned char *inend,
#endif
/* Are there enough bytes in the input buffer? */
- if (__builtin_expect (inptr + (MAX_NEEDED_INPUT - inlen) > inend, 0))
+ if (__builtin_expect (inptr + (MIN_NEEDED_INPUT - inlen) > inend, 0))
{
-#ifdef STORE_REST
*inptrp = inend;
+#ifdef STORE_REST
inptr = bytebuf;
inptrp = &inptr;
inend = &bytebuf[inlen];
@@ -335,28 +335,53 @@ SINGLE(LOOPFCT) (const unsigned char **inptrp, const unsigned char *inend,
/* Now add characters from the normal input buffer. */
do
bytebuf[inlen++] = *inptr++;
- while (inlen < MAX_NEEDED_INPUT);
+ while (inlen < MAX_NEEDED_INPUT && inptr < inend);
inptr = bytebuf;
- inend = &inptr[MAX_NEEDED_INPUT];
+ inend = &bytebuf[inlen];
+#undef NEED_LENGTH_TEST
+#define NEED_LENGTH_TEST 1
do
{
BODY
}
while (0);
- if (result == __GCONV_OK)
+ /* Now we either have produced an output character and consumed all the
+ bytes from the state and at least one more, or the character is still
+ incomplete, or we have some other error (like illegal input character,
+ no space in output buffer). */
+ if (inptr != bytebuf)
{
- /* We successfully converted the character (maybe even more).
- Update the pointers passed in. */
+ /* We found a new character. */
assert (inptr - bytebuf > (state->__count & 7));
*inptrp += inptr - bytebuf - (state->__count & 7);
*outptrp = outptr;
+ result = __GCONV_OK;
+
/* Clear the state buffer. */
state->__count &= ~7;
}
+ else if (result == __GCONV_INCOMPLETE_INPUT)
+ {
+ /* This can only happen if we have less than MAX_NEEDED_INPUT bytes
+ available. */
+ assert (inend != &bytebuf[MAX_NEEDED_INPUT]);
+
+ *inptrp += inend - bytebuf - (state->__count & 7);
+#ifdef STORE_REST
+ inptrp = &inptr;
+
+ STORE_REST
+#else
+ /* We don't have enough input for another complete input
+ character. */
+ while (inptr < inend)
+ state->__value.__wchb[inlen++] = *inptr++;
+#endif
+ }
return result;
}