Back to index

glibc  2.9
iconv.c
Go to the documentation of this file.
00001 /* Convert characters in input buffer using conversion descriptor to
00002    output buffer.
00003    Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
00004    This file is part of the GNU C Library.
00005    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
00006 
00007    The GNU C Library is free software; you can redistribute it and/or
00008    modify it under the terms of the GNU Lesser General Public
00009    License as published by the Free Software Foundation; either
00010    version 2.1 of the License, or (at your option) any later version.
00011 
00012    The GNU C Library is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015    Lesser General Public License for more details.
00016 
00017    You should have received a copy of the GNU Lesser General Public
00018    License along with the GNU C Library; if not, write to the Free
00019    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00020    02111-1307 USA.  */
00021 
00022 #include <stddef.h> /* for NULL */
00023 #include <errno.h>
00024 #include <iconv.h>
00025 
00026 #include <gconv_int.h>
00027 
00028 #include <assert.h>
00029 
00030 
00031 size_t
00032 iconv (iconv_t cd, char **inbuf, size_t *inbytesleft, char **outbuf,
00033        size_t *outbytesleft)
00034 {
00035   __gconv_t gcd = (__gconv_t) cd;
00036   char *outstart = outbuf ? *outbuf : NULL;
00037   size_t irreversible;
00038   int result;
00039 
00040   if (__builtin_expect (inbuf == NULL || *inbuf == NULL, 0))
00041     {
00042       if (outbuf == NULL || *outbuf == NULL)
00043        result = __gconv (gcd, NULL, NULL, NULL, NULL, &irreversible);
00044       else
00045        result = __gconv (gcd, NULL, NULL, (unsigned char **) outbuf,
00046                        (unsigned char *) (outstart + *outbytesleft),
00047                        &irreversible);
00048     }
00049   else
00050     {
00051       const char *instart = *inbuf;
00052 
00053       result = __gconv (gcd, (const unsigned char **) inbuf,
00054                      (const unsigned char *)  (*inbuf + *inbytesleft),
00055                      (unsigned char **) outbuf,
00056                      (unsigned char *) (*outbuf + *outbytesleft),
00057                      &irreversible);
00058 
00059       *inbytesleft -= *inbuf - instart;
00060     }
00061   if (outstart != NULL)
00062     *outbytesleft -= *outbuf - outstart;
00063 
00064   switch (__builtin_expect (result, __GCONV_OK))
00065     {
00066     case __GCONV_ILLEGAL_DESCRIPTOR:
00067       __set_errno (EBADF);
00068       irreversible = (size_t) -1L;
00069       break;
00070 
00071     case __GCONV_ILLEGAL_INPUT:
00072       __set_errno (EILSEQ);
00073       irreversible = (size_t) -1L;
00074       break;
00075 
00076     case __GCONV_FULL_OUTPUT:
00077       __set_errno (E2BIG);
00078       irreversible = (size_t) -1L;
00079       break;
00080 
00081     case __GCONV_INCOMPLETE_INPUT:
00082       __set_errno (EINVAL);
00083       irreversible = (size_t) -1L;
00084       break;
00085 
00086     case __GCONV_EMPTY_INPUT:
00087     case __GCONV_OK:
00088       /* Nothing.  */
00089       break;
00090 
00091     default:
00092       assert (!"Nothing like this should happen");
00093     }
00094 
00095   return irreversible;
00096 }