LCOV - code coverage report
Current view: top level - pulse - utf8.c (source / functions) Hit Total Coverage
Test: lcov.out Lines: 78 99 78.8 %
Date: 2012-07-17 Functions: 6 8 75.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 43 74 58.1 %

           Branch data     Line data    Source code
       1                 :            : /***
       2                 :            :   This file is part of PulseAudio.
       3                 :            : 
       4                 :            :   Copyright 2006 Lennart Poettering
       5                 :            :   Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
       6                 :            : 
       7                 :            :   PulseAudio is free software; you can redistribute it and/or modify
       8                 :            :   it under the terms of the GNU Lesser General Public License as
       9                 :            :   published by the Free Software Foundation; either version 2.1 of the
      10                 :            :   License, or (at your option) any later version.
      11                 :            : 
      12                 :            :   PulseAudio is distributed in the hope that it will be useful, but
      13                 :            :   WITHOUT ANY WARRANTY; without even the implied warranty of
      14                 :            :   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
      15                 :            :   Lesser General Public License for more details.
      16                 :            : 
      17                 :            :   You should have received a copy of the GNU Lesser General Public
      18                 :            :   License along with PulseAudio; if not, write to the Free Software
      19                 :            :   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
      20                 :            :   USA.
      21                 :            : ***/
      22                 :            : 
      23                 :            : /* This file is based on the GLIB utf8 validation functions. The
      24                 :            :  * original license text follows. */
      25                 :            : 
      26                 :            : /* gutf8.c - Operations on UTF-8 strings.
      27                 :            :  *
      28                 :            :  * Copyright (C) 1999 Tom Tromey
      29                 :            :  * Copyright (C) 2000 Red Hat, Inc.
      30                 :            :  *
      31                 :            :  * This library is free software; you can redistribute it and/or
      32                 :            :  * modify it under the terms of the GNU Lesser General Public
      33                 :            :  * License as published by the Free Software Foundation; either
      34                 :            :  * version 2 of the License, or (at your option) any later version.
      35                 :            :  *
      36                 :            :  * This library is distributed in the hope that it will be useful,
      37                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      38                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the GNU
      39                 :            :  * Lesser General Public License for more details.
      40                 :            :  *
      41                 :            :  * You should have received a copy of the GNU Lesser General Public
      42                 :            :  * License along with this library; if not, write to the
      43                 :            :  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
      44                 :            :  * Boston, MA 02111-1307, USA.
      45                 :            :  */
      46                 :            : 
      47                 :            : #ifdef HAVE_CONFIG_H
      48                 :            : #include <config.h>
      49                 :            : #endif
      50                 :            : 
      51                 :            : #include <errno.h>
      52                 :            : #include <stdlib.h>
      53                 :            : #include <inttypes.h>
      54                 :            : #include <string.h>
      55                 :            : 
      56                 :            : #ifdef HAVE_ICONV
      57                 :            : #include <iconv.h>
      58                 :            : #endif
      59                 :            : 
      60                 :            : #include <pulse/xmalloc.h>
      61                 :            : #include <pulsecore/macro.h>
      62                 :            : 
      63                 :            : #include "utf8.h"
      64                 :            : 
      65                 :            : #define FILTER_CHAR '_'
      66                 :            : 
      67                 :            : static inline pa_bool_t is_unicode_valid(uint32_t ch) {
      68                 :            : 
      69         [ +  - ]:          3 :     if (ch >= 0x110000) /* End of unicode space */
      70                 :            :         return FALSE;
      71         [ +  - ]:          3 :     if ((ch & 0xFFFFF800) == 0xD800) /* Reserved area for UTF-16 */
      72                 :            :         return FALSE;
      73         [ +  - ]:          3 :     if ((ch >= 0xFDD0) && (ch <= 0xFDEF)) /* Reserved */
      74                 :            :         return FALSE;
      75         [ +  - ]:          3 :     if ((ch & 0xFFFE) == 0xFFFE) /* BOM (Byte Order Mark) */
      76                 :            :         return FALSE;
      77                 :            : 
      78                 :            :     return TRUE;
      79                 :            : }
      80                 :            : 
      81                 :            : static inline pa_bool_t is_continuation_char(uint8_t ch) {
      82 [ -  + ][ -  + ]:          6 :     if ((ch & 0xc0) != 0x80) /* 10xxxxxx */
                 [ +  - ]
      83                 :            :         return FALSE;
      84                 :            :     return TRUE;
      85                 :            : }
      86                 :            : 
      87                 :            : static inline void merge_continuation_char(uint32_t *u_ch, uint8_t ch) {
      88                 :          3 :     *u_ch <<= 6;
      89                 :          0 :     *u_ch |= ch & 0x3f;
      90                 :            : }
      91                 :            : 
      92                 :        168 : static char* utf8_validate(const char *str, char *output) {
      93                 :        168 :     uint32_t val = 0;
      94                 :        168 :     uint32_t min = 0;
      95                 :            :     const uint8_t *p, *last;
      96                 :            :     int size;
      97                 :            :     uint8_t *o;
      98                 :            : 
      99         [ +  - ]:        168 :     pa_assert(str);
     100                 :            : 
     101                 :            :     o = (uint8_t*) output;
     102         [ +  + ]:       3311 :     for (p = (const uint8_t*) str; *p; p++) {
     103         [ +  + ]:       3144 :         if (*p < 128) {
     104         [ +  + ]:       3134 :             if (o)
     105                 :         98 :                 *o = *p;
     106                 :            :         } else {
     107                 :         10 :             last = p;
     108                 :            : 
     109         [ +  + ]:         10 :             if ((*p & 0xe0) == 0xc0) { /* 110xxxxx two-char seq. */
     110                 :          3 :                 size = 2;
     111                 :          3 :                 min = 128;
     112                 :          3 :                 val = (uint32_t) (*p & 0x1e);
     113                 :          3 :                 goto ONE_REMAINING;
     114         [ +  + ]:          7 :             } else if ((*p & 0xf0) == 0xe0) { /* 1110xxxx three-char seq.*/
     115                 :          1 :                 size = 3;
     116                 :          1 :                 min = (1 << 11);
     117                 :          1 :                 val = (uint32_t) (*p & 0x0f);
     118                 :          1 :                 goto TWO_REMAINING;
     119         [ +  + ]:          6 :             } else if ((*p & 0xf8) == 0xf0) { /* 11110xxx four-char seq */
     120                 :          2 :                 size = 4;
     121                 :          2 :                 min = (1 << 16);
     122                 :          2 :                 val = (uint32_t) (*p & 0x07);
     123                 :            :             } else
     124                 :            :                 goto error;
     125                 :            : 
     126                 :          2 :             p++;
     127         [ -  + ]:          2 :             if (!is_continuation_char(*p))
     128                 :            :                 goto error;
     129                 :          0 :             merge_continuation_char(&val, *p);
     130                 :            : 
     131                 :            : TWO_REMAINING:
     132                 :          1 :             p++;
     133         [ -  + ]:          1 :             if (!is_continuation_char(*p))
     134                 :            :                 goto error;
     135                 :          0 :             merge_continuation_char(&val, *p);
     136                 :            : 
     137                 :            : ONE_REMAINING:
     138                 :          3 :             p++;
     139         [ +  - ]:          3 :             if (!is_continuation_char(*p))
     140                 :            :                 goto error;
     141                 :          3 :             merge_continuation_char(&val, *p);
     142                 :            : 
     143         [ +  - ]:          3 :             if (val < min)
     144                 :            :                 goto error;
     145                 :            : 
     146         [ +  - ]:          3 :             if (!is_unicode_valid(val))
     147                 :            :                 goto error;
     148                 :            : 
     149         [ +  + ]:          3 :             if (o) {
     150                 :          2 :                 memcpy(o, last, (size_t) size);
     151                 :          2 :                 o += size;
     152                 :            :             }
     153                 :            : 
     154                 :          3 :             continue;
     155                 :            : 
     156                 :            : error:
     157         [ +  + ]:          7 :             if (o) {
     158                 :          6 :                 *o = FILTER_CHAR;
     159                 :          6 :                 p = last; /* We retry at the next character */
     160                 :            :             } else
     161                 :            :                 goto failure;
     162                 :            :         }
     163                 :            : 
     164         [ +  + ]:       3140 :         if (o)
     165                 :        104 :             o++;
     166                 :            :     }
     167                 :            : 
     168         [ +  + ]:        167 :     if (o) {
     169                 :          5 :         *o = '\0';
     170                 :        168 :         return output;
     171                 :            :     }
     172                 :            : 
     173                 :            :     return (char*) str;
     174                 :            : 
     175                 :            : failure:
     176                 :            :     return NULL;
     177                 :            : }
     178                 :            : 
     179                 :        163 : char* pa_utf8_valid (const char *str) {
     180                 :        163 :     return utf8_validate(str, NULL);
     181                 :            : }
     182                 :            : 
     183                 :          5 : char* pa_utf8_filter (const char *str) {
     184                 :            :     char *new_str;
     185                 :            : 
     186         [ -  + ]:          5 :     pa_assert(str);
     187                 :          5 :     new_str = pa_xmalloc(strlen(str) + 1);
     188                 :          5 :     return utf8_validate(str, new_str);
     189                 :            : }
     190                 :            : 
     191                 :            : #ifdef HAVE_ICONV
     192                 :            : 
     193                 :         87 : static char* iconv_simple(const char *str, const char *to, const char *from) {
     194                 :            :     char *new_str;
     195                 :            :     size_t len, inlen;
     196                 :            :     iconv_t cd;
     197                 :            :     ICONV_CONST char *inbuf;
     198                 :            :     char *outbuf;
     199                 :            :     size_t res, inbytes, outbytes;
     200                 :            : 
     201         [ -  + ]:         87 :     pa_assert(str);
     202         [ -  + ]:         87 :     pa_assert(to);
     203         [ -  + ]:         87 :     pa_assert(from);
     204                 :            : 
     205                 :         87 :     cd = iconv_open(to, from);
     206         [ +  - ]:         88 :     if (cd == (iconv_t)-1)
     207                 :            :         return NULL;
     208                 :            : 
     209                 :         88 :     inlen = len = strlen(str) + 1;
     210                 :         88 :     new_str = pa_xmalloc(len);
     211                 :            : 
     212                 :            :     for (;;) {
     213                 :         88 :         inbuf = (ICONV_CONST char*) str; /* Brain dead prototype for iconv() */
     214                 :         88 :         inbytes = inlen;
     215                 :         88 :         outbuf = new_str;
     216                 :         88 :         outbytes = len;
     217                 :            : 
     218                 :         88 :         res = iconv(cd, &inbuf, &inbytes, &outbuf, &outbytes);
     219                 :            : 
     220         [ -  + ]:         88 :         if (res != (size_t)-1)
     221                 :            :             break;
     222                 :            : 
     223         [ #  # ]:          0 :         if (errno != E2BIG) {
     224                 :          0 :             pa_xfree(new_str);
     225                 :          0 :             new_str = NULL;
     226                 :          0 :             break;
     227                 :            :         }
     228                 :            : 
     229         [ #  # ]:          0 :         pa_assert(inbytes != 0);
     230                 :            : 
     231                 :          0 :         len += inbytes;
     232                 :          0 :         new_str = pa_xrealloc(new_str, len);
     233                 :          0 :     }
     234                 :            : 
     235                 :         88 :     iconv_close(cd);
     236                 :            : 
     237                 :         88 :     return new_str;
     238                 :            : }
     239                 :            : 
     240                 :         87 : char* pa_utf8_to_locale (const char *str) {
     241                 :         87 :     return iconv_simple(str, "", "UTF-8");
     242                 :            : }
     243                 :            : 
     244                 :          0 : char* pa_locale_to_utf8 (const char *str) {
     245                 :          0 :     return iconv_simple(str, "UTF-8", "");
     246                 :            : }
     247                 :            : 
     248                 :            : #else
     249                 :            : 
     250                 :            : char* pa_utf8_to_locale (const char *str) {
     251                 :            :     pa_assert(str);
     252                 :            : 
     253                 :            :     return pa_ascii_filter(str);
     254                 :            : }
     255                 :            : 
     256                 :            : char* pa_locale_to_utf8 (const char *str) {
     257                 :            :     pa_assert(str);
     258                 :            : 
     259                 :            :     if (pa_utf8_valid(str))
     260                 :            :         return pa_xstrdup(str);
     261                 :            : 
     262                 :            :     return NULL;
     263                 :            : }
     264                 :            : 
     265                 :            : #endif
     266                 :            : 
     267                 :        110 : char *pa_ascii_valid(const char *str) {
     268                 :            :     const char *p;
     269         [ +  - ]:        110 :     pa_assert(str);
     270                 :            : 
     271         [ +  + ]:       1324 :     for (p = str; *p; p++)
     272         [ +  - ]:       1214 :         if ((unsigned char) *p >= 128)
     273                 :            :             return NULL;
     274                 :            : 
     275                 :            :     return (char*) str;
     276                 :            : }
     277                 :            : 
     278                 :          0 : char *pa_ascii_filter(const char *str) {
     279                 :            :     char *r, *s, *d;
     280         [ #  # ]:          0 :     pa_assert(str);
     281                 :            : 
     282                 :          0 :     r = pa_xstrdup(str);
     283                 :            : 
     284         [ #  # ]:          0 :     for (s = r, d = r; *s; s++)
     285         [ #  # ]:          0 :         if ((unsigned char) *s < 128)
     286                 :          0 :             *(d++) = *s;
     287                 :            : 
     288                 :          0 :     *d = 0;
     289                 :            : 
     290                 :          0 :     return r;
     291                 :            : }

Generated by: LCOV version 1.9