LCOV - code coverage report
Current view: top level - src/base - pdf-text-encoding.c (source / functions) Hit Total Coverage
Test: libgnupdf.info Lines: 252 323 78.0 %
Date: 2011-12-09 Functions: 11 11 100.0 %
Branches: 124 166 74.7 %

           Branch data     Line data    Source code
       1                 :            : /* -*- mode: C -*-
       2                 :            :  *
       3                 :            :  *       File:         pdf-text-encoding.c
       4                 :            :  *       Date:         Fri Jan 11 21:09:56 2008
       5                 :            :  *
       6                 :            :  *       GNU PDF Library - Encoded Text handling utilities - Encoding
       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                 :            : #include <stdio.h>
      30                 :            : 
      31                 :            : #include <pdf-text-encoding.h>
      32                 :            : #include <pdf-text-context.h>
      33                 :            : 
      34                 :            : #define PDF_TEXT_CHANGE_ENDIANNESS_16BIT(number)        \
      35                 :            :   ((0x00FF & number) << 8) | ((0xFF00 & number) >> 8)
      36                 :            : 
      37                 :            : #define PDF_TEXT_CHANGE_ENDIANNESS_32BIT(number)    \
      38                 :            :   (((0x000000FF & number) << 24) |                  \
      39                 :            :    ((0x0000FF00 & number) << 8 ) |                  \
      40                 :            :    ((0x00FF0000 & number) >> 8 ) |                  \
      41                 :            :    ((0xFF000000 & number) >> 24))
      42                 :            : 
      43                 :            : /* Mapping between PDF Doc Encoding and UNICODE UTF32 (Host Endian!)
      44                 :            :  * Obtained from PDF Reference v1.7, appendix D.2 */
      45                 :            : #define PDFDOCENC_MAX 256
      46                 :            : static const pdf_u32_t pdfdocenc_map [PDFDOCENC_MAX] = { /* INDEXES */
      47                 :            :   0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 00, 07 */
      48                 :            :   0x0000, 0x0009, 0x000A, 0x0000, 0x0000, 0x000D, 0x0000, 0x0000, /* 08, 0F */
      49                 :            :   0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 10, 17 */
      50                 :            :   0x02D8, 0x02C7, 0x02C6, 0x02D9, 0x02DD, 0x02DB, 0x02DA, 0x02DC, /* 18, 1F */
      51                 :            :   0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, /* 20, 27 */
      52                 :            :   0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F, /* 28, 2F */
      53                 :            :   0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, /* 30, 37 */
      54                 :            :   0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F, /* 38, 3F */
      55                 :            :   0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, /* 40, 47 */
      56                 :            :   0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, /* 48, 4F */
      57                 :            :   0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, /* 50, 57 */
      58                 :            :   0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F, /* 58, 5F */
      59                 :            :   0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, /* 60, 67 */
      60                 :            :   0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, /* 68, 6F */
      61                 :            :   0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, /* 70, 77 */
      62                 :            :   0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x0000, /* 78, 7F */
      63                 :            :   0x2022, 0x2020, 0x2021, 0x2026, 0x2014, 0x2013, 0x0192, 0x2044, /* 80, 87 */
      64                 :            :   0x2039, 0x203A, 0x2212, 0x2030, 0x201E, 0x201C, 0x201D, 0x2018, /* 88, 8F */
      65                 :            :   0x2019, 0x201A, 0x2122, 0xFB01, 0xFB02, 0x0141, 0x0152, 0x0160, /* 90, 97 */
      66                 :            :   0x0178, 0x017D, 0x0131, 0x0142, 0x0153, 0x0161, 0x017E, 0x0000, /* 98, 9F */
      67                 :            :   0x20AC, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, /* A0, A7 */
      68                 :            :   0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x0000, 0x00AE, 0x00AF, /* A8, AF */
      69                 :            :   0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, /* B0, B7 */
      70                 :            :   0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, /* B8, BF */
      71                 :            :   0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, /* C0, C7 */
      72                 :            :   0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, /* C8, CF */
      73                 :            :   0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, /* D0, D7 */
      74                 :            :   0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF, /* D8, DF */
      75                 :            :   0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, /* E0, E7 */
      76                 :            :   0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, /* E8, EF */
      77                 :            :   0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, /* F0, F7 */
      78                 :            :   0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF  /* F8, FF */
      79                 :            : };
      80                 :            : 
      81                 :            : /* Definition of the interval type */
      82                 :            : struct pdfdocenc_map_interval_s {
      83                 :            :   pdf_u8_t interval_start;
      84                 :            :   pdf_u8_t interval_stop;
      85                 :            : };
      86                 :            : typedef struct pdfdocenc_map_interval_s pdfdocenc_map_interval_t;
      87                 :            : 
      88                 :            : /* Direct intervals */
      89                 :            : #define PDFDOCENC_MDI  10
      90                 :            : static const pdfdocenc_map_interval_t pdfdocenc_map_direct[PDFDOCENC_MDI] = {
      91                 :            :   { 0x09, 0x0A },
      92                 :            :   { 0x0D, 0x0D },
      93                 :            :   { 0x20, 0x7E },
      94                 :            :   { 0xA1, 0xAC },
      95                 :            :   { 0xAE, 0xFF }
      96                 :            : };
      97                 :            : 
      98                 :            : /* Indirect intervals */
      99                 :            : #define PDFDOCENC_MII  10
     100                 :            : static const pdfdocenc_map_interval_t pdfdocenc_map_indirect[PDFDOCENC_MII] = {
     101                 :            :   { 0x18, 0x1F },
     102                 :            :   { 0x80, 0x9E },
     103                 :            :   { 0xA0, 0xA0 }
     104                 :            : };
     105                 :            : 
     106                 :            : /* Undefined intervals, probably not really needed */
     107                 :            : /* #define PDFDOCENC_MUI  10 */
     108                 :            : /* static const pdfdocenc_map_interval_t pdfdocenc_map_undefined[PDFDOCENC_MUI] = { */
     109                 :            : /*   { 0x00, 0x08 }, */
     110                 :            : /*   { 0x0B, 0x0C }, */
     111                 :            : /*   { 0x0E, 0x17 }, */
     112                 :            : /*   { 0x7F, 0x7F }, */
     113                 :            : /*   { 0x9F, 0x9F }, */
     114                 :            : /*   { 0xAD, 0xAD } */
     115                 :            : /* }; */
     116                 :            : 
     117                 :            : /* Mapping of the first char in a UTF-8 character representation, which
     118                 :            :  *  determines the number of bytes that will be needed to represent the
     119                 :            :  *  character:
     120                 :            :  *     0xxx xxxx -> 1 byte  [00,7F]
     121                 :            :  *     110x xxxx -> 2 bytes [C0,DF]
     122                 :            :  *     1110 xxxx -> 3 bytes [E0,EF]
     123                 :            :  *     1111 0xxx -> 4 bytes [F0,F7]
     124                 :            :  *  Longer byte sequences are not allowed to represent Unicode points.
     125                 :            :  */
     126                 :            : static const pdf_uchar_t n_bytes_in_utf8_char[256] = {
     127                 :            :   1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 00, 1F */
     128                 :            :   1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 20, 3F */
     129                 :            :   1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 40, 5F */
     130                 :            :   1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 60, 7F */
     131                 :            :   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 80, 9F */
     132                 :            :   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* A0, BF */
     133                 :            :   2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, /* C0, DF */
     134                 :            :   3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,0,0,0,0,0,0,0,0  /* E0, FF */
     135                 :            : };
     136                 :            : 
     137                 :            : /* UNICODE BOM bytes encoded in the different built-in UNICODE encodings */
     138                 :            : static const pdf_text_bom_t unicode_bom[PDF_TEXT_MAX_UNICODE_ENC] = {
     139                 :            :   { {239,187,191,  0}, 3 },    /* PDF_TEXT_UTF8 */
     140                 :            :   { {254,255,  0,  0}, 2 },    /* PDF_TEXT_UTF16_BE */
     141                 :            :   { {255,254,  0,  0}, 2 },    /* PDF_TEXT_UTF16_LE */
     142                 :            :   { {  0,  0,  0,  0}, 0 },    /* N/A (UTF-16 HE) */
     143                 :            :   { {  0,  0,254,255}, 4 },    /* PDF_TEXT_UTF32_BE */
     144                 :            :   { {255,254,  0,  0}, 4 },    /* PDF_TEXT_UTF32_LE */
     145                 :            :   { {  0,  0,  0,  0}, 0 }     /* N/A (UTF-32HE)  */
     146                 :            : };
     147                 :            : 
     148                 :            : /* Name of the different Unicode encodings */
     149                 :            : static const pdf_char_t *unicode_encoding_name[PDF_TEXT_MAX_UNICODE_ENC] = {
     150                 :            :   "UTF-8",    /* PDF_TEXT_UTF8 */
     151                 :            :   "UTF-16BE", /* PDF_TEXT_UTF16_BE */
     152                 :            :   "UTF-16LE", /* PDF_TEXT_UTF16_LE */
     153                 :            :   "UTF-16HE", /* PDF_TEXT_UTF16_HE */
     154                 :            :   "UTF-32BE", /* PDF_TEXT_UTF32_BE */
     155                 :            :   "UTF-32LE", /* PDF_TEXT_UTF32_LE */
     156                 :            :   "UTF-32HE"  /* PDF_TEXT_UTF32_HE */
     157                 :            : };
     158                 :            : 
     159                 :            : /******************** PDF Doc Encoding to UTF-32 conversion *******************/
     160                 :            : 
     161                 :            : static pdf_text_utf32_char_t
     162                 :            : pdf_text_pdfdocenc_point_to_utf32he_point (const pdf_char_t pdfdocenc_val)
     163                 :            : {
     164                 :            :   pdf_text_utf32_char_t utf32val;
     165                 :            : 
     166                 :        262 :   utf32val.i = pdfdocenc_map[(pdf_uchar_t)pdfdocenc_val];
     167                 :        262 :   return utf32val;
     168                 :            : }
     169                 :            : 
     170                 :            : /* Static function to convert from PDF Doc Encoding to UTF-32HE, lossless */
     171                 :            : pdf_bool_t
     172                 :         34 : pdf_text_pdfdocenc_to_utf32he (const pdf_char_t  *input_data,
     173                 :            :                                const pdf_size_t   input_length,
     174                 :            :                                pdf_char_t       **p_output_data,
     175                 :            :                                pdf_size_t        *p_output_length,
     176                 :            :                                pdf_error_t      **error)
     177                 :            : {
     178                 :            :   /* Note: PDF Doc Encoding has always 8 bits per character.
     179                 :            :    *  This means that, if length of origin string is N bytes, the number of
     180                 :            :    *  required bytes for the UTF32 representation of the string is 4N.
     181                 :            :    *  (Each PDFDocEncoding byte is expanded to 4 bytes in UTF32. */
     182                 :            : 
     183                 :            :   pdf_size_t i;  /* index for the origin string data */
     184                 :            :   pdf_size_t j;  /* index for the destination string data */
     185                 :            :   pdf_char_t *data;
     186                 :            :   pdf_size_t new_length;
     187                 :            : 
     188                 :            :   /* Get new string length... */
     189                 :         34 :   new_length = 4 * input_length;
     190                 :            : 
     191                 :            :   /* Create destination string with correct size (but empty!) */
     192                 :         34 :   data = (pdf_char_t *) pdf_alloc (new_length);
     193         [ -  + ]:         34 :   if (data == NULL)
     194                 :            :     {
     195                 :          0 :       pdf_set_error (error,
     196                 :            :                      PDF_EDOMAIN_BASE_TEXT,
     197                 :            :                      PDF_ENOMEM,
     198                 :            :                      "cannot convert PDF doc encoding to UTF-32HE: "
     199                 :            :                      "couldn't allocate %lu bytes",
     200                 :            :                      (unsigned long)new_length);
     201                 :          0 :       return PDF_FALSE;
     202                 :            :     }
     203                 :            : 
     204         [ +  + ]:        284 :   for (i = 0, j = 0; i < input_length; i++, j += 4)
     205                 :            :     {
     206                 :            :       pdf_text_utf32_char_t utf32val;
     207                 :            : 
     208                 :            :       /* Get value... */
     209                 :        524 :       utf32val = pdf_text_pdfdocenc_point_to_utf32he_point (input_data[i]);
     210         [ +  + ]:        262 :       if (utf32val.i == 0)
     211                 :            :         {
     212                 :         12 :           pdf_dealloc (data);
     213                 :         12 :           pdf_set_error (error,
     214                 :            :                          PDF_EDOMAIN_BASE_TEXT,
     215                 :            :                          PDF_EBADDATA,
     216                 :            :                          "cannot convert PDF doc encoding to UTF-32HE: "
     217                 :            :                          "input byte '%d' is undefined in PDF Doc encoding",
     218                 :         12 :                          input_data[i]);
     219                 :         12 :           return PDF_FALSE;
     220                 :            :         }
     221                 :            :       /* Copy converted value to output */
     222                 :        250 :       memcpy (&(data[j]), &(utf32val), 4);
     223                 :            :     }
     224                 :            : 
     225                 :            :   /* Everything went ok, set output data */
     226                 :         22 :   *p_output_data = data;
     227                 :         22 :   *p_output_length = new_length;
     228                 :            : 
     229                 :         34 :   return PDF_TRUE;
     230                 :            : }
     231                 :            : 
     232                 :            : /******************** UTF-32 to PDF Doc Encoding conversion *******************/
     233                 :            : 
     234                 :            : static pdf_char_t
     235                 :            : pdf_text_utf32he_point_to_pdfdocenc_point (const pdf_text_utf32_char_t utf32val)
     236                 :            : {
     237                 :            :   pdf_u8_t i;
     238                 :            : 
     239                 :            :   /* If the given UTF-32 point is encoded in a single byte, then direct
     240                 :            :    *  conversion is possible */
     241         [ +  + ]:        180 :   if (utf32val.i <= 0xFF)
     242                 :            :     {
     243                 :            :       /* Check if direct conversion is possible */
     244         [ +  - ]:        534 :       for (i = 0; i < PDFDOCENC_MDI; ++i)
     245                 :            :         {
     246 [ +  + ][ +  - ]:        534 :           if ((utf32val.i <= pdfdocenc_map_direct[i].interval_stop) &&
     247                 :        178 :               (utf32val.i >= pdfdocenc_map_direct[i].interval_start))
     248                 :            :             {
     249                 :            :               /* If the unicode char is among this intervals, direct conversion
     250                 :            :                * is possible (single byte!) */
     251                 :        178 :               return (pdf_char_t)utf32val.i;
     252                 :            :             }
     253                 :            :         }
     254                 :            :     }
     255                 :            :   else
     256                 :            :     {
     257                 :            :       /* Check if indirect conversion is possible */
     258         [ +  + ]:         22 :       for (i = 0; i < PDFDOCENC_MII; ++i)
     259                 :            :         {
     260                 :            :           /* Simple search in the interval */
     261                 :            :           pdf_size_t search_index;
     262                 :            : 
     263                 :         20 :           search_index = pdfdocenc_map_indirect[i].interval_start;
     264         [ +  + ]:        114 :           while ((search_index <= pdfdocenc_map_indirect[i].interval_stop) )
     265                 :            :             {
     266         [ -  + ]:         94 :               if (pdfdocenc_map[search_index] == utf32val.i)
     267                 :            :                 {
     268                 :            :                   /* Directly apply search index as character */
     269                 :          0 :                   return (pdf_char_t)search_index;
     270                 :            :                 }
     271                 :         94 :               search_index++;
     272                 :            :             }
     273                 :            :         }
     274                 :            :     }
     275                 :            : 
     276                 :            :   /* If neither Direct conversion nor Indirect conversion are available,
     277                 :            :    *  the given character is UNDEFINED. Set default character when there is no
     278                 :            :    *  direct mapping to PDF Doc Encoding. This means that every conversion
     279                 :            :    *  to PDF Doc Encoding will NEVER fail if there is no mapping of a code point
     280                 :            :    *  in PDF Doc Encoding */
     281                 :          2 :   return (pdf_char_t)'?';
     282                 :            : }
     283                 :            : 
     284                 :            : /* Static function to convert from UTF-32HE to PDF Doc Encoding, with loss of
     285                 :            :  information */
     286                 :            : pdf_bool_t
     287                 :         20 : pdf_text_utf32he_to_pdfdocenc (const pdf_char_t  *input_data,
     288                 :            :                                const pdf_size_t   input_length,
     289                 :            :                                pdf_char_t       **p_output_data,
     290                 :            :                                pdf_size_t        *p_output_length,
     291                 :            :                                pdf_error_t      **error)
     292                 :            : {
     293                 :            :   /* Note: UTF-32 has always 32 bits per character.
     294                 :            :    This means that, if length of origin string is 4N bytes, the number of
     295                 :            :    required bytes for the PDFDocEncoding representation of the string is N.
     296                 :            :    (Each UNICODE 4-byte character is represented as 1-byte character in
     297                 :            :    PDFDocEncoding). This means that LOSS of information could happen */
     298                 :            : 
     299                 :            :   int i;  /* index for the origin string data */
     300                 :            :   int j;  /* index for the destination string data */
     301                 :            : 
     302                 :            :   /* Check if the length of the origin string is multiple of 4 bytes */
     303         [ -  + ]:         20 :   if (input_length % 4 != 0)
     304                 :            :     {
     305                 :          0 :       pdf_set_error (error,
     306                 :            :                      PDF_EDOMAIN_BASE_TEXT,
     307                 :            :                      PDF_EBADDATA,
     308                 :            :                      "cannot convert from UTF-32HE to PDF Doc encoding: "
     309                 :            :                      "invalid input data length: %lu",
     310                 :            :                      (unsigned long)input_length);
     311                 :          0 :       return PDF_FALSE;
     312                 :            :     }
     313                 :            : 
     314                 :            :   /* Get new string length... */
     315                 :         20 :   *p_output_length = input_length / 4;
     316                 :            : 
     317                 :            :   /* Create destination string with correct size (but empty!) */
     318                 :         20 :   *p_output_data = (pdf_char_t *) pdf_alloc (*p_output_length);
     319         [ -  + ]:         20 :   if (*p_output_data == NULL)
     320                 :            :     {
     321                 :          0 :       pdf_set_error (error,
     322                 :            :                      PDF_EDOMAIN_BASE_TEXT,
     323                 :            :                      PDF_ENOMEM,
     324                 :            :                      "cannot convert from UTF-32HE to PDF Doc encoding: "
     325                 :            :                      "couldn't allocate %lu bytes",
     326                 :            :                      (unsigned long)*p_output_length);
     327                 :          0 :       return PDF_FALSE;
     328                 :            :     }
     329                 :            : 
     330         [ +  + ]:        200 :   for (i = 0, j = 0; i < input_length; i += 4, j++)
     331                 :            :     {
     332                 :            :       pdf_text_utf32_char_t   utf32val; /* UNICODE char */
     333                 :            : 
     334                 :            :       /* Get UTF-32 char to convert */
     335                 :        180 :       memcpy (&utf32val, &input_data[i], 4);
     336                 :            :       /* Convert character to PDF Doc Encoding */
     337                 :        360 :       (*p_output_data)[j] = pdf_text_utf32he_point_to_pdfdocenc_point (utf32val);
     338                 :            :     }
     339                 :            : 
     340                 :         20 :   return PDF_TRUE;
     341                 :            : }
     342                 :            : 
     343                 :            : /*********************** UTF-32 to UTF-32 conversions *************************/
     344                 :            : 
     345                 :            : /* Function to convert from UTF-32HE to UTF-32HE, lossless */
     346                 :            : pdf_bool_t
     347                 :        759 : pdf_text_utf32he_to_utf32he (const pdf_char_t  *input_data,
     348                 :            :                              const pdf_size_t   input_length,
     349                 :            :                              const pdf_bool_t   swap,
     350                 :            :                              const pdf_bool_t   check_input_he,
     351                 :            :                              const pdf_bool_t   check_output_he,
     352                 :            :                              pdf_char_t       **p_output_data,
     353                 :            :                              pdf_size_t        *p_output_length,
     354                 :            :                              pdf_error_t      **error)
     355                 :            : {
     356                 :            :   pdf_size_t walker;
     357                 :        759 :   pdf_size_t bom_bytes = 0;
     358                 :        759 :   pdf_char_t *new_data = NULL;
     359                 :        759 :   pdf_size_t new_size = 0;
     360                 :            : 
     361         [ +  + ]:        759 :   if (input_length % 4 != 0)
     362                 :            :     {
     363                 :         60 :       pdf_set_error (error,
     364                 :            :                      PDF_EDOMAIN_BASE_TEXT,
     365                 :            :                      PDF_EBADDATA,
     366                 :            :                      "cannot convert from UTF-32HE to UTF-32HE: "
     367                 :            :                      "invalid input data length: %lu",
     368                 :            :                      (unsigned long)input_length);
     369                 :         60 :       return PDF_FALSE;
     370                 :            :     }
     371                 :            : 
     372                 :            :   /* Check if BOM is present... and skip it if so */
     373         [ +  + ]:        699 :   if (pdf_text_check_unicode_bom (input_data,
     374                 :            :                                   input_length,
     375                 :            :                                   PDF_TEXT_UTF32_HE,
     376                 :            :                                   swap))
     377                 :            :     {
     378                 :            :       /* Skip BOM */
     379                 :         30 :       bom_bytes = 4;
     380                 :            :     }
     381                 :            : 
     382                 :            :   /* Allocate memory */
     383                 :        699 :   new_size = input_length - bom_bytes;
     384                 :            :   /* Create destination string with correct size (but empty!) */
     385                 :        699 :   new_data = (pdf_char_t *) pdf_alloc (new_size);
     386         [ -  + ]:        699 :   if (new_data == NULL)
     387                 :            :     {
     388                 :          0 :       pdf_set_error (error,
     389                 :            :                      PDF_EDOMAIN_BASE_TEXT,
     390                 :            :                      PDF_ENOMEM,
     391                 :            :                      "cannot convert from UTF-32HE to UTF-32HE: "
     392                 :            :                      "couldn't allocate %lu bytes",
     393                 :            :                      (unsigned long)new_size);
     394                 :          0 :       return PDF_FALSE;
     395                 :            :     }
     396                 :            : 
     397                 :            :   /* Change endianness of each 32bit value... */
     398         [ +  + ]:       8793 :   for (walker = bom_bytes; walker < input_length; walker += 4)
     399                 :            :     {
     400                 :            :       pdf_text_utf32_char_t utf32val;
     401                 :            : 
     402                 :       8094 :       memcpy (&utf32val, &input_data[walker], 4);
     403                 :            : 
     404                 :            :       /* Check code point validity (if the input is Host Endian) */
     405                 :            :       /* Code point must not be a surrogate code unit, and must be in the
     406                 :            :        * U+00000000 - U+0010FFFF range */
     407 [ +  + ][ -  + ]:       8094 :       if ((check_input_he) &&
     408                 :       3367 :           ((utf32val.i > 0x10FFFF) ||
     409                 :            :            ((utf32val.i >= 0xD800) &&
     410                 :            :             (utf32val.i <= 0xDFFF))))
     411                 :            :         {
     412                 :            :           /* Invalid UTF-32 code point received */
     413                 :          0 :           pdf_set_error (error,
     414                 :            :                          PDF_EDOMAIN_BASE_TEXT,
     415                 :            :                          PDF_EBADTEXT,
     416                 :            :                          "cannot convert from UTF-32HE to UTF-32HE: "
     417                 :            :                          "invalid input code point: "
     418                 :            :                          "%.2X:%.2X:%.2X:%.2X",
     419                 :          0 :                          utf32val.c[0],
     420                 :          0 :                          utf32val.c[1],
     421                 :          0 :                          utf32val.c[2],
     422                 :          0 :                          utf32val.c[3]);
     423                 :          0 :           return PDF_FALSE;
     424                 :            :         }
     425                 :            : 
     426                 :            :       /* Swap bytes */
     427         [ +  + ]:       8094 :       if (swap)
     428                 :            :         {
     429                 :       4768 :           utf32val.i = PDF_TEXT_CHANGE_ENDIANNESS_32BIT (utf32val.i);
     430                 :            :         }
     431                 :            : 
     432                 :            :       /* Check code point validity (if the output is Host Endian) */
     433                 :            :       /* Code point must not be a surrogate code unit, and must be in the
     434                 :            :        * U+00000000 - U+0010FFFF range */
     435 [ +  + ][ -  + ]:       8094 :       if ((check_output_he) &&
     436                 :       4727 :           ((utf32val.i > 0x10FFFF) ||
     437                 :            :            ((utf32val.i >= 0xD800) &&
     438                 :            :             (utf32val.i <= 0xDFFF))))
     439                 :            :         {
     440                 :            :           /* Invalid output UTF-32 code point */
     441                 :          0 :           pdf_set_error (error,
     442                 :            :                          PDF_EDOMAIN_BASE_TEXT,
     443                 :            :                          PDF_EBADTEXT,
     444                 :            :                          "cannot convert from UTF-32HE to UTF-32HE: "
     445                 :            :                          "invalid output code point: "
     446                 :            :                          "%.2X:%.2X:%.2X:%.2X",
     447                 :          0 :                          utf32val.c[0],
     448                 :          0 :                          utf32val.c[1],
     449                 :          0 :                          utf32val.c[2],
     450                 :          0 :                          utf32val.c[3]);
     451                 :          0 :           return PDF_FALSE;
     452                 :            :         }
     453                 :            : 
     454                 :            :       /* Copy value */
     455                 :       8094 :       memcpy (&(new_data[walker-bom_bytes]), &utf32val, 4);
     456                 :            :     }
     457                 :            : 
     458                 :            :   /* Really set output data */
     459                 :        699 :   *p_output_data = new_data;
     460                 :        699 :   *p_output_length = new_size;
     461                 :            : 
     462                 :        759 :   return PDF_TRUE;
     463                 :            : }
     464                 :            : 
     465                 :            : /*********************** UTF-16 to UTF-32 conversions *************************/
     466                 :            : 
     467                 :            : /* Static function to convert a given UTF-16HE character (with one or two words)
     468                 :            :  *  to UTF-32HE. The number of bytes (2 or 4) used from the input UTF-16BE point
     469                 :            :  *  is returned (or 0 if the UTF-16HE point is not valid */
     470                 :            : static pdf_size_t
     471                 :            : pdf_text_utf16he_point_to_utf32he_point (pdf_text_utf16_char_t   utf16val[2],
     472                 :            :                                          pdf_text_utf32_char_t  *p_utf32val,
     473                 :            :                                          pdf_error_t           **error)
     474                 :            : {
     475                 :            :   pdf_size_t n_bytes;
     476                 :            : 
     477                 :            :   /* Ok, so how can we know if the UTF16 character is encoded using 2 or
     478                 :            :    * 4 bytes? A surrogate pair consists on two 16-bit values of the
     479                 :            :    * UTF16 encoding. Each word (16bit-value) within the surrogate pair
     480                 :            :    * doesn't represent a valid character, as it is enclosed in the
     481                 :            :    * following interval: U+D800 - U+DFFF. This means that if the first
     482                 :            :    * word analysed is outside this interval, it will be treated
     483                 :            :    * separately. If the first word is within this interval, it is
     484                 :            :    * expected to have the second word within the interval as well. If
     485                 :            :    * this doesn't happen it will be treated as a badly formatted UTF16
     486                 :            :    * string. In fact, there are two different intervals within the surrogate
     487                 :            :    * points themselves: the High surrogate point will be in the U+D800 -
     488                 :            :    * U+DBFF interval, and the Low surrogate point will be in the U+DC00 -
     489                 :            :    * U+DFFF interval. */
     490                 :            : 
     491         [ +  + ]:       1339 :   if (((utf16val[0].i) >= 0xD800) &&
     492                 :            :       ((utf16val[0].i) <= 0xDFFF))
     493                 :            :     {
     494                 :            :       /* To have a valid surrogate pair, the first UTF-16 value must be the High
     495                 :            :        *  surrogate code unit, and the second UTF-16 value must be the Low
     496                 :            :        *  surrogate code unit. */
     497 [ +  - ][ +  - ]:         40 :       if (((utf16val[0].i) <= 0xDFFF) &&
                 [ +  - ]
     498                 :         40 :           ((utf16val[1].i) >= 0xDC00) &&
     499                 :         40 :           ((utf16val[1].i) <= 0xDFFF))
     500                 :            :         {
     501                 :            :           /* Yes, second word is within the validity interval, it seems a
     502                 :            :            * correct 32-bit representation of a character in UTF16BE */
     503                 :         40 :           n_bytes = 4;
     504                 :         40 :           (*p_utf32val).i = (0x10000 +
     505                 :         40 :                              (((utf16val[0].i) - 0xD800) << 10) +
     506                 :         40 :                              ((utf16val[1].i) - 0xDC00));
     507                 :            :         }
     508                 :            :       /* else Oops, invalid UTF-16HE surrogate pair! Input data is not well
     509                 :            :        * formed... */
     510                 :            :       else
     511                 :            :         {
     512                 :          0 :           pdf_set_error (error,
     513                 :            :                          PDF_EDOMAIN_BASE_TEXT,
     514                 :            :                          PDF_EBADTEXT,
     515                 :            :                          "cannot convert from UTF-16HE to UTF-32HE: "
     516                 :            :                          "invalid input code point: "
     517                 :            :                          "%.2X:%.2X:%.2X:%.2X",
     518                 :          0 :                          utf16val[0].c[0], utf16val[0].c[1],
     519                 :          0 :                          utf16val[1].c[0], utf16val[1].c[1]);
     520                 :          0 :           n_bytes = 0;
     521                 :            :         }
     522                 :            :     }
     523                 :            :   else
     524                 :            :     {
     525                 :            :       /* No multiword representation, just 16bits for this character
     526                 :            :        * So conversion is direct... */
     527                 :       1299 :       n_bytes = 2;
     528                 :       1299 :       (*p_utf32val).i = (utf16val[0]).i;
     529                 :            :     }
     530                 :            : 
     531                 :       1339 :   return n_bytes;
     532                 :            : }
     533                 :            : 
     534                 :            : /* Function to convert from UTF-16HE to UTF-32HE, lossless */
     535                 :            : pdf_bool_t
     536                 :        163 : pdf_text_utf16he_to_utf32he (const pdf_char_t  *input_data,
     537                 :            :                              const pdf_size_t   input_length,
     538                 :            :                              const pdf_bool_t   swap,
     539                 :            :                              pdf_char_t       **p_output_data,
     540                 :            :                              pdf_size_t        *p_output_length,
     541                 :            :                              pdf_char_t       **p_remaining_data,
     542                 :            :                              pdf_size_t        *p_remaining_length,
     543                 :            :                              pdf_error_t      **error)
     544                 :            : {
     545                 :            :   /* Note: UTF-16 has either 16 or 32 bits per character.
     546                 :            :    *  This means that, if length of origin string is N bytes, the number of
     547                 :            :    *  required bytes for the UTF-32 representation of the string is 2N in
     548                 :            :    *  the worst case (in the case of having all the UTF-16 characters encoded
     549                 :            :    *  with 16bits).
     550                 :            :    *  (Each UTF-16 is expanded to 4 bytes in UTF-32. */
     551                 :            : 
     552                 :            :   pdf_char_t *data;
     553                 :            :   pdf_size_t new_string_length;
     554                 :            :   pdf_size_t new_string_length_worst;
     555                 :            :   pdf_size_t delta_in_utf16be;
     556                 :            :   int i;  /* index for the origin string data */
     557                 :            :   int j;  /* index for the destination string data */
     558                 :            :   pdf_text_utf16_char_t utf16val[2];
     559                 :            :   pdf_text_utf32_char_t utf32val;
     560                 :        163 :   short stop_conversion = PDF_FALSE;
     561                 :        163 :   short check_lang_code = PDF_FALSE;
     562                 :        163 :   int bom_bytes = 0;
     563                 :            : 
     564                 :            :   /* Check if length is multiple of 2 (data must come in pairs of bytes!) */
     565 [ +  - ][ +  + ]:        163 :   if ((input_length < 2) ||
     566                 :        163 :       (input_length % 2) != 0)
     567                 :            :     {
     568                 :         60 :       pdf_set_error (error,
     569                 :            :                      PDF_EDOMAIN_BASE_TEXT,
     570                 :            :                      PDF_EBADDATA,
     571                 :            :                      "cannot convert from UTF-16HE to UTF-32HE: "
     572                 :            :                      "invalid input data length: %lu",
     573                 :            :                      (unsigned long)input_length);
     574                 :         60 :       return PDF_FALSE;
     575                 :            :     }
     576                 :            : 
     577                 :            :   /* Check if BOM is present... and skip it if so */
     578         [ +  + ]:        103 :   if (pdf_text_check_unicode_bom (input_data,
     579                 :            :                                   input_length,
     580                 :            :                                   PDF_TEXT_UTF16_HE,
     581                 :            :                                   swap))
     582                 :            :     {
     583                 :            :       /* Skip BOM */
     584                 :         35 :       bom_bytes = 2;
     585                 :            :     }
     586                 :            : 
     587                 :            :   /* Get new string worst length... (don't consider BOM bytes) */
     588                 :        103 :   new_string_length_worst = 2 * (input_length - bom_bytes);
     589                 :            :   /* Create destination string with worst size (but empty!) */
     590                 :        103 :   data = (pdf_char_t *) pdf_alloc (new_string_length_worst);
     591         [ -  + ]:        103 :   if (data == NULL)
     592                 :            :     {
     593                 :          0 :       pdf_set_error (error,
     594                 :            :                      PDF_EDOMAIN_BASE_TEXT,
     595                 :            :                      PDF_ENOMEM,
     596                 :            :                      "cannot convert from UTF-16HE to UTF-32HE: "
     597                 :            :                      "couldn't allocate %lu bytes",
     598                 :            :                      (unsigned long)new_string_length_worst);
     599                 :          0 :       return PDF_FALSE;
     600                 :            :     }
     601                 :            : 
     602                 :            :   /* Initiate final string length */
     603                 :        103 :   new_string_length = 0;
     604                 :            : 
     605                 :            :   /* Initiate indexes */
     606                 :        103 :   i = bom_bytes;  /* Skipping BOM if present... */
     607                 :        103 :   j = 0;
     608                 :            : 
     609                 :            :   /* Check if specific country/language could be found */
     610         [ +  + ]:        103 :   if ((p_remaining_length != NULL) &&
     611                 :        103 :       (p_remaining_data != NULL))
     612                 :            :     {
     613                 :         33 :       check_lang_code = PDF_TRUE;
     614                 :            :     }
     615                 :            : 
     616                 :            :   /* This while loop will be done until the end of the input data OR until
     617                 :            :    *  the moment a new country/language code identifier is found. But, this
     618                 :            :    *  extra stop condition will only be available if valid `p_remaining_data'
     619                 :            :    *  and `p_remaining_length' pointers are given as input. */
     620         [ +  + ]:       1454 :   while ((i < input_length) &&
     621                 :       1454 :          (!stop_conversion))
     622                 :            :     {
     623 [ +  + ][ +  + ]:       1351 :       if ((check_lang_code) &&
                 [ +  - ]
     624                 :        429 :           (input_data[i+1] == PDF_TEXT_LCI_1) &&
     625                 :         12 :           (input_data[i] == PDF_TEXT_LCI_0))
     626                 :            :         {
     627                 :            :           /* Stop conversion... due to new lang/code initializer */
     628                 :         12 :           stop_conversion = PDF_TRUE;
     629                 :            :           /* Set the output remaining data... */
     630                 :         12 :           *p_remaining_length = input_length - i;
     631                 :         12 :           *p_remaining_data = (pdf_char_t *)&input_data[i];
     632                 :            :         }
     633                 :            :       else
     634                 :            :         {
     635                 :            :           /* Store the UTF-16(BE/LE) data in the intermediate variable */
     636                 :       1339 :           utf16val[0].c[0] = input_data[i];
     637                 :       1339 :           utf16val[0].c[1] = input_data[i+1];
     638         [ +  + ]:       1339 :           if ((i+3) < input_length)
     639                 :            :             {
     640                 :       1286 :               utf16val[1].c[0] = input_data[i+2];
     641                 :       1286 :               utf16val[1].c[1] = input_data[i+3];
     642                 :            :             }
     643                 :            :           /* else, last point should be only 1-word length */
     644                 :            :           else
     645                 :            :             {
     646                 :         53 :               utf16val[1].c[0] = 0x00;
     647                 :         53 :               utf16val[1].c[1] = 0x00;
     648                 :            :             }
     649                 :            : 
     650         [ +  + ]:       1339 :           if (swap)
     651                 :            :             {
     652                 :            :               /* Input data must be swapped in order to convert it to
     653                 :            :                *  host endian */
     654                 :        835 :               utf16val[0].i = PDF_TEXT_CHANGE_ENDIANNESS_16BIT (utf16val[0].i);
     655                 :        835 :               utf16val[1].i = PDF_TEXT_CHANGE_ENDIANNESS_16BIT (utf16val[1].i);
     656                 :            :             }
     657                 :            : 
     658                 :            :           /* Change UTF-16HE point to UTF-32HE point */
     659                 :       1339 :           delta_in_utf16be = pdf_text_utf16he_point_to_utf32he_point (utf16val,
     660                 :            :                                                                       &utf32val,
     661                 :            :                                                                       error);
     662         [ -  + ]:       1339 :           if (delta_in_utf16be == 0)
     663                 :            :             {
     664                 :            :               /* Oops, invalid UTF-16HE point found! */
     665                 :          0 :               pdf_dealloc (data);
     666                 :          0 :               return PDF_FALSE;
     667                 :            :             }
     668                 :            : 
     669                 :            :           /* Finally, store the UTF-32 representation of the char in the output
     670                 :            :            * string... */
     671                 :       1339 :           data[j] = utf32val.c[0];
     672                 :       1339 :           data[j+1] = utf32val.c[1];
     673                 :       1339 :           data[j+2] = utf32val.c[2];
     674                 :       1339 :           data[j+3] = utf32val.c[3];
     675                 :            : 
     676                 :            :           /* Update final string length after having added this character */
     677                 :       1339 :           new_string_length += 4;
     678                 :            : 
     679                 :            :           /* Update indexes */
     680                 :       1339 :           i += delta_in_utf16be;
     681                 :       1339 :           j += 4;
     682                 :            :         }
     683                 :            :     }
     684                 :            : 
     685                 :            :   /* Everything went ok, set output data */
     686                 :        103 :   *p_output_data = data;
     687                 :            :   /* Set output length... */
     688                 :        103 :   *p_output_length = new_string_length;
     689                 :            : 
     690                 :            :   /* Check if the stop flag was set due to finding lang/country code
     691                 :            :    *  initializer. If not found, set zero remaining length and NULL
     692                 :            :    *  remaining str */
     693 [ +  + ][ +  - ]:        103 :   if ((!stop_conversion) &&
     694                 :        103 :       (p_remaining_length != NULL) &&
     695                 :            :       (p_remaining_data != NULL))
     696                 :            :     {
     697                 :         21 :       *p_remaining_length = 0;
     698                 :         21 :       *p_remaining_data = NULL;
     699                 :            :     }
     700                 :            : 
     701                 :            :   /* Now, if the real output string length is not equal to the worst string
     702                 :            :    * length, we will reallocate memory for the correct size. This will only
     703                 :            :    * happen when at least one character is not encoded with 32bits in UTF-16. */
     704         [ +  + ]:        103 :   if (new_string_length != new_string_length_worst)
     705                 :            :     {
     706                 :            :       /* Recreate object with correct size... */
     707                 :         50 :       *p_output_data = (pdf_char_t *) pdf_realloc (*p_output_data,
     708                 :            :                                                    new_string_length);
     709         [ -  + ]:         50 :       if (*p_output_data == NULL)
     710                 :            :         {
     711                 :          0 :           pdf_set_error (error,
     712                 :            :                          PDF_EDOMAIN_BASE_TEXT,
     713                 :            :                          PDF_ENOMEM,
     714                 :            :                          "cannot convert from UTF-16HE to UTF-32HE: "
     715                 :            :                          "couldn't reallocate %lu bytes",
     716                 :            :                          (unsigned long)new_string_length);
     717                 :          0 :           return PDF_FALSE;
     718                 :            :         }
     719                 :            :     }
     720                 :            : 
     721                 :        163 :   return PDF_TRUE;
     722                 :            : }
     723                 :            : 
     724                 :            : /*********************** UTF-32 to UTF-16 conversions *************************/
     725                 :            : 
     726                 :            : /* Static function to convert a given UTF-32HE character to UTF-16HE. The number
     727                 :            :  * of bytes used in the output UTF-16HE point is returned (or 0 if the UTF-16HE
     728                 :            :  * point is not valid */
     729                 :            : static pdf_size_t
     730                 :            : pdf_text_utf32he_point_to_utf16he_point (pdf_text_utf32_char_t   utf32val,
     731                 :            :                                          pdf_text_utf16_char_t   utf16val[2],
     732                 :            :                                          pdf_error_t           **error)
     733                 :            : {
     734                 :            :   pdf_size_t n_bytes;
     735                 :            : 
     736         [ -  + ]:       1008 :   if ((utf32val.i >= 0xD800) &&
     737                 :            :       (utf32val.i <= 0xDFFF))
     738                 :            :     {
     739                 :          0 :       pdf_set_error (error,
     740                 :            :                      PDF_EDOMAIN_BASE_TEXT,
     741                 :            :                      PDF_EBADTEXT,
     742                 :            :                      "cannot convert from UTF-32HE to UTF-16HE: "
     743                 :            :                      "invalid input code point (surrogate pair found): "
     744                 :            :                      "%.2X:%.2X:%.2X:%.2X",
     745                 :          0 :                      utf32val.c[0], utf32val.c[1],
     746                 :          0 :                      utf32val.c[2], utf32val.c[3]);
     747                 :          0 :       n_bytes = 0;
     748                 :            :     }
     749                 :            :   /* Check if multiword (32bits) representation is needed */
     750         [ +  + ]:       1008 :   else if (utf32val.i >= 0x10000)
     751                 :            :     {
     752                 :            :       /* Ok so it seems a multiword representation...
     753                 :            :        * Now check input UTF-32HE representation to see if it really is a
     754                 :            :        *  Unicode point (from 0x00000 to 0x10FFFF) */
     755         [ +  - ]:         32 :       if (utf32val.i <= 0x10FFFF)
     756                 :            :         {
     757                 :            :           /* 32 bits are required for this char */
     758                 :         32 :           n_bytes = 4;
     759                 :         32 :           utf32val.i -= 0x10000;
     760                 :            :           /* Process higher 10 bits, by shifting to the right 10 bits */
     761                 :         32 :           (utf16val[0]).i = (utf32val.i >> 10) + 0xD800;
     762                 :            :           /* Process lower 10 bits, by masking the value with 0x03FF */
     763                 :         32 :           (utf16val[1]).i = (utf32val.i & 0x03FF) + 0xDC00;
     764                 :            :         }
     765                 :            :       else
     766                 :            :         {
     767                 :            :           /* else Oops, invalid 32-bit character! Input data is not well
     768                 :            :            * formed... */
     769                 :          0 :           pdf_set_error (error,
     770                 :            :                          PDF_EDOMAIN_BASE_TEXT,
     771                 :            :                          PDF_EBADTEXT,
     772                 :            :                          "cannot convert from UTF-32HE to UTF-16HE: "
     773                 :            :                          "invalid input code point: "
     774                 :            :                          "%.2X:%.2X:%.2X:%.2X",
     775                 :          0 :                          utf32val.c[0], utf32val.c[1],
     776                 :          0 :                          utf32val.c[2], utf32val.c[3]);
     777                 :          0 :           n_bytes = 0;
     778                 :            :         }
     779                 :            :     }
     780                 :            :   else
     781                 :            :     {
     782                 :        976 :       n_bytes = 2;
     783                 :            :       /* No multiword representation, just 16bits for this character
     784                 :            :        * So conversion is direct.... */
     785                 :        976 :       (utf16val[0]).i = utf32val.i;
     786                 :        976 :       (utf16val[1]).i = 0x0000;
     787                 :            :     }
     788                 :            : 
     789                 :       1008 :   return n_bytes;
     790                 :            : }
     791                 :            : 
     792                 :            : /* Function to convert from UTF-32HE to UTF-16, lossless */
     793                 :            : pdf_bool_t
     794                 :         80 : pdf_text_utf32he_to_utf16he (const pdf_char_t  *input_data,
     795                 :            :                              const pdf_size_t   input_length,
     796                 :            :                              pdf_char_t       **p_output_data,
     797                 :            :                              pdf_size_t        *p_output_length,
     798                 :            :                              pdf_bool_t         swap,
     799                 :            :                              pdf_error_t      **error)
     800                 :            : {
     801                 :            :   /* Note: UTF-16BE has either 16 or 32 bits per character.
     802                 :            :    This means that, if length of origin string is 4N bytes, the number of
     803                 :            :    required bytes for the UTF16BE representation of the string is 4N in
     804                 :            :    the worst case. (When all the UTF16be representations have 32bits)
     805                 :            :    */
     806                 :            :   pdf_size_t new_string_length;
     807                 :            :   pdf_size_t new_string_length_worst;
     808                 :            :   pdf_size_t delta_in_utf16be;
     809                 :            :   int i;  /* index for the origin string data */
     810                 :            :   int j;  /* index for the destination string data */
     811                 :            :   pdf_text_utf16_char_t utf16val[2];
     812                 :            :   pdf_text_utf32_char_t utf32val;
     813                 :            :   pdf_char_t *data;
     814                 :            : 
     815                 :            :   /* Get new string length (worst case)... */
     816                 :         80 :   new_string_length_worst = input_length;
     817                 :            :   /* Create destination string with correct size (but empty!) */
     818                 :         80 :   data = (pdf_char_t *) pdf_alloc (new_string_length_worst);
     819         [ -  + ]:         80 :   if (data == NULL)
     820                 :            :     {
     821                 :          0 :       pdf_set_error (error,
     822                 :            :                      PDF_EDOMAIN_BASE_TEXT,
     823                 :            :                      PDF_ENOMEM,
     824                 :            :                      "cannot convert UTF-32HE to UTF-16HE: "
     825                 :            :                      "couldn't allocate %lu bytes",
     826                 :            :                      (unsigned long)new_string_length_worst);
     827                 :          0 :       return PDF_FALSE;
     828                 :            :     }
     829                 :            : 
     830                 :            :   /* Initiate real string length, without considering marker bytes */
     831                 :         80 :   new_string_length = 0;
     832                 :            : 
     833         [ +  + ]:       1088 :   for (i = 0, j = 0; i < input_length; i += 4, j += delta_in_utf16be)
     834                 :            :     {
     835                 :            :       /* Get UCS4 char, as a direct memory copy from the input array */
     836                 :       1008 :       memcpy (&utf32val, &(input_data[i]), 4);
     837                 :            : 
     838                 :       1008 :       delta_in_utf16be = pdf_text_utf32he_point_to_utf16he_point (utf32val,
     839                 :            :                                                                   utf16val,
     840                 :            :                                                                   error);
     841         [ -  + ]:       1008 :       if (delta_in_utf16be == 0)
     842                 :            :         {
     843                 :            :           /* Oops, invalid UTF-16HE point found! */
     844                 :          0 :           pdf_dealloc (data);
     845                 :          0 :           return PDF_FALSE;
     846                 :            :         }
     847                 :            : 
     848                 :            :       /* Change endianness of each output word if required */
     849         [ +  + ]:       1008 :       if (swap)
     850                 :            :         {
     851                 :            :           /* Change to BE */
     852                 :        756 :           (utf16val[0]).i = PDF_TEXT_CHANGE_ENDIANNESS_16BIT ((utf16val[0]).i);
     853                 :        756 :           (utf16val[1]).i = PDF_TEXT_CHANGE_ENDIANNESS_16BIT ((utf16val[1]).i);
     854                 :            :         }
     855                 :            : 
     856                 :            :       /* Finally, store the UTF16BE representation of the char in the output
     857                 :            :        * string... */
     858                 :       1008 :       memcpy (&(data[j]), &utf16val[0], delta_in_utf16be);
     859                 :            :       /* Update new string legth... */
     860                 :       1008 :       new_string_length += delta_in_utf16be;
     861                 :            :     }
     862                 :            : 
     863                 :            :   /* If everything went ok, set output data */
     864                 :         80 :   *p_output_data = data;
     865                 :            :   /* Set final output length of the generated string */
     866                 :         80 :   *p_output_length = new_string_length;
     867                 :            : 
     868                 :            :   /* If the real required string length is not equal to the initial worst length
     869                 :            :    * then update string with correct length. */
     870         [ +  - ]:         80 :   if (new_string_length != new_string_length_worst)
     871                 :            :     {
     872                 :            :       /* Recreate object with correct smaller size... */
     873                 :         80 :       *p_output_data = (pdf_char_t *) pdf_realloc (*p_output_data,
     874                 :            :                                                    new_string_length);
     875         [ -  + ]:         80 :       if (*p_output_data == NULL)
     876                 :            :         {
     877                 :          0 :           pdf_set_error (error,
     878                 :            :                          PDF_EDOMAIN_BASE_TEXT,
     879                 :            :                          PDF_ENOMEM,
     880                 :            :                          "cannot convert from UTF-16HE to UTF-32HE: "
     881                 :            :                          "couldn't allocate %lu bytes",
     882                 :            :                          (unsigned long)new_string_length);
     883                 :          0 :           return PDF_FALSE;
     884                 :            :         }
     885                 :            :     }
     886                 :            : 
     887                 :         80 :   return PDF_TRUE;
     888                 :            : }
     889                 :            : 
     890                 :            : /************************ UTF-8 to UTF-32 conversions *************************/
     891                 :            : 
     892                 :            : /* Static function to convert a given UTF-8 character to UTF-32HE. The number
     893                 :            :  * of bytes used in the input UTF-8 point is returned (or 0 if the UTF-8 point
     894                 :            :  * is not valid */
     895                 :            : static pdf_size_t
     896                 :       2749 : pdf_text_utf8_point_to_utf32he_point (const pdf_uchar_t       utf8val[4],
     897                 :            :                                       const pdf_size_t        n_bytes,
     898                 :            :                                       pdf_text_utf32_char_t  *p_utf32val,
     899                 :            :                                       pdf_error_t           **error)
     900                 :            : {
     901                 :            :   int c;  /* index for the utf-8 representation of every char */
     902                 :            : 
     903                 :            :   /* Check validity of the UTF-8 bytes:
     904                 :            :    *  - First byte can be neither 0xFF nor 0xFE
     905                 :            :    *  - The following bytes must be in the [80-BF] range! (10xxxxxx) */
     906         [ +  + ]:       5540 :   for (c = 0; c < n_bytes; c++)
     907                 :            :     {
     908 [ +  + ][ +  - ]:       2791 :       if (((c == 0) && ((utf8val[0] == 0xFF) || (utf8val[0] == 0xFE))) ||
         [ +  + ][ -  + ]
     909                 :         42 :           ((c != 0) && ((utf8val[c]  < 0x80) || (utf8val[c]  > 0xBF))))
     910                 :            :         {
     911 [ #  # ][ #  # ]:          0 :           pdf_set_error (error,
                 [ #  # ]
     912                 :            :                          PDF_EDOMAIN_BASE_TEXT,
     913                 :            :                          PDF_EBADTEXT,
     914                 :            :                          "cannot convert from UTF-8 to UTF-32HE: "
     915                 :            :                          "invalid input code point: "
     916                 :            :                          "%.2X:%.2X:%.2X:%.2X",
     917                 :          0 :                          (pdf_uchar_t)utf8val[0],
     918                 :          0 :                          ((n_bytes>1)?((pdf_uchar_t)utf8val[1]):0),
     919                 :          0 :                          ((n_bytes>2)?((pdf_uchar_t)utf8val[2]):0),
     920                 :          0 :                          ((n_bytes>3)?((pdf_uchar_t)utf8val[3]):0));
     921                 :          0 :           return 0;
     922                 :            :         }
     923                 :            :     }
     924                 :            : 
     925                 :            :   /* Load all the bytes of the UTF-8 representation in the UTF-32HE var */
     926   [ +  +  +  +  :       2749 :   switch (n_bytes)
                      - ]
     927                 :            :     {
     928                 :            :     case 1:
     929                 :       2727 :       (*p_utf32val).i = (utf8val[0] & 0x7F);          /* 0111 1111 */
     930                 :       2727 :       break;
     931                 :            :     case 2:
     932                 :         20 :       (*p_utf32val).i = ((utf8val[0] & 0x1F) << 6) +  /* 0001 1111 */
     933                 :         10 :         (utf8val[1] & 0x3F);          /* 0011 1111 */
     934                 :         10 :       break;
     935                 :            :     case 3:
     936                 :          8 :       (*p_utf32val).i = ((utf8val[0] & 0x0F) << 12) + /* 0000 1111 */
     937                 :          4 :                         ((utf8val[1] & 0x3F) << 6) +  /* 0011 1111 */
     938                 :          4 :                         (utf8val[2] & 0x3F);          /* 0011 1111 */
     939                 :          4 :       break;
     940                 :            :     case 4:
     941                 :         16 :       (*p_utf32val).i = ((utf8val[0] & 0x07) << 18) +  /* 0000 1111 */
     942                 :          8 :                         ((utf8val[1] & 0x3F) << 12) +  /* 0000 1111 */
     943                 :          8 :                         ((utf8val[2] & 0x3F) << 6) +   /* 0011 1111 */
     944                 :          8 :                         (utf8val[3] & 0x3F);           /* 0011 1111 */
     945                 :          8 :       break;
     946                 :            :     default:
     947                 :            :       /* Should never happen! */
     948                 :          0 :       PDF_ASSERT_TRACE_NOT_REACHED ();
     949                 :          0 :       return 0;
     950                 :            :     }
     951                 :            : 
     952                 :       2749 :   return n_bytes;
     953                 :            : }
     954                 :            : 
     955                 :            : /* Function to convert from UTF-8 to UTF-32HE, lossless */
     956                 :            : pdf_bool_t
     957                 :        950 : pdf_text_utf8_to_utf32he (const pdf_char_t  *input_data,
     958                 :            :                           const pdf_size_t   input_length,
     959                 :            :                           pdf_char_t       **p_output_data,
     960                 :            :                           pdf_size_t        *p_output_length,
     961                 :            :                           pdf_error_t      **error)
     962                 :            : {
     963                 :            :   /* Note: PDF Doc Encoding has always 8 bits per character.
     964                 :            :    *  This means that, if length of origin string is N bytes, the number of
     965                 :            :    *  required bytes for the UTF32 representation of the string is 4N.
     966                 :            :    *  (Each PDFDocEncoding byte is expanded to 4 bytes in UTF32. */
     967                 :            :   pdf_size_t new_string_length;
     968                 :            :   pdf_size_t new_string_length_worst;
     969                 :            :   pdf_size_t bom_bytes;
     970                 :            :   int i;  /* index for the origin string data */
     971                 :            :   int j;  /* index for the destination string data */
     972                 :            :   pdf_size_t delta_in_utf8;
     973                 :            :   pdf_char_t *data;
     974                 :            : 
     975                 :            :   /* Check if BOM is present... and skip it if so */
     976                 :        950 :   bom_bytes = 0;
     977         [ +  + ]:        950 :   if (pdf_text_check_unicode_bom (input_data, input_length, PDF_TEXT_UTF8, 0))
     978                 :            :     {
     979                 :            :       /* Skip BOM in UTF-8 */
     980                 :         30 :       bom_bytes = 3;
     981                 :            :     }
     982                 :            : 
     983                 :            :   /* Get new string length... */
     984                 :        950 :   new_string_length_worst = 4 * (input_length - bom_bytes);
     985                 :            : 
     986                 :            :   /* Create destination string with worst size (but empty!) */
     987                 :        950 :   data = (pdf_char_t *) pdf_alloc (new_string_length_worst);
     988         [ -  + ]:        950 :   if (data == NULL)
     989                 :            :     {
     990                 :          0 :       pdf_set_error (error,
     991                 :            :                      PDF_EDOMAIN_BASE_TEXT,
     992                 :            :                      PDF_ENOMEM,
     993                 :            :                      "cannot convert from UTF-8 to UTF-32HE: "
     994                 :            :                      "couldn't allocate %lu bytes",
     995                 :            :                      (unsigned long)new_string_length_worst);
     996                 :          0 :       return PDF_FALSE;
     997                 :            :     }
     998                 :            : 
     999                 :        950 :   new_string_length = 0;
    1000         [ +  + ]:       3699 :   for (i = bom_bytes, j = 0; i < input_length; i += delta_in_utf8, j += 4)
    1001                 :            :     {
    1002                 :            :       pdf_text_utf32_char_t utf32val;
    1003                 :            :       pdf_uchar_t utf8val[4];
    1004                 :            : 
    1005                 :            :       /* Check number of bytes needed for the UTF-8 char */
    1006                 :       2789 :       delta_in_utf8 = n_bytes_in_utf8_char[(pdf_uchar_t)input_data[i]];
    1007                 :            : 
    1008                 :            :       /* Check validity of first byte in UTF-8 */
    1009                 :            :       /* Check if the required bytes are outside the input data stream */
    1010 [ +  + ][ -  + ]:       2789 :       if ((delta_in_utf8 == 0) ||
    1011                 :       2749 :           ((input_length - i) < delta_in_utf8))
    1012                 :            :         {
    1013                 :         40 :           pdf_dealloc (data);
    1014                 :         40 :           pdf_set_error (error,
    1015                 :            :                          PDF_EDOMAIN_BASE_TEXT,
    1016                 :            :                          PDF_EBADDATA,
    1017                 :            :                          "cannot convert UTF-8 to UTF-32HE: "
    1018                 :            :                          "wrong UTF-8 data received (UTF-8 length: %d, "
    1019                 :            :                          "remaining length: %d)",
    1020                 :            :                          delta_in_utf8,
    1021                 :            :                          (input_length - i));
    1022                 :         40 :           return PDF_FALSE;
    1023                 :            :         }
    1024                 :            : 
    1025                 :            :       /* Store data in intermediate UTF-8 variable */
    1026                 :       2749 :       memcpy (&utf8val[0], &input_data[i], delta_in_utf8);
    1027                 :            : 
    1028         [ -  + ]:       2749 :       if (pdf_text_utf8_point_to_utf32he_point (utf8val,
    1029                 :            :                                                 delta_in_utf8,
    1030                 :            :                                                 &utf32val,
    1031                 :            :                                                 error) == 0)
    1032                 :            :         {
    1033                 :          0 :           pdf_dealloc (data);
    1034                 :          0 :           return PDF_FALSE;
    1035                 :            :         }
    1036                 :            : 
    1037                 :            :       /* Copy converted value (in UTF-32HE) to output */
    1038                 :       2749 :       memcpy (&(data[j]), &(utf32val), 4);
    1039                 :            : 
    1040                 :            :       /* Update new string length */
    1041                 :       2749 :       new_string_length += 4;
    1042                 :            :     }
    1043                 :            : 
    1044                 :            :   /* If everything went ok, set output data */
    1045                 :        910 :   *p_output_data = data;
    1046                 :            :   /* Set final output length of the generated string */
    1047                 :        910 :   *p_output_length = new_string_length;
    1048                 :            : 
    1049                 :            :   /* If the real required string length is not equal to the initial worst length
    1050                 :            :    * then update string with correct length. */
    1051         [ +  + ]:        910 :   if (new_string_length != new_string_length_worst)
    1052                 :            :     {
    1053                 :            :       /* Recreate object with correct smaller size... */
    1054                 :         14 :       *p_output_data = (pdf_char_t *) pdf_realloc (*p_output_data,
    1055                 :            :                                                    new_string_length);
    1056         [ -  + ]:         14 :       if (*p_output_data == NULL)
    1057                 :            :         {
    1058                 :          0 :           pdf_set_error (error,
    1059                 :            :                          PDF_EDOMAIN_BASE_TEXT,
    1060                 :            :                          PDF_ENOMEM,
    1061                 :            :                          "cannot convert from UTF-8 to UTF-32HE: "
    1062                 :            :                          "couldn't reallocate %lu bytes",
    1063                 :            :                          (unsigned long)new_string_length);
    1064                 :          0 :           return PDF_FALSE;
    1065                 :            :         }
    1066                 :            :     }
    1067                 :            : 
    1068                 :        950 :   return PDF_TRUE;
    1069                 :            : }
    1070                 :            : 
    1071                 :            : /************************ UTF-32 to UTF-8 conversions *************************/
    1072                 :            : 
    1073                 :            : /* Static function to convert a given UTF-32HE character to UTF-8. The number
    1074                 :            :  * of bytes used in the output UTF-8 point is returned (or 0 if the UTF-8 point
    1075                 :            :  * is not valid */
    1076                 :            : static pdf_size_t
    1077                 :            : pdf_text_utf32he_point_to_utf8_point (const pdf_text_utf32_char_t   utf32val,
    1078                 :            :                                       pdf_uchar_t                   utf8val[4],
    1079                 :            :                                       pdf_error_t                 **error)
    1080                 :            : {
    1081                 :            :   pdf_size_t n_bytes;
    1082                 :            : 
    1083         [ +  + ]:       1597 :   if (utf32val.i < 0x80)
    1084                 :            :     {
    1085                 :            :       /* Output is 1 byte */
    1086                 :       1581 :       n_bytes = 1;
    1087                 :       1581 :       utf8val[0] = (pdf_uchar_t)utf32val.i;
    1088                 :            :     }
    1089         [ +  + ]:         16 :   else if (utf32val.i < 0x800)
    1090                 :            :     {
    1091                 :            :       /* Output is 2 bytes */
    1092                 :          4 :       n_bytes = 2;
    1093                 :            :       /* Get first byte, using upper 5 bits --> 110xxxxx */
    1094                 :          4 :       utf8val[0] = ((pdf_uchar_t)(utf32val.i >> 6)) | 0xC0;
    1095                 :            :       /* Get second byte, using lower 6 bits --> 10xxxxxx */
    1096                 :          4 :       utf8val[1] = ((pdf_uchar_t)(utf32val.i & 0x3F)) | 0x80;
    1097                 :            :     }
    1098         [ +  + ]:         12 :   else if (utf32val.i < 0x10000)
    1099                 :            :     {
    1100                 :            :       /* Output is 3 bytes */
    1101                 :          4 :       n_bytes = 3;
    1102                 :            :       /* Get first byte, using upper 4 bits --> 1110xxxx */
    1103                 :          4 :       utf8val[0] = ((pdf_uchar_t)(utf32val.i >> 12)) | 0xE0;
    1104                 :            :       /* Get second byte, using middle 6 bits --> 10xxxxxx */
    1105                 :          4 :       utf8val[1] = ((pdf_uchar_t)((utf32val.i >> 6) & 0x3F)) | 0x80;
    1106                 :            :       /* Get third byte, using lower 6 bits --> 10xxxxxx */
    1107                 :          4 :       utf8val[2] = ((pdf_uchar_t)(utf32val.i & 0x3F)) | 0x80;
    1108                 :            :     }
    1109         [ +  - ]:          8 :   else if (utf32val.i < 0x0010FFFF)
    1110                 :            :     {
    1111                 :            :       /* Output is 4 bytes */
    1112                 :          8 :       n_bytes = 4;
    1113                 :            :       /* Get first byte, using upper 3 bits --> 11110xxx */
    1114                 :          8 :       utf8val[0] = ((pdf_uchar_t)(utf32val.i >> 18)) | 0xF0;
    1115                 :            :       /* Get second byte, using upper-middle 6 bits --> 10xxxxxx */
    1116                 :          8 :       utf8val[1] = (((pdf_uchar_t)(utf32val.i >> 12)) & 0x3F) | 0x80;
    1117                 :            :       /* Get second byte, using lower-middle 6 bits --> 10xxxxxx */
    1118                 :          8 :       utf8val[2] = (((pdf_uchar_t)(utf32val.i >> 6)) & 0x3F) | 0x80;
    1119                 :            :       /* Get third byte, using lower 6 bits --> 10xxxxxx */
    1120                 :          8 :       utf8val[3] = ((pdf_uchar_t)(utf32val.i & 0x3F)) | 0x80;
    1121                 :            :     }
    1122                 :            :   else
    1123                 :            :     {
    1124                 :          0 :       pdf_set_error (error,
    1125                 :            :                      PDF_EDOMAIN_BASE_TEXT,
    1126                 :            :                      PDF_EBADTEXT,
    1127                 :            :                      "cannot convert from UTF-32HE to UTF-8: "
    1128                 :            :                      "invalid input code point: "
    1129                 :            :                      "%.2X:%.2X:%.2X:%.2X",
    1130                 :          0 :                      utf32val.c[0],
    1131                 :          0 :                      utf32val.c[1],
    1132                 :          0 :                      utf32val.c[2],
    1133                 :          0 :                      utf32val.c[3]);
    1134                 :          0 :       n_bytes = 0;
    1135                 :            :     }
    1136                 :            : 
    1137                 :       1597 :   return n_bytes;
    1138                 :            : }
    1139                 :            : 
    1140                 :            : /* Function to convert from UTF-32HE to UTF-8, lossless */
    1141                 :            : pdf_bool_t
    1142                 :         86 : pdf_text_utf32he_to_utf8 (const pdf_char_t  *input_data,
    1143                 :            :                           const pdf_size_t   input_length,
    1144                 :            :                           pdf_char_t       **p_output_data,
    1145                 :            :                           pdf_size_t        *p_output_length,
    1146                 :            :                           pdf_error_t      **error)
    1147                 :            : {
    1148                 :            :   /* Note: UTF-8 has either 8, 16, 24 or 32 bits per character.
    1149                 :            :    This means that, if length of origin string is 4N bytes, the number of
    1150                 :            :    required bytes for the UTF-8 representation of the string is 4N in
    1151                 :            :    the worst case. (When all the UTF-8 representations have 32bits)
    1152                 :            :    */
    1153                 :            :   pdf_size_t new_string_length;
    1154                 :            :   pdf_size_t new_string_length_worst;
    1155                 :            :   int i;  /* index for the origin string data */
    1156                 :            :   int j;  /* index for the destination string data */
    1157                 :            :   pdf_char_t *data;
    1158                 :            :   pdf_size_t delta_in_utf8;
    1159                 :            : 
    1160                 :            :   /* Get new string length (worst case)... */
    1161                 :         86 :   new_string_length_worst = input_length;
    1162                 :            :   /* Create destination string with correct size (but empty!) */
    1163                 :         86 :   data = (pdf_char_t *) pdf_alloc (new_string_length_worst);
    1164         [ -  + ]:         86 :   if (data == NULL)
    1165                 :            :     {
    1166                 :          0 :       pdf_set_error (error,
    1167                 :            :                      PDF_EDOMAIN_BASE_TEXT,
    1168                 :            :                      PDF_ENOMEM,
    1169                 :            :                      "cannot convert UTF-32HE to UTF-8: "
    1170                 :            :                      "couldn't allocate %lu bytes",
    1171                 :            :                      (unsigned long)new_string_length_worst);
    1172                 :          0 :       return PDF_FALSE;
    1173                 :            :     }
    1174                 :            : 
    1175                 :            :   /* Initiate real string length, without considering marker bytes */
    1176                 :         86 :   new_string_length = 0;
    1177                 :            : 
    1178         [ +  + ]:       1683 :   for (i = 0, j = 0; i < input_length; i += 4, j += delta_in_utf8)
    1179                 :            :     {
    1180                 :            :       pdf_text_utf32_char_t utf32val;
    1181                 :            :       pdf_uchar_t utf8val[4];
    1182                 :            : 
    1183                 :            :       /* Get UTF-32 char, as a direct memory copy from the input array */
    1184                 :       1597 :       memcpy (&utf32val, &(input_data[i]), 4);
    1185                 :            : 
    1186                 :       1597 :       delta_in_utf8 = pdf_text_utf32he_point_to_utf8_point (utf32val,
    1187                 :            :                                                             utf8val,
    1188                 :            :                                                             error);
    1189         [ -  + ]:       1597 :       if (delta_in_utf8 == 0)
    1190                 :            :         {
    1191                 :          0 :           pdf_dealloc (data);
    1192                 :          0 :           return PDF_FALSE;
    1193                 :            :         }
    1194                 :            : 
    1195                 :            :       /* Store UTF-8 val in output array */
    1196                 :       1597 :       memcpy (&data[j], &(utf8val[0]), delta_in_utf8);
    1197                 :            : 
    1198                 :            :       /* Update new_string_length, depending on the bytes used to represent
    1199                 :            :        *  this character in UTF-8 */
    1200                 :       1597 :       new_string_length += delta_in_utf8;
    1201                 :            :     }
    1202                 :            : 
    1203                 :            :   /* If everything went ok, set output data */
    1204                 :         86 :   *p_output_data = data;
    1205                 :            :   /* Set final output length of the generated string */
    1206                 :         86 :   *p_output_length = new_string_length;
    1207                 :            : 
    1208                 :            :   /* If the real required string length is not equal to the initial worst length
    1209                 :            :    * then update string with correct length. */
    1210         [ +  + ]:         86 :   if (new_string_length != new_string_length_worst)
    1211                 :            :     {
    1212                 :            :       /* Recreate object with correct smaller size... */
    1213                 :         82 :       *p_output_data = (pdf_char_t *) pdf_realloc (*p_output_data,
    1214                 :            :                                                    new_string_length);
    1215         [ -  + ]:         82 :       if (*p_output_data == NULL)
    1216                 :            :         {
    1217                 :          0 :           pdf_set_error (error,
    1218                 :            :                          PDF_EDOMAIN_BASE_TEXT,
    1219                 :            :                          PDF_ENOMEM,
    1220                 :            :                          "cannot convert from UTF-32HE to UTF-8: "
    1221                 :            :                          "couldn't allocate %lu bytes",
    1222                 :            :                          (unsigned long)new_string_length);
    1223                 :          0 :           return PDF_FALSE;
    1224                 :            :         }
    1225                 :            :     }
    1226                 :            : 
    1227                 :         86 :   return PDF_TRUE;
    1228                 :            : }
    1229                 :            : 
    1230                 :            : /*************************** BOM-related functions ****************************/
    1231                 :            : 
    1232                 :            : pdf_text_bom_t
    1233                 :        108 : pdf_text_get_unicode_bom (enum pdf_text_unicode_encoding_e unicode_encoding)
    1234                 :            : {
    1235                 :        108 :   return unicode_bom[unicode_encoding];
    1236                 :            : }
    1237                 :            : 
    1238                 :            : pdf_bool_t
    1239                 :       1799 : pdf_text_check_unicode_bom (const pdf_char_t *data,
    1240                 :            :                             const pdf_size_t  size,
    1241                 :            :                             enum pdf_text_unicode_encoding_e enc,
    1242                 :            :                             int               swap)
    1243                 :            : {
    1244      [ +  +  - ]:       1799 :   switch(enc)
    1245                 :            :     {
    1246                 :            :     case PDF_TEXT_UTF16_HE:
    1247                 :            :     case PDF_TEXT_UTF32_HE:
    1248                 :            :       {
    1249         [ +  + ]:        802 :         enc += ((PDF_IS_BIG_ENDIAN ^ swap) ? PDF_TEXT_HE_TO_BE:PDF_TEXT_HE_TO_LE);
    1250                 :            :       }
    1251                 :            :     case PDF_TEXT_UTF8:
    1252                 :            :     case PDF_TEXT_UTF16_BE:
    1253                 :            :     case PDF_TEXT_UTF16_LE:
    1254                 :            :     case PDF_TEXT_UTF32_BE:
    1255                 :            :     case PDF_TEXT_UTF32_LE:
    1256                 :            :       {
    1257 [ +  + ][ +  + ]:       1799 :         if ((size >= unicode_bom[enc].bom_bytes) &&
    1258                 :       2052 :             (memcmp (data,
    1259                 :       1026 :                      unicode_bom[enc].bom_data,
    1260                 :            :                      unicode_bom[enc].bom_bytes) == 0))
    1261                 :            :           {
    1262                 :        116 :             return PDF_TRUE;
    1263                 :            :           }
    1264                 :            :       }
    1265                 :            :     default:
    1266                 :       1799 :       return PDF_FALSE;
    1267                 :            :     }
    1268                 :            : }
    1269                 :            : 
    1270                 :            : /*************************** Other helper functions ****************************/
    1271                 :            : 
    1272                 :            : const pdf_char_t *
    1273                 :         80 : pdf_text_get_unicode_encoding_name (enum pdf_text_unicode_encoding_e unicode_encoding)
    1274                 :            : {
    1275                 :         80 :   return unicode_encoding_name[unicode_encoding];
    1276                 :            : }
    1277                 :            : 
    1278                 :            : /* End of pdf-text-encoding.c */

Generated by: LCOV version 1.8