LCOV - code coverage report
Current view: top level - builds/libidn/libidn2/lib - context.c (source / functions) Hit Total Coverage
Test: Libidn2-2.3.7.3-61ee Code Coverage Lines: 91 96 94.8 %
Date: 2024-12-01 07:08:19 Functions: 4 4 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* context.c - check contextual rule on label
       2             :    Copyright (C) 2011-2024 Simon Josefsson
       3             : 
       4             :    Libidn2 is free software: you can redistribute it and/or modify it
       5             :    under the terms of either:
       6             : 
       7             :      * the GNU Lesser General Public License as published by the Free
       8             :        Software Foundation; either version 3 of the License, or (at
       9             :        your option) any later version.
      10             : 
      11             :    or
      12             : 
      13             :      * the GNU General Public License as published by the Free
      14             :        Software Foundation; either version 2 of the License, or (at
      15             :        your option) any later version.
      16             : 
      17             :    or both in parallel, as here.
      18             : 
      19             :    This program is distributed in the hope that it will be useful,
      20             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      21             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      22             :    GNU General Public License for more details.
      23             : 
      24             :    You should have received copies of the GNU General Public License and
      25             :    the GNU Lesser General Public License along with this program.  If
      26             :    not, see <http://www.gnu.org/licenses/>.
      27             : */
      28             : 
      29             : #include <config.h>
      30             : 
      31             : #include "idn2.h"
      32             : #include "tables.h"
      33             : #include <unictype.h>             /* uc_combining_class, UC_CCC_VR */
      34             : #include "context.h"
      35             : 
      36             : int
      37     1409907 : _idn2_contextj_rule (const uint32_t *label, size_t llen, size_t pos)
      38             : {
      39             :   uint32_t cp;
      40             : 
      41     1409907 :   if (llen == 0)
      42           0 :     return IDN2_OK;
      43             : 
      44     1409907 :   cp = label[pos];
      45             : 
      46     1409907 :   if (!_idn2_contextj_p (cp))
      47     1408342 :     return IDN2_OK;
      48             : 
      49        1565 :   switch (cp)
      50             :     {
      51         988 :     case 0x200C:                /* ZERO WIDTH NON-JOINER */
      52         988 :       if (pos > 0)
      53             :         {
      54             :           /* If Canonical_Combining_Class(Before(cp)) .eq.  Virama Then True; */
      55         843 :           uint32_t before_cp = label[pos - 1];
      56         843 :           int cc = uc_combining_class (before_cp);
      57         843 :           if (cc == UC_CCC_VR)
      58         252 :             return IDN2_OK;
      59             :         }
      60             : 
      61             :       /* See http://permalink.gmane.org/gmane.ietf.idnabis/6980 for
      62             :          clarified rule. */
      63             : 
      64         736 :       if (pos == 0 || pos == llen - 1)
      65         177 :         return IDN2_CONTEXTJ;
      66             : 
      67             :       {
      68             :         int jt;
      69             :         size_t tmp;
      70             : 
      71             :         /* Search backwards. */
      72         559 :         for (tmp = pos - 1;; tmp--)
      73             :           {
      74         352 :             jt = uc_joining_type (label[tmp]);
      75         911 :             if (jt == UC_JOINING_TYPE_L || jt == UC_JOINING_TYPE_D)
      76             :               break;
      77         490 :             if (tmp == 0)
      78          58 :               return IDN2_CONTEXTJ;
      79         432 :             if (jt == UC_JOINING_TYPE_T)
      80         352 :               continue;
      81          80 :             return IDN2_CONTEXTJ;
      82             :           }
      83             : 
      84             :         /* Search forward. */
      85         685 :         for (tmp = pos + 1; tmp < llen; tmp++)
      86             :           {
      87         685 :             jt = uc_joining_type (label[tmp]);
      88         685 :             if (jt == UC_JOINING_TYPE_R || jt == UC_JOINING_TYPE_D)
      89             :               break;
      90         337 :             if (tmp == llen - 1)
      91          64 :               return IDN2_CONTEXTJ;
      92         273 :             if (jt == UC_JOINING_TYPE_T)
      93         264 :               continue;
      94           9 :             return IDN2_CONTEXTJ;
      95             :           }
      96             :       }
      97             : 
      98         348 :       return IDN2_OK;
      99             :       break;
     100             : 
     101         577 :     case 0x200D:                /* ZERO WIDTH JOINER */
     102         577 :       if (pos > 0)
     103             :         {
     104         433 :           uint32_t before_cp = label[pos - 1];
     105         433 :           int cc = uc_combining_class (before_cp);
     106         433 :           if (cc == UC_CCC_VR)
     107         346 :             return IDN2_OK;
     108             :         }
     109         231 :       return IDN2_CONTEXTJ;
     110             :     }
     111             : 
     112           0 :   return IDN2_CONTEXTJ_NO_RULE;
     113             : }
     114             : 
     115             : static const char *
     116        2038 : _uc_script_name (ucs4_t uc)
     117             : {
     118        2038 :   const uc_script_t *ucs = uc_script (uc);
     119             : 
     120        2038 :   if (!ucs)
     121         252 :     return "";
     122             : 
     123        1786 :   return ucs->name;
     124             : }
     125             : 
     126             : int
     127        4918 : _idn2_contexto_rule (const uint32_t *label, size_t llen, size_t pos)
     128             : {
     129        4918 :   uint32_t cp = label[pos];
     130             : 
     131        4918 :   if (!_idn2_contexto_p (cp))
     132        2266 :     return IDN2_OK;
     133             : 
     134        2652 :   switch (cp)
     135             :     {
     136          12 :     case 0x00B7:
     137             :       /* MIDDLE DOT */
     138          12 :       if (llen < 3)
     139           4 :         return IDN2_CONTEXTO;
     140           8 :       if (pos == 0 || pos == llen - 1)
     141           0 :         return IDN2_CONTEXTO;
     142           8 :       if (label[pos - 1] == 0x006C && label[pos + 1] == 0x006C)
     143           5 :         return IDN2_OK;
     144           3 :       return IDN2_CONTEXTO;
     145             :       break;
     146             : 
     147          44 :     case 0x0375:
     148             :       /* GREEK LOWER NUMERAL SIGN (KERAIA) */
     149          44 :       if (pos == llen - 1)
     150           2 :         return IDN2_CONTEXTO;
     151          42 :       if (strcmp (_uc_script_name (label[pos + 1]), "Greek") == 0)
     152          33 :         return IDN2_OK;
     153           9 :       return IDN2_CONTEXTO;
     154             :       break;
     155             : 
     156         189 :     case 0x05F3:
     157             :       /* HEBREW PUNCTUATION GERESH */
     158             :     case 0x05F4:
     159             :       /* HEBREW PUNCTUATION GERSHAYIM */
     160         189 :       if (pos == 0)
     161           4 :         return IDN2_CONTEXTO;
     162         185 :       if (strcmp (_uc_script_name (label[pos - 1]), "Hebrew") == 0)
     163         172 :         return IDN2_OK;
     164          13 :       return IDN2_CONTEXTO;
     165             :       break;
     166             : 
     167        1044 :     case 0x0660:
     168             :     case 0x0661:
     169             :     case 0x0662:
     170             :     case 0x0663:
     171             :     case 0x0664:
     172             :     case 0x0665:
     173             :     case 0x0666:
     174             :     case 0x0667:
     175             :     case 0x0668:
     176             :     case 0x0669:
     177             :       {
     178             :         /* ARABIC-INDIC DIGITS */
     179             :         size_t i;
     180       28157 :         for (i = 0; i < llen; i++)
     181       27121 :           if (label[i] >= 0x6F0 && label[i] <= 0x06F9)
     182           8 :             return IDN2_CONTEXTO;
     183        1036 :         return IDN2_OK;
     184             :         break;
     185             :       }
     186             : 
     187        1135 :     case 0x06F0:
     188             :     case 0x06F1:
     189             :     case 0x06F2:
     190             :     case 0x06F3:
     191             :     case 0x06F4:
     192             :     case 0x06F5:
     193             :     case 0x06F6:
     194             :     case 0x06F7:
     195             :     case 0x06F8:
     196             :     case 0x06F9:
     197             :       {
     198             :         /* EXTENDED ARABIC-INDIC DIGITS */
     199             :         size_t i;
     200       33383 :         for (i = 0; i < llen; i++)
     201       32252 :           if (label[i] >= 0x660 && label[i] <= 0x0669)
     202           4 :             return IDN2_CONTEXTO;
     203        1131 :         return IDN2_OK;
     204             :         break;
     205             :       }
     206         228 :     case 0x30FB:
     207             :       {
     208             :         /* KATAKANA MIDDLE DOT */
     209             :         size_t i;
     210         228 :         bool script_ok = false;
     211             : 
     212         914 :         for (i = 0; !script_ok && i < llen; i++)
     213         686 :           if (strcmp (_uc_script_name (label[i]), "Hiragana") == 0
     214         619 :               || strcmp (_uc_script_name (label[i]), "Katakana") == 0
     215         506 :               || strcmp (_uc_script_name (label[i]), "Han") == 0)
     216         224 :             script_ok = true;
     217             : 
     218         228 :         if (script_ok)
     219         224 :           return IDN2_OK;
     220           4 :         return IDN2_CONTEXTO;
     221             :         break;
     222             :       }
     223             :     }
     224             : 
     225           0 :   return IDN2_CONTEXTO_NO_RULE;
     226             : }
     227             : 
     228             : bool
     229        6468 : _idn2_contexto_with_rule (uint32_t cp)
     230             : {
     231        6468 :   switch (cp)
     232             :     {
     233        6468 :     case 0x00B7:
     234             :       /* MIDDLE DOT */
     235             :     case 0x0375:
     236             :       /* GREEK LOWER NUMERAL SIGN (KERAIA) */
     237             :     case 0x05F3:
     238             :       /* HEBREW PUNCTUATION GERESH */
     239             :     case 0x05F4:
     240             :       /* HEBREW PUNCTUATION GERSHAYIM */
     241             :     case 0x0660:
     242             :     case 0x0661:
     243             :     case 0x0662:
     244             :     case 0x0663:
     245             :     case 0x0664:
     246             :     case 0x0665:
     247             :     case 0x0666:
     248             :     case 0x0667:
     249             :     case 0x0668:
     250             :     case 0x0669:
     251             :       /* ARABIC-INDIC DIGITS */
     252             :     case 0x06F0:
     253             :     case 0x06F1:
     254             :     case 0x06F2:
     255             :     case 0x06F3:
     256             :     case 0x06F4:
     257             :     case 0x06F5:
     258             :     case 0x06F6:
     259             :     case 0x06F7:
     260             :     case 0x06F8:
     261             :     case 0x06F9:
     262             :       /* EXTENDED ARABIC-INDIC DIGITS */
     263             :     case 0x30FB:
     264             :       /* KATAKANA MIDDLE DOT */
     265        6468 :       return true;
     266             :       break;
     267             :     }
     268             : 
     269           0 :   return false;
     270             : }

Generated by: LCOV version 1.16