root/maint/gnulib/lib/uniconv/u16-conv-to-enc.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. FUNC

   1 /* Conversion from UTF-16 to legacy encodings.
   2    Copyright (C) 2002, 2006-2021 Free Software Foundation, Inc.
   3 
   4    This file is free software.
   5    It is dual-licensed under "the GNU LGPLv3+ or the GNU GPLv2+".
   6    You can redistribute it and/or modify it under either
   7      - the terms of the GNU Lesser General Public License as published
   8        by the Free Software Foundation; either version 3, or (at your
   9        option) any later version, or
  10      - the terms of the GNU General Public License as published by the
  11        Free Software Foundation; either version 2, or (at your option)
  12        any later version, or
  13      - the same dual license "the GNU LGPLv3+ or the GNU GPLv2+".
  14 
  15    This file is distributed in the hope that it will be useful,
  16    but WITHOUT ANY WARRANTY; without even the implied warranty of
  17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  18    Lesser General Public License and the GNU General Public License
  19    for more details.
  20 
  21    You should have received a copy of the GNU Lesser General Public
  22    License and of the GNU General Public License along with this
  23    program.  If not, see <https://www.gnu.org/licenses/>.  */
  24 
  25 /* Written by Bruno Haible <bruno@clisp.org>.  */
  26 
  27 #include <config.h>
  28 
  29 /* Specification.  */
  30 #include "uniconv.h"
  31 
  32 #include <errno.h>
  33 #include <stdlib.h>
  34 #include <string.h>
  35 
  36 #include "striconveha.h"
  37 #include "unistr.h"
  38 
  39 #define SIZEOF(array) (sizeof (array) / sizeof (array[0]))
  40 
  41 /* Name of UTF-16 encoding with machine dependent endianness and alignment.  */
  42 #if defined _LIBICONV_VERSION || (((__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2)) && !defined __UCLIBC__)
  43 # ifdef WORDS_BIGENDIAN
  44 #  define UTF16_NAME "UTF-16BE"
  45 # else
  46 #  define UTF16_NAME "UTF-16LE"
  47 # endif
  48 #endif
  49 
  50 
  51 #if !defined UTF16_NAME
  52 
  53 /* A variant of u16_to_u8 that treats an incomplete sequence of units at the
  54    end as a harmless no-op, rather than reporting it as an EILSEQ error.  */
  55 
  56 #define FUNC u16_to_u8_lenient
  57 #define SRC_UNIT uint16_t
  58 #define DST_UNIT uint8_t
  59 
  60 static DST_UNIT *
  61 FUNC (const SRC_UNIT *s, size_t n, DST_UNIT *resultbuf, size_t *lengthp)
     /* [previous][next][first][last][top][bottom][index][help] */
  62 {
  63   const SRC_UNIT *s_end = s + n;
  64   /* Output string accumulator.  */
  65   DST_UNIT *result;
  66   size_t allocated;
  67   size_t length;
  68 
  69   if (resultbuf != NULL)
  70     {
  71       result = resultbuf;
  72       allocated = *lengthp;
  73     }
  74   else
  75     {
  76       result = NULL;
  77       allocated = 0;
  78     }
  79   length = 0;
  80   /* Invariants:
  81      result is either == resultbuf or == NULL or malloc-allocated.
  82      If length > 0, then result != NULL.  */
  83 
  84   while (s < s_end)
  85     {
  86       ucs4_t uc;
  87       int count;
  88 
  89       /* Fetch a Unicode character from the input string.  */
  90       count = u16_mbtoucr (&uc, s, s_end - s);
  91       if (count < 0)
  92         {
  93           if (count == -2)
  94             /* Incomplete sequence of units.  */
  95             break;
  96           if (!(result == resultbuf || result == NULL))
  97             free (result);
  98           errno = EILSEQ;
  99           return NULL;
 100         }
 101       s += count;
 102 
 103       /* Store it in the output string.  */
 104       count = u8_uctomb (result + length, uc, allocated - length);
 105       if (count == -1)
 106         {
 107           if (!(result == resultbuf || result == NULL))
 108             free (result);
 109           errno = EILSEQ;
 110           return NULL;
 111         }
 112       if (count == -2)
 113         {
 114           DST_UNIT *memory;
 115 
 116           allocated = (allocated > 0 ? 2 * allocated : 12);
 117           if (length + 6 > allocated)
 118             allocated = length + 6;
 119           if (result == resultbuf || result == NULL)
 120             memory = (DST_UNIT *) malloc (allocated * sizeof (DST_UNIT));
 121           else
 122             memory =
 123               (DST_UNIT *) realloc (result, allocated * sizeof (DST_UNIT));
 124 
 125           if (memory == NULL)
 126             {
 127               if (!(result == resultbuf || result == NULL))
 128                 free (result);
 129               errno = ENOMEM;
 130               return NULL;
 131             }
 132           if (result == resultbuf && length > 0)
 133             memcpy ((char *) memory, (char *) result,
 134                     length * sizeof (DST_UNIT));
 135           result = memory;
 136           count = u8_uctomb (result + length, uc, allocated - length);
 137           if (count < 0)
 138             abort ();
 139         }
 140       length += count;
 141     }
 142 
 143   if (length == 0)
 144     {
 145       if (result == NULL)
 146         {
 147           /* Return a non-NULL value.  NULL means error.  */
 148           result = (DST_UNIT *) malloc (1);
 149           if (result == NULL)
 150             {
 151               errno = ENOMEM;
 152               return NULL;
 153             }
 154         }
 155     }
 156   else if (result != resultbuf && length < allocated)
 157     {
 158       /* Shrink the allocated memory if possible.  */
 159       DST_UNIT *memory;
 160 
 161       memory = (DST_UNIT *) realloc (result, length * sizeof (DST_UNIT));
 162       if (memory != NULL)
 163         result = memory;
 164     }
 165 
 166   *lengthp = length;
 167   return result;
 168 }
 169 
 170 #undef DST_UNIT
 171 #undef SRC_UNIT
 172 #undef FUNC
 173 
 174 #endif
 175 
 176 
 177 #define FUNC u16_conv_to_encoding
 178 #define UNIT uint16_t
 179 #define U_TO_U8 u16_to_u8_lenient
 180 #define U_MBLEN u16_mblen
 181 #if defined UTF16_NAME
 182 # define UTF_NAME UTF16_NAME
 183 # define HAVE_UTF_NAME 1
 184 #endif
 185 #include "u-conv-to-enc.h"

/* [previous][next][first][last][top][bottom][index][help] */