LCOV - code coverage report
Current view: top level - src/base - pdf-text-host-encoding.c (source / functions) Hit Total Coverage
Test: libgnupdf.info Lines: 68 105 64.8 %
Date: 2011-12-09 Functions: 5 5 100.0 %
Branches: 25 44 56.8 %

           Branch data     Line data    Source code
       1                 :            : /* -*- mode: C -*-
       2                 :            :  *
       3                 :            :  *       File:         pdf-text-host-encoding.c
       4                 :            :  *       Date:         Fri Jan 11 21:09:23 2008
       5                 :            :  *
       6                 :            :  *       GNU PDF Library - Encoded Text handling utilities - Host Encodings
       7                 :            :  *
       8                 :            :  */
       9                 :            : 
      10                 :            : /* Copyright (C) 2008-2011 Free Software Foundation, Inc. */
      11                 :            : 
      12                 :            : /* This program is free software: you can redistribute it and/or modify
      13                 :            :  * it under the terms of the GNU General Public License as published by
      14                 :            :  * the Free Software Foundation, either version 3 of the License, or
      15                 :            :  * (at your option) any later version.
      16                 :            :  *
      17                 :            :  * This program is distributed in the hope that it will be useful,
      18                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      19                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      20                 :            :  * GNU General Public License for more details.
      21                 :            :  *
      22                 :            :  * You should have received a copy of the GNU General Public License
      23                 :            :  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
      24                 :            :  */
      25                 :            : 
      26                 :            : #include <config.h>
      27                 :            : 
      28                 :            : #include <string.h>
      29                 :            : #ifdef PDF_HOST_WIN32
      30                 :            :  #include <windows.h>
      31                 :            : #else
      32                 :            :  #include <iconv.h>
      33                 :            :  #include <errno.h>
      34                 :            : #endif
      35                 :            : 
      36                 :            : #include <pdf-types.h>
      37                 :            : #include <pdf-text.h>
      38                 :            : #include <pdf-text-context.h>
      39                 :            : #include <pdf-text-encoding.h>
      40                 :            : #include <pdf-text-host-encoding.h>
      41                 :            : 
      42                 :            : /*
      43                 :            :  * ICONV API
      44                 :            :  * -----------
      45                 :            :  * iconv_t iconv_open (const char* tocode, const char* fromcode)
      46                 :            :  *
      47                 :            :  * size_t iconv (iconv_t cd,
      48                 :            :  *               const char **inbuf, size_t *inbytesleft,
      49                 :            :  *               char **outbuf, size_t *outbytesleft);
      50                 :            :  *
      51                 :            :  * int iconv_close (iconv_t cd);
      52                 :            :  */
      53                 :            : 
      54                 :            : /*
      55                 :            :  * WINDOWS API
      56                 :            :  * -------------
      57                 :            :  * int MultiByteToWideChar(UINT CodePage,
      58                 :            :  *                         DWORD dwFlags,
      59                 :            :  *                         LPCSTR lpMultiByteStr,
      60                 :            :  *                         int cbMultiByte,
      61                 :            :  *                         LPWSTR lpWideCharStr,
      62                 :            :  *                         int cchWideChar);
      63                 :            :  *
      64                 :            :  * int WideCharToMultiByte(UINT CodePage,
      65                 :            :  *                         DWORD dwFlags,
      66                 :            :  *                         LPCWSTR lpWideCharStr,
      67                 :            :  *                         int cchWideChar,
      68                 :            :  *                         LPSTR lpMultiByteStr,
      69                 :            :  *                         int cbMultiByte,
      70                 :            :  *                         LPCSTR lpDefaultChar,
      71                 :            :  *                         LPBOOL lpUsedDefaultChar);
      72                 :            :  *
      73                 :            :  * UINT GetACP(void);
      74                 :            :  *
      75                 :            :  */
      76                 :            : 
      77                 :            : #ifdef PDF_HOST_WIN32
      78                 :            : static DWORD
      79                 :            : pdf_text_get_dwflags_for_cp (UINT  CodePage,
      80                 :            :                              DWORD def_dwflags)
      81                 :            : {
      82                 :            :   /* dwFlags has some restrictions */
      83                 :            :   switch(CodePage)
      84                 :            :     {
      85                 :            :     case 50220:
      86                 :            :     case 50221:
      87                 :            :     case 50222:
      88                 :            :     case 50225:
      89                 :            :     case 50227:
      90                 :            :     case 50229:
      91                 :            :     case 52936:
      92                 :            :     case 54936:
      93                 :            :     case 57002:
      94                 :            :     case 57003:
      95                 :            :     case 57004:
      96                 :            :     case 57005:
      97                 :            :     case 57006:
      98                 :            :     case 57007:
      99                 :            :     case 57008:
     100                 :            :     case 57009:
     101                 :            :     case 57010:
     102                 :            :     case 57011:
     103                 :            :     case 65000:
     104                 :            :     case 42:
     105                 :            :       return 0;
     106                 :            :     default:
     107                 :            :       return def_dwflags;
     108                 :            :     }
     109                 :            : }
     110                 :            : 
     111                 :            : static pdf_bool_t
     112                 :            : pdf_text_convert_encoding_name_to_CP (const pdf_char_t  *encoding_name,
     113                 :            :                                       UINT              *pCP,
     114                 :            :                                       pdf_error_t      **error)
     115                 :            : {
     116                 :            :   UINT CodePage;
     117                 :            :   char *end_char;
     118                 :            : 
     119                 :            :   /* In windows, the charset name is stored as a string, in the following
     120                 :            :    * format: "CPn", where 'n' is the code page number (unsigned integer)
     121                 :            :    * obtained with GetACP() */
     122                 :            : 
     123                 :            :   /* So first of all, check windows host encoding */
     124                 :            :   if ((strlen (encoding_name) < 3) ||
     125                 :            :       (strncmp (encoding_name, "CP", 2) != 0))
     126                 :            :     {
     127                 :            :       pdf_set_error (error,
     128                 :            :                      PDF_EDOMAIN_BASE_TEXT,
     129                 :            :                      PDF_EBADDATA,
     130                 :            :                      "host encoding received (%s) seems not valid",
     131                 :            :                      encoding_name);
     132                 :            :       return PDF_FALSE;
     133                 :            :     }
     134                 :            : 
     135                 :            :   /* Get codepage as unsigned integer. `strtol' will return 0 if it was not
     136                 :            :    *  able to correctly parse the string. BTW, 0 is not a valid code page. */
     137                 :            :   CodePage = (UINT) strtol (&encoding_name[2],
     138                 :            :                             &end_char,
     139                 :            :                             10);
     140                 :            :   if (CodePage == 0)
     141                 :            :     {
     142                 :            :       pdf_set_error (error,
     143                 :            :                      PDF_EDOMAIN_BASE_TEXT,
     144                 :            :                      PDF_ETEXTENC,
     145                 :            :                      "Problem converting input CP value '%s'",
     146                 :            :                      encoding_name);
     147                 :            :       return PDF_FALSE;
     148                 :            :     }
     149                 :            : 
     150                 :            :   *pCP = CodePage;
     151                 :            :   return PDF_TRUE;
     152                 :            : }
     153                 :            : 
     154                 :            : pdf_bool_t
     155                 :            : pdf_text_host_encoding_is_available (const pdf_char_t  *encoding_name,
     156                 :            :                                      pdf_error_t      **error)
     157                 :            : {
     158                 :            :   UINT CodePage;
     159                 :            : 
     160                 :            :   if (!pdf_text_convert_encoding_name_to_CP (encoding_name,
     161                 :            :                                              &CodePage,
     162                 :            :                                              error))
     163                 :            :     return PDF_FALSE;
     164                 :            : 
     165                 :            :   /* Check given code page in the system */
     166                 :            :   return ((IsValidCodePage (CodePage)) ? PDF_TRUE : PDF_FALSE);
     167                 :            : }
     168                 :            : 
     169                 :            : static pdf_bool_t
     170                 :            : pdf_text_utf32he_to_host_win32 (const pdf_char_t  *input_data,
     171                 :            :                                 const pdf_size_t   input_length,
     172                 :            :                                 const pdf_char_t  *enc,
     173                 :            :                                 pdf_char_t       **p_output_data,
     174                 :            :                                 pdf_size_t        *p_output_length,
     175                 :            :                                 pdf_error_t      **error)
     176                 :            : {
     177                 :            :   pdf_char_t *temp_data;
     178                 :            :   pdf_size_t  temp_size;
     179                 :            :   UINT CodePage;
     180                 :            :   DWORD dwFlags;
     181                 :            :   int output_nmbyte;
     182                 :            :   BOOL default_used = 0;
     183                 :            : 
     184                 :            :   /* Firstly, convert from UTF-32HE to UTF-16LE */
     185                 :            :   if (!pdf_text_utf32he_to_utf16le (input_data,
     186                 :            :                                     input_length,
     187                 :            :                                     &temp_data,
     188                 :            :                                     &temp_size,
     189                 :            :                                     error))
     190                 :            :     return PDF_FALSE;
     191                 :            : 
     192                 :            :   /* So check windows host encoding */
     193                 :            :   if (!pdf_text_convert_encoding_name_to_CP (enc,
     194                 :            :                                              &CodePage,
     195                 :            :                                              error))
     196                 :            :     {
     197                 :            :       pdf_dealloc (temp_data);
     198                 :            :       return PDF_FALSE;
     199                 :            :     }
     200                 :            : 
     201                 :            :   /* Get dwFlags value */
     202                 :            :   dwFlags = 0;
     203                 :            : 
     204                 :            :   /* First of all, query the length of the output string */
     205                 :            :   SetLastError (0);
     206                 :            :   output_nmbyte =  WideCharToMultiByte (CodePage,     /* CodePage */
     207                 :            :                                         dwFlags,      /* dwFlags */
     208                 :            :                                         (LPCWSTR)temp_data, /* lpWideCharStr */
     209                 :            :                                         (temp_size/sizeof(WCHAR)), /* cbWideChar */
     210                 :            :                                         NULL,         /* lpMultiByteStr */
     211                 :            :                                         0,            /* ccMultiByte */
     212                 :            :                                         NULL,            /* lpDefaultChar */
     213                 :            :                                         &default_used); /* lpUsedDefaultChar */
     214                 :            : 
     215                 :            :   /* Check if we got an error with the call to WideCharToMultiByte */
     216                 :            :   if (output_nmbyte == 0 || default_used)
     217                 :            :     {
     218                 :            :       switch (GetLastError ())
     219                 :            :         {
     220                 :            :         case ERROR_INVALID_FLAGS:
     221                 :            :           pdf_set_error (error,
     222                 :            :                          PDF_EDOMAIN_BASE_TEXT,
     223                 :            :                          PDF_EBADTEXT,
     224                 :            :                          "cannot convert to host encoding: invalid flags");
     225                 :            :           break;
     226                 :            :         default:
     227                 :            :           pdf_set_error (error,
     228                 :            :                          PDF_EDOMAIN_BASE_TEXT,
     229                 :            :                          PDF_EBADTEXT,
     230                 :            :                          "cannot convert to host encoding: invalid data");
     231                 :            :           break;
     232                 :            :         }
     233                 :            : 
     234                 :            :       pdf_dealloc (temp_data);
     235                 :            :       return PDF_FALSE;
     236                 :            :     }
     237                 :            : 
     238                 :            :   /* Allocate memory for output buffer */
     239                 :            :   *p_output_length = output_nmbyte;
     240                 :            :   *p_output_data = (pdf_char_t *) pdf_alloc (*p_output_length);
     241                 :            :   if (*p_output_data == NULL)
     242                 :            :     {
     243                 :            :       pdf_set_error (error,
     244                 :            :                      PDF_EDOMAIN_BASE_TEXT,
     245                 :            :                      PDF_ENOMEM,
     246                 :            :                      "cannot convert to host encoding: "
     247                 :            :                      "couldn't allocate %lu bytes",
     248                 :            :                      (unsigned long)*p_output_length);
     249                 :            :       pdf_dealloc (temp_data);
     250                 :            :       return PDF_FALSE;
     251                 :            :     }
     252                 :            : 
     253                 :            :   /* Launch the conversion to host encoding */
     254                 :            :   SetLastError (0);
     255                 :            :   default_used = 0;
     256                 :            :   if ((WideCharToMultiByte (CodePage,     /* CodePage */
     257                 :            :                             dwFlags,      /* dwFlags */
     258                 :            :                             (LPCWSTR)temp_data, /* lpWideCharStr */
     259                 :            :                             (temp_size/sizeof(WCHAR)), /* cbWideChar */
     260                 :            :                             *p_output_data, /* lpMultiByteStr */
     261                 :            :                             *p_output_length, /* ccMultiByte */
     262                 :            :                             NULL,            /* lpDefaultChar */
     263                 :            :                             &default_used) != output_nmbyte) || \
     264                 :            :       (default_used))
     265                 :            :     {
     266                 :            :       pdf_set_error (error,
     267                 :            :                      PDF_EDOMAIN_BASE_TEXT,
     268                 :            :                      PDF_ETEXTENC,
     269                 :            :                      "cannot convert to host encoding: "
     270                 :            :                      "wide char to multibyte conversion failed");
     271                 :            :       pdf_dealloc (*p_output_data);
     272                 :            :       pdf_dealloc (temp_data);
     273                 :            :       return PDF_FALSE;
     274                 :            :     }
     275                 :            : 
     276                 :            :   /* Check last byte... could be NUL and we don't want it */
     277                 :            :   if ((*p_output_data)[*p_output_length -1] == '\0')
     278                 :            :     {
     279                 :            :       pdf_char_t *temp;
     280                 :            : 
     281                 :            :       temp = pdf_realloc ((*p_output_data), (*p_output_length -1));
     282                 :            :       if (temp)
     283                 :            :         {
     284                 :            :           *p_output_data = temp;
     285                 :            :           *p_output_length = *p_output_length - 1;
     286                 :            :         }
     287                 :            :     }
     288                 :            : 
     289                 :            :   pdf_dealloc (temp_data);
     290                 :            :   return PDF_TRUE;
     291                 :            : }
     292                 :            : 
     293                 :            : static pdf_bool_t
     294                 :            : pdf_text_host_to_utf32he_win32 (const pdf_char_t  *input_data,
     295                 :            :                                 const pdf_size_t   input_length,
     296                 :            :                                 const pdf_char_t  *enc,
     297                 :            :                                 pdf_char_t       **p_output_data,
     298                 :            :                                 pdf_size_t        *p_output_length,
     299                 :            :                                 pdf_error_t      **error)
     300                 :            : {
     301                 :            :   UINT CodePage;
     302                 :            :   DWORD dwFlags;
     303                 :            :   int output_nwchars;
     304                 :            :   pdf_char_t *temp_data;
     305                 :            :   pdf_size_t temp_size;
     306                 :            : 
     307                 :            :   /* So first of all, check windows host encoding */
     308                 :            :   if (!pdf_text_convert_encoding_name_to_CP (enc,
     309                 :            :                                              &CodePage,
     310                 :            :                                              error))
     311                 :            :     return PDF_FALSE;
     312                 :            : 
     313                 :            :   /* Get dwFlags value */
     314                 :            :   dwFlags = pdf_text_get_dwflags_for_cp (CodePage, MB_ERR_INVALID_CHARS);
     315                 :            : 
     316                 :            :   /* For ASCII-7, check MSB... MultiByteToWideChar doesn't do it, and the
     317                 :            :    *  behaviour should be equal to that of iconv() */
     318                 :            :   if (CodePage == 20127 &&
     319                 :            :       !pdf_text_is_ascii7 (input_data, input_length))
     320                 :            :     {
     321                 :            :       pdf_set_error (error,
     322                 :            :                      PDF_EDOMAIN_BASE_TEXT,
     323                 :            :                      PDF_ETEXTENC,
     324                 :            :                      "cannot convert from host encoding: "
     325                 :            :                      "not ASCII-7");
     326                 :            :       return PDF_FALSE;
     327                 :            :     }
     328                 :            : 
     329                 :            :   /* First of all, query the length of the output string */
     330                 :            :   SetLastError (0);
     331                 :            :   output_nwchars =  MultiByteToWideChar (CodePage,     /* CodePage */
     332                 :            :                                          dwFlags,      /* dwFlags */
     333                 :            :                                          input_data,   /* lpMultiByteStr */
     334                 :            :                                          input_length, /* cbMultiByte */
     335                 :            :                                          NULL,         /* lpWideCharStr */
     336                 :            :                                          0);           /* cchWideChar */
     337                 :            : 
     338                 :            :   /* Check if we got an error with the call to MultiByteToWideChar*/
     339                 :            :   if (output_nwchars == 0)
     340                 :            :     {
     341                 :            :       switch (GetLastError ())
     342                 :            :         {
     343                 :            :         case ERROR_INVALID_FLAGS:
     344                 :            :           pdf_set_error (error,
     345                 :            :                          PDF_EDOMAIN_BASE_TEXT,
     346                 :            :                          PDF_EBADTEXT,
     347                 :            :                          "cannot convert from host encoding: invalid flags");
     348                 :            :           break;
     349                 :            :         case ERROR_NO_UNICODE_TRANSLATION:
     350                 :            :           pdf_set_error (error,
     351                 :            :                          PDF_EDOMAIN_BASE_TEXT,
     352                 :            :                          PDF_EBADTEXT,
     353                 :            :                          "cannot convert from host encoding:"
     354                 :            :                          " no unicode translation");
     355                 :            :           break;
     356                 :            :         default:
     357                 :            :           pdf_set_error (error,
     358                 :            :                          PDF_EDOMAIN_BASE_TEXT,
     359                 :            :                          PDF_EBADTEXT,
     360                 :            :                          "cannot convert from host encoding: invalid data");
     361                 :            :           break;
     362                 :            :         }
     363                 :            :       return PDF_FALSE;
     364                 :            :     }
     365                 :            : 
     366                 :            :   /* Allocate memory for output buffer */
     367                 :            :   temp_size = output_nwchars * sizeof (WCHAR);
     368                 :            :   temp_data = (pdf_char_t *) pdf_alloc (temp_size);
     369                 :            :   if (temp_data == NULL)
     370                 :            :     {
     371                 :            :       pdf_set_error (error,
     372                 :            :                      PDF_EDOMAIN_BASE_TEXT,
     373                 :            :                      PDF_ENOMEM,
     374                 :            :                      "cannot convert from host encoding: "
     375                 :            :                      "couldn't allocate %lu bytes",
     376                 :            :                      (unsigned long)temp_size);
     377                 :            :       return PDF_FALSE;
     378                 :            :     }
     379                 :            : 
     380                 :            :   /* Launch the conversion to UTF-16LE */
     381                 :            :   SetLastError (0);
     382                 :            :   if (MultiByteToWideChar (CodePage,           /* CodePage */
     383                 :            :                            dwFlags,            /* dwFlags */
     384                 :            :                            input_data,         /* lpMultiByteStr */
     385                 :            :                            input_length,       /* cbMultiByte */
     386                 :            :                            (LPWSTR)temp_data,  /* lpWideCharStr */
     387                 :            :                            output_nwchars) != output_nwchars) /* cchWideChar */
     388                 :            :     {
     389                 :            :       pdf_set_error (error,
     390                 :            :                      PDF_EDOMAIN_BASE_TEXT,
     391                 :            :                      PDF_ETEXTENC,
     392                 :            :                      "cannot convert from host encoding: "
     393                 :            :                      "multibyte to wide char conversion failed");
     394                 :            :       pdf_dealloc (temp_data);
     395                 :            :       return PDF_FALSE;
     396                 :            :     }
     397                 :            : 
     398                 :            :   /* Finally, convert to UTF-32HE */
     399                 :            :   if (!pdf_text_utf16le_to_utf32he (temp_data,
     400                 :            :                                     temp_size,
     401                 :            :                                     p_output_data,
     402                 :            :                                     p_output_length,
     403                 :            :                                     error))
     404                 :            :     {
     405                 :            :       pdf_dealloc (temp_data);
     406                 :            :       return PDF_FALSE;
     407                 :            :     }
     408                 :            :   pdf_dealloc (temp_data);
     409                 :            :   return PDF_TRUE;
     410                 :            : }
     411                 :            : 
     412                 :            : #else
     413                 :            : 
     414                 :            : pdf_bool_t
     415                 :          3 : pdf_text_host_encoding_is_available (const pdf_char_t  *encoding_name,
     416                 :            :                                      pdf_error_t      **error)
     417                 :            : {
     418                 :            :   iconv_t check;
     419                 :            : 
     420                 :            :   /* Check conversion from Host Encoding to UTF-32HE */
     421                 :          3 :   check = iconv_open (encoding_name,
     422                 :            :                       (PDF_IS_BIG_ENDIAN ? "UTF-32BE" : "UTF-32LE"));
     423         [ +  + ]:          3 :   if (check == (iconv_t)-1)
     424                 :            :     {
     425                 :            :       /* No need to set any error here */
     426                 :          1 :       return PDF_FALSE;
     427                 :            :     }
     428                 :          2 :   iconv_close (check);
     429                 :            : 
     430                 :            :   /* Check conversion from UTF-32HE to Host Encoding */
     431                 :          2 :   check = iconv_open ((PDF_IS_BIG_ENDIAN ? "UTF-32BE" : "UTF-32LE"),
     432                 :            :                       encoding_name);
     433         [ -  + ]:          2 :   if (check == (iconv_t)-1)
     434                 :            :     {
     435                 :            :       /* No need to set any error here */
     436                 :          0 :       return PDF_FALSE;
     437                 :            :     }
     438                 :          2 :   iconv_close (check);
     439                 :            : 
     440                 :          3 :   return PDF_TRUE;
     441                 :            : }
     442                 :            : 
     443                 :            : static pdf_bool_t
     444                 :         33 : pdf_text_utf32he_to_host_iconv (const pdf_char_t  *input_data,
     445                 :            :                                 const pdf_size_t   input_length,
     446                 :            :                                 const pdf_char_t  *enc,
     447                 :            :                                 pdf_char_t       **p_output_data,
     448                 :            :                                 pdf_size_t        *p_output_length,
     449                 :            :                                 pdf_error_t      **error)
     450                 :            : {
     451                 :            :   iconv_t to_host;
     452                 :            :   size_t n_conv;
     453                 :            :   pdf_char_t *in_str;
     454                 :            :   size_t n_in;
     455                 :            :   size_t n_out;
     456                 :            :   pdf_char_t *new_data;
     457                 :            :   pdf_char_t *out_str;
     458                 :            :   pdf_size_t worst_length;
     459                 :            :   pdf_size_t new_length;
     460                 :            : 
     461                 :            :   /* Check if conversion is available. If we just specify "UTF-32" as the
     462                 :            :    *  input encoding requested, iconv will expect the BOM by default, and
     463                 :            :    *  we don't want it, so we specify directly the endianness required in the
     464                 :            :    *  name of the encoding, depending on the host endianness */
     465                 :         33 :   to_host = iconv_open (enc,
     466                 :            :                         (PDF_IS_BIG_ENDIAN ? "UTF-32BE" : "UTF-32LE"));
     467         [ +  + ]:         33 :   if (to_host == (iconv_t)-1)
     468                 :            :     {
     469                 :          3 :       pdf_set_error (error,
     470                 :            :                      PDF_EDOMAIN_BASE_TEXT,
     471                 :            :                      PDF_ETEXTENC,
     472                 :            :                      "cannot convert to host encoding: "
     473                 :            :                      "conversion from UTF-32 to '%s' not available: '%s'",
     474                 :            :                      enc,
     475                 :            :                      strerror (errno));
     476                 :          3 :       return PDF_FALSE;
     477                 :            :     }
     478                 :            : 
     479                 :            :   /* Prepare lengths and locations.
     480                 :            :    *  The worst length is computed as having one single output byte for each
     481                 :            :    *  input single byte */
     482                 :         30 :   worst_length = input_length + 4;
     483                 :         30 :   new_data = (pdf_char_t *) pdf_alloc (worst_length);
     484         [ -  + ]:         30 :   if (new_data == NULL)
     485                 :            :     {
     486                 :          0 :       pdf_set_error (error,
     487                 :            :                      PDF_EDOMAIN_BASE_TEXT,
     488                 :            :                      PDF_ENOMEM,
     489                 :            :                      "cannot convert to host encoding: "
     490                 :            :                      "couldn't allocate %lu bytes",
     491                 :            :                      (unsigned long)worst_length);
     492                 :          0 :       iconv_close (to_host);
     493                 :          0 :       return PDF_FALSE;
     494                 :            :     }
     495                 :            : 
     496                 :         30 :   n_out = worst_length;
     497                 :            : 
     498                 :            :   /* This cast is legit because
     499                 :            :    * iconv increments the pointer
     500                 :            :    * but does not change the
     501                 :            :    * pointed memory.  */
     502                 :         30 :   in_str = (char *)input_data;
     503                 :         30 :   out_str = new_data;
     504                 :         30 :   n_in = input_length;
     505                 :            : 
     506         [ +  + ]:         60 :   while (n_in > 0)
     507                 :            :     {
     508                 :            :       /* Convert */
     509                 :         30 :       n_conv = iconv (to_host, &in_str, &n_in, &out_str, &n_out);
     510                 :            : 
     511                 :            :       /* Check conversion output status. We check errno to see if the problem
     512                 :            :        *  is that more buffer is needed in the output. If this is the case,
     513                 :            :        *  we just give a second try to the worst length and reallocate memory.
     514                 :            :        *  There is no problem to use errno in multi-threaded applications
     515                 :            :        *  if the library is compiled with -D_REENTRANT */
     516         [ -  + ]:         30 :       if (n_conv == (size_t)-1)
     517                 :            :         {
     518         [ #  # ]:          0 :           if (errno == E2BIG)
     519                 :            :             {
     520                 :          0 :               pdf_size_t n_bytes_generated = 0;
     521                 :            : 
     522                 :            :               /* Compute the number of bytes actually generated in the
     523                 :            :                *  output buffer. */
     524                 :          0 :               n_bytes_generated = (pdf_size_t) (worst_length - n_out);
     525                 :            : 
     526                 :            :               /* We need more output buffer */
     527                 :          0 :               worst_length += (n_in);
     528                 :            : 
     529                 :            :               PDF_DEBUG_BASE ("Reallocating to '%lu'. "
     530                 :            :                               "'%lu' bytes are already generated",
     531                 :            :                               (unsigned long) worst_length,
     532                 :            :                               (unsigned long) n_bytes_generated);
     533                 :            : 
     534                 :            :               /* Reallocate buffer with greater size */
     535                 :          0 :               new_data = (pdf_char_t *) pdf_realloc (new_data, worst_length);
     536         [ #  # ]:          0 :               if (new_data == NULL)
     537                 :            :                 {
     538                 :          0 :                   iconv_close (to_host);
     539                 :          0 :                   pdf_set_error (error,
     540                 :            :                                  PDF_EDOMAIN_BASE_TEXT,
     541                 :            :                                  PDF_ENOMEM,
     542                 :            :                                  "cannot convert to host encoding: "
     543                 :            :                                  "couldn't rellocate '%lu' bytes",
     544                 :            :                                  (unsigned long)worst_length);
     545                 :          0 :                   return PDF_FALSE;
     546                 :            :                 }
     547                 :            : 
     548                 :            :               /* The re-allocated new data does not have to be in the same
     549                 :            :                *  memory place as the original one, so the `out_str' pointer
     550                 :            :                *  must be reset */
     551                 :          0 :               out_str = &new_data[n_bytes_generated];
     552                 :            : 
     553                 :            :               /* The number of bytes available in the buffer must also be
     554                 :            :                *  reset */
     555                 :          0 :               n_out = (worst_length - n_bytes_generated);
     556                 :            :             }
     557                 :            :           else
     558                 :            :             {
     559                 :          0 :               iconv_close (to_host);
     560                 :          0 :               pdf_set_error (error,
     561                 :            :                              PDF_EDOMAIN_BASE_TEXT,
     562                 :            :                              PDF_ETEXTENC,
     563                 :            :                              "cannot convert to host encoding: "
     564                 :            :                              "invalid data to convert to host encoding, '%s'",
     565                 :            :                              strerror (errno));
     566                 :          0 :               return PDF_FALSE;
     567                 :            :             }
     568                 :            :         }
     569                 :            :     }
     570                 :            : 
     571                 :            :   /* Compute new final length */
     572                 :         30 :   new_length = worst_length - n_out;
     573                 :            : 
     574                 :            :   /* Finally, reset the buffer length to its correct size */
     575         [ +  - ]:         30 :   if (new_length != worst_length)
     576                 :            :     {
     577                 :         30 :       new_data = (pdf_char_t *) pdf_realloc (new_data, new_length);
     578         [ -  + ]:         30 :       if (new_data == NULL)
     579                 :            :         {
     580                 :          0 :           iconv_close (to_host);
     581                 :          0 :           pdf_set_error (error,
     582                 :            :                          PDF_EDOMAIN_BASE_TEXT,
     583                 :            :                          PDF_ENOMEM,
     584                 :            :                          "cannot convert to host encoding: "
     585                 :            :                          "couldn't rellocate '%lu' bytes",
     586                 :            :                          (unsigned long)new_length);
     587                 :          0 :           return PDF_FALSE;
     588                 :            :         }
     589                 :            :     }
     590                 :            : 
     591                 :            :   /* And set the output values */
     592                 :         30 :   *p_output_data = new_data;
     593                 :         30 :   *p_output_length = new_length;
     594                 :            : 
     595                 :         30 :   iconv_close (to_host);
     596                 :         33 :   return PDF_TRUE;
     597                 :            : }
     598                 :            : 
     599                 :            : static pdf_bool_t
     600                 :         10 : pdf_text_host_to_utf32he_iconv (const pdf_char_t  *input_data,
     601                 :            :                                 const pdf_size_t   input_length,
     602                 :            :                                 const pdf_char_t  *enc,
     603                 :            :                                 pdf_char_t       **p_output_data,
     604                 :            :                                 pdf_size_t        *p_output_length,
     605                 :            :                                 pdf_error_t      **error)
     606                 :            : {
     607                 :            :   iconv_t from_host;
     608                 :            :   size_t n_conv;
     609                 :            :   pdf_char_t *in_str;
     610                 :            :   size_t n_in;
     611                 :            :   size_t n_out;
     612                 :            :   pdf_char_t *new_data;
     613                 :            :   pdf_char_t *out_str;
     614                 :            :   pdf_size_t worst_length;
     615                 :            :   pdf_size_t new_length;
     616                 :            : 
     617                 :            :   /* Check if conversion is available. If we just specify "UTF-32" as the
     618                 :            :    *  output encoding requested, iconv will insert the BOM by default, and
     619                 :            :    *  we don't want it, so we specify directly the endianness required in the
     620                 :            :    *  name of the encoding, depending on the host endianness */
     621                 :         10 :   from_host = iconv_open ((PDF_IS_BIG_ENDIAN ? "UTF-32BE" : "UTF-32LE"),
     622                 :            :                           enc);
     623         [ +  + ]:         10 :   if (from_host == (iconv_t)-1)
     624                 :            :     {
     625                 :          2 :       pdf_set_error (error,
     626                 :            :                      PDF_EDOMAIN_BASE_TEXT,
     627                 :            :                      PDF_ETEXTENC,
     628                 :            :                      "cannot convert from host encoding: "
     629                 :            :                      "conversion from '%s' to UTF-32 not available",
     630                 :            :                      enc);
     631                 :          2 :       return PDF_FALSE;
     632                 :            :     }
     633                 :            : 
     634                 :            :   /* Prepare lengths and locations.
     635                 :            :    *  The worst length is computed as having 4 output bytes for each input
     636                 :            :    *  single byte, taking into account that iconv adds an extra 32-bit NUL
     637                 :            :    *  value (4 bytes equal to 0) at the end of the converted string. */
     638                 :          8 :   worst_length = (input_length + 1) * 4;
     639                 :          8 :   new_data = (pdf_char_t *) pdf_alloc (worst_length);
     640         [ -  + ]:          8 :   if (new_data == NULL)
     641                 :            :     {
     642                 :          0 :       pdf_set_error (error,
     643                 :            :                      PDF_EDOMAIN_BASE_TEXT,
     644                 :            :                      PDF_ENOMEM,
     645                 :            :                      "cannot convert from host encoding: "
     646                 :            :                      "couldn't allocate %lu bytes",
     647                 :            :                      (unsigned long)worst_length);
     648                 :          0 :       iconv_close (from_host);
     649                 :          0 :       return PDF_FALSE;
     650                 :            :     }
     651                 :            : 
     652                 :          8 :   n_out = worst_length;
     653                 :            : 
     654                 :            :   /* This cast is legit because
     655                 :            :    * iconv increments the pointer
     656                 :            :    * but does not change the
     657                 :            :    * pointed memory.  */
     658                 :          8 :   in_str = (char *)input_data;
     659                 :          8 :   out_str = new_data;
     660                 :          8 :   n_in = input_length;
     661                 :            : 
     662         [ +  + ]:         14 :   while (n_in > 0)
     663                 :            :     {
     664                 :            :       /* Convert */
     665                 :          8 :       n_conv = iconv (from_host, &in_str, &n_in, &out_str, &n_out);
     666                 :            : 
     667                 :            :       /* Check conversion output status. We check errno to see if the problem
     668                 :            :        *  is that more buffer is needed in the output. If this is the case,
     669                 :            :        *  we just give a second try to the worst length and reallocate memory.
     670                 :            :        *  There is no problem to use errno in multi-threaded applications
     671                 :            :        *  if the library is compiled with -D_REENTRANT */
     672         [ +  + ]:          8 :       if (n_conv == (size_t)-1)
     673                 :            :         {
     674         [ -  + ]:          2 :           if (errno == E2BIG)
     675                 :            :             {
     676                 :          0 :               pdf_size_t n_bytes_generated = 0;
     677                 :            : 
     678                 :            :               /* Compute the number of bytes actually generated in the
     679                 :            :                *  output buffer. `n_out' stores the number of bytes still
     680                 :            :                *  available in the output buffer. As the number of bytes
     681                 :            :                *  allocated is multiple of four, and UTF-32 always uses 4
     682                 :            :                *  bytes for each character, this value should always be 0 */
     683                 :          0 :               n_bytes_generated = (pdf_size_t) (worst_length - n_out);
     684                 :            : 
     685                 :            :               /* We need more output buffer */
     686                 :          0 :               worst_length += (n_in * 4);
     687                 :            :               PDF_DEBUG_BASE ("Reallocating to '%lu'. "
     688                 :            :                               "'%lu' bytes are already generated",
     689                 :            :                               (unsigned long) worst_length,
     690                 :            :                               (unsigned long) n_bytes_generated);
     691                 :            : 
     692                 :            :               /* Reallocate buffer with greater size */
     693                 :          0 :               new_data = (pdf_char_t *) pdf_realloc (new_data, worst_length);
     694         [ #  # ]:          0 :               if (new_data == NULL)
     695                 :            :                 {
     696                 :          0 :                   pdf_set_error (error,
     697                 :            :                                  PDF_EDOMAIN_BASE_TEXT,
     698                 :            :                                  PDF_ENOMEM,
     699                 :            :                                  "cannot convert from host encoding: "
     700                 :            :                                  "couldn't allocate %lu bytes",
     701                 :            :                                  (unsigned long)worst_length);
     702                 :          0 :                   iconv_close (from_host);
     703                 :          0 :                   return PDF_FALSE;
     704                 :            :                 }
     705                 :            : 
     706                 :            :               /* The re-allocated new data does not have to be in the same
     707                 :            :                *  memory place as the original one, so the `out_str' pointer
     708                 :            :                *  must be reset */
     709                 :          0 :               out_str =  &new_data[n_bytes_generated];
     710                 :            : 
     711                 :            :               /* The number of bytes available in the buffer must also be
     712                 :            :                *  reset */
     713                 :          0 :               n_out = (worst_length - n_bytes_generated);
     714                 :            :             }
     715                 :            :           else
     716                 :            :             {
     717                 :          2 :               iconv_close (from_host);
     718                 :          2 :               pdf_dealloc (new_data);
     719                 :          2 :               pdf_set_error (error,
     720                 :            :                              PDF_EDOMAIN_BASE_TEXT,
     721                 :            :                              PDF_EBADTEXT,
     722                 :            :                              "cannot convert to host encoding: "
     723                 :            :                              "invalid data to convert from host encoding, '%s'",
     724                 :            :                              strerror (errno));
     725                 :          2 :               return PDF_FALSE;
     726                 :            :             }
     727                 :            :         }
     728                 :            :     }
     729                 :            : 
     730                 :            :   /* Compute new final length */
     731                 :          6 :   new_length = worst_length - n_out;
     732                 :            : 
     733                 :            :   /* Remove from the length the bytes related to the 4-byte NUL UTF-32 char */
     734 [ +  - ][ +  - ]:          6 :   if ((new_data[new_length-1] == '\0') &&
         [ +  - ][ -  + ]
     735                 :          6 :       (new_data[new_length-2] == '\0') &&
     736                 :          6 :       (new_data[new_length-3] == '\0') &&
     737                 :          6 :       (new_data[new_length-4] == '\0'))
     738                 :            :     {
     739                 :          0 :       new_length -= 4;
     740                 :            :     }
     741                 :            : 
     742                 :            :   /* Finally, reset the buffer length to its correct size */
     743         [ +  - ]:          6 :   if (new_length != worst_length)
     744                 :            :     {
     745                 :          6 :       new_data = (pdf_char_t *) pdf_realloc (new_data, new_length);
     746         [ -  + ]:          6 :       if (new_data == NULL)
     747                 :            :         {
     748                 :          0 :           pdf_set_error (error,
     749                 :            :                          PDF_EDOMAIN_BASE_TEXT,
     750                 :            :                          PDF_ENOMEM,
     751                 :            :                          "cannot convert from host encoding: "
     752                 :            :                          "couldn't rellocate '%lu' bytes",
     753                 :            :                          (unsigned long)new_length);
     754                 :          0 :           return PDF_FALSE;
     755                 :            :         }
     756                 :            :     }
     757                 :            : 
     758                 :            :   /* And set the output values within pdf_text_t */
     759                 :          6 :   *p_output_data = new_data;
     760                 :          6 :   *p_output_length = new_length;
     761                 :            : 
     762                 :          6 :   iconv_close (from_host);
     763                 :         10 :   return PDF_TRUE;
     764                 :            : }
     765                 :            : 
     766                 :            : #endif /* PDF_HOST_WIN32 */
     767                 :            : 
     768                 :            : pdf_bool_t
     769                 :         33 : pdf_text_utf32he_to_host (const pdf_char_t  *input_data,
     770                 :            :                           const pdf_size_t   input_length,
     771                 :            :                           const pdf_char_t  *enc,
     772                 :            :                           pdf_char_t       **p_output_data,
     773                 :            :                           pdf_size_t        *p_output_length,
     774                 :            :                           pdf_error_t      **error)
     775                 :            : {
     776                 :            : #ifdef PDF_HOST_WIN32
     777                 :            :   return pdf_text_utf32he_to_host_win32 (input_data,
     778                 :            :                                          input_length,
     779                 :            :                                          enc,
     780                 :            :                                          p_output_data,
     781                 :            :                                          p_output_length,
     782                 :            :                                          error);
     783                 :            : #else
     784                 :         33 :   return pdf_text_utf32he_to_host_iconv (input_data,
     785                 :            :                                          input_length,
     786                 :            :                                          enc,
     787                 :            :                                          p_output_data,
     788                 :            :                                          p_output_length,
     789                 :            :                                          error);
     790                 :            : #endif /* PDF_HOST_WIN32 */
     791                 :            : }
     792                 :            : 
     793                 :            : pdf_bool_t
     794                 :         10 : pdf_text_host_to_utf32he (const pdf_char_t  *input_data,
     795                 :            :                           const pdf_size_t   input_length,
     796                 :            :                           const pdf_char_t  *enc,
     797                 :            :                           pdf_char_t       **p_output_data,
     798                 :            :                           pdf_size_t        *p_output_length,
     799                 :            :                           pdf_error_t      **error)
     800                 :            : {
     801                 :            : #ifdef PDF_HOST_WIN32
     802                 :            :   return pdf_text_host_to_utf32he_win32 (input_data,
     803                 :            :                                          input_length,
     804                 :            :                                          enc,
     805                 :            :                                          p_output_data,
     806                 :            :                                          p_output_length,
     807                 :            :                                          error);
     808                 :            : #else
     809                 :         10 :   return pdf_text_host_to_utf32he_iconv (input_data,
     810                 :            :                                          input_length,
     811                 :            :                                          enc,
     812                 :            :                                          p_output_data,
     813                 :            :                                          p_output_length,
     814                 :            :                                          error);
     815                 :            : #endif
     816                 :            : }
     817                 :            : 
     818                 :            : /* End of pdf-text-host-encoding.c */

Generated by: LCOV version 1.8