LCOV - code coverage report
Current view: top level - third_party/heimdal/lib/wind - utf8.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 151 257 58.8 %
Date: 2024-04-21 15:09:00 Functions: 9 11 81.8 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2004, 2006, 2007, 2008 Kungliga Tekniska Högskolan
       3             :  * (Royal Institute of Technology, Stockholm, Sweden).
       4             :  * All rights reserved.
       5             :  *
       6             :  * Redistribution and use in source and binary forms, with or without
       7             :  * modification, are permitted provided that the following conditions
       8             :  * are met:
       9             :  *
      10             :  * 1. Redistributions of source code must retain the above copyright
      11             :  *    notice, this list of conditions and the following disclaimer.
      12             :  *
      13             :  * 2. Redistributions in binary form must reproduce the above copyright
      14             :  *    notice, this list of conditions and the following disclaimer in the
      15             :  *    documentation and/or other materials provided with the distribution.
      16             :  *
      17             :  * 3. Neither the name of the Institute nor the names of its contributors
      18             :  *    may be used to endorse or promote products derived from this software
      19             :  *    without specific prior written permission.
      20             :  *
      21             :  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
      22             :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      23             :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      24             :  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
      25             :  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      26             :  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      27             :  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      28             :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      29             :  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      30             :  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      31             :  * SUCH DAMAGE.
      32             :  */
      33             : 
      34             : #include <config.h>
      35             : #include "windlocl.h"
      36             : 
      37             : static int
      38     2093950 : utf8toutf32(const unsigned char **pp, uint32_t *out)
      39             : {
      40     2093950 :     const unsigned char *p = *pp;
      41     2093950 :     uint32_t c = *p;
      42       73346 :     uint32_t out_val;
      43             : 
      44     2093950 :     if (c & 0x80) {
      45        1932 :         if ((c & 0xE0) == 0xC0) {
      46          52 :             const uint32_t c2 = *++p;
      47          52 :             if ((c2 & 0xC0) == 0x80) {
      48          52 :                 out_val =  ((c  & 0x1F) << 6)
      49          52 :                     | (c2 & 0x3F);
      50          52 :                 if (out_val < 0x80) {
      51           0 :                     return WIND_ERR_INVALID_UTF8;
      52             :                 }
      53             :             } else {
      54           0 :                 return WIND_ERR_INVALID_UTF8;
      55             :             }
      56        1880 :         } else if ((c & 0xF0) == 0xE0) {
      57        1868 :             const uint32_t c2 = *++p;
      58        1868 :             if ((c2 & 0xC0) == 0x80) {
      59        1868 :                 const uint32_t c3 = *++p;
      60        1868 :                 if ((c3 & 0xC0) == 0x80) {
      61        1868 :                     out_val =   ((c  & 0x0F) << 12)
      62        1868 :                         | ((c2 & 0x3F) << 6)
      63        1868 :                         |  (c3 & 0x3F);
      64        1868 :                     if (out_val < 0x800) {
      65           0 :                         return WIND_ERR_INVALID_UTF8;
      66             :                     }
      67             :                 } else {
      68           0 :                     return WIND_ERR_INVALID_UTF8;
      69             :                 }
      70             :             } else {
      71           0 :                 return WIND_ERR_INVALID_UTF8;
      72             :             }
      73          12 :         } else if ((c & 0xF8) == 0xF0) {
      74          12 :             const uint32_t c2 = *++p;
      75          12 :             if ((c2 & 0xC0) == 0x80) {
      76          12 :                 const uint32_t c3 = *++p;
      77          12 :                 if ((c3 & 0xC0) == 0x80) {
      78          12 :                     const uint32_t c4 = *++p;
      79          12 :                     if ((c4 & 0xC0) == 0x80) {
      80          12 :                         out_val =   ((c  & 0x07) << 18)
      81          12 :                             | ((c2 & 0x3F) << 12)
      82          12 :                             | ((c3 & 0x3F) <<  6)
      83          12 :                             |  (c4 & 0x3F);
      84          12 :                         if (out_val < 0x10000) {
      85           0 :                             return WIND_ERR_INVALID_UTF8;
      86             :                         }
      87             :                     } else {
      88           0 :                         return WIND_ERR_INVALID_UTF8;
      89             :                     }
      90             :                 } else {
      91           0 :                     return WIND_ERR_INVALID_UTF8;
      92             :                 }
      93             :             } else {
      94           0 :                 return WIND_ERR_INVALID_UTF8;
      95             :             }
      96             :         } else {
      97           0 :             return WIND_ERR_INVALID_UTF8;
      98             :         }
      99             :     } else {
     100     2018672 :         out_val = c;
     101             :     }
     102             : 
     103             :     /* Allow unpaired surrogates (in the range 0xd800–0xdfff). */
     104             : 
     105     2093950 :     if (out_val > 0x10ffff) {
     106           0 :         return WIND_ERR_INVALID_UTF8;
     107             :     }
     108             : 
     109     2093950 :     *out = out_val;
     110     2093950 :     *pp = p;
     111             : 
     112     2093950 :     return 0;
     113             : }
     114             : 
     115             : /**
     116             :  * Convert an UTF-8 string to an UCS4 string.
     117             :  *
     118             :  * @param in an UTF-8 string to convert.
     119             :  * @param out the resulting UCS4 string, must be at least
     120             :  * wind_utf8ucs4_length() long.  If out is NULL, the function will
     121             :  * calculate the needed space for the out variable (just like
     122             :  * wind_utf8ucs4_length()).
     123             :  * @param out_len before processing out_len should be the length of
     124             :  * the out variable, after processing it will be the length of the out
     125             :  * string.
     126             :  *
     127             :  * @return returns 0 on success, an wind error code otherwise
     128             :  * @ingroup wind
     129             :  */
     130             : 
     131             : int
     132        5620 : wind_utf8ucs4(const char *in, uint32_t *out, size_t *out_len)
     133             : {
     134           0 :     const unsigned char *p;
     135        5620 :     size_t o = 0;
     136           0 :     int ret;
     137             : 
     138       89920 :     for (p = (const unsigned char *)in; *p != '\0'; ++p) {
     139           0 :         uint32_t u;
     140             : 
     141       84300 :         ret = utf8toutf32(&p, &u);
     142       84300 :         if (ret)
     143           0 :             return ret;
     144             : 
     145       84300 :         if (out) {
     146       42150 :             if (o >= *out_len)
     147           0 :                 return WIND_ERR_OVERRUN;
     148       42150 :             out[o] = u;
     149             :         }
     150       84300 :         o++;
     151             :     }
     152        5620 :     *out_len = o;
     153        5620 :     return 0;
     154             : }
     155             : 
     156             : /**
     157             :  * Calculate the length of from converting a UTF-8 string to a UCS4
     158             :  * string.
     159             :  *
     160             :  * @param in an UTF-8 string to convert.
     161             :  * @param out_len the length of the resulting UCS4 string.
     162             :  *
     163             :  * @return returns 0 on success, an wind error code otherwise
     164             :  * @ingroup wind
     165             :  */
     166             : 
     167             : int
     168        2810 : wind_utf8ucs4_length(const char *in, size_t *out_len)
     169             : {
     170        2810 :     return wind_utf8ucs4(in, NULL, out_len);
     171             : }
     172             : 
     173             : static const char first_char[4] =
     174             :     { 0x00, 0xC0, 0xE0, 0xF0 };
     175             : 
     176             : /**
     177             :  * Convert an UCS4 string to a UTF-8 string.
     178             :  *
     179             :  * @param in an UCS4 string to convert.
     180             :  * @param in_len the length input array.
     181             : 
     182             :  * @param out the resulting UTF-8 string, must be at least
     183             :  * wind_ucs4utf8_length() + 1 long (the extra char for the NUL).  If
     184             :  * out is NULL, the function will calculate the needed space for the
     185             :  * out variable (just like wind_ucs4utf8_length()).
     186             : 
     187             :  * @param out_len before processing out_len should be the length of
     188             :  * the out variable, after processing it will be the length of the out
     189             :  * string.
     190             :  *
     191             :  * @return returns 0 on success, an wind error code otherwise
     192             :  * @ingroup wind
     193             :  */
     194             : 
     195             : int
     196           0 : wind_ucs4utf8(const uint32_t *in, size_t in_len, char *out, size_t *out_len)
     197             : {
     198           0 :     uint32_t ch;
     199           0 :     size_t i, len, o;
     200             : 
     201           0 :     for (o = 0, i = 0; i < in_len; i++) {
     202           0 :         ch = in[i];
     203             : 
     204           0 :         if (ch < 0x80) {
     205           0 :             len = 1;
     206           0 :         } else if (ch < 0x800) {
     207           0 :             len = 2;
     208           0 :         } else if (ch < 0x10000) {
     209           0 :             len = 3;
     210           0 :         } else if (ch <= 0x10FFFF) {
     211           0 :             len = 4;
     212             :         } else
     213           0 :             return WIND_ERR_INVALID_UTF32;
     214             : 
     215           0 :         o += len;
     216             : 
     217           0 :         if (out) {
     218           0 :             if (o >= *out_len)
     219           0 :                 return WIND_ERR_OVERRUN;
     220             : 
     221           0 :             switch(len) {
     222           0 :             case 4:
     223           0 :                 out[3] = (ch | 0x80) & 0xbf;
     224           0 :                 ch = ch >> 6;
     225           0 :                 HEIM_FALLTHROUGH;
     226           0 :             case 3:
     227           0 :                 out[2] = (ch | 0x80) & 0xbf;
     228           0 :                 ch = ch >> 6;
     229           0 :                 HEIM_FALLTHROUGH;
     230           0 :             case 2:
     231           0 :                 out[1] = (ch | 0x80) & 0xbf;
     232           0 :                 ch = ch >> 6;
     233           0 :                 HEIM_FALLTHROUGH;
     234           0 :             case 1:
     235           0 :                 out[0] = ch | first_char[len - 1];
     236           0 :                 HEIM_FALLTHROUGH;
     237           0 :             default:
     238           0 :                 break;
     239             :             }
     240           0 :             out += len;
     241             :         }
     242             :     }
     243           0 :     if (out) {
     244           0 :         if (o + 1 >= *out_len)
     245           0 :             return WIND_ERR_OVERRUN;
     246           0 :         *out = '\0';
     247             :     }
     248           0 :     *out_len = o;
     249           0 :     return 0;
     250             : }
     251             : 
     252             : /**
     253             :  * Calculate the length of from converting a UCS4 string to an UTF-8 string.
     254             :  *
     255             :  * @param in an UCS4 string to convert.
     256             :  * @param in_len the length of UCS4 string to convert.
     257             :  * @param out_len the length of the resulting UTF-8 string.
     258             :  *
     259             :  * @return returns 0 on success, an wind error code otherwise
     260             :  * @ingroup wind
     261             :  */
     262             : 
     263             : int
     264           0 : wind_ucs4utf8_length(const uint32_t *in, size_t in_len, size_t *out_len)
     265             : {
     266           0 :     return wind_ucs4utf8(in, in_len, NULL, out_len);
     267             : }
     268             : 
     269             : /**
     270             :  * Read in an UCS2 from a buffer.
     271             :  *
     272             :  * @param ptr The input buffer to read from.
     273             :  * @param len the length of the input buffer.
     274             :  * @param flags Flags to control the behavior of the function.
     275             :  * @param out the output UCS2, the array must be at least out/2 long.
     276             :  * @param out_len the output length
     277             :  *
     278             :  * @return returns 0 on success, an wind error code otherwise.
     279             :  * @ingroup wind
     280             :  */
     281             : 
     282             : int
     283      415872 : wind_ucs2read(const void *ptr, size_t len, unsigned int *flags,
     284             :               uint16_t *out, size_t *out_len)
     285             : {
     286      415872 :     const unsigned char *p = ptr;
     287      415872 :     int little = ((*flags) & WIND_RW_LE);
     288      415872 :     size_t olen = *out_len;
     289             : 
     290             :     /** if len is zero, flags are unchanged */
     291      415872 :     if (len == 0) {
     292           0 :         *out_len = 0;
     293           0 :         return 0;
     294             :     }
     295             : 
     296             :     /** if len is odd, WIND_ERR_LENGTH_NOT_MOD2 is returned */
     297      415872 :     if (len & 1)
     298           0 :         return WIND_ERR_LENGTH_NOT_MOD2;
     299             : 
     300             :     /**
     301             :      * If the flags WIND_RW_BOM is set, check for BOM. If not BOM is
     302             :      * found, check is LE/BE flag is already and use that otherwise
     303             :      * fail with WIND_ERR_NO_BOM. When done, clear WIND_RW_BOM and
     304             :      * the LE/BE flag and set the resulting LE/BE flag.
     305             :      */
     306      415872 :     if ((*flags) & WIND_RW_BOM) {
     307           0 :         uint16_t bom = (p[0] << 8) + p[1];
     308           0 :         if (bom == 0xfffe || bom == 0xfeff) {
     309           0 :             little = (bom == 0xfffe);
     310           0 :             p += 2;
     311           0 :             len -= 2;
     312           0 :         } else if (((*flags) & (WIND_RW_LE|WIND_RW_BE)) != 0) {
     313             :             /* little already set */
     314             :         } else
     315           0 :             return WIND_ERR_NO_BOM;
     316           0 :         *flags = ((*flags) & ~(WIND_RW_BOM|WIND_RW_LE|WIND_RW_BE));
     317           0 :         *flags |= little ? WIND_RW_LE : WIND_RW_BE;
     318             :     }
     319             : 
     320     9057873 :     while (len) {
     321     8642001 :         if (olen < 1)
     322           0 :             return WIND_ERR_OVERRUN;
     323     8642001 :         if (little)
     324     8642001 :             *out = (p[1] << 8) + p[0];
     325             :         else
     326           0 :             *out = (p[0] << 8) + p[1];
     327     8642001 :         out++; p += 2; len -= 2; olen--;
     328             :     }
     329      415872 :     *out_len -= olen;
     330      415872 :     return 0;
     331             : }
     332             : 
     333             : /**
     334             :  * Write an UCS2 string to a buffer.
     335             :  *
     336             :  * @param in The input UCS2 string.
     337             :  * @param in_len the length of the input buffer.
     338             :  * @param flags Flags to control the behavior of the function.
     339             :  * @param ptr The input buffer to write to, the array must be at least
     340             :  * (in + 1) * 2 bytes long.
     341             :  * @param out_len the output length
     342             :  *
     343             :  * @return returns 0 on success, an wind error code otherwise.
     344             :  * @ingroup wind
     345             :  */
     346             : 
     347             : int
     348       79586 : wind_ucs2write(const uint16_t *in, size_t in_len, unsigned int *flags,
     349             :                void *ptr, size_t *out_len)
     350             : {
     351       79586 :     unsigned char *p = ptr;
     352       79586 :     size_t len = *out_len;
     353             : 
     354             :     /** If in buffer is not of length be mod 2, WIND_ERR_LENGTH_NOT_MOD2 is returned*/
     355       79586 :     if (len & 1)
     356           0 :         return WIND_ERR_LENGTH_NOT_MOD2;
     357             : 
     358             :     /** On zero input length, flags are preserved */
     359       79586 :     if (in_len == 0) {
     360           0 :         *out_len = 0;
     361           0 :         return 0;
     362             :     }
     363             :     /** If flags have WIND_RW_BOM set, the byte order mark is written
     364             :      * first to the output data */
     365       79586 :     if ((*flags) & WIND_RW_BOM) {
     366           0 :         uint16_t bom = 0xfffe;
     367             : 
     368           0 :         if (len < 2)
     369           0 :             return WIND_ERR_OVERRUN;
     370             : 
     371           0 :         if ((*flags) & WIND_RW_LE) {
     372           0 :             p[0] = (bom     ) & 0xff;
     373           0 :             p[1] = (bom >> 8) & 0xff;
     374             :         } else {
     375           0 :             p[1] = (bom     ) & 0xff;
     376           0 :             p[0] = (bom >> 8) & 0xff;
     377             :         }
     378           0 :         len -= 2;
     379             :     }
     380             : 
     381     1056138 :     while (in_len) {
     382             :         /** If the output wont fit into out_len, WIND_ERR_OVERRUN is returned */
     383      976552 :         if (len < 2)
     384           0 :             return WIND_ERR_OVERRUN;
     385      976552 :         if ((*flags) & WIND_RW_LE) {
     386      976552 :             p[0] = (in[0]     ) & 0xff;
     387      976552 :             p[1] = (in[0] >> 8) & 0xff;
     388             :         } else {
     389           0 :             p[1] = (in[0]     ) & 0xff;
     390           0 :             p[0] = (in[0] >> 8) & 0xff;
     391             :         }
     392      976552 :         len -= 2;
     393      976552 :         in_len--;
     394      976552 :         p += 2;
     395      976552 :         in++;
     396             :     }
     397       79586 :     *out_len -= len;
     398       79586 :     return 0;
     399             : }
     400             : 
     401             : 
     402             : /**
     403             :  * Convert an UTF-8 string to an UCS2 string.
     404             :  *
     405             :  * @param in an UTF-8 string to convert.
     406             :  * @param out the resulting UCS2 string, must be at least
     407             :  * wind_utf8ucs2_length() long.  If out is NULL, the function will
     408             :  * calculate the needed space for the out variable (just like
     409             :  * wind_utf8ucs2_length()).
     410             :  * @param out_len before processing out_len should be the length of
     411             :  * the out variable, after processing it will be the length of the out
     412             :  * string.
     413             :  *
     414             :  * @return returns 0 on success, an wind error code otherwise
     415             :  * @ingroup wind
     416             :  */
     417             : 
     418             : int
     419      161536 : wind_utf8ucs2(const char *in, uint16_t *out, size_t *out_len)
     420             : {
     421        5668 :     const unsigned char *p;
     422      161536 :     size_t o = 0;
     423        5668 :     int ret;
     424             : 
     425     2171186 :     for (p = (const unsigned char *)in; *p != '\0'; ++p) {
     426       73346 :         uint32_t u;
     427             : 
     428     2009650 :         ret = utf8toutf32(&p, &u);
     429     2009650 :         if (ret)
     430           0 :             return ret;
     431             : 
     432     2009650 :         if (u >= 0x10000) {
     433          12 :             if (out) {
     434           0 :                 uint16_t high_ten_bits;
     435           0 :                 uint16_t low_ten_bits;
     436             : 
     437           6 :                 if (o + 2 > *out_len)
     438           0 :                     return WIND_ERR_OVERRUN;
     439             : 
     440           6 :                 u -= 0x10000;
     441           6 :                 high_ten_bits = (u >> 10) & 0x3ff;
     442           6 :                 low_ten_bits = u & 0x3ff;
     443             : 
     444           6 :                 out[o] = 0xd800 | high_ten_bits;
     445           6 :                 out[o+1] = 0xdc00 | low_ten_bits;
     446             :             }
     447          12 :             o += 2;
     448             :         } else {
     449     2009638 :             if (out) {
     450     1004819 :                 if (o >= *out_len)
     451           0 :                     return WIND_ERR_OVERRUN;
     452     1004819 :                 out[o] = u;
     453             :             }
     454     2009638 :             o++;
     455             :         }
     456             :     }
     457      161536 :     *out_len = o;
     458      161536 :     return 0;
     459             : }
     460             : 
     461             : /**
     462             :  * Calculate the length of from converting a UTF-8 string to a UCS2
     463             :  * string.
     464             :  *
     465             :  * @param in an UTF-8 string to convert.
     466             :  * @param out_len the length of the resulting UCS2 string.
     467             :  *
     468             :  * @return returns 0 on success, an wind error code otherwise
     469             :  * @ingroup wind
     470             :  */
     471             : 
     472             : int
     473       80768 : wind_utf8ucs2_length(const char *in, size_t *out_len)
     474             : {
     475       80768 :     return wind_utf8ucs2(in, NULL, out_len);
     476             : }
     477             : 
     478             : /**
     479             :  * Convert an UCS2 string to a UTF-8 string.
     480             :  *
     481             :  * @param in an UCS2 string to convert.
     482             :  * @param in_len the length of the in UCS2 string.
     483             :  * @param out the resulting UTF-8 string, must be at least
     484             :  * wind_ucs2utf8_length() long.  If out is NULL, the function will
     485             :  * calculate the needed space for the out variable (just like
     486             :  * wind_ucs2utf8_length()).
     487             :  * @param out_len before processing out_len should be the length of
     488             :  * the out variable, after processing it will be the length of the out
     489             :  * string.
     490             :  *
     491             :  * @return returns 0 on success, an wind error code otherwise
     492             :  * @ingroup wind
     493             :  */
     494             : 
     495             : int
     496      831744 : wind_ucs2utf8(const uint16_t *in, size_t in_len, char *out, size_t *out_len)
     497             : {
     498       20312 :     uint32_t ch;
     499       20312 :     size_t i, len, o;
     500             : 
     501    18115704 :     for (o = 0, i = 0; i < in_len; i++) {
     502    17283960 :         ch = in[i];
     503             : 
     504    17283960 :         if (ch < 0x80) {
     505    16853930 :             len = 1;
     506          42 :         } else if (ch < 0x800) {
     507           0 :             len = 2;
     508          42 :         } else if (ch < 0xd800 || ch >= 0xe000) {
     509           0 :             len = 3;
     510          42 :         } else if (ch < 0xdc00) {
     511             :             /* A high surrogate. */
     512          42 :             if (i < in_len - 1) {
     513          42 :                 uint16_t ch2 = in[i + 1];
     514             : 
     515          42 :                 if (ch2 >= 0xdc00 && ch2 < 0xe000) {
     516           0 :                     uint16_t high_ten_bits;
     517           0 :                     uint16_t low_ten_bits;
     518             : 
     519             :                     /* A surrogate pair. */
     520          42 :                     high_ten_bits = ch & 0x3ff;
     521          42 :                     low_ten_bits = ch2 & 0x3ff;
     522             : 
     523          42 :                     ch = 0x10000 + ((uint32_t)high_ten_bits << 10 | low_ten_bits);
     524          42 :                     len = 4;
     525          42 :                     ++i;
     526             :                 } else {
     527             :                     /* An unpaired high surrogate. */
     528           0 :                     len = 3;
     529             :                 }
     530             :             } else {
     531             :                 /* An unpaired high surrogate. */
     532           0 :                 len = 3;
     533             :             }
     534             :         } else {
     535             :             /* An unpaired low surrogate. */
     536           0 :             len = 3;
     537             :         }
     538             : 
     539    17283960 :         o += len;
     540             : 
     541    17283960 :         if (out) {
     542     8641980 :             if (o >= *out_len)
     543           0 :                 return WIND_ERR_OVERRUN;
     544             : 
     545     8641980 :             switch(len) {
     546          21 :             case 4:
     547          21 :                 out[3] = (ch | 0x80) & 0xbf;
     548          21 :                 ch = ch >> 6;
     549           0 :                 HEIM_FALLTHROUGH;
     550          21 :             case 3:
     551          21 :                 out[2] = (ch | 0x80) & 0xbf;
     552          21 :                 ch = ch >> 6;
     553           0 :                 HEIM_FALLTHROUGH;
     554          21 :             case 2:
     555          21 :                 out[1] = (ch | 0x80) & 0xbf;
     556          21 :                 ch = ch >> 6;
     557      214994 :                 HEIM_FALLTHROUGH;
     558     8641980 :             case 1:
     559     8641980 :                 out[0] = ch | first_char[len - 1];
     560      214994 :                 HEIM_FALLTHROUGH;
     561     8426986 :             default:
     562     8641980 :                 break;
     563             :             }
     564     8641980 :             out += len;
     565             :         }
     566             :     }
     567      831744 :     if (out) {
     568      415872 :         if (o >= *out_len)
     569           0 :             return WIND_ERR_OVERRUN;
     570      415872 :         *out = '\0';
     571             :     }
     572      831744 :     *out_len = o;
     573      831744 :     return 0;
     574             : }
     575             : 
     576             : /**
     577             :  * Calculate the length of from converting a UCS2 string to an UTF-8 string.
     578             :  *
     579             :  * @param in an UCS2 string to convert.
     580             :  * @param in_len an UCS2 string length to convert.
     581             :  * @param out_len the length of the resulting UTF-8 string.
     582             :  *
     583             :  * @return returns 0 on success, an wind error code otherwise
     584             :  * @ingroup wind
     585             :  */
     586             : 
     587             : int
     588      415872 : wind_ucs2utf8_length(const uint16_t *in, size_t in_len, size_t *out_len)
     589             : {
     590      415872 :     return wind_ucs2utf8(in, in_len, NULL, out_len);
     591             : }

Generated by: LCOV version 1.14