mirror of
git://sourceware.org/git/glibc.git
synced 2025-03-06 20:58:33 +01:00
iconv: Remove _STRING_ARCH_unaligned usage
Use put/get macros __builtin_bswap32 instead. It allows to remove the unaligned routines, the compiler will generate unaligned access if the ABI allows it. Checked on x86_64-linux-gnu and i686-linux-gnu. Reviewed-by: Wilco Dijkstra <Wilco.Dijkstra@arm.com>
This commit is contained in:
parent
5729e0e9af
commit
3e20ddade3
3 changed files with 59 additions and 407 deletions
|
@ -86,13 +86,15 @@ internal_ucs4_loop (struct __gconv_step *step,
|
||||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||||
/* Sigh, we have to do some real work. */
|
/* Sigh, we have to do some real work. */
|
||||||
size_t cnt;
|
size_t cnt;
|
||||||
uint32_t *outptr32 = (uint32_t *) outptr;
|
|
||||||
|
|
||||||
for (cnt = 0; cnt < n_convert; ++cnt, inptr += 4)
|
for (cnt = 0; cnt < n_convert; ++cnt, inptr += 4, outptr += 4)
|
||||||
*outptr32++ = bswap_32 (*(const uint32_t *) inptr);
|
{
|
||||||
|
uint32_t val = get32 (inptr);
|
||||||
|
put32 (outptr, __builtin_bswap32 (val));
|
||||||
|
}
|
||||||
|
|
||||||
*inptrp = inptr;
|
*inptrp = inptr;
|
||||||
*outptrp = (unsigned char *) outptr32;
|
*outptrp = outptr;
|
||||||
#elif __BYTE_ORDER == __BIG_ENDIAN
|
#elif __BYTE_ORDER == __BIG_ENDIAN
|
||||||
/* Simply copy the data. */
|
/* Simply copy the data. */
|
||||||
*inptrp = inptr + n_convert * 4;
|
*inptrp = inptr + n_convert * 4;
|
||||||
|
@ -112,56 +114,6 @@ internal_ucs4_loop (struct __gconv_step *step,
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !_STRING_ARCH_unaligned
|
|
||||||
static inline int
|
|
||||||
__attribute ((always_inline))
|
|
||||||
internal_ucs4_loop_unaligned (struct __gconv_step *step,
|
|
||||||
struct __gconv_step_data *step_data,
|
|
||||||
const unsigned char **inptrp,
|
|
||||||
const unsigned char *inend,
|
|
||||||
unsigned char **outptrp,
|
|
||||||
const unsigned char *outend,
|
|
||||||
size_t *irreversible)
|
|
||||||
{
|
|
||||||
const unsigned char *inptr = *inptrp;
|
|
||||||
unsigned char *outptr = *outptrp;
|
|
||||||
size_t n_convert = MIN (inend - inptr, outend - outptr) / 4;
|
|
||||||
int result;
|
|
||||||
|
|
||||||
# if __BYTE_ORDER == __LITTLE_ENDIAN
|
|
||||||
/* Sigh, we have to do some real work. */
|
|
||||||
size_t cnt;
|
|
||||||
|
|
||||||
for (cnt = 0; cnt < n_convert; ++cnt, inptr += 4, outptr += 4)
|
|
||||||
{
|
|
||||||
outptr[0] = inptr[3];
|
|
||||||
outptr[1] = inptr[2];
|
|
||||||
outptr[2] = inptr[1];
|
|
||||||
outptr[3] = inptr[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
*inptrp = inptr;
|
|
||||||
*outptrp = outptr;
|
|
||||||
# elif __BYTE_ORDER == __BIG_ENDIAN
|
|
||||||
/* Simply copy the data. */
|
|
||||||
*inptrp = inptr + n_convert * 4;
|
|
||||||
*outptrp = __mempcpy (outptr, inptr, n_convert * 4);
|
|
||||||
# else
|
|
||||||
# error "This endianess is not supported."
|
|
||||||
# endif
|
|
||||||
|
|
||||||
/* Determine the status. */
|
|
||||||
if (*inptrp == inend)
|
|
||||||
result = __GCONV_EMPTY_INPUT;
|
|
||||||
else if (*outptrp + 4 > outend)
|
|
||||||
result = __GCONV_FULL_OUTPUT;
|
|
||||||
else
|
|
||||||
result = __GCONV_INCOMPLETE_INPUT;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
__attribute ((always_inline))
|
__attribute ((always_inline))
|
||||||
|
@ -242,12 +194,9 @@ ucs4_internal_loop (struct __gconv_step *step,
|
||||||
|
|
||||||
for (; inptr + 4 <= inend && outptr + 4 <= outend; inptr += 4)
|
for (; inptr + 4 <= inend && outptr + 4 <= outend; inptr += 4)
|
||||||
{
|
{
|
||||||
uint32_t inval;
|
uint32_t inval = get32 (inptr);
|
||||||
|
|
||||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||||
inval = bswap_32 (*(const uint32_t *) inptr);
|
inval = __builtin_bswap32 (inval);
|
||||||
#else
|
|
||||||
inval = *(const uint32_t *) inptr;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (__glibc_unlikely (inval > 0x7fffffff))
|
if (__glibc_unlikely (inval > 0x7fffffff))
|
||||||
|
@ -272,7 +221,7 @@ ucs4_internal_loop (struct __gconv_step *step,
|
||||||
return __GCONV_ILLEGAL_INPUT;
|
return __GCONV_ILLEGAL_INPUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
*((uint32_t *) outptr) = inval;
|
put32 (outptr, inval);
|
||||||
outptr += sizeof (uint32_t);
|
outptr += sizeof (uint32_t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -290,75 +239,6 @@ ucs4_internal_loop (struct __gconv_step *step,
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !_STRING_ARCH_unaligned
|
|
||||||
static inline int
|
|
||||||
__attribute ((always_inline))
|
|
||||||
ucs4_internal_loop_unaligned (struct __gconv_step *step,
|
|
||||||
struct __gconv_step_data *step_data,
|
|
||||||
const unsigned char **inptrp,
|
|
||||||
const unsigned char *inend,
|
|
||||||
unsigned char **outptrp,
|
|
||||||
const unsigned char *outend,
|
|
||||||
size_t *irreversible)
|
|
||||||
{
|
|
||||||
int flags = step_data->__flags;
|
|
||||||
const unsigned char *inptr = *inptrp;
|
|
||||||
unsigned char *outptr = *outptrp;
|
|
||||||
int result;
|
|
||||||
|
|
||||||
for (; inptr + 4 <= inend && outptr + 4 <= outend; inptr += 4)
|
|
||||||
{
|
|
||||||
if (__glibc_unlikely (inptr[0] > 0x80))
|
|
||||||
{
|
|
||||||
/* The value is too large. We don't try transliteration here since
|
|
||||||
this is not an error because of the lack of possibilities to
|
|
||||||
represent the result. This is a genuine bug in the input since
|
|
||||||
UCS4 does not allow such values. */
|
|
||||||
if (irreversible == NULL)
|
|
||||||
/* We are transliterating, don't try to correct anything. */
|
|
||||||
return __GCONV_ILLEGAL_INPUT;
|
|
||||||
|
|
||||||
if (flags & __GCONV_IGNORE_ERRORS)
|
|
||||||
{
|
|
||||||
/* Just ignore this character. */
|
|
||||||
++*irreversible;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
*inptrp = inptr;
|
|
||||||
*outptrp = outptr;
|
|
||||||
return __GCONV_ILLEGAL_INPUT;
|
|
||||||
}
|
|
||||||
|
|
||||||
# if __BYTE_ORDER == __LITTLE_ENDIAN
|
|
||||||
outptr[3] = inptr[0];
|
|
||||||
outptr[2] = inptr[1];
|
|
||||||
outptr[1] = inptr[2];
|
|
||||||
outptr[0] = inptr[3];
|
|
||||||
# else
|
|
||||||
outptr[0] = inptr[0];
|
|
||||||
outptr[1] = inptr[1];
|
|
||||||
outptr[2] = inptr[2];
|
|
||||||
outptr[3] = inptr[3];
|
|
||||||
# endif
|
|
||||||
outptr += 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
*inptrp = inptr;
|
|
||||||
*outptrp = outptr;
|
|
||||||
|
|
||||||
/* Determine the status. */
|
|
||||||
if (*inptrp == inend)
|
|
||||||
result = __GCONV_EMPTY_INPUT;
|
|
||||||
else if (*outptrp + 4 > outend)
|
|
||||||
result = __GCONV_FULL_OUTPUT;
|
|
||||||
else
|
|
||||||
result = __GCONV_INCOMPLETE_INPUT;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
__attribute ((always_inline))
|
__attribute ((always_inline))
|
||||||
|
@ -453,11 +333,12 @@ internal_ucs4le_loop (struct __gconv_step *step,
|
||||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||||
/* Sigh, we have to do some real work. */
|
/* Sigh, we have to do some real work. */
|
||||||
size_t cnt;
|
size_t cnt;
|
||||||
uint32_t *outptr32 = (uint32_t *) outptr;
|
|
||||||
|
|
||||||
for (cnt = 0; cnt < n_convert; ++cnt, inptr += 4)
|
for (cnt = 0; cnt < n_convert; ++cnt, inptr += 4, outptr += 4)
|
||||||
*outptr32++ = bswap_32 (*(const uint32_t *) inptr);
|
{
|
||||||
outptr = (unsigned char *) outptr32;
|
uint32_t val = get32 (inptr);
|
||||||
|
put32 (outptr, __builtin_bswap32 (val));
|
||||||
|
}
|
||||||
|
|
||||||
*inptrp = inptr;
|
*inptrp = inptr;
|
||||||
*outptrp = outptr;
|
*outptrp = outptr;
|
||||||
|
@ -480,59 +361,6 @@ internal_ucs4le_loop (struct __gconv_step *step,
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !_STRING_ARCH_unaligned
|
|
||||||
static inline int
|
|
||||||
__attribute ((always_inline))
|
|
||||||
internal_ucs4le_loop_unaligned (struct __gconv_step *step,
|
|
||||||
struct __gconv_step_data *step_data,
|
|
||||||
const unsigned char **inptrp,
|
|
||||||
const unsigned char *inend,
|
|
||||||
unsigned char **outptrp,
|
|
||||||
const unsigned char *outend,
|
|
||||||
size_t *irreversible)
|
|
||||||
{
|
|
||||||
const unsigned char *inptr = *inptrp;
|
|
||||||
unsigned char *outptr = *outptrp;
|
|
||||||
size_t n_convert = MIN (inend - inptr, outend - outptr) / 4;
|
|
||||||
int result;
|
|
||||||
|
|
||||||
# if __BYTE_ORDER == __BIG_ENDIAN
|
|
||||||
/* Sigh, we have to do some real work. */
|
|
||||||
size_t cnt;
|
|
||||||
|
|
||||||
for (cnt = 0; cnt < n_convert; ++cnt, inptr += 4, outptr += 4)
|
|
||||||
{
|
|
||||||
outptr[0] = inptr[3];
|
|
||||||
outptr[1] = inptr[2];
|
|
||||||
outptr[2] = inptr[1];
|
|
||||||
outptr[3] = inptr[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
*inptrp = inptr;
|
|
||||||
*outptrp = outptr;
|
|
||||||
# elif __BYTE_ORDER == __LITTLE_ENDIAN
|
|
||||||
/* Simply copy the data. */
|
|
||||||
*inptrp = inptr + n_convert * 4;
|
|
||||||
*outptrp = __mempcpy (outptr, inptr, n_convert * 4);
|
|
||||||
# else
|
|
||||||
# error "This endianess is not supported."
|
|
||||||
# endif
|
|
||||||
|
|
||||||
/* Determine the status. */
|
|
||||||
if (*inptrp == inend)
|
|
||||||
result = __GCONV_EMPTY_INPUT;
|
|
||||||
else if (*inptrp + 4 > inend)
|
|
||||||
result = __GCONV_INCOMPLETE_INPUT;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
assert (*outptrp + 4 > outend);
|
|
||||||
result = __GCONV_FULL_OUTPUT;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
__attribute ((always_inline))
|
__attribute ((always_inline))
|
||||||
|
@ -612,12 +440,9 @@ ucs4le_internal_loop (struct __gconv_step *step,
|
||||||
|
|
||||||
for (; inptr + 4 <= inend && outptr + 4 <= outend; inptr += 4)
|
for (; inptr + 4 <= inend && outptr + 4 <= outend; inptr += 4)
|
||||||
{
|
{
|
||||||
uint32_t inval;
|
uint32_t inval = get32 (inptr);
|
||||||
|
|
||||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||||
inval = bswap_32 (*(const uint32_t *) inptr);
|
inval = __builtin_bswap32 (inval);
|
||||||
#else
|
|
||||||
inval = *(const uint32_t *) inptr;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (__glibc_unlikely (inval > 0x7fffffff))
|
if (__glibc_unlikely (inval > 0x7fffffff))
|
||||||
|
@ -642,7 +467,7 @@ ucs4le_internal_loop (struct __gconv_step *step,
|
||||||
return __GCONV_ILLEGAL_INPUT;
|
return __GCONV_ILLEGAL_INPUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
*((uint32_t *) outptr) = inval;
|
put32 (outptr, inval);
|
||||||
outptr += sizeof (uint32_t);
|
outptr += sizeof (uint32_t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -663,79 +488,6 @@ ucs4le_internal_loop (struct __gconv_step *step,
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !_STRING_ARCH_unaligned
|
|
||||||
static inline int
|
|
||||||
__attribute ((always_inline))
|
|
||||||
ucs4le_internal_loop_unaligned (struct __gconv_step *step,
|
|
||||||
struct __gconv_step_data *step_data,
|
|
||||||
const unsigned char **inptrp,
|
|
||||||
const unsigned char *inend,
|
|
||||||
unsigned char **outptrp,
|
|
||||||
const unsigned char *outend,
|
|
||||||
size_t *irreversible)
|
|
||||||
{
|
|
||||||
int flags = step_data->__flags;
|
|
||||||
const unsigned char *inptr = *inptrp;
|
|
||||||
unsigned char *outptr = *outptrp;
|
|
||||||
int result;
|
|
||||||
|
|
||||||
for (; inptr + 4 <= inend && outptr + 4 <= outend; inptr += 4)
|
|
||||||
{
|
|
||||||
if (__glibc_unlikely (inptr[3] > 0x80))
|
|
||||||
{
|
|
||||||
/* The value is too large. We don't try transliteration here since
|
|
||||||
this is not an error because of the lack of possibilities to
|
|
||||||
represent the result. This is a genuine bug in the input since
|
|
||||||
UCS4 does not allow such values. */
|
|
||||||
if (irreversible == NULL)
|
|
||||||
/* We are transliterating, don't try to correct anything. */
|
|
||||||
return __GCONV_ILLEGAL_INPUT;
|
|
||||||
|
|
||||||
if (flags & __GCONV_IGNORE_ERRORS)
|
|
||||||
{
|
|
||||||
/* Just ignore this character. */
|
|
||||||
++*irreversible;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
*inptrp = inptr;
|
|
||||||
*outptrp = outptr;
|
|
||||||
return __GCONV_ILLEGAL_INPUT;
|
|
||||||
}
|
|
||||||
|
|
||||||
# if __BYTE_ORDER == __BIG_ENDIAN
|
|
||||||
outptr[3] = inptr[0];
|
|
||||||
outptr[2] = inptr[1];
|
|
||||||
outptr[1] = inptr[2];
|
|
||||||
outptr[0] = inptr[3];
|
|
||||||
# else
|
|
||||||
outptr[0] = inptr[0];
|
|
||||||
outptr[1] = inptr[1];
|
|
||||||
outptr[2] = inptr[2];
|
|
||||||
outptr[3] = inptr[3];
|
|
||||||
# endif
|
|
||||||
|
|
||||||
outptr += 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
*inptrp = inptr;
|
|
||||||
*outptrp = outptr;
|
|
||||||
|
|
||||||
/* Determine the status. */
|
|
||||||
if (*inptrp == inend)
|
|
||||||
result = __GCONV_EMPTY_INPUT;
|
|
||||||
else if (*inptrp + 4 > inend)
|
|
||||||
result = __GCONV_INCOMPLETE_INPUT;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
assert (*outptrp + 4 > outend);
|
|
||||||
result = __GCONV_FULL_OUTPUT;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
__attribute ((always_inline))
|
__attribute ((always_inline))
|
||||||
|
|
66
iconv/loop.c
66
iconv/loop.c
|
@ -58,12 +58,7 @@
|
||||||
#include <libc-diag.h>
|
#include <libc-diag.h>
|
||||||
|
|
||||||
#undef FCTNAME2
|
#undef FCTNAME2
|
||||||
#if _STRING_ARCH_unaligned || !defined DEFINE_UNALIGNED
|
#define FCTNAME(name) name
|
||||||
# define FCTNAME2(name) name
|
|
||||||
#else
|
|
||||||
# define FCTNAME2(name) name##_unaligned
|
|
||||||
#endif
|
|
||||||
#define FCTNAME(name) FCTNAME2(name)
|
|
||||||
|
|
||||||
|
|
||||||
/* We need at least one byte for the next round. */
|
/* We need at least one byte for the next round. */
|
||||||
|
@ -279,20 +274,9 @@ FCTNAME (LOOPFCT) (struct __gconv_step *step,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Include the file a second time to define the function to handle
|
#if MAX_NEEDED_INPUT > 1
|
||||||
unaligned access. */
|
# define SINGLE(fct) SINGLE2 (fct)
|
||||||
#if !defined DEFINE_UNALIGNED && !_STRING_ARCH_unaligned \
|
# define SINGLE2(fct) fct##_single
|
||||||
&& MIN_NEEDED_INPUT != 1 && MAX_NEEDED_INPUT % MIN_NEEDED_INPUT == 0 \
|
|
||||||
&& MIN_NEEDED_OUTPUT != 1 && MAX_NEEDED_OUTPUT % MIN_NEEDED_OUTPUT == 0
|
|
||||||
# undef unaligned
|
|
||||||
|
|
||||||
# define DEFINE_UNALIGNED
|
|
||||||
# include "loop.c"
|
|
||||||
# undef DEFINE_UNALIGNED
|
|
||||||
#else
|
|
||||||
# if MAX_NEEDED_INPUT > 1
|
|
||||||
# define SINGLE(fct) SINGLE2 (fct)
|
|
||||||
# define SINGLE2(fct) fct##_single
|
|
||||||
static inline int
|
static inline int
|
||||||
__attribute ((always_inline))
|
__attribute ((always_inline))
|
||||||
SINGLE(LOOPFCT) (struct __gconv_step *step,
|
SINGLE(LOOPFCT) (struct __gconv_step *step,
|
||||||
|
@ -302,37 +286,37 @@ SINGLE(LOOPFCT) (struct __gconv_step *step,
|
||||||
size_t *irreversible EXTRA_LOOP_DECLS)
|
size_t *irreversible EXTRA_LOOP_DECLS)
|
||||||
{
|
{
|
||||||
mbstate_t *state = step_data->__statep;
|
mbstate_t *state = step_data->__statep;
|
||||||
# ifdef LOOP_NEED_FLAGS
|
# ifdef LOOP_NEED_FLAGS
|
||||||
int flags = step_data->__flags;
|
int flags = step_data->__flags;
|
||||||
# endif
|
# endif
|
||||||
# ifdef LOOP_NEED_DATA
|
# ifdef LOOP_NEED_DATA
|
||||||
void *data = step->__data;
|
void *data = step->__data;
|
||||||
# endif
|
# endif
|
||||||
int result = __GCONV_OK;
|
int result = __GCONV_OK;
|
||||||
unsigned char bytebuf[MAX_NEEDED_INPUT];
|
unsigned char bytebuf[MAX_NEEDED_INPUT];
|
||||||
const unsigned char *inptr = *inptrp;
|
const unsigned char *inptr = *inptrp;
|
||||||
unsigned char *outptr = *outptrp;
|
unsigned char *outptr = *outptrp;
|
||||||
size_t inlen;
|
size_t inlen;
|
||||||
|
|
||||||
# ifdef INIT_PARAMS
|
# ifdef INIT_PARAMS
|
||||||
INIT_PARAMS;
|
INIT_PARAMS;
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
# ifdef UNPACK_BYTES
|
# ifdef UNPACK_BYTES
|
||||||
UNPACK_BYTES
|
UNPACK_BYTES
|
||||||
# else
|
# else
|
||||||
/* Add the bytes from the state to the input buffer. */
|
/* Add the bytes from the state to the input buffer. */
|
||||||
assert ((state->__count & 7) <= sizeof (state->__value));
|
assert ((state->__count & 7) <= sizeof (state->__value));
|
||||||
for (inlen = 0; inlen < (size_t) (state->__count & 7); ++inlen)
|
for (inlen = 0; inlen < (size_t) (state->__count & 7); ++inlen)
|
||||||
bytebuf[inlen] = state->__value.__wchb[inlen];
|
bytebuf[inlen] = state->__value.__wchb[inlen];
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
/* Are there enough bytes in the input buffer? */
|
/* Are there enough bytes in the input buffer? */
|
||||||
if (MIN_NEEDED_INPUT > 1
|
if (MIN_NEEDED_INPUT > 1
|
||||||
&& __builtin_expect (inptr + (MIN_NEEDED_INPUT - inlen) > inend, 0))
|
&& __builtin_expect (inptr + (MIN_NEEDED_INPUT - inlen) > inend, 0))
|
||||||
{
|
{
|
||||||
*inptrp = inend;
|
*inptrp = inend;
|
||||||
# ifdef STORE_REST
|
# ifdef STORE_REST
|
||||||
|
|
||||||
/* Building with -O3 GCC emits a `array subscript is above array
|
/* Building with -O3 GCC emits a `array subscript is above array
|
||||||
bounds' warning. GCC BZ #64739 has been opened for this. */
|
bounds' warning. GCC BZ #64739 has been opened for this. */
|
||||||
|
@ -347,14 +331,14 @@ SINGLE(LOOPFCT) (struct __gconv_step *step,
|
||||||
inend = &bytebuf[inlen];
|
inend = &bytebuf[inlen];
|
||||||
|
|
||||||
STORE_REST
|
STORE_REST
|
||||||
# else
|
# else
|
||||||
/* We don't have enough input for another complete input
|
/* We don't have enough input for another complete input
|
||||||
character. */
|
character. */
|
||||||
size_t inlen_after = inlen + (inend - inptr);
|
size_t inlen_after = inlen + (inend - inptr);
|
||||||
assert (inlen_after <= sizeof (state->__value.__wchb));
|
assert (inlen_after <= sizeof (state->__value.__wchb));
|
||||||
for (; inlen < inlen_after; inlen++)
|
for (; inlen < inlen_after; inlen++)
|
||||||
state->__value.__wchb[inlen] = *inptr++;
|
state->__value.__wchb[inlen] = *inptr++;
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
return __GCONV_INCOMPLETE_INPUT;
|
return __GCONV_INCOMPLETE_INPUT;
|
||||||
}
|
}
|
||||||
|
@ -406,11 +390,11 @@ SINGLE(LOOPFCT) (struct __gconv_step *step,
|
||||||
result = __GCONV_OK;
|
result = __GCONV_OK;
|
||||||
|
|
||||||
/* Clear the state buffer. */
|
/* Clear the state buffer. */
|
||||||
# ifdef CLEAR_STATE
|
# ifdef CLEAR_STATE
|
||||||
CLEAR_STATE;
|
CLEAR_STATE;
|
||||||
# else
|
# else
|
||||||
state->__count &= ~7;
|
state->__count &= ~7;
|
||||||
# endif
|
# endif
|
||||||
}
|
}
|
||||||
else if (result == __GCONV_INCOMPLETE_INPUT)
|
else if (result == __GCONV_INCOMPLETE_INPUT)
|
||||||
{
|
{
|
||||||
|
@ -419,11 +403,11 @@ SINGLE(LOOPFCT) (struct __gconv_step *step,
|
||||||
assert (inend != &bytebuf[MAX_NEEDED_INPUT]);
|
assert (inend != &bytebuf[MAX_NEEDED_INPUT]);
|
||||||
|
|
||||||
*inptrp += inend - bytebuf - (state->__count & 7);
|
*inptrp += inend - bytebuf - (state->__count & 7);
|
||||||
# ifdef STORE_REST
|
# ifdef STORE_REST
|
||||||
inptrp = &inptr;
|
inptrp = &inptr;
|
||||||
|
|
||||||
STORE_REST
|
STORE_REST
|
||||||
# else
|
# else
|
||||||
/* We don't have enough input for another complete input
|
/* We don't have enough input for another complete input
|
||||||
character. */
|
character. */
|
||||||
assert (inend - inptr > (state->__count & ~7));
|
assert (inend - inptr > (state->__count & ~7));
|
||||||
|
@ -432,14 +416,13 @@ SINGLE(LOOPFCT) (struct __gconv_step *step,
|
||||||
for (inlen = 0; inlen < inend - inptr; inlen++)
|
for (inlen = 0; inlen < inend - inptr; inlen++)
|
||||||
state->__value.__wchb[inlen] = inptr[inlen];
|
state->__value.__wchb[inlen] = inptr[inlen];
|
||||||
inptr = inend;
|
inptr = inend;
|
||||||
# endif
|
# endif
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
# undef SINGLE
|
# undef SINGLE
|
||||||
# undef SINGLE2
|
# undef SINGLE2
|
||||||
# endif
|
|
||||||
|
|
||||||
|
|
||||||
# ifdef ONEBYTE_BODY
|
# ifdef ONEBYTE_BODY
|
||||||
|
@ -471,4 +454,3 @@ gconv_btowc (struct __gconv_step *step, unsigned char c)
|
||||||
#undef LOOP_NEED_STATE
|
#undef LOOP_NEED_STATE
|
||||||
#undef LOOP_NEED_FLAGS
|
#undef LOOP_NEED_FLAGS
|
||||||
#undef LOOP_NEED_DATA
|
#undef LOOP_NEED_DATA
|
||||||
#undef unaligned
|
|
||||||
|
|
118
iconv/skeleton.c
118
iconv/skeleton.c
|
@ -448,33 +448,6 @@ FUNCTION_NAME (struct __gconv_step *step, struct __gconv_step_data *data,
|
||||||
size_t lirreversible = 0;
|
size_t lirreversible = 0;
|
||||||
size_t *lirreversiblep = irreversible ? &lirreversible : NULL;
|
size_t *lirreversiblep = irreversible ? &lirreversible : NULL;
|
||||||
|
|
||||||
/* The following assumes that encodings, which have a variable length
|
|
||||||
what might unalign a buffer even though it is an aligned in the
|
|
||||||
beginning, either don't have the minimal number of bytes as a divisor
|
|
||||||
of the maximum length or have a minimum length of 1. This is true
|
|
||||||
for all known and supported encodings.
|
|
||||||
We use && instead of || to combine the subexpression for the FROM
|
|
||||||
encoding and for the TO encoding, because usually one of them is
|
|
||||||
INTERNAL, for which the subexpression evaluates to 1, but INTERNAL
|
|
||||||
buffers are always aligned correctly. */
|
|
||||||
#define POSSIBLY_UNALIGNED \
|
|
||||||
(!_STRING_ARCH_unaligned \
|
|
||||||
&& (((FROM_LOOP_MIN_NEEDED_FROM != 1 \
|
|
||||||
&& FROM_LOOP_MAX_NEEDED_FROM % FROM_LOOP_MIN_NEEDED_FROM == 0) \
|
|
||||||
&& (FROM_LOOP_MIN_NEEDED_TO != 1 \
|
|
||||||
&& FROM_LOOP_MAX_NEEDED_TO % FROM_LOOP_MIN_NEEDED_TO == 0)) \
|
|
||||||
|| ((TO_LOOP_MIN_NEEDED_FROM != 1 \
|
|
||||||
&& TO_LOOP_MAX_NEEDED_FROM % TO_LOOP_MIN_NEEDED_FROM == 0) \
|
|
||||||
&& (TO_LOOP_MIN_NEEDED_TO != 1 \
|
|
||||||
&& TO_LOOP_MAX_NEEDED_TO % TO_LOOP_MIN_NEEDED_TO == 0))))
|
|
||||||
#if POSSIBLY_UNALIGNED
|
|
||||||
int unaligned;
|
|
||||||
# define GEN_unaligned(name) GEN_unaligned2 (name)
|
|
||||||
# define GEN_unaligned2(name) name##_unaligned
|
|
||||||
#else
|
|
||||||
# define unaligned 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef PREPARE_LOOP
|
#ifdef PREPARE_LOOP
|
||||||
PREPARE_LOOP
|
PREPARE_LOOP
|
||||||
#endif
|
#endif
|
||||||
|
@ -514,18 +487,6 @@ FUNCTION_NAME (struct __gconv_step *step, struct __gconv_step_data *data,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if POSSIBLY_UNALIGNED
|
|
||||||
unaligned =
|
|
||||||
((FROM_DIRECTION
|
|
||||||
&& ((uintptr_t) inptr % FROM_LOOP_MIN_NEEDED_FROM != 0
|
|
||||||
|| ((data->__flags & __GCONV_IS_LAST)
|
|
||||||
&& (uintptr_t) outbuf % FROM_LOOP_MIN_NEEDED_TO != 0)))
|
|
||||||
|| (!FROM_DIRECTION
|
|
||||||
&& (((data->__flags & __GCONV_IS_LAST)
|
|
||||||
&& (uintptr_t) outbuf % TO_LOOP_MIN_NEEDED_TO != 0)
|
|
||||||
|| (uintptr_t) inptr % TO_LOOP_MIN_NEEDED_FROM != 0)));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
/* Remember the start value for this round. */
|
/* Remember the start value for this round. */
|
||||||
|
@ -543,34 +504,14 @@ FUNCTION_NAME (struct __gconv_step *step, struct __gconv_step_data *data,
|
||||||
SAVE_RESET_STATE (1);
|
SAVE_RESET_STATE (1);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (__glibc_likely (!unaligned))
|
if (FROM_DIRECTION)
|
||||||
{
|
/* Run the conversion loop. */
|
||||||
if (FROM_DIRECTION)
|
status = FROM_LOOP (step, data, inptrp, inend, &outbuf, outend,
|
||||||
/* Run the conversion loop. */
|
lirreversiblep EXTRA_LOOP_ARGS);
|
||||||
status = FROM_LOOP (step, data, inptrp, inend, &outbuf, outend,
|
|
||||||
lirreversiblep EXTRA_LOOP_ARGS);
|
|
||||||
else
|
|
||||||
/* Run the conversion loop. */
|
|
||||||
status = TO_LOOP (step, data, inptrp, inend, &outbuf, outend,
|
|
||||||
lirreversiblep EXTRA_LOOP_ARGS);
|
|
||||||
}
|
|
||||||
#if POSSIBLY_UNALIGNED
|
|
||||||
else
|
else
|
||||||
{
|
/* Run the conversion loop. */
|
||||||
if (FROM_DIRECTION)
|
status = TO_LOOP (step, data, inptrp, inend, &outbuf, outend,
|
||||||
/* Run the conversion loop. */
|
lirreversiblep EXTRA_LOOP_ARGS);
|
||||||
status = GEN_unaligned (FROM_LOOP) (step, data, inptrp, inend,
|
|
||||||
&outbuf, outend,
|
|
||||||
lirreversiblep
|
|
||||||
EXTRA_LOOP_ARGS);
|
|
||||||
else
|
|
||||||
/* Run the conversion loop. */
|
|
||||||
status = GEN_unaligned (TO_LOOP) (step, data, inptrp, inend,
|
|
||||||
&outbuf, outend,
|
|
||||||
lirreversiblep
|
|
||||||
EXTRA_LOOP_ARGS);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* If we were called as part of an error handling module we
|
/* If we were called as part of an error handling module we
|
||||||
don't do anything else here. */
|
don't do anything else here. */
|
||||||
|
@ -635,41 +576,18 @@ FUNCTION_NAME (struct __gconv_step *step, struct __gconv_step_data *data,
|
||||||
SAVE_RESET_STATE (0);
|
SAVE_RESET_STATE (0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (__glibc_likely (!unaligned))
|
if (FROM_DIRECTION)
|
||||||
{
|
/* Run the conversion loop. */
|
||||||
if (FROM_DIRECTION)
|
nstatus = FROM_LOOP (step, data, inptrp, inend,
|
||||||
/* Run the conversion loop. */
|
&outbuf, outerr,
|
||||||
nstatus = FROM_LOOP (step, data, inptrp, inend,
|
lirreversiblep
|
||||||
&outbuf, outerr,
|
EXTRA_LOOP_ARGS);
|
||||||
lirreversiblep
|
|
||||||
EXTRA_LOOP_ARGS);
|
|
||||||
else
|
|
||||||
/* Run the conversion loop. */
|
|
||||||
nstatus = TO_LOOP (step, data, inptrp, inend,
|
|
||||||
&outbuf, outerr,
|
|
||||||
lirreversiblep
|
|
||||||
EXTRA_LOOP_ARGS);
|
|
||||||
}
|
|
||||||
#if POSSIBLY_UNALIGNED
|
|
||||||
else
|
else
|
||||||
{
|
/* Run the conversion loop. */
|
||||||
if (FROM_DIRECTION)
|
nstatus = TO_LOOP (step, data, inptrp, inend,
|
||||||
/* Run the conversion loop. */
|
&outbuf, outerr,
|
||||||
nstatus = GEN_unaligned (FROM_LOOP) (step, data,
|
lirreversiblep
|
||||||
inptrp, inend,
|
EXTRA_LOOP_ARGS);
|
||||||
&outbuf,
|
|
||||||
outerr,
|
|
||||||
lirreversiblep
|
|
||||||
EXTRA_LOOP_ARGS);
|
|
||||||
else
|
|
||||||
/* Run the conversion loop. */
|
|
||||||
nstatus = GEN_unaligned (TO_LOOP) (step, data,
|
|
||||||
inptrp, inend,
|
|
||||||
&outbuf, outerr,
|
|
||||||
lirreversiblep
|
|
||||||
EXTRA_LOOP_ARGS);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* We must run out of output buffer space in this
|
/* We must run out of output buffer space in this
|
||||||
rerun. */
|
rerun. */
|
||||||
|
|
Loading…
Add table
Reference in a new issue