Home | History | Annotate | Line # | Download | only in import
mbrtowc.c revision 1.1
      1  1.1  christos /* Convert multibyte character to wide character.
      2  1.1  christos    Copyright (C) 1999-2002, 2005-2020 Free Software Foundation, Inc.
      3  1.1  christos    Written by Bruno Haible <bruno (at) clisp.org>, 2008.
      4  1.1  christos 
      5  1.1  christos    This program is free software: you can redistribute it and/or modify
      6  1.1  christos    it under the terms of the GNU General Public License as published by
      7  1.1  christos    the Free Software Foundation; either version 3 of the License, or
      8  1.1  christos    (at your option) any later version.
      9  1.1  christos 
     10  1.1  christos    This program is distributed in the hope that it will be useful,
     11  1.1  christos    but WITHOUT ANY WARRANTY; without even the implied warranty of
     12  1.1  christos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13  1.1  christos    GNU General Public License for more details.
     14  1.1  christos 
     15  1.1  christos    You should have received a copy of the GNU General Public License
     16  1.1  christos    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
     17  1.1  christos 
     18  1.1  christos #include <config.h>
     19  1.1  christos 
     20  1.1  christos /* Specification.  */
     21  1.1  christos #include <wchar.h>
     22  1.1  christos 
     23  1.1  christos #if GNULIB_defined_mbstate_t
     24  1.1  christos /* Implement mbrtowc() on top of mbtowc() for the non-UTF-8 locales
     25  1.1  christos    and directly for the UTF-8 locales.  */
     26  1.1  christos 
     27  1.1  christos # include <errno.h>
     28  1.1  christos # include <stdint.h>
     29  1.1  christos # include <stdlib.h>
     30  1.1  christos 
     31  1.1  christos # if defined _WIN32 && !defined __CYGWIN__
     32  1.1  christos 
     33  1.1  christos #  define WIN32_LEAN_AND_MEAN  /* avoid including junk */
     34  1.1  christos #  include <windows.h>
     35  1.1  christos 
     36  1.1  christos # elif HAVE_PTHREAD_API
     37  1.1  christos 
     38  1.1  christos #  include <pthread.h>
     39  1.1  christos #  if HAVE_THREADS_H && HAVE_WEAK_SYMBOLS
     40  1.1  christos #   include <threads.h>
     41  1.1  christos #   pragma weak thrd_exit
     42  1.1  christos #   define c11_threads_in_use() (thrd_exit != NULL)
     43  1.1  christos #  else
     44  1.1  christos #   define c11_threads_in_use() 0
     45  1.1  christos #  endif
     46  1.1  christos 
     47  1.1  christos # elif HAVE_THREADS_H
     48  1.1  christos 
     49  1.1  christos #  include <threads.h>
     50  1.1  christos 
     51  1.1  christos # endif
     52  1.1  christos 
     53  1.1  christos # include "attribute.h"
     54  1.1  christos # include "verify.h"
     55  1.1  christos # include "lc-charset-dispatch.h"
     56  1.1  christos # include "mbtowc-lock.h"
     57  1.1  christos 
     58  1.1  christos verify (sizeof (mbstate_t) >= 4);
     59  1.1  christos static char internal_state[4];
     60  1.1  christos 
     61  1.1  christos size_t
     62  1.1  christos mbrtowc (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps)
     63  1.1  christos {
     64  1.1  christos # define FITS_IN_CHAR_TYPE(wc)  ((wc) <= WCHAR_MAX)
     65  1.1  christos # include "mbrtowc-impl.h"
     66  1.1  christos }
     67  1.1  christos 
     68  1.1  christos #else
     69  1.1  christos /* Override the system's mbrtowc() function.  */
     70  1.1  christos 
     71  1.1  christos # if MBRTOWC_IN_C_LOCALE_MAYBE_EILSEQ
     72  1.1  christos #  include "hard-locale.h"
     73  1.1  christos #  include <locale.h>
     74  1.1  christos # endif
     75  1.1  christos 
     76  1.1  christos # undef mbrtowc
     77  1.1  christos 
     78  1.1  christos size_t
     79  1.1  christos rpl_mbrtowc (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps)
     80  1.1  christos {
     81  1.1  christos   size_t ret;
     82  1.1  christos   wchar_t wc;
     83  1.1  christos 
     84  1.1  christos # if MBRTOWC_NULL_ARG2_BUG || MBRTOWC_RETVAL_BUG || MBRTOWC_EMPTY_INPUT_BUG
     85  1.1  christos   if (s == NULL)
     86  1.1  christos     {
     87  1.1  christos       pwc = NULL;
     88  1.1  christos       s = "";
     89  1.1  christos       n = 1;
     90  1.1  christos     }
     91  1.1  christos # endif
     92  1.1  christos 
     93  1.1  christos # if MBRTOWC_EMPTY_INPUT_BUG
     94  1.1  christos   if (n == 0)
     95  1.1  christos     return (size_t) -2;
     96  1.1  christos # endif
     97  1.1  christos 
     98  1.1  christos   if (! pwc)
     99  1.1  christos     pwc = &wc;
    100  1.1  christos 
    101  1.1  christos # if MBRTOWC_RETVAL_BUG
    102  1.1  christos   {
    103  1.1  christos     static mbstate_t internal_state;
    104  1.1  christos 
    105  1.1  christos     /* Override mbrtowc's internal state.  We cannot call mbsinit() on the
    106  1.1  christos        hidden internal state, but we can call it on our variable.  */
    107  1.1  christos     if (ps == NULL)
    108  1.1  christos       ps = &internal_state;
    109  1.1  christos 
    110  1.1  christos     if (!mbsinit (ps))
    111  1.1  christos       {
    112  1.1  christos         /* Parse the rest of the multibyte character byte for byte.  */
    113  1.1  christos         size_t count = 0;
    114  1.1  christos         for (; n > 0; s++, n--)
    115  1.1  christos           {
    116  1.1  christos             ret = mbrtowc (&wc, s, 1, ps);
    117  1.1  christos 
    118  1.1  christos             if (ret == (size_t)(-1))
    119  1.1  christos               return (size_t)(-1);
    120  1.1  christos             count++;
    121  1.1  christos             if (ret != (size_t)(-2))
    122  1.1  christos               {
    123  1.1  christos                 /* The multibyte character has been completed.  */
    124  1.1  christos                 *pwc = wc;
    125  1.1  christos                 return (wc == 0 ? 0 : count);
    126  1.1  christos               }
    127  1.1  christos           }
    128  1.1  christos         return (size_t)(-2);
    129  1.1  christos       }
    130  1.1  christos   }
    131  1.1  christos # endif
    132  1.1  christos 
    133  1.1  christos # if MBRTOWC_STORES_INCOMPLETE_BUG
    134  1.1  christos   ret = mbrtowc (&wc, s, n, ps);
    135  1.1  christos   if (ret < (size_t) -2 && pwc != NULL)
    136  1.1  christos     *pwc = wc;
    137  1.1  christos # else
    138  1.1  christos   ret = mbrtowc (pwc, s, n, ps);
    139  1.1  christos # endif
    140  1.1  christos 
    141  1.1  christos # if MBRTOWC_NUL_RETVAL_BUG
    142  1.1  christos   if (ret < (size_t) -2 && !*pwc)
    143  1.1  christos     return 0;
    144  1.1  christos # endif
    145  1.1  christos 
    146  1.1  christos # if MBRTOWC_IN_C_LOCALE_MAYBE_EILSEQ
    147  1.1  christos   if ((size_t) -2 <= ret && n != 0 && ! hard_locale (LC_CTYPE))
    148  1.1  christos     {
    149  1.1  christos       unsigned char uc = *s;
    150  1.1  christos       *pwc = uc;
    151  1.1  christos       return 1;
    152  1.1  christos     }
    153  1.1  christos # endif
    154  1.1  christos 
    155  1.1  christos   return ret;
    156  1.1  christos }
    157  1.1  christos 
    158  1.1  christos #endif
    159