⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gconv_simple.c

📁 Newlib 嵌入式 C库 标准实现代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* Simple transformations functions.   Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.   This file is part of the GNU C Library.   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.   The GNU C Library is free software; you can redistribute it and/or   modify it under the terms of the GNU Lesser General Public   License as published by the Free Software Foundation; either   version 2.1 of the License, or (at your option) any later version.   The GNU C Library is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU   Lesser General Public License for more details.   You should have received a copy of the GNU Lesser General Public   License along with the GNU C Library; if not, write to the Free   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA   02111-1307 USA.  */#include <byteswap.h>#include <dlfcn.h>#include <endian.h>#include <errno.h>#include <gconv.h>#include <stdint.h>#include <stdlib.h>#include <string.h>#include <wchar.h>#include <sys/param.h>#define BUILTIN_ALIAS(s1, s2) /* nothing */#define BUILTIN_TRANSFORMATION(From, To, Cost, Name, Fct, MinF, MaxF, \			       MinT, MaxT) \  extern int Fct (struct __gconv_step *, struct __gconv_step_data *,	      \		  __const unsigned char **, __const unsigned char *,	      \		  unsigned char **, size_t *, int, int);#include "gconv_builtin.h"#ifndef EILSEQ# define EILSEQ EINVAL#endif/* Transform from the internal, UCS4-like format, to UCS4.  The   difference between the internal ucs4 format and the real UCS4   format is, if any, the endianess.  The Unicode/ISO 10646 says that   unless some higher protocol specifies it differently, the byte   order is big endian.*/#define DEFINE_INIT		0#define DEFINE_FINI		0#define MIN_NEEDED_FROM		4#define MIN_NEEDED_TO		4#define FROM_DIRECTION		1#define FROM_LOOP		internal_ucs4_loop#define TO_LOOP			internal_ucs4_loop /* This is not used.  */#define FUNCTION_NAME		__gconv_transform_internal_ucs4static inline intinternal_ucs4_loop (struct __gconv_step *step,		    struct __gconv_step_data *step_data,		    const unsigned char **inptrp, const unsigned char *inend,		    unsigned char **outptrp, 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)    {      *((uint32_t *) outptr) = bswap_32 (*(const uint32_t *) inptr);      outptr = (unsigned char *)((uint32_t *) outptr + 1);    }  *inptrp = inptr;  *outptrp = outptr;#elif __BYTE_ORDER == __BIG_ENDIAN  /* Simply copy the data.  */  *inptrp = inptr + n_convert * 4;  *outptrp = memcpy (outptr, inptr, n_convert * 4);  *outptrp += 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;}#ifndef _STRING_ARCH_unalignedstatic inline intinternal_ucs4_loop_unaligned (struct __gconv_step *step,			      struct __gconv_step_data *step_data,			      const unsigned char **inptrp,			      const unsigned char *inend,			      unsigned char **outptrp, 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 = memcpy (outptr, inptr, n_convert * 4);  *outptrp += 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;}#endifstatic inline intinternal_ucs4_loop_single (struct __gconv_step *step,			   struct __gconv_step_data *step_data,			   const unsigned char **inptrp,			   const unsigned char *inend,			   unsigned char **outptrp, unsigned char *outend,			   size_t *irreversible){  mbstate_t *state = step_data->__statep;  size_t cnt = state->__count & 7;  while (*inptrp < inend && cnt < 4)    state->__value.__wchb[cnt++] = *(*inptrp)++;  if (__builtin_expect (cnt < 4, 0))    {      /* Still not enough bytes.  Store the ones in the input buffer.  */      state->__count &= ~7;      state->__count |= cnt;      return __GCONV_INCOMPLETE_INPUT;    }#if __BYTE_ORDER == __LITTLE_ENDIAN  (*outptrp)[0] = state->__value.__wchb[3];  (*outptrp)[1] = state->__value.__wchb[2];  (*outptrp)[2] = state->__value.__wchb[1];  (*outptrp)[3] = state->__value.__wchb[0];  *outptrp += 4;#elif __BYTE_ORDER == __BIG_ENDIAN  {    uint32_t **p = (uint32_t **)outptrp;    uint32_t *q = *p;    /* XXX unaligned */    *q = state->__value.__wch;    outptrp = (unsigned char *)(p + 1);  }#else# error "This endianess is not supported."#endif  /* Clear the state buffer.  */  state->__count &= ~7;  return __GCONV_OK;}#include <iconv/skeleton.c>/* Transform from UCS4 to the internal, UCS4-like format.  Unlike   for the other direction we have to check for correct values here.  */#define DEFINE_INIT		0#define DEFINE_FINI		0#define MIN_NEEDED_FROM		4#define MIN_NEEDED_TO		4#define FROM_DIRECTION		1#define FROM_LOOP		ucs4_internal_loop#define TO_LOOP			ucs4_internal_loop /* This is not used.  */#define FUNCTION_NAME		__gconv_transform_ucs4_internalstatic inline intucs4_internal_loop (struct __gconv_step *step,		    struct __gconv_step_data *step_data,		    const unsigned char **inptrp, const unsigned char *inend,		    unsigned char **outptrp, unsigned char *outend,		    size_t *irreversible){  int flags = step_data->__flags;  const unsigned char *inptr = *inptrp;  unsigned char *outptr = *outptrp;  size_t n_convert = MIN (inend - inptr, outend - outptr) / 4;  int result;  size_t cnt;  for (cnt = 0; cnt < n_convert; ++cnt, inptr += 4)    {      uint32_t inval;#if __BYTE_ORDER == __LITTLE_ENDIAN      inval = bswap_32 (*(const uint32_t *) inptr);#else      inval = *(const uint32_t *) inptr;#endif      if (__builtin_expect (inval > 0x7fffffff, 0))	{	  /* 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 = *irreversible + 1;	      continue;	    }	  *inptrp = inptr;	  *outptrp = outptr;	  return __GCONV_ILLEGAL_INPUT;	}      *((uint32_t *) outptr) = inval;      outptr = (unsigned char *) ((uint32_t *) outptr + 1);    }  *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;}#ifndef _STRING_ARCH_unalignedstatic inline intucs4_internal_loop_unaligned (struct __gconv_step *step,			      struct __gconv_step_data *step_data,			      const unsigned char **inptrp,			      const unsigned char *inend,			      unsigned char **outptrp, unsigned char *outend,			      size_t *irreversible){  int flags = step_data->__flags;  const unsigned char *inptr = *inptrp;  unsigned char *outptr = *outptrp;  size_t n_convert = MIN (inend - inptr, outend - outptr) / 4;  int result;  size_t cnt;  for (cnt = 0; cnt < n_convert; ++cnt, inptr += 4)    {      if (__builtin_expect (inptr[0] > 0x80, 0))	{	  /* 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 = *irreversible + 1;	      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;}#endifstatic inline intucs4_internal_loop_single (struct __gconv_step *step,			   struct __gconv_step_data *step_data,			   const unsigned char **inptrp,			   const unsigned char *inend,			   unsigned char **outptrp, unsigned char *outend,			   size_t *irreversible){  mbstate_t *state = step_data->__statep;  int flags = step_data->__flags;  size_t cnt = state->__count & 7;  while (*inptrp < inend && cnt < 4)    state->__value.__wchb[cnt++] = *(*inptrp)++;  if (__builtin_expect (cnt < 4, 0))    {      /* Still not enough bytes.  Store the ones in the input buffer.  */      state->__count &= ~7;      state->__count |= cnt;      return __GCONV_INCOMPLETE_INPUT;    }  if (__builtin_expect (((unsigned char *) state->__value.__wchb)[0] > 0x80,			0))    {      /* 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 (!(flags & __GCONV_IGNORE_ERRORS))	{	  *inptrp -= cnt - (state->__count & 7);	  return __GCONV_ILLEGAL_INPUT;	}    }  else    {#if __BYTE_ORDER == __LITTLE_ENDIAN      (*outptrp)[0] = state->__value.__wchb[3];      (*outptrp)[1] = state->__value.__wchb[2];      (*outptrp)[2] = state->__value.__wchb[1];      (*outptrp)[3] = state->__value.__wchb[0];#elif __BYTE_ORDER == __BIG_ENDIAN      (*outptrp)[0] = state->__value.__wchb[0];      (*outptrp)[1] = state->__value.__wchb[1];      (*outptrp)[2] = state->__value.__wchb[2];      (*outptrp)[3] = state->__value.__wchb[3];#endif      *outptrp += 4;    }  /* Clear the state buffer.  */  state->__count &= ~7;  return __GCONV_OK;}#include <iconv/skeleton.c>/* Similarly for the little endian form.  */#define DEFINE_INIT		0#define DEFINE_FINI		0#define MIN_NEEDED_FROM		4#define MIN_NEEDED_TO		4#define FROM_DIRECTION		1#define FROM_LOOP		internal_ucs4le_loop#define TO_LOOP			internal_ucs4le_loop /* This is not used.  */#define FUNCTION_NAME		__gconv_transform_internal_ucs4lestatic inline intinternal_ucs4le_loop (struct __gconv_step *step,		      struct __gconv_step_data *step_data,		      const unsigned char **inptrp, const unsigned char *inend,		      unsigned char **outptrp, 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)    *((uint32_t *) outptr)++ = bswap_32 (*(const uint32_t *) inptr);  *inptrp = inptr;  *outptrp = outptr;#elif __BYTE_ORDER == __LITTLE_ENDIAN  /* Simply copy the data.  */  *inptrp = inptr + n_convert * 4;  *outptrp = memcpy (outptr, inptr, n_convert * 4);  *outptrp += n_convert * 4;#else

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -