LCOV - code coverage report
Current view: top level - src - ichiprt2.c (source / functions) Coverage Total Hit
Test: InChI Unit Test Coverage Lines: 43.8 % 1013 444
Test Date: 2026-05-04 07:05:02 Functions: 68.8 % 32 22
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 34.0 % 995 338

             Branch data     Line data    Source code
       1                 :             : /*
       2                 :             :  * International Chemical Identifier (InChI)
       3                 :             :  * Version 1
       4                 :             :  * Software version 1.07
       5                 :             :  * April 30, 2024
       6                 :             :  *
       7                 :             :  * MIT License
       8                 :             :  *
       9                 :             :  * Copyright (c) 2024 IUPAC and InChI Trust
      10                 :             :  *
      11                 :             :  * Permission is hereby granted, free of charge, to any person obtaining a copy
      12                 :             :  * of this software and associated documentation files (the "Software"), to deal
      13                 :             :  * in the Software without restriction, including without limitation the rights
      14                 :             :  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      15                 :             :  * copies of the Software, and to permit persons to whom the Software is
      16                 :             :  * furnished to do so, subject to the following conditions:
      17                 :             :  *
      18                 :             :  * The above copyright notice and this permission notice shall be included in all
      19                 :             :  * copies or substantial portions of the Software.
      20                 :             :  *
      21                 :             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      22                 :             :  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23                 :             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      24                 :             :  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25                 :             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      26                 :             :  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      27                 :             :  * SOFTWARE.
      28                 :             : *
      29                 :             : * The InChI library and programs are free software developed under the
      30                 :             :  * auspices of the International Union of Pure and Applied Chemistry (IUPAC).
      31                 :             :  * Originally developed at NIST.
      32                 :             :  * Modifications and additions by IUPAC and the InChI Trust.
      33                 :             :  * Some portions of code were developed/changed by external contributors
      34                 :             :  * (either contractor or volunteer) which are listed in the file
      35                 :             :  * 'External-contributors' included in this distribution.
      36                 :             :  *
      37                 :             :  * info@inchi-trust.org
      38                 :             :  *
      39                 :             : */
      40                 :             : 
      41                 :             : #include <stdlib.h>
      42                 :             : #include <string.h>
      43                 :             : #include <ctype.h>
      44                 :             : #include <limits.h>
      45                 :             : 
      46                 :             : #include "mode.h"
      47                 :             : #include "ichimain.h"
      48                 :             : #include "ichimake.h"
      49                 :             : #include "ichi_io.h"
      50                 :             : 
      51                 :             : #include "bcf_s.h"
      52                 :             : 
      53                 :             :  /****************************************************************************/
      54                 :          62 : int Eql_INChI_Stereo( INChI_Stereo  *s1,
      55                 :             :                       int           eql1,
      56                 :             :                       INChI_Stereo  *s2,
      57                 :             :                       int           eql2,
      58                 :             :                       int           bRelRac )
      59                 :             : {
      60                 :          62 :     int inv1 = 0, inv2 = 0, len;
      61                 :             : 
      62         [ -  + ]:          62 :     if (!s1)
      63                 :             :     {
      64                 :           0 :         return 0;
      65                 :             :     }
      66                 :             : #if ( REL_RAC_STEREO_IGN_1_SC == 1 )
      67                 :             : #else
      68                 :          62 :     bRelRac = 0;
      69                 :             : #endif
      70                 :             : 
      71         [ -  + ]:          62 :     if (EQL_SP2 == eql1)
      72                 :             :     {
      73   [ #  #  #  #  :           0 :         if (( len = s1->nNumberOfStereoBonds ) > 0 && s1->b_parity && s1->nBondAtom1 && s1->nBondAtom2)
             #  #  #  # ]
      74                 :             :         {
      75         [ #  # ]:           0 :             if (!s2)
      76                 :             :             {
      77         [ #  # ]:           0 :                 if (EQL_EXISTS == eql2)
      78                 :             :                 {
      79                 :             :                     /* find whether double bond stereo exists*/
      80                 :           0 :                     return 1;
      81                 :             :                 }
      82                 :           0 :                 return 0;
      83                 :             :             }
      84         [ #  # ]:           0 :             if (EQL_SP2 == eql2 &&
      85   [ #  #  #  #  :           0 :                  len == s2->nNumberOfStereoBonds && s2->b_parity && s2->nBondAtom1 && s2->nBondAtom2 &&
             #  #  #  # ]
      86         [ #  # ]:           0 :                  !memcmp( s1->nBondAtom1, s2->nBondAtom1, len * sizeof( s1->nBondAtom1[0] ) ) &&
      87         [ #  # ]:           0 :                  !memcmp( s1->nBondAtom2, s2->nBondAtom2, len * sizeof( s1->nBondAtom2[0] ) ) &&
      88         [ #  # ]:           0 :                  !memcmp( s1->b_parity, s2->b_parity, len * sizeof( s1->b_parity[0] ) ))
      89                 :             :             {
      90                 :           0 :                 return 1;
      91                 :             :             }
      92                 :             :         }
      93                 :           0 :         return 0;
      94                 :             :     }
      95                 :             : 
      96                 :             :     else
      97                 :             :     {
      98   [ +  +  +  - ]:          62 :         if (( eql1 == EQL_SP3 || ( inv1 = ( eql1 == EQL_SP3_INV ) ) ) &&
      99         [ +  + ]:          62 :             ( len = s1->nNumberOfStereoCenters ) > ( bRelRac ? 1 : 0 )) /* djb-rwth: addressing coverity ID #499484 -- bRelRac does not have to be 0 */
     100                 :             :         {
     101                 :             : 
     102                 :             :             S_CHAR  *t_parity1, *t_parity2;
     103                 :             :             AT_NUMB *nNumber1, *nNumber2;
     104         [ +  + ]:          60 :             if (inv1)
     105                 :             :             {
     106         [ +  - ]:          51 :                 if (s1->nCompInv2Abs)
     107                 :             :                 {
     108                 :          51 :                     t_parity1 = s1->t_parityInv;
     109                 :          51 :                     nNumber1 = s1->nNumberInv;
     110                 :             :                 }
     111                 :             :                 else
     112                 :             :                 {
     113                 :           0 :                     return 0;
     114                 :             :                 }
     115                 :             :             }
     116                 :             :             else
     117                 :             :             {
     118                 :           9 :                 t_parity1 = s1->t_parity;
     119                 :           9 :                 nNumber1 = s1->nNumber;
     120                 :             :             }
     121   [ +  -  +  - ]:          60 :             if (t_parity1 && nNumber1)
     122                 :             :             {
     123         [ -  + ]:          60 :                 if (!s2)
     124                 :             :                 {
     125   [ #  #  #  #  :           0 :                     if (EQL_EXISTS == eql2 && ( !inv1 || s1->nCompInv2Abs ))
                   #  # ]
     126                 :             :                     {
     127                 :             :                         /* the 1st sp3 (inverted if requested) stereo exists*/
     128                 :           0 :                         return 1;
     129                 :             :                     }
     130                 :           0 :                     return 0;  /* both sp3 do not exist */
     131                 :             :                 }
     132   [ -  +  -  - ]:          60 :                 if (( eql2 == EQL_SP3 || ( inv2 = ( eql2 == EQL_SP3_INV ) ) ) &&
     133         [ +  + ]:          60 :                     len == s2->nNumberOfStereoCenters)
     134                 :             :                 {
     135         [ -  + ]:          57 :                     if (inv2)
     136                 :             :                     {
     137   [ #  #  #  # ]:           0 :                         if (s2->nCompInv2Abs && s1->nCompInv2Abs)
     138                 :             :                         {
     139                 :           0 :                             t_parity2 = s2->t_parityInv;
     140                 :           0 :                             nNumber2 = s2->nNumberInv;
     141                 :             :                         }
     142                 :             :                         else
     143                 :             :                         {
     144                 :             :                             /* if one sp3 is inverted then another should have non-trivial inverted stereo */
     145                 :           0 :                             return 0;
     146                 :             :                         }
     147                 :             :                     }
     148                 :             :                     else
     149                 :             :                     {
     150   [ +  +  -  + ]:          57 :                         if (inv1 && !s2->nCompInv2Abs)
     151                 :             :                         {
     152                 :             :                             /* if one sp3 is inverted then another should have non-trivial inverted stereo */
     153                 :           0 :                             return 0;
     154                 :             :                         }
     155                 :          57 :                         t_parity2 = s2->t_parity;
     156                 :          57 :                         nNumber2 = s2->nNumber;
     157                 :             :                     }
     158   [ +  -  +  - ]:          57 :                     if (t_parity2 && nNumber2)
     159                 :             :                     {
     160         [ +  + ]:          57 :                         if (inv1 ^ inv2)
     161                 :             :                         {
     162                 :             :                             int i, num_inv;
     163         [ +  + ]:         187 :                             for (i = 0, num_inv = 0; i < len; i++)
     164                 :             :                             {
     165         [ -  + ]:         149 :                                 if (nNumber1[i] != nNumber2[i])
     166                 :           0 :                                     break;
     167   [ +  -  +  + ]:         149 :                                 if (ATOM_PARITY_WELL_DEF( t_parity1[i] ) &&
     168   [ +  -  +  - ]:         136 :                                      ATOM_PARITY_WELL_DEF( t_parity2[i] ))
     169                 :             :                                 {
     170         [ +  + ]:         136 :                                     if (3 == t_parity1[i] + t_parity2[i])
     171                 :             :                                     {
     172                 :         123 :                                         num_inv++;
     173                 :             :                                     }
     174                 :             :                                     else
     175                 :             :                                     {
     176                 :          13 :                                         break;
     177                 :             :                                     }
     178                 :             :                                 }
     179                 :             :                                 else
     180         [ -  + ]:          13 :                                     if (t_parity1[i] != t_parity2[i])
     181                 :             :                                     {
     182                 :           0 :                                         break;
     183                 :             :                                     }
     184                 :             :                             }
     185   [ +  +  +  - ]:          51 :                             return ( len == i && num_inv > 0 );
     186                 :             :                         }
     187                 :             :                         else
     188                 :             :                         {
     189         [ +  - ]:          12 :                             return !memcmp( t_parity1, t_parity2, len * sizeof( t_parity1[0] ) ) &&
     190         [ +  + ]:           6 :                                 !memcmp( nNumber1, nNumber2, len * sizeof( nNumber1[0] ) );
     191                 :             :                         }
     192                 :             :                     }
     193                 :             :                 }
     194                 :             :             }
     195                 :             :         }
     196                 :             :     }
     197                 :             : 
     198                 :           5 :     return 0;
     199                 :             : }
     200                 :             : 
     201                 :             : 
     202                 :             : /****************************************************************************/
     203                 :           0 : int Eql_INChI_Isotopic( INChI *i1, INChI *i2 )
     204                 :             : {
     205                 :           0 :     int eq = i1
     206         [ #  # ]:           0 :             && i2
     207         [ #  # ]:           0 :             && !i1->bDeleted
     208         [ #  # ]:           0 :             && !i2->bDeleted
     209   [ #  #  #  # ]:           0 :             && ( i1->nNumberOfIsotopicAtoms > 0 || i1->nNumberOfIsotopicTGroups > 0 )
     210         [ #  # ]:           0 :             && i1->nNumberOfIsotopicAtoms == i2->nNumberOfIsotopicAtoms
     211         [ #  # ]:           0 :             && i1->nNumberOfIsotopicTGroups == i2->nNumberOfIsotopicTGroups
     212         [ #  # ]:           0 :             && ( !i1->nNumberOfIsotopicAtoms ||
     213   [ #  #  #  # ]:           0 :                 (i1->IsotopicAtom && i2->IsotopicAtom &&
     214                 :           0 :                 !memcmp( i1->IsotopicAtom, i2->IsotopicAtom,
     215         [ #  # ]:           0 :                         i1->nNumberOfIsotopicAtoms * sizeof( i1->IsotopicAtom[0] ) )) )
     216   [ #  #  #  # ]:           0 :             && ( !i1->nNumberOfIsotopicTGroups ||
     217   [ #  #  #  # ]:           0 :                 (i1->IsotopicTGroup && i2->IsotopicTGroup &&
     218                 :           0 :                 !memcmp( i1->IsotopicTGroup, i2->IsotopicTGroup,
     219         [ #  # ]:           0 :                     i1->nNumberOfIsotopicTGroups * sizeof( i1->IsotopicAtom[0] )) )
     220                 :             :             ); /* djb-rwth: addressing LLVM warnings */
     221                 :             : 
     222                 :           0 :     return eq;
     223                 :             : }
     224                 :             : 
     225                 :             : 
     226                 :             : /****************************************************************************/
     227                 :          21 : int Eql_INChI_Aux_Equ( INChI_Aux *a1, int eql1, INChI_Aux *a2, int eql2 )
     228                 :             : {
     229                 :          21 :     int t1 = 0, t2 = 0, len = 0;
     230                 :          21 :     AT_NUMB *n1 = NULL, *n2 = NULL;
     231   [ +  +  -  + ]:          21 :     if (!a1 || !a2)
     232                 :             :     {
     233                 :          13 :         return 0;
     234                 :             :     }
     235                 :           8 :     t1 = ( eql1 & EQL_EQU_TG );
     236                 :           8 :     t2 = ( eql2 & EQL_EQU_TG );
     237   [ -  +  -  - ]:           8 :     if (t1 && t2)
     238                 :             :     {
     239   [ #  #  #  #  :           0 :         if (( len = a1->nNumberOfTGroups ) > 0 && len == a2->nNumberOfTGroups && !a1->bDeleted && !a2->bDeleted)
             #  #  #  # ]
     240                 :             :         {
     241         [ #  # ]:           0 :             if (eql1 & EQL_EQU_ISO)
     242                 :             :             {
     243         [ #  # ]:           0 :                 if (a1->bIsIsotopic)
     244                 :             :                 {
     245                 :           0 :                     n1 = a1->nConstitEquIsotopicTGroupNumbers;
     246                 :             :                 }
     247                 :             :             }
     248                 :             :             else
     249                 :             :             {
     250                 :           0 :                 n1 = a1->nConstitEquTGroupNumbers;
     251                 :             :             }
     252         [ #  # ]:           0 :             if (eql2 & EQL_EQU_ISO)
     253                 :             :             {
     254         [ #  # ]:           0 :                 if (a2->bIsIsotopic)
     255                 :             :                 {
     256                 :           0 :                     n2 = a2->nConstitEquIsotopicTGroupNumbers;
     257                 :             :                 }
     258                 :             :             }
     259                 :             :             else
     260                 :             :             {
     261                 :           0 :                 n2 = a2->nConstitEquTGroupNumbers;
     262                 :             :             }
     263                 :             :         }
     264                 :             :     }
     265                 :             :     else
     266   [ +  -  +  - ]:           8 :         if (!t1 && !t2)
     267                 :             :         {
     268   [ +  -  +  +  :           8 :             if (( len = a1->nNumberOfAtoms ) > 0 && len == a2->nNumberOfAtoms && !a1->bDeleted && !a2->bDeleted)
             +  -  +  - ]
     269                 :             :             {
     270         [ -  + ]:           3 :                 if (eql1 & EQL_EQU_ISO)
     271                 :             :                 {
     272         [ #  # ]:           0 :                     if (a1->bIsIsotopic)
     273                 :             :                     {
     274                 :           0 :                         n1 = a1->nConstitEquIsotopicNumbers;
     275                 :             :                     }
     276                 :             :                 }
     277                 :             :                 else
     278                 :             :                 {
     279                 :           3 :                     n1 = a1->nConstitEquNumbers;
     280                 :             :                 }
     281         [ -  + ]:           3 :                 if (eql2 & EQL_EQU_ISO)
     282                 :             :                 {
     283         [ #  # ]:           0 :                     if (a2->bIsIsotopic)
     284                 :             :                     {
     285                 :           0 :                         n2 = a2->nConstitEquIsotopicNumbers;
     286                 :             :                     }
     287                 :             :                 }
     288                 :             :                 else
     289                 :             :                 {
     290                 :           3 :                     n2 = a2->nConstitEquNumbers;
     291                 :             :                 }
     292                 :             :             }
     293                 :             :         }
     294   [ +  +  +  -  :           8 :     if (n1 && n2 && !memcmp( n1, n2, len * sizeof( n1[0] ) ) && bHasEquString( n1, len ))
             +  -  +  + ]
     295                 :             :     {
     296                 :           1 :         return 1;
     297                 :             :     }
     298                 :             : 
     299                 :           7 :     return 0;
     300                 :             : }
     301                 :             : 
     302                 :             : 
     303                 :             : 
     304                 :             : /****************************************************************************/
     305                 :           0 : int Eql_INChI_Aux_Num( INChI_Aux *a1, int eql1, INChI_Aux *a2, int eql2 )
     306                 :             : {
     307                 :             :     int len;
     308                 :           0 :     AT_NUMB *n1 = NULL, *n2 = NULL;
     309   [ #  #  #  # ]:           0 :     if (!a1 || !a2)
     310                 :             :     {
     311                 :           0 :         return 0;
     312                 :             :     }
     313   [ #  #  #  #  :           0 :     if (( len = a1->nNumberOfAtoms ) <= 0 || len != a2->nNumberOfAtoms || a1->bDeleted || a2->bDeleted)
             #  #  #  # ]
     314                 :             :     {
     315                 :           0 :         return 0;
     316                 :             :     }
     317   [ #  #  #  # ]:           0 :     if ((( eql1 & EQL_NUM_ISO ) && !a1->bIsIsotopic) ||
     318   [ #  #  #  # ]:           0 :         (( eql2 & EQL_NUM_ISO ) && !a2->bIsIsotopic)) /* djb-rwth: addressing LLVM warnings */
     319                 :             :     {
     320                 :           0 :         return 0;
     321                 :             :     }
     322                 :             : 
     323   [ #  #  #  #  :           0 :     switch (eql1)
                      # ]
     324                 :             :     {
     325                 :           0 :         case EQL_NUM:
     326                 :           0 :             n1 = a1->nOrigAtNosInCanonOrd;
     327                 :           0 :             break;
     328                 :           0 :         case EQL_NUM_ISO:
     329                 :           0 :             n1 = a1->nIsotopicOrigAtNosInCanonOrd;
     330                 :           0 :             break;
     331                 :           0 :         case EQL_NUM_INV:
     332                 :           0 :             n1 = a1->nOrigAtNosInCanonOrdInv;
     333                 :           0 :             break;
     334                 :           0 :         case ( EQL_NUM_INV | EQL_NUM_ISO ):
     335                 :           0 :             n1 = a1->nIsotopicOrigAtNosInCanonOrdInv;
     336                 :           0 :             break;
     337                 :           0 :         default:
     338                 :           0 :             return 0;
     339                 :             :     }
     340                 :             : 
     341   [ #  #  #  #  :           0 :     switch (eql2)
                      # ]
     342                 :             :     {
     343                 :           0 :         case EQL_NUM:
     344                 :           0 :             n2 = a2->nOrigAtNosInCanonOrd;
     345                 :           0 :             break;
     346                 :           0 :         case EQL_NUM_ISO:
     347                 :           0 :             n2 = a2->nIsotopicOrigAtNosInCanonOrd;
     348                 :           0 :             break;
     349                 :           0 :         case EQL_NUM_INV:
     350                 :           0 :             n2 = a2->nOrigAtNosInCanonOrdInv;
     351                 :           0 :             break;
     352                 :           0 :         case ( EQL_NUM_INV | EQL_NUM_ISO ):
     353                 :           0 :             n2 = a2->nIsotopicOrigAtNosInCanonOrdInv;
     354                 :           0 :             break;
     355                 :           0 :         default:
     356                 :           0 :             return 0;
     357                 :             :     }
     358                 :             : 
     359   [ #  #  #  #  :           0 :     if (n1 && n2 && !memcmp( n1, n2, len * sizeof( n1[0] ) ))
                   #  # ]
     360                 :             :     {
     361                 :           0 :         return 1;
     362                 :             :     }
     363                 :             : 
     364                 :           0 :     return 0;
     365                 :             : }
     366                 :             : 
     367                 :             : 
     368                 :             : /****************************************************************************/
     369                 :          75 : int bHasOrigInfo( ORIG_INFO *OrigInfo, int num_atoms )
     370                 :             : {
     371                 :          75 :     int i, bFound = 0;
     372   [ +  -  +  - ]:          75 :     if (OrigInfo && num_atoms > 0)
     373                 :             :     {
     374   [ +  +  +  + ]:         695 :         for (i = 0; !bFound && i < num_atoms; i++)
     375                 :             :         {
     376                 :         620 :             bFound |= ( 0 != OrigInfo[i].cCharge ) ||
     377   [ +  +  +  - ]:        1235 :                 ( 0 != OrigInfo[i].cRadical ) ||
     378         [ +  + ]:         615 :                 ( 0 != OrigInfo[i].cUnusualValence );
     379                 :             :         }
     380                 :             :     }
     381                 :             : 
     382                 :          75 :     return bFound;
     383                 :             : }
     384                 :             : 
     385                 :             : 
     386                 :             : /****************************************************************************/
     387                 :           8 : int EqlOrigInfo( INChI_Aux *a1, INChI_Aux *a2 )
     388                 :             : {
     389   [ +  +  +  +  :           6 :     int ret = a1 && a2 && a1->nNumberOfAtoms == a2->nNumberOfAtoms &&
                   +  - ]
     390   [ +  +  +  - ]:          15 :         bHasOrigInfo( a1->OrigInfo, a1->nNumberOfAtoms ) && a2->OrigInfo &&
     391         [ -  + ]:           1 :         !memcmp( a1->OrigInfo, a2->OrigInfo, a1->nNumberOfAtoms * sizeof( a1->OrigInfo[0] ) );
     392                 :             : 
     393                 :           8 :     return ret;
     394                 :             : }
     395                 :             : 
     396                 :             : 
     397                 :             : /****************************************************************************/
     398                 :          95 : int bHasEquString( AT_NUMB *LinearCT, int nLenCT )
     399                 :             : {
     400                 :             :     /*  produce output string; */
     401                 :             :     int i, k;
     402         [ +  + ]:          95 :     if (!LinearCT)
     403                 :             :     {
     404                 :           3 :         return 0;
     405                 :             :     }
     406         [ +  + ]:         702 :     for (k = 0; k < nLenCT; k++)
     407                 :             :     {
     408                 :             :         /*  find the first equivalence number */
     409         [ +  + ]:         642 :         if (k != (int) LinearCT[k] - 1)
     410                 :             :         {
     411                 :         610 :             continue;
     412                 :             :         }
     413         [ +  - ]:          64 :         for (i = k; i < nLenCT; i++)
     414                 :             :         {
     415         [ -  + ]:          64 :             if (k != (int) LinearCT[i] - 1)
     416                 :             :             {
     417                 :           0 :                 continue;
     418                 :             :             }
     419         [ +  + ]:          64 :             if (k < i)
     420                 :             :             {
     421                 :          32 :                 return 1;
     422                 :             :             }
     423                 :             :         }
     424                 :             :     }
     425                 :             : 
     426                 :          60 :     return 0;
     427                 :             : }
     428                 :             : 
     429                 :             : 
     430                 :             : /****************************************************************************/
     431                 :         256 : int MakeMult( int mult,
     432                 :             :               const char       *szTailingDelim,
     433                 :             :               INCHI_IOS_STRING *buf,
     434                 :             :               int              nCtMode,
     435                 :             :               int              *bOverflow )
     436                 :             : {
     437                 :             :     char szValue[2048];
     438                 :         256 :     int  len = 0, len_delim, n;
     439                 :             : 
     440   [ +  +  -  + ]:         256 :     if (mult == 1 || *bOverflow)
     441                 :             :     {
     442                 :         229 :         return 0;
     443                 :             :     }
     444         [ -  + ]:          27 :     if (nCtMode & CT_MODE_ABC_NUMBERS)
     445                 :             :     {
     446                 :           0 :         len += MakeAbcNumber( szValue, ( int )sizeof( szValue ), NULL, mult );
     447                 :             :     }
     448                 :             :     else
     449                 :             :     {
     450                 :          27 :         len += MakeDecNumber( szValue, ( int )sizeof( szValue ), NULL, mult );
     451                 :             :     }
     452                 :          27 :     len_delim = (int) strlen( szTailingDelim );
     453                 :             : 
     454         [ +  - ]:          27 :     if (len + len_delim < ( int )sizeof( szValue ))
     455                 :             :     {
     456                 :          27 :         strcpy(szValue + len, szTailingDelim);
     457                 :          27 :         n = inchi_strbuf_printf( buf, "%s", szValue );
     458         [ -  + ]:          27 :         if (-1 == n) *bOverflow |= 1;
     459                 :          27 :         return n;
     460                 :             :         /*
     461                 :             :         len += len_delim;
     462                 :             :         if ( len < nLen_szLinearCT )
     463                 :             :         {
     464                 :             :             strcpy( szLinearCT, szValue );
     465                 :             :             return len;
     466                 :             :         }*/
     467                 :             :     }
     468                 :             : 
     469                 :           0 :     *bOverflow |= 1;
     470                 :             : 
     471                 :           0 :     return 0;
     472                 :             : }
     473                 :             : 
     474                 :             : /**
     475                 :             :  * @brief Adds the number to the string buffer.
     476                 :             :  *
     477                 :             :  * @param number Input number to be added
     478                 :             :  * @param szTailingDelim Pointer to the trailing delimiter string
     479                 :             :  * @param buf Pointer to the output string buffer
     480                 :             :  * @param nCtMode Mode flag for string representation
     481                 :             :  * @param bOverflow Pointer to overflow flag
     482                 :             :  * @return Returns the number of characters added to the buffer
     483                 :             :  */
     484                 :         163 : int MakeNumber_EnhStereo( int number,
     485                 :             :                           const char       *szTailingDelim,
     486                 :             :                           INCHI_IOS_STRING *buf,
     487                 :             :                           int              nCtMode,
     488                 :             :                           int              *bOverflow )
     489                 :             : {
     490                 :             :     char szValue[2048];
     491                 :         163 :     int  len = 0;
     492                 :             :     int len_delim;
     493                 :             :     int n;
     494                 :             : 
     495         [ -  + ]:         163 :     if (*bOverflow)
     496                 :             :     {
     497                 :           0 :         return 0;
     498                 :             :     }
     499         [ -  + ]:         163 :     if (nCtMode & CT_MODE_ABC_NUMBERS)
     500                 :             :     {
     501                 :           0 :         len += MakeAbcNumber( szValue, ( int )sizeof( szValue ), NULL, number );
     502                 :             :     }
     503                 :             :     else
     504                 :             :     {
     505                 :         163 :         len += MakeDecNumber( szValue, ( int )sizeof( szValue ), NULL, number );
     506                 :             :     }
     507                 :         163 :     len_delim = (int) strlen( szTailingDelim );
     508                 :             : 
     509         [ +  - ]:         163 :     if (len + len_delim < ( int )sizeof( szValue ))
     510                 :             :     {
     511                 :         163 :         strcpy(szValue + len, szTailingDelim);
     512                 :         163 :         n = inchi_strbuf_printf( buf, "%s", szValue );
     513         [ -  + ]:         163 :         if (-1 == n) *bOverflow |= 1;
     514                 :         163 :         return n;
     515                 :             :     }
     516                 :             : 
     517                 :           0 :     *bOverflow |= 1;
     518                 :             : 
     519                 :           0 :     return 0;
     520                 :             : }
     521                 :             : 
     522                 :             : 
     523                 :             : /****************************************************************************/
     524                 :             : /**
     525                 :             :  * @brief Adds the delimiter to the string buffer if it is not empty and there is no overflow.
     526                 :             :  *
     527                 :             :  * @param szTailingDelim Pointer to the trailing delimiter string
     528                 :             :  * @param buf Pointer to the output string buffer
     529                 :             :  * @param bOverflow Pointer to overflow flag
     530                 :             :  * @return Returns the number of characters added to the buffer, or 0 if the delimiter is empty or there is an overflow
     531                 :             :  */
     532                 :         495 : int MakeDelim( const char       *szTailingDelim,
     533                 :             :                INCHI_IOS_STRING *buf,
     534                 :             :                int              *bOverflow )
     535                 :             : {
     536                 :             :     int n;
     537   [ +  -  +  -  :         495 :     if (!szTailingDelim || !*szTailingDelim || *bOverflow)
                   -  + ]
     538                 :             :     {
     539                 :           0 :         return 0;
     540                 :             :     }
     541                 :             : 
     542                 :         495 :     n = inchi_strbuf_printf( buf, szTailingDelim );
     543         [ -  + ]:         495 :     if (-1 == n)
     544                 :             :     {
     545                 :           0 :         *bOverflow |= 1;
     546                 :             :     }
     547                 :             : 
     548                 :         495 :     return n;
     549                 :             :     /*
     550                 :             :     len_delim = (int) strlen(szTailingDelim);
     551                 :             :     if ( len_delim < nLen_szLinearCT ) {
     552                 :             :     strcpy( szLinearCT, szTailingDelim );
     553                 :             :     return len_delim;
     554                 :             :     }
     555                 :             :     *bOverflow |= 1;
     556                 :             :     return 0;
     557                 :             :     */
     558                 :             : }
     559                 :             : 
     560                 :             : 
     561                 :             : /****************************************************************************/
     562                 :          35 : int MakeEqStr( const char       *szTailingDelim,
     563                 :             :                int              mult,
     564                 :             :                INCHI_IOS_STRING *buf,
     565                 :             :                int              *bOverflow )
     566                 :             : {
     567                 :          35 :     int  n = 0, n0;
     568                 :             :     char szValue[2048];
     569                 :             : 
     570   [ +  -  +  -  :          35 :     if (!szTailingDelim || !*szTailingDelim || *bOverflow)
                   -  + ]
     571                 :             :     {
     572                 :           0 :         return 0;
     573                 :             :     }
     574                 :             : 
     575                 :          35 :     n0 = buf->nUsedLength;
     576                 :             : 
     577         [ +  + ]:          35 :     if (mult != 1)
     578                 :             :     {
     579                 :           3 :         n = MakeDecNumber( szValue, ( int )sizeof( szValue ), NULL, mult );
     580         [ -  + ]:           3 :         if (-1 == n)
     581                 :             :         {
     582                 :           0 :             *bOverflow |= 1;
     583                 :           0 :             return -1;
     584                 :             :         }
     585                 :             :     }
     586         [ +  + ]:          35 :     if (n > 0)
     587                 :             :     {
     588                 :           3 :         n = inchi_strbuf_printf( buf, "%-s", szValue );
     589         [ -  + ]:           3 :         if (-1 == n) *bOverflow |= 1;
     590                 :             :     }
     591                 :          35 :     n = inchi_strbuf_printf( buf, "%-s", szTailingDelim );
     592         [ -  + ]:          35 :     if (-1 == n)
     593                 :             :     {
     594                 :           0 :         *bOverflow |= 1;
     595                 :             :     }
     596                 :             : 
     597                 :          35 :     return ( buf->nUsedLength - n0 );
     598                 :             : }
     599                 :             : 
     600                 :             : 
     601                 :             : /****************************************************************************
     602                 :             : Prepare InChI atomic numbers substring (connections, for InChI)
     603                 :             :     nCtMode =    0: full
     604                 :             :                 1: censored CT (no orphans)
     605                 :             :                 2: compressed CT (Abs numbers)
     606                 :             : ****************************************************************************/
     607                 :          58 : int MakeCtStringNew( CANON_GLOBALS    *pCG,
     608                 :             :                      AT_NUMB          *LinearCT,
     609                 :             :                      int              nLenCT,
     610                 :             :                      int              bAddDelim,
     611                 :             :                      S_CHAR           *nNum_H,
     612                 :             :                      int              num_atoms,
     613                 :             :                      INCHI_IOS_STRING *strbuf,
     614                 :             :                      int              nCtMode,
     615                 :             :                      int              *bOverflow )
     616                 :             : {
     617                 :             :     /*  produce output string; */
     618                 :          58 :     int nUsedLength0 = 0, nLen = 0, len, i, bOvfl = *bOverflow;
     619                 :             :     char szValue[2048];
     620                 :             :     int   nValue, nDelim, num_H;
     621                 :          58 :     AT_NUMB *nDfsOrderCT = NULL;
     622                 :          58 :     int      bNoNum_H = ( NULL == nNum_H );
     623                 :             :     int      nNumRingClosures;
     624                 :          58 :     int      bAbcNumbers = ( 0 != ( nCtMode & CT_MODE_ABC_NUMBERS ) );
     625                 :          58 :     int      bPredecessors = ( 0 != ( nCtMode & CT_MODE_PREDECESSORS ) );
     626   [ -  +  -  -  :          58 :     int      bCountRingClosures = bAbcNumbers && bPredecessors && ( nCtMode & CT_MODE_ABC_NUM_CLOSURES );
                   -  - ]
     627                 :             : 
     628         [ -  + ]:          58 :     if (nLenCT <= 1)
     629                 :             :     {
     630                 :           0 :         return 0;  /*  no atoms or a single atom: no connection table */
     631                 :             :     }
     632                 :             : 
     633                 :          58 :     nUsedLength0 = strbuf->nUsedLength;
     634                 :             : 
     635                 :             :     /*  make array containing connection string data */
     636         [ -  + ]:          58 :     if (!( nDfsOrderCT = GetDfsOrder4CT( pCG, LinearCT, nLenCT,
     637                 :             :         nNum_H, num_atoms, nCtMode ) ))
     638                 :             :     {
     639                 :           0 :         ( *bOverflow )++;
     640                 :           0 :         return 0;
     641                 :             :     }
     642                 :             : 
     643                 :             :     /*  add connection table string */
     644   [ +  -  -  + ]:          58 :     if (!bOvfl && bAddDelim)
     645                 :             :     {
     646                 :           0 :         inchi_strbuf_printf( strbuf, "," );
     647                 :             :     }
     648                 :             : 
     649         [ +  - ]:          58 :     if (!bOvfl)
     650                 :             :     {
     651                 :          58 :         nNumRingClosures = 0;
     652         [ +  + ]:         604 :         for (i = 0; nDfsOrderCT[i]/* && nLen < nLen_szLinearCT*/; i += 3)
     653                 :             :         {
     654         [ +  - ]:         546 :             nValue = ( nDfsOrderCT[i] > MAX_ATOMS ) ? 0 : nDfsOrderCT[i];
     655         [ -  + ]:         546 :             num_H = nDfsOrderCT[i + 1] ? nDfsOrderCT[i + 1] - 16 : 0;
     656                 :         546 :             nDelim = nDfsOrderCT[i + 2];
     657                 :         546 :             len = 0;
     658                 :             :             /*  delimiter */
     659         [ -  + ]:         546 :             if (bPredecessors)
     660                 :             :             {
     661         [ #  # ]:           0 :                 if (bCountRingClosures)
     662                 :             :                 {
     663   [ #  #  #  #  :           0 :                     if (nDelim == '-' && i > 3 && bNoNum_H)
                   #  # ]
     664                 :             :                     {
     665         [ #  # ]:           0 :                         if (!nNumRingClosures)
     666                 :             :                         {
     667                 :             :                             int j;
     668   [ #  #  #  # ]:           0 :                             for (j = i; nDfsOrderCT[j] && '-' == nDfsOrderCT[j + 2]; j += 3)
     669                 :             :                             {
     670                 :           0 :                                 nNumRingClosures++;
     671                 :             :                             }
     672         [ #  # ]:           0 :                             if (nNumRingClosures)
     673                 :             :                             {
     674                 :           0 :                                 len += MakeDecNumber( szValue + len, ( int )sizeof( szValue ) - len, NULL, nNumRingClosures );
     675                 :             :                             }
     676                 :           0 :                             nNumRingClosures--;
     677                 :             :                         }
     678                 :             :                         else
     679                 :             :                         {
     680                 :           0 :                             nNumRingClosures--;
     681                 :             :                         }
     682                 :             :                     }
     683                 :             :                     else
     684                 :             :                     {
     685                 :           0 :                         nNumRingClosures = 0;
     686                 :             :                     }
     687                 :             :                 }
     688   [ #  #  #  #  :           0 :                 else if (nDelim && !( bAbcNumbers && nDelim == ',' ))
                   #  # ]
     689                 :             :                 {
     690   [ #  #  #  # ]:           0 :                     if (nNum_H || i > 3)
     691                 :             :                     {
     692                 :           0 :                         szValue[len++] = nDelim;
     693                 :             :                     }
     694                 :             :                 }
     695                 :             :             }
     696                 :             :             else
     697                 :             :             {
     698   [ +  +  -  +  :         546 :                 if (nDelim && !( bAbcNumbers && nDelim == '-' ))
                   -  - ]
     699                 :             :                 {
     700                 :         488 :                     szValue[len++] = nDelim;
     701                 :             :                 }
     702                 :             :             }
     703         [ -  + ]:         546 :             if (bAbcNumbers)
     704                 :             :             {
     705   [ #  #  #  # ]:           0 :                 if (nValue || i)
     706                 :             :                 {
     707                 :             :                     /* the 1st value may be zero in case of presdecessor list */
     708                 :           0 :                     len += MakeAbcNumber( szValue + len, ( int )sizeof( szValue ) - len, NULL, nValue );
     709                 :             :                 }
     710         [ #  # ]:           0 :                 if (num_H)
     711                 :             :                 {
     712                 :           0 :                     len += MakeDecNumber( szValue + len, ( int )sizeof( szValue ) - len, NULL, num_H );
     713                 :             :                 }
     714                 :             :             }
     715                 :             :             else
     716                 :             :             {
     717   [ -  +  -  - ]:         546 :                 if (nValue || i)
     718                 :             :                 {
     719                 :             :                     /* the 1st value may be zero in case of presdecessor list */
     720                 :         546 :                     len += MakeDecNumber( szValue + len, ( int )sizeof( szValue ) - len, NULL, nValue );
     721                 :             :                 }
     722         [ -  + ]:         546 :                 if (num_H)
     723                 :             :                 {
     724                 :           0 :                     szValue[len] = 'H';
     725                 :           0 :                     len++;
     726         [ #  # ]:           0 :                     if (num_H > 1)
     727                 :             :                     {
     728                 :           0 :                         len += MakeDecNumber( szValue + len, ( int )sizeof( szValue ) - len, NULL, num_H );
     729                 :             :                     }
     730                 :             :                 }
     731                 :             :             }
     732                 :             : 
     733         [ +  - ]:         546 :             if (len > 0)
     734                 :             :             {
     735                 :         546 :                 inchi_strbuf_printf( strbuf, "%s", szValue );
     736                 :             :             }
     737                 :             :         }
     738                 :             :     }
     739                 :             : 
     740                 :          58 :     *bOverflow |= bOvfl;
     741         [ +  - ]:          58 :     if (nDfsOrderCT)
     742                 :             :     {
     743         [ +  - ]:          58 :         inchi_free( nDfsOrderCT );
     744                 :             :     }
     745                 :             : 
     746                 :          58 :     nLen = strbuf->nUsedLength - nUsedLength0;
     747                 :             : 
     748                 :          58 :     return nLen;
     749                 :             : }
     750                 :             : 
     751                 :             : 
     752                 :             : /****************************************************************************
     753                 :             :     Prepare InChI atomic numbers substring (for AuxInfo)
     754                 :             : 
     755                 :             :     nCtMode =    0: full
     756                 :             :                 1: censored CT (no orphans)
     757                 :             :                 2: compressed CT (Abs numbers)
     758                 :             : ****************************************************************************/
     759                 :          69 : int MakeCtStringOld( AT_NUMB          *LinearCT,
     760                 :             :                      int              nLenCT,
     761                 :             :                      int              bAddDelim,
     762                 :             :                      INCHI_IOS_STRING *strbuf,
     763                 :             :                      int              nCtMode,
     764                 :             :                      int              *bOverflow )
     765                 :             : {
     766                 :             :     /*  produce output string; */
     767                 :          69 :     int nUsedLength0 = 0, nLen = 0, len, i, bLessThanPrev, bOvfl = *bOverflow;
     768                 :          69 :     AT_NUMB nMax = 0;
     769                 :             :     char szValue[2048];
     770                 :          69 :     int   nValue, bNext = 0;
     771                 :             : 
     772                 :          69 :     nUsedLength0 = strbuf->nUsedLength;
     773                 :             : 
     774                 :             :     /*  add connection table string */
     775   [ +  -  +  -  :          69 :     if (!( nCtMode & CT_MODE_ABC_NUMBERS ) && !bOvfl && bAddDelim)
                   -  + ]
     776                 :             :     {
     777                 :           0 :         inchi_strbuf_printf( strbuf, "," );
     778                 :             :                                         /*
     779                 :             :                                         if ( nLen_szLinearCT > 1 ) {
     780                 :             :                                             strcpy( szLinearCT, "," );
     781                 :             :                                             nLen ++;
     782                 :             :                                         } else {
     783                 :             :                                             bOvfl = 1;
     784                 :             :                                         }*/
     785                 :             :     }
     786         [ +  - ]:          69 :     if (!bOvfl)
     787                 :             :     {
     788         [ +  + ]:         688 :         for (i = 0; i < nLenCT/* && nLen < nLen_szLinearCT*/; i++)
     789                 :             :         {
     790                 :         619 :             bLessThanPrev = 0;
     791   [ -  +  -  - ]:         619 :             if (!( nCtMode & CT_MODE_NO_ORPHANS ) || ( ( bLessThanPrev = LinearCT[i] < nMax ) ||
     792   [ #  #  #  # ]:           0 :                 (i + 1 < nLenCT && LinearCT[i + 1] < ( nMax = LinearCT[i] )) )) /* djb-rwth: addressing LLVM warning */
     793                 :             :             {
     794                 :         619 :                 nValue = LinearCT[i];
     795         [ -  + ]:         619 :                 if (nCtMode & CT_MODE_ABC_NUMBERS)
     796                 :             :                 {
     797   [ #  #  #  # ]:           0 :                     len = MakeAbcNumber( szValue, ( int )sizeof( szValue ), ( !bNext && bAddDelim ) ? ITEM_DELIMETER : NULL, nValue );
     798                 :             :                 }
     799                 :             :                 else
     800                 :             :                 {
     801         [ -  + ]:         619 :                     if (nCtMode & CT_MODE_NO_ORPHANS)
     802                 :             :                     {
     803                 :             :                         /*  censored CT */
     804                 :             :                         /*  output '-' as a delimiter to show a bonding for decimal output of the connection table */
     805         [ #  # ]:           0 :                         len = MakeDecNumber( szValue, ( int )sizeof( szValue ), bLessThanPrev ? "-" : ITEM_DELIMETER, nValue );
     806                 :             :                     }
     807                 :             :                     else
     808                 :             :                     {
     809         [ +  + ]:         619 :                         len = MakeDecNumber( szValue, ( int )sizeof( szValue ), i ? ITEM_DELIMETER : NULL, nValue );
     810                 :             :                     }
     811                 :             :                 }
     812         [ +  - ]:         619 :                 if (len > 0)
     813                 :             :                 {
     814                 :         619 :                     inchi_strbuf_printf( strbuf, "%s", szValue );
     815                 :         619 :                     bNext++;
     816                 :             :                 }
     817                 :             : 
     818                 :             :                 /*if ( 0 <= len && nLen+len < nLen_szLinearCT) {
     819                 :             :                     if ( len ) {
     820                 :             :                         strcpy( szLinearCT+nLen, szValue );
     821                 :             :                         nLen += len;
     822                 :             :                         bNext ++;
     823                 :             :                     }
     824                 :             :                     } else {
     825                 :             :                         bOvfl = 1;
     826                 :             :                         break;
     827                 :             :                     }*/
     828                 :             :             }
     829                 :             :         }
     830                 :             :     }
     831                 :          69 :     *bOverflow |= bOvfl;
     832                 :             : 
     833                 :          69 :     nLen = strbuf->nUsedLength - nUsedLength0;
     834                 :             : 
     835                 :          69 :     return nLen;
     836                 :             : }
     837                 :             : 
     838                 :             : 
     839                 :             : /****************************************************************************
     840                 :             :     MakeHString( ... )
     841                 :             : 
     842                 :             :     nCtMode =   0: decimal
     843                 :             :                 2: compressed CT (Abc numbers)
     844                 :             : ****************************************************************************/
     845                 :          56 : int MakeHString( int              bAddDelim,
     846                 :             :                  S_CHAR           *LinearCT,
     847                 :             :                  int              nLenCT,
     848                 :             :                  INCHI_IOS_STRING *strbuf,
     849                 :             :                  int              nCtMode,
     850                 :             :                  int              *bOverflow )
     851                 :             : {
     852                 :             : #define INIT_MIN_NUM_H (-4)
     853                 :             : #define INIT_MAX_NUM_H 16
     854                 :             : #define INIT_LEN_NUM_H (INIT_MAX_NUM_H - INIT_MIN_NUM_H + 1)
     855                 :             : 
     856                 :             :     /*  produce output string; */
     857                 :          56 :     int nUsedLength0 = 0, nLen = 0, len, i, iFirst, nVal, bOvfl = *bOverflow;
     858                 :             :     char szValue[2048];
     859                 :             :     const char *pH;
     860                 :          56 :     int  bNext = 0;
     861                 :             : 
     862                 :          56 :     nUsedLength0 = strbuf->nUsedLength;
     863                 :             : 
     864                 :             :     /*  add connection table string */
     865   [ +  -  +  -  :          56 :     if (!( nCtMode & CT_MODE_ABC_NUMBERS ) && !bOvfl && bAddDelim)
                   -  + ]
     866                 :             :     {
     867                 :           0 :         inchi_strbuf_printf( strbuf, "," );
     868                 :             :                             /*if ( nLen_szLinearCT > 1 ) {
     869                 :             :                                 strcpy( szLinearCT, "," );
     870                 :             :                                 nLen ++;
     871                 :             :                                 } else {
     872                 :             :                                     bOvfl = 1;
     873                 :             :                             }*/
     874                 :             :     }
     875   [ +  -  +  -  :          56 :     if (!bOvfl && 0 < nLenCT && LinearCT)
                   +  - ]
     876                 :             :     {
     877         [ +  - ]:          56 :         if (nCtMode & CT_MODE_EQL_H_TOGETHER)
     878                 :             :         {
     879                 :          56 :             int  curMinH = INIT_MIN_NUM_H;
     880                 :          56 :             int  curMaxH = INIT_MAX_NUM_H;
     881                 :          56 :             int  curLenH = INIT_LEN_NUM_H;
     882                 :             :             int  nInitNumH[INIT_LEN_NUM_H];
     883                 :          56 :             int *nNumH = nInitNumH;
     884                 :             :             int  numAt, curNumH;
     885                 :             :             int      j, bOutOfRange, tot_num_no_H;
     886                 :             :             /* count atoms H */
     887                 :             :             do
     888                 :             :             {
     889                 :          56 :                 bOutOfRange = 0;
     890                 :          56 :                 tot_num_no_H = 0; /* number of atoms that have no H */
     891                 :          56 :                 memset( nNumH, 0, curLenH * sizeof( nNumH[0] ) ); /* djb-rwth: memset_s C11/Annex K variant? */
     892         [ +  + ]:         573 :                 for (i = 0; i < nLenCT; i++)
     893                 :             :                 {
     894                 :         517 :                     curNumH = LinearCT[i];
     895         [ -  + ]:         517 :                     if (curNumH < curMinH)
     896                 :             :                     {
     897                 :           0 :                         curMinH = curNumH;
     898                 :           0 :                         bOutOfRange++;
     899                 :             :                     }
     900                 :             :                     else
     901                 :             :                     {
     902         [ -  + ]:         517 :                         if (curNumH > curMaxH)
     903                 :             :                         {
     904                 :           0 :                             curMaxH = curNumH;
     905                 :           0 :                             bOutOfRange++;
     906                 :             :                         }
     907                 :             :                         else
     908         [ +  - ]:         517 :                             if (!bOutOfRange)
     909                 :             :                             {
     910                 :         517 :                                 nNumH[curNumH - curMinH] ++;
     911                 :             :                             }
     912                 :             :                     }
     913                 :         517 :                     tot_num_no_H += !curNumH;
     914                 :             :                 }
     915         [ -  + ]:          56 :                 if (tot_num_no_H == nLenCT)
     916                 :             :                 {
     917                 :           0 :                     return nLen; /* empty string */
     918                 :             :                 }
     919         [ -  + ]:          56 :                 if (bOutOfRange)
     920                 :             :                 {
     921                 :             :                     /* for debug only */
     922         [ #  # ]:           0 :                     if (nNumH != nInitNumH)
     923                 :             :                     {
     924                 :           0 :                         *bOverflow |= 1;
     925         [ #  # ]:           0 :                         inchi_free( nNumH );
     926                 :           0 :                         return nLen;
     927                 :             :                     }
     928                 :             :                     /* end debug */
     929                 :           0 :                     curLenH = curMaxH - curMinH + 1;
     930                 :           0 :                     nNumH = (int*) inchi_malloc( curLenH * sizeof( nNumH[0] ) );
     931         [ #  # ]:           0 :                     if (!nNumH)
     932                 :             :                     {
     933                 :           0 :                         *bOverflow |= 1;
     934                 :           0 :                         return nLen;
     935                 :             :                     }
     936                 :             :                 }
     937                 :             :             }
     938         [ -  + ]:          56 :             while (bOutOfRange); /* the loop may be executed 1 or 2 times only */
     939                 :             : 
     940         [ +  + ]:        1232 :             for (curNumH = curMinH; curNumH <= curMaxH; curNumH++)
     941                 :             :             {
     942                 :        1176 :                 numAt = nNumH[curNumH - curMinH]; /* number of atoms that have curNumH atoms H */
     943   [ +  +  +  + ]:        1176 :                 if (!numAt || !curNumH)
     944                 :             :                 {
     945                 :        1038 :                     continue; /* no atom has this number of H or number of H = 0 */
     946                 :             :                 }
     947                 :         138 :                 j = 0;
     948   [ +  +  +  + ]:         637 :                 while (j < nLenCT && numAt)
     949                 :             :                 {
     950         [ +  + ]:         499 :                     if (curNumH == LinearCT[j])
     951                 :             :                     {
     952                 :         175 :                         iFirst = ++j;
     953                 :         175 :                         numAt--;
     954   [ +  +  +  +  :         439 :                         for (; j < nLenCT && curNumH == LinearCT[j] && numAt; j++)
                   +  - ]
     955                 :             :                         {
     956                 :         264 :                             numAt--;
     957                 :             :                         }
     958         [ -  + ]:         175 :                         if (nCtMode & CT_MODE_ABC_NUMBERS)
     959                 :             :                         {
     960                 :           0 :                             len = MakeAbcNumber( szValue, ( int )sizeof( szValue ), NULL, iFirst );
     961                 :             :                         }
     962                 :             :                         else
     963                 :             :                         {
     964         [ +  + ]:         175 :                             len = MakeDecNumber( szValue, ( int )sizeof( szValue ), bNext ? ITEM_DELIMETER : NULL, iFirst );
     965                 :         175 :                             bNext++; /* add a delimiter (comma) before all except the first */
     966                 :             :                         }
     967         [ +  + ]:         175 :                         if (iFirst < j)
     968                 :             :                         {
     969                 :             :                             /* output last canonical number */
     970         [ -  + ]:         106 :                             if (nCtMode & CT_MODE_ABC_NUMBERS)
     971                 :             :                             {
     972                 :           0 :                                 len += MakeAbcNumber( szValue + len, ( int )sizeof( szValue ), NULL, j );
     973                 :             :                             }
     974                 :             :                             else
     975                 :             :                             {
     976                 :         106 :                                 len += MakeDecNumber( szValue + len, ( int )sizeof( szValue ) - len, "-", j );
     977                 :             :                             }
     978                 :             :                         }
     979   [ +  +  -  + ]:         175 :                         if (!numAt || ( nCtMode & CT_MODE_ABC_NUMBERS ))
     980                 :             :                         {
     981                 :             :                             /* add number of H */
     982                 :             :                             /* output number of H */
     983                 :         138 :                             nVal = curNumH;
     984         [ -  + ]:         138 :                             if (nCtMode & CT_MODE_ABC_NUMBERS)
     985                 :             :                             {
     986                 :           0 :                                 len += MakeDecNumber( szValue + len, ( int )sizeof( szValue ) - len, NULL, nVal );
     987                 :             :                             }
     988                 :             :                             else
     989                 :             :                             {
     990         [ +  - ]:         138 :                                 pH = nVal > 0 ? "H" : "h";
     991                 :         138 :                                 nVal = abs( nVal );
     992         [ +  + ]:         138 :                                 if (nVal > 1)
     993                 :             :                                 {
     994                 :          84 :                                     len += MakeDecNumber( szValue + len, ( int )sizeof( szValue ) - len, pH, nVal );
     995                 :             :                                 }
     996                 :             :                                 else
     997                 :             :                                 {
     998                 :          54 :                                     strcpy(szValue + len, pH);
     999                 :          54 :                                     len++;
    1000                 :             :                                 }
    1001                 :             :                             }
    1002                 :             :                         }
    1003                 :             :                         /* add to the output */
    1004         [ +  - ]:         175 :                         if (len > 0)
    1005                 :             :                         {
    1006                 :         175 :                             inchi_strbuf_printf( strbuf, "%-s", szValue );
    1007                 :         175 :                             bNext++;
    1008                 :             :                         }
    1009                 :             :                         /*
    1010                 :             :                         if ( 0 <= len && nLen+len < nLen_szLinearCT ) {
    1011                 :             :                             if ( len ) {
    1012                 :             :                                 strcpy( szLinearCT+nLen, szValue );
    1013                 :             :                                 nLen += len;
    1014                 :             :                                 bNext ++;
    1015                 :             :                             }
    1016                 :             :                         } else {
    1017                 :             :                             bOvfl = 1;
    1018                 :             :                             break;
    1019                 :             :                         }*/
    1020                 :             :                     }
    1021                 :             :                     else
    1022                 :             :                     {
    1023                 :         324 :                         j++;
    1024                 :             :                     }
    1025                 :             :                 }
    1026                 :             :             }
    1027         [ -  + ]:          56 :             if (nNumH != nInitNumH)
    1028                 :             :             {
    1029         [ #  # ]:           0 :                 inchi_free( nNumH );
    1030                 :             :             }
    1031                 :             :         }
    1032                 :             :         else
    1033                 :             :         {
    1034                 :           0 :             iFirst = 0;
    1035         [ #  # ]:           0 :             for (i = iFirst + 1; i <= nLenCT/* && nLen < nLen_szLinearCT*/; i++)
    1036                 :             :             {
    1037   [ #  #  #  # ]:           0 :                 if (i < nLenCT && LinearCT[i] == LinearCT[iFirst])
    1038                 :             :                 {
    1039                 :           0 :                     continue;
    1040                 :             :                 }
    1041                 :             :                 /* output identical values located at i = iFirst..i-1 */
    1042         [ #  # ]:           0 :                 if (LinearCT[iFirst])
    1043                 :             :                 { /* output only non-zero values */
    1044                 :             :                   /* first canonical number */
    1045                 :           0 :                     nVal = LinearCT[iFirst];
    1046                 :           0 :                     iFirst++;
    1047         [ #  # ]:           0 :                     if (nCtMode & CT_MODE_ABC_NUMBERS)
    1048                 :             :                     {
    1049                 :           0 :                         len = MakeAbcNumber( szValue, ( int )sizeof( szValue ), NULL, iFirst );
    1050                 :             :                     }
    1051                 :             :                     else
    1052                 :             :                     {
    1053         [ #  # ]:           0 :                         len = MakeDecNumber( szValue, ( int )sizeof( szValue ), bNext ? ITEM_DELIMETER : NULL, iFirst );
    1054                 :             :                     }
    1055         [ #  # ]:           0 :                     if (iFirst < i)
    1056                 :             :                     {
    1057                 :             :                         /* output last canonical number */
    1058         [ #  # ]:           0 :                         if (nCtMode & CT_MODE_ABC_NUMBERS)
    1059                 :             :                         {
    1060                 :           0 :                             len += MakeAbcNumber( szValue + len, ( int )sizeof( szValue ), NULL, i );
    1061                 :             :                         }
    1062                 :             :                         else
    1063                 :             :                         {
    1064                 :           0 :                             len += MakeDecNumber( szValue + len, ( int )sizeof( szValue ) - len, "-", i );
    1065                 :             :                         }
    1066                 :             :                     }
    1067                 :             :                     /* output number of H */
    1068         [ #  # ]:           0 :                     if (nCtMode & CT_MODE_ABC_NUMBERS)
    1069                 :             :                     {
    1070                 :           0 :                         len += MakeDecNumber( szValue + len, ( int )sizeof( szValue ) - len, NULL, nVal );
    1071                 :             :                     }
    1072                 :             :                     else
    1073                 :             :                     {
    1074         [ #  # ]:           0 :                         pH = nVal > 0 ? "H" : "h";
    1075                 :           0 :                         nVal = abs( nVal );
    1076         [ #  # ]:           0 :                         if (nVal > 1)
    1077                 :             :                         {
    1078                 :           0 :                             len += MakeDecNumber( szValue + len, ( int )sizeof( szValue ) - len, pH, nVal );
    1079                 :             :                         }
    1080                 :             :                         else
    1081                 :             :                         {
    1082                 :           0 :                             strcpy(szValue + len, pH); /* djb-rwth: GCC 14 false positive */
    1083                 :           0 :                             len++;
    1084                 :             :                         }
    1085                 :             :                     }
    1086         [ #  # ]:           0 :                     if (0 <= len/* && nLen+len < nLen_szLinearCT*/)
    1087                 :             :                     {
    1088         [ #  # ]:           0 :                         if (len)
    1089                 :             :                         {
    1090                 :           0 :                             inchi_strbuf_printf( strbuf, "%-s", szValue );
    1091                 :             :                                         /*strcpy( szLinearCT+nLen, szValue );
    1092                 :             :                                         nLen += len;*/
    1093                 :           0 :                             bNext++;
    1094                 :             :                         }
    1095                 :             :                     }
    1096                 :             :                     else
    1097                 :             :                     {
    1098                 :           0 :                         bOvfl = 1;
    1099                 :           0 :                         break;
    1100                 :             :                     }
    1101                 :             :                 }
    1102                 :           0 :                 iFirst = i;
    1103                 :             :             }
    1104                 :             :         }
    1105                 :             :     }
    1106                 :          56 :     *bOverflow |= bOvfl;
    1107                 :             : 
    1108                 :          56 :     nLen = strbuf->nUsedLength - nUsedLength0;
    1109                 :          56 :     return nLen;
    1110                 :             : 
    1111                 :             : #undef INIT_MIN_NUM_H
    1112                 :             : #undef INIT_MAX_NUM_H
    1113                 :             : #undef INIT_LEN_NUM_H
    1114                 :             : }
    1115                 :             : 
    1116                 :             : 
    1117                 :             : /****************************************************************************
    1118                 :             :     Prepare InChI atomic numbers substring
    1119                 :             : 
    1120                 :             :     nCtMode =    0: full
    1121                 :             :                 1: censored CT (no orphans, that CT should
    1122                 :             :                    have only atoms with neighbors)
    1123                 :             :                 2: compressed CT (Abc numbers)
    1124                 :             :  ****************************************************************************/
    1125                 :          69 : int MakeCtString( CANON_GLOBALS    *pCG,
    1126                 :             :                   AT_NUMB          *LinearCT,
    1127                 :             :                   int              nLenCT,
    1128                 :             :                   int              bAddDelim,
    1129                 :             :                   S_CHAR           *nNum_H,
    1130                 :             :                   int              num_atoms,
    1131                 :             :                   INCHI_IOS_STRING *strbuf,
    1132                 :             :                   int              nCtMode,
    1133                 :             :                   int              *bOverflow )
    1134                 :             : {
    1135                 :             : 
    1136   [ -  +  -  - ]:          69 :     if (!nNum_H || !( nCtMode & CT_MODE_NO_ORPHANS ))
    1137                 :             :     {
    1138                 :          69 :         return MakeCtStringOld( LinearCT, nLenCT, bAddDelim, strbuf, nCtMode, bOverflow );
    1139                 :             :     }
    1140                 :             :     else
    1141                 :             :     {
    1142                 :           0 :         return MakeCtStringNew( pCG, LinearCT, nLenCT, bAddDelim, nNum_H,
    1143                 :             :                                 num_atoms, strbuf, nCtMode, bOverflow );
    1144                 :             :     }
    1145                 :             : }
    1146                 :             : 
    1147                 :             : 
    1148                 :             : /****************************************************************************
    1149                 :             :     MakeTautString(  )
    1150                 :             : 
    1151                 :             :     nCtMode =    0: full: decimal-only, with parentheses around t-groups
    1152                 :             :                 2: compressed CT:    do not add comma before the output string if bAddDelim != 0
    1153                 :             :                                     do not add parentheses around t-groups
    1154                 :             :                                     atom canon numbers an Abc
    1155                 :             :     LinearCT format:
    1156                 :             :         N      = number of tautomeric groups
    1157                 :             :         n      = number of endpoints + 1 in a tautomeric group #1
    1158                 :             :         next INCHI_T_NUM_MOVABLE lines (any after the first non-zero):
    1159                 :             :         h      = number of hydrogen atoms in the tautomeric group
    1160                 :             :         m      = number of negative charges
    1161                 :             :         ...    (the rest of the INCHI_T_NUM_MOVABLE has not been established, ignore them)
    1162                 :             :         c(1)   = canonical number of the first atom in the t-group
    1163                 :             :         ...
    1164                 :             :         c(n-1) = canonical number of the last atom in the t-group
    1165                 :             : 
    1166                 :             : ****************************************************************************/
    1167                 :          56 : int MakeTautString( AT_NUMB          *LinearCT,
    1168                 :             :                     int              nLenCT,
    1169                 :             :                     int              bAddDelim,
    1170                 :             :                     INCHI_IOS_STRING *strbuf,
    1171                 :             :                     int              nCtMode,
    1172                 :             :                     int              *bOverflow )
    1173                 :             : {
    1174                 :             :     /*  produce output string; */
    1175                 :          56 :     int nUsedLength0 = 0, nLen = 0, len, i, bOvfl = *bOverflow;
    1176                 :             :     char szValue[2048];
    1177                 :             :     const char *p;
    1178                 :             :     int   nValue, nGroupLen, iGroupOutputCount, bCompressed;
    1179                 :             :     /*  make tautomer string */
    1180   [ +  +  +  -  :          56 :     if (!nLenCT || !LinearCT || !*LinearCT)
                   +  - ]
    1181                 :             :     {
    1182                 :          56 :         return nLen;
    1183                 :             :     }
    1184                 :             : 
    1185                 :           0 :     nUsedLength0 = strbuf->nUsedLength;
    1186                 :             : 
    1187                 :           0 :     bCompressed = ( nCtMode & CT_MODE_ABC_NUMBERS );
    1188   [ #  #  #  #  :           0 :     if (!bCompressed && !bOvfl && bAddDelim)
                   #  # ]
    1189                 :             :     {
    1190                 :           0 :         inchi_strbuf_printf( strbuf, "%s", COMMA_EXTRA_SPACE );
    1191                 :             :         /*if ( nLen_szLinearCT > 1+LEN_EXTRA_SPACE ) {
    1192                 :             :             strcpy( szLinearCT, COMMA_EXTRA_SPACE);
    1193                 :             :             nLen += 1+LEN_EXTRA_SPACE;
    1194                 :             :         } else {
    1195                 :             :             bOvfl = 1;
    1196                 :             :         }*/
    1197                 :             :     }
    1198                 :           0 :     LinearCT++; /*  bypass number of tautomeric groups */
    1199                 :           0 :     nLenCT--;
    1200                 :             : 
    1201         [ #  # ]:           0 :     if (!bOvfl)
    1202                 :             :     {
    1203         [ #  # ]:           0 :         for (i = nGroupLen = iGroupOutputCount = 0; i < nLenCT/* && nLen < nLen_szLinearCT*/; i++)
    1204                 :             :         {
    1205                 :           0 :             nValue = (int) LinearCT[i];
    1206         [ #  # ]:           0 :             if (nGroupLen == iGroupOutputCount)
    1207                 :             :             {
    1208                 :           0 :                 nGroupLen = nValue;
    1209                 :           0 :                 iGroupOutputCount = 0;
    1210                 :             :                 /* group delimiter (uncompressed) */
    1211         [ #  # ]:           0 :                 if (!bCompressed)
    1212                 :             :                 {
    1213         [ #  # ]:           0 :                     if (!i)
    1214                 :             :                     {
    1215                 :           0 :                         strcpy( szValue, "(" );
    1216                 :           0 :                         len = 1;
    1217                 :             :                     }
    1218                 :             :                     else
    1219                 :             :                     {
    1220                 :           0 :                         strcpy( szValue, ")(" );
    1221                 :           0 :                         len = 2;
    1222                 :             :                     }
    1223                 :             :                 }
    1224                 :             :                 else
    1225                 :             :                 {
    1226                 :           0 :                     len = 0;
    1227                 :             :                 }
    1228                 :             :             }
    1229                 :             :             else
    1230                 :             :             {
    1231   [ #  #  #  # ]:           0 :                 if (bCompressed && iGroupOutputCount >= INCHI_T_NUM_MOVABLE)
    1232                 :             :                 {
    1233                 :             :                     /*  compressed canon number in Abc */
    1234                 :           0 :                     len = MakeAbcNumber( szValue, ( int )sizeof( szValue ), NULL, nValue );
    1235                 :           0 :                     iGroupOutputCount++;
    1236                 :             :                 }
    1237                 :             :                 else
    1238                 :             :                 {
    1239                 :             :                     /*  always output number of hydrogen atoms as a decimal */
    1240                 :             :                     /*  output leading space if: */
    1241                 :             :                     /*  (a) this is the first output value in compressed mode (i==1 && bCompressed) */
    1242                 :             :                     /*  (b) this is not the first output value in non-compressed mode ( iGroupOutputCount && !bCompressed) */
    1243         [ #  # ]:           0 :                     if (bCompressed)
    1244                 :             :                     {
    1245                 :           0 :                         p = NULL;
    1246                 :           0 :                         len = 0;
    1247   [ #  #  #  # ]:           0 :                         switch (iGroupOutputCount)
    1248                 :             :                         {
    1249                 :           0 :                             case 0:
    1250         [ #  # ]:           0 :                                 len = MakeDecNumber( szValue, ( int )sizeof( szValue ), ( i == 1 ) ? ITEM_DELIMETER : NULL, nValue );
    1251                 :           0 :                                 break;
    1252                 :           0 :                             case 1:
    1253                 :           0 :                                 p = "-";
    1254                 :           0 :                                 break;
    1255                 :           0 :                             case 2:
    1256                 :           0 :                                 p = "+";
    1257                 :           0 :                                 break;
    1258                 :             :                         }
    1259         [ #  # ]:           0 :                         if (p)
    1260                 :             :                         {
    1261      [ #  #  # ]:           0 :                             switch (nValue)
    1262                 :             :                             {
    1263                 :           0 :                                 case 0:
    1264                 :           0 :                                     len = 0;
    1265                 :           0 :                                     break;
    1266                 :           0 :                                 case 1:
    1267                 :           0 :                                     strcpy(szValue, p);
    1268                 :           0 :                                     len = (int) strlen( szValue );
    1269                 :           0 :                                     break;
    1270                 :           0 :                                 default:
    1271                 :           0 :                                     len = MakeDecNumber( szValue, ( int )sizeof( szValue ), p, nValue );
    1272                 :           0 :                                     break;
    1273                 :             :                             }
    1274                 :             :                         }
    1275                 :             :                     }
    1276                 :             :                     else
    1277                 :             :                     {
    1278         [ #  # ]:           0 :                         if (iGroupOutputCount >= INCHI_T_NUM_MOVABLE)
    1279                 :             :                         {
    1280                 :             :                             /*  canonical number of the atom in the tautomeric group */
    1281                 :           0 :                             len = MakeDecNumber( szValue, ( int )sizeof( szValue ), ITEM_DELIMETER, nValue );
    1282                 :             :                         }
    1283                 :             :                         else
    1284                 :             :                         {
    1285                 :           0 :                             p = NULL;
    1286                 :           0 :                             len = 0;
    1287         [ #  # ]:           0 :                             if (nValue)
    1288                 :             :                             {
    1289   [ #  #  #  # ]:           0 :                                 switch (iGroupOutputCount)
    1290                 :             :                                 {
    1291                 :           0 :                                     case 0:
    1292                 :           0 :                                         p = "H";
    1293                 :           0 :                                         break;
    1294                 :           0 :                                     case 1:
    1295                 :           0 :                                         p = "-";
    1296                 :           0 :                                         break;
    1297                 :           0 :                                     case 2:
    1298                 :           0 :                                         p = "+";
    1299                 :           0 :                                         break;
    1300                 :             :                                 }
    1301         [ #  # ]:           0 :                                 if (p)
    1302                 :             :                                 {
    1303                 :             :                                     /*  number of hydrogens */
    1304         [ #  # ]:           0 :                                     if (nValue == 1)
    1305                 :             :                                     {
    1306                 :           0 :                                         strcpy(szValue, p);
    1307                 :           0 :                                         len = (int) strlen( szValue );
    1308                 :             :                                     }
    1309                 :             :                                     else
    1310                 :             :                                     {
    1311                 :           0 :                                         len = MakeDecNumber( szValue, ( int )sizeof( szValue ), p, nValue );
    1312                 :             :                                     }
    1313                 :             :                                 }
    1314                 :             :                             }
    1315                 :             :                         }
    1316                 :             :                     }
    1317                 :           0 :                     iGroupOutputCount++;
    1318                 :             :                 }
    1319                 :             :             }
    1320                 :             : 
    1321         [ #  # ]:           0 :             if (len > 0)
    1322                 :             :             {
    1323                 :           0 :                 inchi_strbuf_printf( strbuf, "%s", szValue );
    1324                 :             :             }
    1325                 :             :             /*if ( 0 <= len && nLen+len < nLen_szLinearCT ) {
    1326                 :             :                 if ( len ) {
    1327                 :             :                     strcpy( szLinearCT+nLen, szValue );
    1328                 :             :                     nLen += len;
    1329                 :             :                 }
    1330                 :             :             } else {
    1331                 :             :                 bOvfl = 1;
    1332                 :             :                 break;
    1333                 :             :             }*/
    1334                 :             :         }
    1335                 :             : 
    1336   [ #  #  #  #  :           0 :         if (!bOvfl && !bCompressed && i)
                   #  # ]
    1337                 :             :         {
    1338                 :           0 :             inchi_strbuf_printf( strbuf, ")" );
    1339                 :             :             /*if ( nLen + 1 < nLen_szLinearCT ) {
    1340                 :             :                 strcpy( szLinearCT+nLen, ")" );
    1341                 :             :                 nLen ++;
    1342                 :             :             } else {
    1343                 :             :                 bOvfl = 1;
    1344                 :             :             }*/
    1345                 :             :         }
    1346                 :             :     }
    1347                 :           0 :     *bOverflow |= bOvfl;
    1348                 :             : 
    1349                 :           0 :     nLen = strbuf->nUsedLength - nUsedLength0;
    1350                 :             : 
    1351                 :           0 :     return nLen;
    1352                 :             : }
    1353                 :             : 
    1354                 :             : 
    1355                 :             : /****************************************************************************
    1356                 :             :     MakeCRVString( ... )
    1357                 :             : 
    1358                 :             :     nCtMode =    0: full
    1359                 :             :                 2: compressed CT
    1360                 :             :                 22+3s3:  22=canon. number; +3=charge; s=singlet (d=doublet, t=triplet, s is omitted if valence=0), 3 = valence
    1361                 :             :                 22+3.3, (charge, valence) 22.3 (valence) 22t3 (triplet, valence)
    1362                 :             :                 Ab+3t4:  Ab=canon. number; +3=charge or "." t=triplet (or s, d), 4=valence
    1363                 :             : ****************************************************************************/
    1364                 :           4 : int MakeCRVString( ORIG_INFO        *OrigInfo,
    1365                 :             :                    int              nLenCT,
    1366                 :             :                    int              bAddDelim,
    1367                 :             :                    INCHI_IOS_STRING *strbuf,
    1368                 :             :                    int              nCtMode,
    1369                 :             :                    int              *bOverflow )
    1370                 :             : {
    1371                 :             :     /*  produce output string; */
    1372                 :           4 :     int nUsedLength0 = 0, nLen = 0, len, k, bAbcNumbers;
    1373                 :           4 :     int bOvfl = *bOverflow;
    1374                 :           4 :     char szValue[2048] = { 0 };
    1375                 :           4 :     int  bNext = 0;
    1376                 :           4 :     bAbcNumbers = ( nCtMode & CT_MODE_ABC_NUMBERS );
    1377                 :             : 
    1378                 :           4 :     nUsedLength0 = strbuf->nUsedLength;
    1379                 :             : 
    1380                 :             :     /*  add connection table string */
    1381   [ +  -  -  + ]:           4 :     if (!bOvfl && bAddDelim)
    1382                 :             :     {
    1383                 :           0 :         inchi_strbuf_printf( strbuf, ", " );
    1384                 :             :         /*if ( nLen_szLinearCT > 2 ) {
    1385                 :             :             strcpy( szLinearCT, ", " );
    1386                 :             :             nLen += 2;
    1387                 :             :         } else {
    1388                 :             :             bOvfl = 1;
    1389                 :             :         }*/
    1390                 :             :     }
    1391                 :             : 
    1392   [ +  -  +  + ]:          25 :     for (k = 0; !bOvfl && k < nLenCT/* && nLen < nLen_szLinearCT*/; k++)
    1393                 :             :     {
    1394                 :             :         /*  find the next non-empty entry */
    1395   [ +  +  +  -  :          21 :         if (OrigInfo[k].cCharge || OrigInfo[k].cRadical || OrigInfo[k].cUnusualValence)
                   +  + ]
    1396                 :             :         {
    1397         [ -  + ]:           6 :             if (bAbcNumbers)
    1398                 :             :             {
    1399                 :             :                 /*
    1400                 :             :                 3 items: Ad+3d4 (canon. numb=Ad, charge=+3, doublet, valence = 4
    1401                 :             :                 2 items: Ad.d4  Ad+3.4  Ad+3d
    1402                 :             :                 1 item:  Ad+3   Ad.d     Ad4
    1403                 :             : 
    1404                 :             :                 dot output before radical: no charge, radical is present
    1405                 :             :                 dot before valence:        charge is present, no radical, valence is present
    1406                 :             :                 */
    1407                 :           0 :                 len = MakeAbcNumber( szValue, ( int )sizeof( szValue ), NULL, k + 1 );
    1408                 :             : 
    1409                 :             :                 /* charge */
    1410         [ #  # ]:           0 :                 if (OrigInfo[k].cCharge)
    1411                 :             :                 {
    1412         [ #  # ]:           0 :                     if (OrigInfo[k].cCharge > 0)
    1413                 :             :                     {
    1414                 :           0 :                         len += MakeDecNumber( szValue + len, ( int )sizeof( szValue ) - len, "+", OrigInfo[k].cCharge );
    1415                 :             :                     }
    1416                 :             :                     else
    1417                 :             :                     {
    1418                 :           0 :                         len += MakeDecNumber( szValue + len, ( int )sizeof( szValue ) - len, NULL, OrigInfo[k].cCharge );
    1419                 :             :                     }
    1420                 :             :                 }
    1421                 :             :                 /* radical */
    1422         [ #  # ]:           0 :                 if (OrigInfo[k].cRadical)
    1423                 :             :                 {
    1424         [ #  # ]:           0 :                     if (!OrigInfo[k].cCharge)
    1425                 :             :                     {
    1426         [ #  # ]:           0 :                         if (len >= 2047) /* djb-rwth: fixing coverity ID #499515 */
    1427                 :             :                         {
    1428                 :           0 :                             len = 2047;
    1429                 :           0 :                             goto early_break;
    1430                 :             :                         }
    1431         [ #  # ]:           0 :                         else if (len < 0) /* djb-rwth: fixing coverity ID #500400 */
    1432                 :             :                         {
    1433                 :           0 :                             len = 0;
    1434                 :           0 :                             goto early_break;
    1435                 :             :                         }
    1436                 :             :                         else
    1437                 :             :                         {
    1438                 :           0 :                             szValue[len] = '.';
    1439                 :           0 :                             len++;
    1440                 :             :                         }
    1441                 :             :                     }
    1442         [ #  # ]:           0 :                     if (len >= 2047) /* djb-rwth: fixing coverity ID #499515 */
    1443                 :             :                     {
    1444                 :           0 :                         len = 2047;
    1445                 :           0 :                         goto early_break;
    1446                 :             :                     }
    1447         [ #  # ]:           0 :                     else if (len < 0) /* djb-rwth: fixing coverity ID #500382 */
    1448                 :             :                     {
    1449                 :           0 :                         len = 0;
    1450                 :           0 :                         goto early_break;
    1451                 :             :                     }
    1452                 :             :                     else
    1453                 :             :                     {
    1454      [ #  #  # ]:           0 :                         switch (OrigInfo[k].cRadical)
    1455                 :             :                         {
    1456                 :           0 :                             case 1:
    1457                 :             :                                 /* djb-rwth: fixing coverity ID #499515 -- false positive, len tested for overflow */
    1458                 :           0 :                                 szValue[len] = 'd';
    1459                 :           0 :                                 len++;
    1460                 :           0 :                                 break;
    1461                 :           0 :                             case 2:
    1462                 :           0 :                                 szValue[len] = 't';
    1463                 :           0 :                                 len++;
    1464                 :           0 :                                 break;
    1465                 :           0 :                             default:
    1466                 :           0 :                                 szValue[len] = 'u';
    1467                 :           0 :                                 len++;
    1468                 :           0 :                                 break;
    1469                 :             :                         }
    1470                 :             :                     }
    1471                 :             :                 }
    1472                 :             :                 /* valence */
    1473         [ #  # ]:           0 :                 if (OrigInfo[k].cUnusualValence)
    1474                 :             :                 {
    1475   [ #  #  #  # ]:           0 :                     if (OrigInfo[k].cCharge && !OrigInfo[k].cRadical)
    1476                 :             :                     {
    1477         [ #  # ]:           0 :                         if (len >= 2047) /* djb-rwth: fixing coverity ID #499515 */
    1478                 :             :                         {
    1479                 :           0 :                             len = 2047;
    1480                 :           0 :                             goto early_break;
    1481                 :             :                         }
    1482         [ #  # ]:           0 :                         else if (len < 0) /* djb-rwth: fixing coverity ID #500382 */
    1483                 :             :                         {
    1484                 :           0 :                             len = 0;
    1485                 :           0 :                             goto early_break;
    1486                 :             :                         }
    1487                 :             :                         else
    1488                 :             :                         {
    1489                 :           0 :                             szValue[len] = '.';
    1490                 :           0 :                             len++;
    1491                 :             :                         }
    1492                 :             :                     }
    1493                 :           0 :                     len += MakeDecNumber( szValue + len, ( int )sizeof( szValue ) - len, NULL, OrigInfo[k].cUnusualValence );
    1494                 :             :                 }
    1495                 :             :             }
    1496                 :             :             else
    1497                 :             :             {
    1498                 :             :                 /*
    1499                 :             :                     3 items: 22+3d4 (canon. numb=22, charge=+3, doublet, valence = 4
    1500                 :             :                     2 items: 22d4  22+3.4  22+3d
    1501                 :             :                     1 item:  22+3  22d     22.4
    1502                 :             : 
    1503                 :             :                     dot output before valence:
    1504                 :             :                                 (a) charge,    no radical, valence
    1505                 :             :                                 (b) no charge, no radical, valence
    1506                 :             :                     that is, whenever valence is present and no radical
    1507                 :             :                 */
    1508         [ +  + ]:           6 :                 len = MakeDecNumber( szValue, ( int )sizeof( szValue ), bNext ? ITEM_DELIMETER : NULL, k + 1 );
    1509                 :             :                 /* charge */
    1510         [ +  + ]:           6 :                 if (OrigInfo[k].cCharge)
    1511                 :             :                 {
    1512         [ -  + ]:           3 :                     if (OrigInfo[k].cCharge > 0)
    1513                 :             :                     {
    1514                 :           0 :                         len += MakeDecNumber( szValue + len, ( int )sizeof( szValue ) - len, "+", OrigInfo[k].cCharge );
    1515                 :             :                     }
    1516                 :             :                     else
    1517                 :             :                     {
    1518                 :           3 :                         len += MakeDecNumber( szValue + len, ( int )sizeof( szValue ) - len, NULL, OrigInfo[k].cCharge );
    1519                 :             :                     }
    1520                 :             :                 }
    1521                 :             :                 /* radical */
    1522         [ -  + ]:           6 :                 if (OrigInfo[k].cRadical)
    1523                 :             :                 {
    1524         [ #  # ]:           0 :                     if (len >= 2047) /* djb-rwth: fixing coverity ID #499515 */
    1525                 :             :                     {
    1526                 :           0 :                         len = 2047;
    1527                 :           0 :                         goto early_break;
    1528                 :             :                     }
    1529         [ #  # ]:           0 :                     else if (len < 0) /* djb-rwth: fixing coverity ID #500382 */
    1530                 :             :                     {
    1531                 :           0 :                         len = 0;
    1532                 :           0 :                         goto early_break;
    1533                 :             :                     }
    1534                 :             :                     else
    1535                 :             :                     {
    1536      [ #  #  # ]:           0 :                         switch (OrigInfo[k].cRadical)
    1537                 :             :                         {
    1538                 :           0 :                             case 1:
    1539                 :           0 :                                 szValue[len] = 'd'; /* djb-rwth: GCC 14 false positive */
    1540                 :           0 :                                 len++;
    1541                 :           0 :                                 break;
    1542                 :           0 :                             case 2:
    1543                 :           0 :                                 szValue[len] = 't';
    1544                 :           0 :                                 len++;
    1545                 :           0 :                                 break;
    1546                 :           0 :                             default:
    1547                 :           0 :                                 szValue[len] = 'u';
    1548                 :           0 :                                 len++;
    1549                 :           0 :                                 break;
    1550                 :             :                         }
    1551                 :             :                     }
    1552                 :             :                 }
    1553                 :             :                 /* valence */
    1554         [ +  + ]:           6 :                 if (OrigInfo[k].cUnusualValence)
    1555                 :             :                 {
    1556         [ +  - ]:           3 :                     if (!OrigInfo[k].cRadical)
    1557                 :             :                     {
    1558         [ -  + ]:           3 :                         if (len >= 2047) /* djb-rwth: fixing coverity ID #499515 */
    1559                 :             :                         {
    1560                 :           0 :                             len = 2047;
    1561                 :           0 :                             goto early_break;
    1562                 :             :                         }
    1563         [ -  + ]:           3 :                         else if (len < 0) /* djb-rwth: fixing coverity ID #500382 */
    1564                 :             :                         {
    1565                 :           0 :                             len = 0;
    1566                 :           0 :                             goto early_break;
    1567                 :             :                         }
    1568                 :             :                         else
    1569                 :             :                         {
    1570                 :           3 :                             szValue[len] = '.';
    1571                 :           3 :                             len++;
    1572                 :             :                         }
    1573                 :             :                     }
    1574                 :           3 :                     len += MakeDecNumber(szValue + len, (int)sizeof(szValue) - len, NULL, OrigInfo[k].cUnusualValence);
    1575                 :             :                 }
    1576                 :             :             }
    1577                 :             :         }
    1578                 :             :         else
    1579                 :             :         {
    1580                 :          15 :             len = 0;
    1581                 :             :         }
    1582                 :             : 
    1583                 :          21 : early_break:
    1584         [ +  + ]:          21 :         if (len)
    1585                 :             :         {
    1586                 :           6 :             szValue[len] = '\0';
    1587                 :           6 :             inchi_strbuf_printf( strbuf, "%s", szValue );
    1588                 :           6 :             bNext++;
    1589                 :           6 :             szValue[0] = '\0';
    1590                 :             :         }
    1591                 :             :         /*if ( len && nLen+len < nLen_szLinearCT ) {
    1592                 :             :             strcpy( szLinearCT+nLen, szValue );
    1593                 :             :             nLen += len;
    1594                 :             :             bNext ++;
    1595                 :             :         } else
    1596                 :             :         if ( len ) {
    1597                 :             :             bOvfl = 1;
    1598                 :             :             break;
    1599                 :             :         }*/
    1600                 :             :     }
    1601                 :           4 :     *bOverflow |= bOvfl;
    1602                 :             : 
    1603                 :           4 :     nLen = strbuf->nUsedLength - nUsedLength0;
    1604                 :             : 
    1605                 :           4 :     return nLen;
    1606                 :             : }
    1607                 :             : 
    1608                 :             : 
    1609                 :             : /****************************************************************************
    1610                 :             :     MakeEquString( ... )
    1611                 :             : 
    1612                 :             :     nCtMode =   0: full
    1613                 :             :                 2: compressed CT
    1614                 :             : ****************************************************************************/
    1615                 :          15 : int MakeEquString( AT_NUMB          *LinearCT,
    1616                 :             :                    int              nLenCT,
    1617                 :             :                    int              bAddDelim,
    1618                 :             :                    INCHI_IOS_STRING *strbuf,
    1619                 :             :                    int              nCtMode,
    1620                 :             :                    int              *bOverflow )
    1621                 :             : {
    1622                 :             :     /*  produce output string; */
    1623                 :          15 :     int nUsedLength0 = 0, nLen = 0, len, i, k, bAbcNumbers; /* djb-rwth: ignoring LLVM warning: variable used to store function return value */
    1624                 :          15 :     int bOvfl = *bOverflow;
    1625                 :             :     char szValue[2048];
    1626                 :          15 :     int  bNext = 0;
    1627                 :             : 
    1628                 :          15 :     nUsedLength0 = strbuf->nUsedLength;
    1629                 :             : 
    1630                 :          15 :     bAbcNumbers = ( nCtMode & CT_MODE_ABC_NUMBERS );
    1631                 :             :     /*  add connection table string */
    1632   [ +  -  -  + ]:          15 :     if (!bOvfl && bAddDelim)
    1633                 :             :     {
    1634                 :           0 :         inchi_strbuf_printf( strbuf, ", " );
    1635                 :             :         /*if ( nLen_szLinearCT > 2 ) {
    1636                 :             :             strcpy( szLinearCT, ", " );
    1637                 :             :             nLen += 2;
    1638                 :             :         } else {
    1639                 :             :             bOvfl = 1;
    1640                 :             :         }*/
    1641                 :             :     }
    1642   [ +  -  +  + ]:         138 :     for (k = 0; !bOvfl && k < nLenCT/* && nLen < nLen_szLinearCT*/; k++)
    1643                 :             :     {
    1644                 :             :         /*  find the first equivalence number */
    1645         [ +  + ]:         123 :         if (k != (int) LinearCT[k] - 1)
    1646                 :             :         {
    1647                 :          92 :             continue;
    1648                 :             :         }
    1649         [ +  + ]:         250 :         for (i = k; i < nLenCT/* && nLen < nLen_szLinearCT*/; i++)
    1650                 :             :         {
    1651         [ +  + ]:         219 :             if (k != (int) LinearCT[i] - 1)
    1652                 :             :             {
    1653                 :         145 :                 continue;
    1654                 :             :             }
    1655                 :             :             /*  equivalence number: a minimal canon_number out of a group of equivalent atoms */
    1656                 :             :             /*  is at canon_number-1 position of each equivalent atom.  */
    1657         [ -  + ]:          74 :             if (bAbcNumbers)
    1658                 :             :             {
    1659   [ #  #  #  # ]:           0 :                 len = MakeAbcNumber( szValue, ( int )sizeof( szValue ), ( i == k && bNext ) ? ITEM_DELIMETER : NULL, i + 1 ); /* djb-rwth: ignoring LLVM warning: possible presence of global variables */
    1660                 :             :             }
    1661                 :             :             else
    1662                 :             :             {
    1663         [ +  + ]:          74 :                 len = MakeDecNumber( szValue, ( int )sizeof( szValue ), ( i == k ) ? "(" : ITEM_DELIMETER, i + 1 ); /* djb-rwth: ignoring LLVM warning: possible presence of global variables */
    1664                 :             :             }
    1665                 :          74 :             inchi_strbuf_printf( strbuf, "%s", szValue );
    1666                 :          74 :             bNext++;
    1667                 :             :             /*if ( 0 <= len && nLen+len < nLen_szLinearCT ) {
    1668                 :             :                 strcpy( szLinearCT+nLen, szValue );
    1669                 :             :                 nLen += len;
    1670                 :             :                 bNext ++;
    1671                 :             :             } else
    1672                 :             :             if ( 0 > len ) {
    1673                 :             :                 bOvfl = 1;
    1674                 :             :                 break;
    1675                 :             :             }*/
    1676                 :             :         }
    1677                 :          31 :         inchi_strbuf_printf( strbuf, ")" );
    1678                 :             :         /*if ( !bOvfl && !bAbcNumbers ) {
    1679                 :             :             if ( nLen + 2 < nLen_szLinearCT ) {
    1680                 :             :                 strcpy( szLinearCT+nLen, ")" );
    1681                 :             :                 nLen ++;
    1682                 :             :             } else {
    1683                 :             :                 bOvfl = 1;
    1684                 :             :             }
    1685                 :             :         }*/
    1686                 :             :     }
    1687                 :          15 :     *bOverflow |= bOvfl;
    1688                 :             : 
    1689                 :          15 :     nLen = strbuf->nUsedLength - nUsedLength0;
    1690                 :             : 
    1691                 :          15 :     return nLen;
    1692                 :             : }
    1693                 :             : 
    1694                 :             : 
    1695                 :             : /****************************************************************************
    1696                 :             :     MakeIsoAtomString( ... )
    1697                 :             : 
    1698                 :             :     nCtMode =    0: full
    1699                 :             :                  2: compressed CT
    1700                 :             : ****************************************************************************/
    1701                 :           0 : int MakeIsoAtomString( INChI_IsotopicAtom *IsotopicAtom,
    1702                 :             :                        int                nNumberOfIsotopicAtoms,
    1703                 :             :                        INCHI_IOS_STRING   *strbuf,
    1704                 :             :                        int                nCtMode,
    1705                 :             :                        int                *bOverflow )
    1706                 :             : {
    1707                 :             :     /*  produce output string; */
    1708                 :           0 :     int nUsedLength0 = 0, nLen = 0, len, tot_len, ret, i, j, bOvfl = *bOverflow;
    1709                 :             :     char szValue[2048];
    1710                 :             :     char *p;
    1711                 :             :     int   nValue;
    1712                 :           0 :     int   bAbcNumbers = ( nCtMode & CT_MODE_ABC_NUMBERS );
    1713                 :             :     static const char letter[] = "itdh";
    1714                 :             :     static const char *h[] = { "T", "D", "H" };
    1715                 :             :     static const char *sign[] = { "-", "+" };
    1716                 :             : 
    1717                 :           0 :     nUsedLength0 = strbuf->nUsedLength;
    1718                 :             : 
    1719         [ #  # ]:           0 :     if (!bOvfl)
    1720                 :             :     {
    1721         [ #  # ]:           0 :         for (i = 0; i < nNumberOfIsotopicAtoms/* && nLen < nLen_szLinearCT*/; i++)
    1722                 :             :         {
    1723                 :           0 :             p = szValue;
    1724                 :           0 :             tot_len = 0;
    1725         [ #  # ]:           0 :             for (j = 0; j < 5; j++)
    1726                 :             :             {
    1727                 :           0 :                 len = 0;
    1728   [ #  #  #  #  :           0 :                 switch (j)
                   #  # ]
    1729                 :             :                 {
    1730                 :           0 :                     case 0:
    1731                 :           0 :                         nValue = (int) IsotopicAtom[i].nAtomNumber;
    1732                 :           0 :                         break;
    1733                 :           0 :                     case 1:
    1734                 :           0 :                         nValue = (int) IsotopicAtom[i].nIsoDifference;
    1735                 :           0 :                         break;
    1736                 :           0 :                     case 2:
    1737                 :           0 :                         nValue = (int) IsotopicAtom[i].nNum_T;
    1738                 :           0 :                         break;
    1739                 :           0 :                     case 3:
    1740                 :           0 :                         nValue = (int) IsotopicAtom[i].nNum_D;
    1741                 :           0 :                         break;
    1742                 :           0 :                     case 4:
    1743                 :           0 :                         nValue = (int) IsotopicAtom[i].nNum_H;
    1744                 :           0 :                         break;
    1745                 :             :                 }
    1746         [ #  # ]:           0 :                 if (!j)
    1747                 :             :                 {
    1748                 :             :                     /*  atom canonical number */
    1749   [ #  #  #  # ]:           0 :                     len = ( bAbcNumbers ? MakeAbcNumber : MakeDecNumber )
    1750                 :             :                         ( p, ( int )sizeof( szValue ) - tot_len,
    1751         [ #  # ]:           0 :                           bAbcNumbers ? NULL : ( i ? ITEM_DELIMETER : EXTRA_SPACE ), nValue
    1752                 :             :                         );
    1753                 :             :                 }
    1754                 :             :                 else
    1755                 :             :                 {
    1756         [ #  # ]:           0 :                     if (bAbcNumbers)
    1757                 :             :                     {
    1758                 :             :                         /*  Abc output */
    1759      [ #  #  # ]:           0 :                         switch (j)
    1760                 :             :                         {
    1761                 :           0 :                             case 1: /* nIsoDifference */
    1762                 :           0 :                                 len = MakeDecNumber( p, ( int )sizeof( szValue ) - tot_len, NULL, nValue );
    1763                 :           0 :                                 break;
    1764                 :           0 :                             case 2: /* nNum_T */
    1765                 :             :                             case 3: /* nNum_D */
    1766                 :             :                             case 4: /* nNum_H */
    1767         [ #  # ]:           0 :                                 if (nValue)
    1768                 :             :                                 {
    1769         [ #  # ]:           0 :                                     if (( int )sizeof( szValue ) - tot_len > 1)
    1770                 :             :                                     {
    1771                 :           0 :                                         p[len++] = letter[j - 1];
    1772         [ #  # ]:           0 :                                         if (1 == nValue)
    1773                 :             :                                         {
    1774                 :           0 :                                             p[len] = '\0';
    1775                 :             :                                         }
    1776                 :             :                                         else
    1777                 :             :                                         {
    1778                 :           0 :                                             ret = MakeDecNumber( p + len, ( int )sizeof( szValue ) - tot_len - len, NULL, nValue );
    1779         [ #  # ]:           0 :                                             len = ( ret >= 0 ) ? len + ret : ret;
    1780                 :             :                                         }
    1781                 :             :                                     }
    1782                 :             :                                     else
    1783                 :             :                                     {
    1784                 :           0 :                                         len = -1; /* overflow */
    1785                 :             :                                     }
    1786                 :             :                                 }
    1787                 :             :                         }
    1788                 :             :                     }
    1789                 :             :                     else
    1790                 :             :                     {
    1791         [ #  # ]:           0 :                         if (nValue)
    1792                 :             :                         {
    1793         [ #  # ]:           0 :                             if (j == 1)
    1794                 :             :                             {
    1795                 :             :                                 /*  Decimal output */
    1796                 :             :                                 /*  signed isotopic mass difference */
    1797                 :           0 :                                 int subtract = ( nValue > 0 );
    1798                 :             :                                 /*  (n = mass difference) > 0 corresponds to nValue = n+1 */
    1799                 :             :                                 /*  subtract 1 from it so that mass difference for 35Cl or 12C is zero */
    1800                 :           0 :                                 len = MakeDecNumber( p, ( int )sizeof( szValue ) - tot_len, sign[nValue >= 0], abs( nValue - subtract ) );
    1801                 :             :                             }
    1802                 :             :                             else
    1803                 :             :                             {
    1804                 :             :                                 /*  hydrogen isotope */
    1805         [ #  # ]:           0 :                                 if (nValue != 1)
    1806                 :             :                                 {
    1807                 :           0 :                                     len = MakeDecNumber( p, ( int )sizeof( szValue ) - tot_len, h[j - 2], nValue );
    1808                 :             :                                 }
    1809                 :             :                                 else
    1810                 :             :                                 {
    1811         [ #  # ]:           0 :                                     if (( int )sizeof( szValue ) - tot_len > 1)
    1812                 :             :                                     {
    1813                 :           0 :                                         strcpy(p, h[j - 2]);
    1814                 :           0 :                                         len = 1;
    1815                 :             :                                     }
    1816                 :             :                                     else
    1817                 :             :                                     {
    1818                 :           0 :                                         len = -1; /*  overflow */
    1819                 :             :                                     }
    1820                 :             :                                 }
    1821                 :             :                             }
    1822                 :             :                         }
    1823                 :             :                         else
    1824                 :             :                         {
    1825                 :           0 :                             continue; /*  do not write zeroes */
    1826                 :             :                         }
    1827                 :             :                     }
    1828                 :             :                 }
    1829         [ #  # ]:           0 :                 if (len < 0)
    1830                 :             :                 {
    1831                 :           0 :                     bOvfl = 1;
    1832                 :           0 :                     break;
    1833                 :             :                 }
    1834                 :           0 :                 tot_len += len;
    1835                 :           0 :                 p += len;
    1836                 :             :             }
    1837                 :           0 :             inchi_strbuf_printf( strbuf, "%s", szValue );
    1838                 :             :             /*if ( nLen+tot_len < nLen_szLinearCT )
    1839                 :             :             {
    1840                 :             :                 memcpy( szLinearCT+nLen, szValue, tot_len+1 );
    1841                 :             :                 nLen += tot_len;
    1842                 :             :             }
    1843                 :             :             else
    1844                 :             :             {
    1845                 :             :                 bOvfl = 1;
    1846                 :             :                 break;
    1847                 :             :             }*/
    1848                 :             :         }
    1849                 :             :     }
    1850                 :           0 :     *bOverflow |= bOvfl;
    1851                 :             : 
    1852                 :           0 :     nLen = strbuf->nUsedLength - nUsedLength0;
    1853                 :             : 
    1854                 :           0 :     return nLen;
    1855                 :             : }
    1856                 :             : 
    1857                 :             : 
    1858                 :             : /****************************************************************************/
    1859                 :           0 : int MakeIsoTautString( INChI_IsotopicTGroup *IsotopicTGroup,
    1860                 :             :                        int                  nNumberOfIsotopicTGroups,
    1861                 :             :                        INCHI_IOS_STRING     *strbuf,
    1862                 :             :                        int                  nCtMode,
    1863                 :             :                        int                  *bOverflow )
    1864                 :             : {
    1865                 :             :     /*  produce output string; */
    1866                 :           0 :     int nUsedLength0 = 0, nLen = 0, len, tot_len, i, j, bOvfl = *bOverflow;
    1867                 :             :     /* djb-rwth: removing redundant variables */
    1868                 :             :     char szValue[2048];
    1869                 :             :     char *p;
    1870                 :             :     int   nValue;
    1871                 :           0 :     int   bAbcNumbers = ( nCtMode & CT_MODE_ABC_NUMBERS );
    1872                 :             :     static const char letter[] = "tdh";
    1873                 :             :     static const char *h[] = { "T", "D", "H" };
    1874                 :             : 
    1875                 :           0 :     nUsedLength0 = strbuf->nUsedLength;
    1876                 :             : 
    1877                 :             :     /*  add connection table string */
    1878                 :             :     /* djb-rwth: removing redundant code */
    1879         [ #  # ]:           0 :     if (!bOvfl)
    1880                 :             :     {
    1881         [ #  # ]:           0 :         for (i = 0; i < nNumberOfIsotopicTGroups/* && nLen < nLen_szLinearCT*/; i++)
    1882                 :             :         {
    1883                 :           0 :             p = szValue;
    1884                 :           0 :             tot_len = 0;
    1885         [ #  # ]:           0 :             for (j = 0; j < 4; j++)
    1886                 :             :             {
    1887   [ #  #  #  #  :           0 :                 switch (j)
                      # ]
    1888                 :             :                 {
    1889                 :           0 :                     case 0:
    1890                 :           0 :                         nValue = (int) IsotopicTGroup[i].nTGroupNumber;
    1891                 :           0 :                         break;
    1892                 :           0 :                     case 1:
    1893                 :           0 :                         nValue = (int) IsotopicTGroup[i].nNum_T;
    1894                 :           0 :                         break;
    1895                 :           0 :                     case 2:
    1896                 :           0 :                         nValue = (int) IsotopicTGroup[i].nNum_D;
    1897                 :           0 :                         break;
    1898                 :           0 :                     case 3:
    1899                 :           0 :                         nValue = (int) IsotopicTGroup[i].nNum_H;
    1900                 :           0 :                         break;
    1901                 :             :                 }
    1902         [ #  # ]:           0 :                 if (!j)
    1903                 :             :                 {
    1904                 :             :                     /*  atom canonical number */
    1905   [ #  #  #  # ]:           0 :                     len = ( bAbcNumbers ? MakeAbcNumber : MakeDecNumber )
    1906                 :             :                         ( p, ( int )sizeof( szValue ) - tot_len,
    1907         [ #  # ]:           0 :                           bAbcNumbers ? NULL : ( i ? ITEM_DELIMETER : EXTRA_SPACE ),
    1908                 :             :                           nValue
    1909                 :             :                         );
    1910                 :             :                 }
    1911                 :             :                 else
    1912         [ #  # ]:           0 :                     if (nValue)
    1913                 :             :                     {
    1914         [ #  # ]:           0 :                         if (bAbcNumbers)
    1915                 :             :                         {
    1916                 :           0 :                             len = MakeDecNumber( p, ( int )sizeof( szValue ) - tot_len, NULL, nValue );
    1917         [ #  # ]:           0 :                             if (len > 0)
    1918                 :             :                             { /*  make sure overflow has not happened */
    1919         [ #  # ]:           0 :                                 if (( int )sizeof( szValue ) - tot_len - len > 1)
    1920                 :             :                                 {
    1921                 :           0 :                                     p[len++] = letter[j - 1];
    1922                 :           0 :                                     p[len] = '\0';
    1923                 :             :                                 }
    1924                 :             :                                 else
    1925                 :             :                                 {
    1926                 :           0 :                                     len = -1; /*  overflow */
    1927                 :             :                                 }
    1928                 :             :                             }
    1929                 :             :                         }
    1930                 :             :                         else
    1931                 :             :                         {
    1932                 :             :                             /*  hydrogen isotope */
    1933         [ #  # ]:           0 :                             if (nValue != 1)
    1934                 :             :                             {
    1935                 :           0 :                                 len = MakeDecNumber( p, ( int )sizeof( szValue ) - tot_len, h[j - 1], nValue );
    1936                 :             :                             }
    1937                 :             :                             else
    1938         [ #  # ]:           0 :                                 if (( int )sizeof( szValue ) - tot_len > 1)
    1939                 :             :                                 {
    1940                 :           0 :                                     strcpy(p, h[j - 1]);
    1941                 :           0 :                                     len = 1;
    1942                 :             :                                 }
    1943                 :             :                                 else
    1944                 :             :                                 {
    1945                 :           0 :                                     len = -1; /*  overflow */
    1946                 :             :                                 }
    1947                 :             :                         }
    1948                 :             :                     }
    1949                 :             :                     else
    1950                 :             :                     {
    1951                 :           0 :                         continue; /*  do not write zeroes */
    1952                 :             :                     }
    1953         [ #  # ]:           0 :                 if (len < 0)
    1954                 :             :                 {
    1955                 :           0 :                     bOvfl = 1;
    1956                 :           0 :                     break;
    1957                 :             :                 }
    1958                 :           0 :                 p += len;
    1959                 :           0 :                 tot_len += len;
    1960                 :             :             }
    1961                 :           0 :             inchi_strbuf_printf( strbuf, "%s", szValue );
    1962                 :             :             /*if ( nLen+tot_len < nLen_szLinearCT ) {
    1963                 :             :                 memcpy( szLinearCT+nLen, szValue, tot_len+1 );
    1964                 :             :                 nLen += tot_len;
    1965                 :             :             } else {
    1966                 :             :                 bOvfl = 1;
    1967                 :             :                 break;
    1968                 :             :             }*/
    1969                 :             :         }
    1970                 :             :     }
    1971                 :           0 :     *bOverflow |= bOvfl;
    1972                 :             : 
    1973                 :           0 :     nLen = strbuf->nUsedLength - nUsedLength0;
    1974                 :             : 
    1975                 :           0 :     return nLen;
    1976                 :             : }
    1977                 :             : 
    1978                 :             : 
    1979                 :             : /****************************************************************************/
    1980                 :           0 : int MakeIsoHString( int              num_iso_H[],
    1981                 :             :                     INCHI_IOS_STRING *strbuf,
    1982                 :             :                     int              nCtMode,
    1983                 :             :                     int              *bOverflow )
    1984                 :             : {
    1985                 :             :     /*  produce output string; */
    1986                 :           0 :     int nUsedLength0 = 0, nLen = 0, len, tot_len, j, bOvfl = *bOverflow;
    1987                 :             :     /* djb-rwth: removing redundant variables */
    1988                 :             :     char szValue[2048];
    1989                 :             :     char *p;
    1990                 :             :     int   nValue;
    1991                 :           0 :     int   bAbcNumbers = ( nCtMode & CT_MODE_ABC_NUMBERS );
    1992                 :             :     static const char letter[] = "tdh";
    1993                 :             :     static const char *h[] = { "T", "D", "H" };
    1994                 :             : 
    1995                 :           0 :     nUsedLength0 = strbuf->nUsedLength;
    1996                 :             : 
    1997                 :             :     /*  add connection table string */
    1998                 :             :     /* djb-rwth: removing redundant code */
    1999         [ #  # ]:           0 :     if (!bOvfl)
    2000                 :             :     {
    2001                 :           0 :         p = szValue;
    2002                 :           0 :         tot_len = 0;
    2003         [ #  # ]:           0 :         for (j = 1; j < 4; j++)
    2004                 :             :         {
    2005                 :           0 :             nValue = num_iso_H[NUM_H_ISOTOPES - j];/* j: 1=>T, 2=>D, 3=>1H */
    2006         [ #  # ]:           0 :             if (nValue)
    2007                 :             :             {
    2008         [ #  # ]:           0 :                 if (bAbcNumbers)
    2009                 :             :                 {
    2010                 :           0 :                     len = MakeDecNumber( p, ( int )sizeof( szValue ) - tot_len, NULL, nValue );
    2011         [ #  # ]:           0 :                     if (len > 0)
    2012                 :             :                     {
    2013                 :             :                         /*  make sure overflow has not happened */
    2014         [ #  # ]:           0 :                         if (( int )sizeof( szValue ) - tot_len - len > 1)
    2015                 :             :                         {
    2016                 :           0 :                             p[len++] = letter[j - 1];
    2017                 :           0 :                             p[len] = '\0';
    2018                 :             :                         }
    2019                 :             :                         else
    2020                 :             :                         {
    2021                 :           0 :                             len = -1; /*  overflow */
    2022                 :             :                         }
    2023                 :             :                     }
    2024                 :             :                 }
    2025                 :             :                 else
    2026                 :             :                 {
    2027                 :             :                     /*  hydrogen isotope */
    2028         [ #  # ]:           0 :                     if (nValue != 1)
    2029                 :             :                     {
    2030                 :           0 :                         len = MakeDecNumber( p, ( int )sizeof( szValue ) - tot_len, h[j - 1], nValue );
    2031                 :             :                     }
    2032                 :             :                     else
    2033                 :             :                     {
    2034         [ #  # ]:           0 :                         if (( int )sizeof( szValue ) - tot_len > 1)
    2035                 :             :                         {
    2036                 :           0 :                             strcpy(p, h[j - 1]);
    2037                 :           0 :                             len = 1;
    2038                 :             :                         }
    2039                 :             :                         else
    2040                 :             :                         {
    2041                 :           0 :                             len = -1; /*  overflow */
    2042                 :             :                         }
    2043                 :             :                     }
    2044                 :             :                 }
    2045                 :             :             }
    2046                 :             :             else
    2047                 :             :             {
    2048                 :           0 :                 continue; /*  do not write zeroes */
    2049                 :             :             }
    2050         [ #  # ]:           0 :             if (len < 0)
    2051                 :             :             {
    2052                 :           0 :                 bOvfl = 1;
    2053                 :           0 :                 break;
    2054                 :             :             }
    2055                 :           0 :             p += len;
    2056                 :           0 :             tot_len += len;
    2057                 :             :         }
    2058                 :           0 :         inchi_strbuf_printf( strbuf, "%s", szValue );
    2059                 :             :         /*if ( nLen+tot_len < nLen_szLinearCT ) {
    2060                 :             :             memcpy( szLinearCT+nLen, szValue, tot_len+1 );
    2061                 :             :             nLen += tot_len;
    2062                 :             :         } else {
    2063                 :             :             bOvfl = 1;
    2064                 :             :         }*/
    2065                 :             :     }
    2066                 :           0 :     *bOverflow |= bOvfl;
    2067                 :             : 
    2068                 :           0 :     nLen = strbuf->nUsedLength - nUsedLength0;
    2069                 :             : 
    2070                 :           0 :     return nLen;
    2071                 :             : }
    2072                 :             : 
    2073                 :             : 
    2074                 :             : /****************************************************************************/
    2075                 :          59 : int MakeStereoString( AT_NUMB          *at1,
    2076                 :             :                       AT_NUMB          *at2,
    2077                 :             :                       S_CHAR           *parity,
    2078                 :             :                       int              bAddDelim,
    2079                 :             :                       int              nLenCT,
    2080                 :             :                       INCHI_IOS_STRING *strbuf,
    2081                 :             :                       int              nCtMode,
    2082                 :             :                       int              *bOverflow )
    2083                 :             : {
    2084                 :             :     /*  produce output string; */
    2085                 :          59 :     int nUsedLength0 = 0, nLen = 0, len, tot_len, i, j, bOvfl = *bOverflow;
    2086                 :             :     char szValue[2048];
    2087                 :             :     char *p;
    2088                 :             :     int   nValue;
    2089                 :             :     static const char parity_char[] = "!-+u?";
    2090                 :             : 
    2091                 :          59 :     nUsedLength0 = strbuf->nUsedLength;
    2092                 :          59 :     bAddDelim = 0;
    2093                 :             : 
    2094         [ +  - ]:          59 :     if (!bOvfl)
    2095                 :             :     {
    2096         [ +  + ]:         274 :         for (i = 0; i < nLenCT/* && nLen < nLen_szLinearCT*/; i++)
    2097                 :             :         {
    2098                 :         215 :             p = szValue;
    2099                 :         215 :             tot_len = 0;
    2100         [ +  + ]:         860 :             for (j = 0; j < 3; j++)
    2101                 :             :             {
    2102   [ +  +  +  - ]:         645 :                 if (j == 0 && at1)
    2103                 :             :                 {
    2104                 :         215 :                     nValue = (int) at1[i];
    2105                 :             :                 }
    2106                 :             :                 else
    2107                 :             :                 {
    2108   [ +  +  -  + ]:         430 :                     if (j == 1 && at2)
    2109                 :             :                     {
    2110                 :           0 :                         nValue = (int) at2[i];
    2111                 :             :                     }
    2112                 :             :                     else
    2113                 :             :                     {
    2114   [ +  +  +  - ]:         430 :                         if (j == 2 && parity)
    2115                 :             :                         {
    2116                 :         215 :                             nValue = (int) parity[i];
    2117                 :             :                         }
    2118                 :             :                         else
    2119                 :             :                         {
    2120                 :         215 :                             continue;
    2121                 :             :                         }
    2122                 :             :                     }
    2123                 :             :                 }
    2124         [ -  + ]:         430 :                 if (nCtMode & CT_MODE_ABC_NUMBERS)
    2125                 :             :                 {
    2126         [ #  # ]:           0 :                     len = ( j == 2 ? MakeDecNumber : MakeAbcNumber )( p, ( int )sizeof( szValue ) - tot_len, NULL, nValue );
    2127                 :             :                 }
    2128                 :             :                 else
    2129                 :             :                 {
    2130         [ +  + ]:         430 :                     if (j < 2)
    2131                 :             :                     {
    2132   [ +  -  +  +  :         215 :                         len = MakeDecNumber( p, ( int )sizeof( szValue ) - tot_len, tot_len ? "-" : ( i || bAddDelim ) ? ITEM_DELIMETER : NULL, nValue );
                   -  + ]
    2133                 :             :                     }
    2134                 :             :                     else
    2135                 :             :                     {
    2136         [ +  - ]:         215 :                         if (tot_len + 1 < ( int )sizeof( szValue ))
    2137                 :             :                         {
    2138   [ +  -  +  - ]:         215 :                             *p++ = ( 0 <= nValue && nValue <= 4 ) ? parity_char[nValue] : parity_char[0];
    2139                 :         215 :                             *p = '\0';
    2140                 :         215 :                             len = 1;
    2141                 :             :                         }
    2142                 :             :                         else
    2143                 :             :                         {
    2144                 :           0 :                             len = -1; /*  Overflow */
    2145                 :             :                         }
    2146                 :             :                     }
    2147                 :             :                 }
    2148         [ -  + ]:         430 :                 if (len < 0)
    2149                 :             :                 {
    2150                 :           0 :                     bOvfl = 1;
    2151                 :           0 :                     break;
    2152                 :             :                 }
    2153                 :         430 :                 p += len;
    2154                 :         430 :                 tot_len += len;
    2155                 :             :             }
    2156                 :             : 
    2157                 :         215 :             inchi_strbuf_printf( strbuf, "%s", szValue );
    2158                 :             :             /*
    2159                 :             :             if ( nLen+tot_len < nLen_szLinearCT ) {
    2160                 :             :                 memcpy(  szLinearCT+nLen, szValue, tot_len+1 );
    2161                 :             :                 nLen += tot_len;
    2162                 :             :             } else {
    2163                 :             :                 bOvfl = 1;
    2164                 :             :                 break;
    2165                 :             :             }*/
    2166                 :             :         }
    2167                 :             :     }
    2168                 :          59 :     *bOverflow |= bOvfl;
    2169                 :             : 
    2170                 :          59 :     nLen = strbuf->nUsedLength - nUsedLength0;
    2171                 :             : 
    2172                 :          59 :     return nLen;
    2173                 :             : }
    2174                 :             : 
    2175                 :             : /**
    2176                 :             :  * @brief Compares two integers for qsort.
    2177                 :             :  *
    2178                 :             :  * @param a First integer pointer.
    2179                 :             :  * @param b Second integer pointer.
    2180                 :             :  * @return Returns negative, zero, or positive value based on comparison.
    2181                 :             :  */
    2182                 :         207 : int compare_ints(const void *a, const void *b) {
    2183                 :         207 :     int arg1 = *(const int *)a;
    2184                 :         207 :     int arg2 = *(const int *)b;
    2185                 :         207 :     return (arg1 > arg2) - (arg1 < arg2);
    2186                 :             : }
    2187                 :             : 
    2188                 :             : /**
    2189                 :             :  * @brief Compares the third value of two integer arrays for qsort. Used to sort enhanced stereochemistry groups based on the canonical atom number of the first atom in the group.
    2190                 :             :  *
    2191                 :             :  * @param a First integer array pointer.
    2192                 :             :  * @param b Second integer array pointer.
    2193                 :             :  * @return Returns negative, zero, or positive value based on comparison.
    2194                 :             :  */
    2195                 :         113 : int compare_third_value(const void *a, const void *b) {
    2196                 :         113 :     const int *arr1 = *(const int **)a;
    2197                 :         113 :     const int *arr2 = *(const int **)b;
    2198                 :         113 :     return arr1[2] - arr2[2];
    2199                 :             : }
    2200                 :             : 
    2201                 :             : /**
    2202                 :             :  * @brief Creates the enhanced stereochemistry string for the s - layer.
    2203                 :             :  *
    2204                 :             :  * @param pAux Pointer to the INCHI_AUX structure.
    2205                 :             :  * @param conf_stereo_string Pointer to the configuration stereochemistry string (abs, rel, rac).
    2206                 :             :  * @param enh_stereo Pointer to list of enhanced stereochemistry groups.
    2207                 :             :  * @param nof_stereo_groups Number of enhanced stereochemistry groups.
    2208                 :             :  * @param strbuf Pointer to the output string buffer.
    2209                 :             :  * @param nCtMode Mode flag for string representation.
    2210                 :             :  * @param bOverflow Pointer to overflow flag.
    2211                 :             :  * @return Returns the length of the created string.
    2212                 :             :  */
    2213                 :         138 : int MakeEnhStereoString( INChI_Aux        *pAux,
    2214                 :             :                          INCHI_IOS_STRING *strbuf,
    2215                 :             :                          const char*      conf_stereo_string,
    2216                 :             :                          int              **enh_stereo,
    2217                 :             :                          int              nof_stereo_groups,
    2218                 :             :                          int              nCtMode,
    2219                 :             :                          int              *bOverflow )
    2220                 :             : {
    2221                 :         138 :     int tot_len = 0;
    2222                 :         138 :     int count_added = 0;
    2223                 :             : 
    2224         [ -  + ]:         138 :     if (pAux == NULL) {
    2225                 :           0 :         return 0;
    2226                 :             :     }
    2227                 :             : 
    2228         [ +  + ]:         138 :     if (enh_stereo == NULL) {
    2229                 :          46 :         return 0;
    2230                 :             :     }
    2231                 :             : 
    2232         [ -  + ]:          92 :     if (nof_stereo_groups < 1) {
    2233                 :           0 :         return 0;
    2234                 :             :     }
    2235                 :             : 
    2236                 :          92 :     tot_len += MakeDelim( conf_stereo_string, strbuf, bOverflow );
    2237                 :             : 
    2238                 :          92 :     int **enh_stereo_canon = (int**)inchi_calloc(nof_stereo_groups, sizeof(int*));
    2239                 :             : 
    2240                 :             :     // Converts the original atom numbers in the enhanced stereochemistry groups to canonical atom numbers
    2241                 :             :     // and sorts the atoms within each group based on their canonical atom numbers. This ensures that the order of
    2242                 :             :     // atoms in the string representation is consistent and does not depend on the order of atoms in the input data.
    2243                 :             :     // enh_stereo_canon is a 2D array where each row corresponds to an enhanced stereochemistry group. The first element
    2244                 :             :     // of each row (index 0) stores the number of atoms in the group, the second element (index 1) stores the count of found
    2245                 :             :     // atoms, and the remaining elements (starting from index 2) store the canonical atom numbers of the atoms in the group.
    2246         [ +  + ]:         267 :     for (int i = 0; i < nof_stereo_groups; i++) {
    2247                 :         175 :         const int *atom_numbers = &enh_stereo[i][2];
    2248                 :         175 :         int count_found_atoms = 0;
    2249                 :         175 :         int nof_atoms = enh_stereo[i][1];
    2250                 :             : 
    2251                 :         175 :         enh_stereo_canon[i] = (int*)inchi_calloc(nof_atoms + 2, sizeof(int));
    2252                 :         175 :         enh_stereo_canon[i][0] = nof_atoms;
    2253         [ +  + ]:         507 :         for (int j = 0; j < nof_atoms; j++)  {
    2254                 :             : 
    2255                 :         332 :             int orig_atom_num = atom_numbers[j];
    2256                 :         332 :             int canon_atom_num = get_canonical_atom_number(pAux, orig_atom_num);
    2257         [ +  + ]:         332 :             if (canon_atom_num != -1) {
    2258                 :         163 :                 count_found_atoms++;
    2259                 :             :             } else {
    2260                 :         169 :                 canon_atom_num = INT_MAX;
    2261                 :             :             }
    2262                 :             : 
    2263                 :         332 :             enh_stereo_canon[i][j + 2] = canon_atom_num;
    2264                 :             :         }
    2265                 :         175 :         enh_stereo_canon[i][1] = count_found_atoms;
    2266                 :             : 
    2267         [ +  + ]:         175 :         if (nof_atoms > 1) {
    2268                 :          92 :             qsort(&enh_stereo_canon[i][2], nof_atoms, sizeof(int), compare_ints);
    2269                 :             :         }
    2270                 :             :     }
    2271                 :             : 
    2272                 :             :     // Sorts the enhanced stereochemistry groups based on the canonical atom number of the first atom in the group.
    2273                 :             :     // This ensures that the groups are always in a consistent order in the string representation, regardless of the
    2274                 :             :     // order they were added to the input data (e.g. AND1, AND2, ... or OR1, OR2, ...).
    2275                 :          92 :     qsort(enh_stereo_canon, nof_stereo_groups, sizeof(int*), compare_third_value);
    2276                 :             : 
    2277                 :             :     // Creates the string for the stereo group based on the canonical atom numbers of the atoms in the group. If no
    2278                 :             :     // atoms were found for the group, it will not be added to the string.
    2279         [ +  + ]:         267 :     for (int i = 0; i < nof_stereo_groups; i++) {
    2280                 :         175 :         int nof_atoms = enh_stereo_canon[i][0];
    2281                 :         175 :         int nof_found_atoms = enh_stereo_canon[i][1];
    2282                 :             : 
    2283         [ +  + ]:         175 :         if (nof_found_atoms > 0) {
    2284                 :         114 :             tot_len += MakeDelim( "(", strbuf, bOverflow );
    2285         [ +  + ]:         277 :             for (int j = 0; j < nof_found_atoms; j++)  {
    2286                 :         163 :                 tot_len += MakeNumber_EnhStereo( enh_stereo_canon[i][j + 2], "", strbuf, nCtMode, bOverflow );
    2287                 :         163 :                 count_added++;
    2288                 :             : 
    2289         [ +  + ]:         163 :                 if ((j + 1) < nof_found_atoms) {
    2290                 :          49 :                     tot_len += MakeDelim( ",", strbuf, bOverflow );
    2291                 :             :                 }
    2292                 :             :             }
    2293                 :         114 :             tot_len += MakeDelim( ")", strbuf, bOverflow );
    2294                 :             :         }
    2295                 :             :     }
    2296                 :             : 
    2297         [ +  + ]:         267 :     for (int i = 0; i < nof_stereo_groups; i++) {
    2298         [ +  - ]:         175 :         inchi_free(enh_stereo_canon[i]);
    2299                 :             :     }
    2300         [ +  - ]:          92 :     inchi_free(enh_stereo_canon);
    2301                 :             : 
    2302                 :             :     // Removes the last value for the stereo group (1,2,3) if no atoms were added to the string
    2303         [ +  + ]:          92 :     if (count_added == 0) {
    2304   [ +  -  +  - ]:           8 :         if (strbuf && strbuf->nUsedLength > 0) {
    2305                 :           8 :             strbuf->nUsedLength--;
    2306                 :           8 :             strbuf->pStr[strbuf->nUsedLength] = '\0';
    2307                 :             :         }
    2308                 :             : 
    2309                 :           8 :         tot_len = tot_len - 1;
    2310                 :             :     }
    2311                 :             : 
    2312                 :          92 :     return tot_len;
    2313                 :             : }
    2314                 :             : 
    2315                 :             : /**
    2316                 :             :  * @brief Creates the string for the s - layer based on the enhanced stereochemistry information.
    2317                 :             :  *
    2318                 :             :  * @param orig_inp_data Pointer to the original atom data.
    2319                 :             :  * @param pINChISort Pointer to the INCHI_SORT structure.
    2320                 :             :  * @param bOutType Output type flag.
    2321                 :             :  * @param num_components Number of components in the molecule.
    2322                 :             :  * @param strbuf Pointer to the output string buffer.
    2323                 :             :  * @param nCtMode Mode flag for string representation.
    2324                 :             :  * @param bOverflow Pointer to overflow flag.
    2325                 :             :  * @return Returns the length of the created string.
    2326                 :             :  */
    2327                 :          36 : int MakeSlayerString( ORIG_ATOM_DATA   *orig_inp_data,
    2328                 :             :                       INCHI_SORT       *pINChISort,
    2329                 :             :                       INCHI_IOS_STRING *strbuf,
    2330                 :             :                       int              bOutType,
    2331                 :             :                       int              num_components,
    2332                 :             :                       int              nCtMode,
    2333                 :             :                       int              *bOverflow )
    2334                 :             : {
    2335                 :             : 
    2336                 :          36 :     int tot_len = 0;
    2337                 :             :     int          ii;
    2338                 :             : 
    2339                 :          36 :     const char* x_abs = "1";
    2340                 :          36 :     const char* x_rel = "2";
    2341                 :          36 :     const char* x_rac = "3";
    2342                 :             : 
    2343                 :          36 :     const INCHI_SORT   *is = NULL;
    2344                 :          36 :     const INCHI_SORT  *is0 = pINChISort;
    2345                 :             : 
    2346                 :             :     // INChI        *pINChI = NULL;
    2347                 :          36 :     INChI_Aux    *pAux = NULL;
    2348                 :             : 
    2349                 :          36 :     char **dictionary = (char**)inchi_calloc(ENH_STEREO_DICT_SIZE, sizeof(char*));
    2350                 :          36 :     int *counts = (int*)inchi_calloc(ENH_STEREO_DICT_SIZE, sizeof(int));
    2351                 :             : 
    2352         [ +  + ]:        3636 :     for (int i = 0; i < ENH_STEREO_DICT_SIZE; i++) {
    2353                 :        3600 :         dictionary[i] = NULL;
    2354                 :        3600 :         counts[i] = 0;
    2355                 :             :     }
    2356                 :             : 
    2357                 :          36 :     INCHI_IOS_STRING tmpbuf  = {0};
    2358                 :             : 
    2359   [ +  -  +  + ]:          82 :     for (int cur_c = 0; !*bOverflow && cur_c < num_components; cur_c++)
    2360                 :             :     {
    2361                 :             : 
    2362                 :          46 :         is = is0 + cur_c;
    2363                 :             :         // pINChI = ( 0 <= ( ii = GET_II( bOutType, is ) ) ) ? is->pINChI[ii] : NULL;
    2364   [ -  +  -  -  :          46 :         pAux = ( 0 <= ( ii = GET_II( bOutType, is ) ) ) ? is->pINChI_Aux[ii] : NULL;
          -  -  -  -  -  
          -  -  -  -  -  
          +  -  +  -  +  
          -  -  +  -  -  
          -  -  -  -  -  
          -  -  -  -  -  
          -  -  -  -  -  
          -  -  -  -  -  
          -  -  -  -  -  
          -  -  -  -  -  
                   +  - ]
    2365                 :             : 
    2366                 :          46 :         inchi_strbuf_init(&tmpbuf, INCHI_STRBUF_INITIAL_SIZE, INCHI_STRBUF_SIZE_INCREMENT);
    2367                 :             : 
    2368                 :             :         // s1
    2369                 :          92 :         tot_len += MakeEnhStereoString( pAux,
    2370                 :             :                                         &tmpbuf,
    2371                 :             :                                         x_abs,
    2372                 :          46 :                                         orig_inp_data->v3000->lists_steabs,
    2373                 :          46 :                                         orig_inp_data->v3000->n_steabs,
    2374                 :             :                                         nCtMode,
    2375                 :             :                                         bOverflow);
    2376                 :             : 
    2377                 :             :         // s2
    2378                 :          92 :         tot_len += MakeEnhStereoString( pAux,
    2379                 :             :                                         &tmpbuf,
    2380                 :             :                                         x_rel,
    2381                 :          46 :                                         orig_inp_data->v3000->lists_sterel,
    2382                 :          46 :                                         orig_inp_data->v3000->n_sterel,
    2383                 :             :                                         nCtMode,
    2384                 :             :                                         bOverflow);
    2385                 :             : 
    2386                 :             :         // s3
    2387                 :          92 :         tot_len += MakeEnhStereoString( pAux,
    2388                 :             :                                         &tmpbuf,
    2389                 :             :                                         x_rac,
    2390                 :          46 :                                         orig_inp_data->v3000->lists_sterac,
    2391                 :          46 :                                         orig_inp_data->v3000->n_sterac,
    2392                 :             :                                         nCtMode,
    2393                 :             :                                         bOverflow);
    2394                 :             : 
    2395                 :          46 :         int found = 0;
    2396         [ +  + ]:        4147 :         for (int i = 0; i < ENH_STEREO_DICT_SIZE; i++) {
    2397   [ +  +  +  + ]:        4106 :             if (dictionary[i] && strcmp(tmpbuf.pStr, dictionary[i]) == 0) {
    2398                 :           5 :                 counts[i]++;
    2399                 :           5 :                 found = 1;
    2400                 :           5 :                 break;
    2401                 :             :             }
    2402                 :             :         }
    2403         [ +  + ]:          46 :         if (!found) {
    2404         [ +  - ]:          47 :             for (int i = 0; i < ENH_STEREO_DICT_SIZE; i++) {
    2405         [ +  + ]:          47 :                 if (dictionary[i] == NULL) {
    2406                 :          41 :                     dictionary[i] = strdup(tmpbuf.pStr);
    2407                 :          41 :                     counts[i] = 1;
    2408                 :          41 :                     break;
    2409                 :             :                 }
    2410                 :             :             }
    2411                 :             :         }
    2412                 :          46 :         inchi_strbuf_close(&tmpbuf);
    2413                 :             :     }
    2414                 :             : 
    2415                 :             :     // String deduplication based on dictionary and counts
    2416                 :          36 :     int count = 0;
    2417         [ +  + ]:        3636 :     for (int i = 0; i < ENH_STEREO_DICT_SIZE; i++) {
    2418         [ +  + ]:        3600 :         if (dictionary[i]) {
    2419         [ +  + ]:          41 :             if (count > 0) {
    2420                 :           5 :                 tot_len += MakeDelim( ";", strbuf, bOverflow );
    2421                 :             :             }
    2422         [ +  + ]:          41 :             if (counts[i] > 1) {
    2423                 :           5 :                 tot_len = inchi_strbuf_printf(strbuf, "%d*%s", counts[i], dictionary[i]);
    2424                 :             :             } else {
    2425                 :          36 :                 tot_len = inchi_strbuf_printf(strbuf, "%s", dictionary[i]);
    2426                 :             :             }
    2427         [ +  - ]:          41 :             inchi_free(dictionary[i]);
    2428                 :          41 :             count++;
    2429                 :             :         }
    2430                 :             :     }
    2431                 :             : 
    2432         [ +  - ]:          36 :     inchi_free(dictionary);
    2433         [ +  - ]:          36 :     inchi_free(counts);
    2434                 :             : 
    2435                 :          36 :     return tot_len;
    2436                 :             : }
    2437                 :             : 
    2438                 :             : #ifdef ALPHA_BASE
    2439                 :             : #if ( ALPHA_BASE != 27 )
    2440                 :             : #error ALPHA_BASE definitions mismatch
    2441                 :             : #endif
    2442                 :             : #else
    2443                 :             : #define ALPHA_BASE     27
    2444                 :             : #endif
    2445                 :             : 
    2446                 :             : #define ALPHA_MINUS    '-'
    2447                 :             : #define ALPHA_ZERO_VAL '.'
    2448                 :             : #define ALPHA_ONE      'a'
    2449                 :             : #define ALPHA_ZERO     '@'
    2450                 :             : 
    2451                 :             : 
    2452                 :             : /****************************************************************************
    2453                 :             :   MakeAbcNumber( ... )
    2454                 :             : 
    2455                 :             :     Produce an "Alphabetic" number, base 27 (27 digits: 0, a, b, ..., z)
    2456                 :             :     The leading "digit" uppercase, the rest -- lowercase
    2457                 :             :     szString length nStringLen includes 1 byte for zero termination
    2458                 :             :     Return Value: length without zero termination; -1 means not enough room
    2459                 :             :     Note: ASCII-encoding specific implementation
    2460                 :             : ****************************************************************************/
    2461                 :           0 : int MakeAbcNumber( char      *szString,
    2462                 :             :                   int        nStringLen,
    2463                 :             :                   const char *szLeadingDelim,
    2464                 :             :                   int        nValue )
    2465                 :             : {
    2466                 :           0 :     char *p = szString;
    2467                 :             :     char *q;
    2468                 :             :     int  nChar;
    2469                 :             : 
    2470         [ #  # ]:           0 :     if (nStringLen < 2)
    2471                 :           0 :         return -1;
    2472   [ #  #  #  #  :           0 :     while (szLeadingDelim && *szLeadingDelim && --nStringLen)
                   #  # ]
    2473                 :             :     {
    2474                 :           0 :         *p++ = *szLeadingDelim++;
    2475                 :             :     }
    2476         [ #  # ]:           0 :     if (nStringLen < 2)
    2477                 :           0 :         return -1;
    2478         [ #  # ]:           0 :     if (!nValue)
    2479                 :             :     {
    2480                 :           0 :         *p++ = ALPHA_ZERO_VAL;  /*  zero value (cannot use 0) */
    2481                 :           0 :         *p = '\0';
    2482                 :           0 :         return 1;
    2483                 :             :     }
    2484         [ #  # ]:           0 :     if (nValue < 0)
    2485                 :             :     {
    2486                 :           0 :         *p++ = ALPHA_MINUS;
    2487                 :           0 :         nStringLen--;
    2488                 :           0 :         nValue = -nValue;
    2489                 :             :     }
    2490   [ #  #  #  # ]:           0 :     for (q = p; nValue && --nStringLen; nValue /= ALPHA_BASE)
    2491                 :             :     {
    2492         [ #  # ]:           0 :         if ((nChar = nValue % ALPHA_BASE)) /* djb-rwth: addressing LLVM warning */
    2493                 :             :         {
    2494                 :           0 :             nChar = ALPHA_ONE + nChar - 1;
    2495                 :             :         }
    2496                 :             :         else
    2497                 :             :         {
    2498                 :           0 :             nChar = ALPHA_ZERO;
    2499                 :             :         }
    2500                 :           0 :         *q++ = nChar;
    2501                 :             :     }
    2502         [ #  # ]:           0 :     if (nStringLen <= 0)
    2503                 :           0 :         return -1;
    2504                 :           0 :     *q = '\0';
    2505                 :           0 :     mystrrev( p );
    2506                 :           0 :     p[0] = toupper( p[0] );
    2507                 :             : 
    2508                 :           0 :     return (int) ( q - szString );
    2509                 :             : }
    2510                 :             : 
    2511                 :             : 
    2512                 :             : #if 1 /* ( READ_INCHI_STRING == 1 ) */
    2513                 :             : 
    2514                 :             : 
    2515                 :             : static long abctol( const char *szString, char **q );   /* keep compiler happy */
    2516                 :             : 
    2517                 :             : 
    2518                 :             : /****************************************************************************
    2519                 :             : abctol( ... ) - analog of strtol() dealing with 'compressed InChI' input strings
    2520                 :             : ****************************************************************************/
    2521                 :           0 : long abctol( const char *szString, char **q )
    2522                 :             : {
    2523                 :             : #define __MYTOLOWER(c) ( ((c) >= 'A') && ((c) <= 'Z') ? ((c) - 'A' + 'a') : (c) )
    2524                 :             : 
    2525                 :           0 :     long        val = 0;
    2526                 :             :     /* djb-rwth: removing redundant variables */
    2527                 :           0 :     const char *p = szString, *pp = szString;
    2528                 :           0 :     long treshold = ( LONG_MAX - 1 ) / ALPHA_BASE;
    2529                 :             : 
    2530         [ #  # ]:           0 :     if (*p == ALPHA_MINUS)
    2531                 :             :     {
    2532                 :           0 :         p++;
    2533                 :             :         /* djb-rwth: removing redundant code */
    2534                 :             :     }
    2535         [ #  # ]:           0 :     if (*p == ALPHA_ZERO)
    2536                 :             :     {
    2537                 :           0 :         p++;
    2538                 :           0 :         goto exit_function;
    2539                 :             :     }
    2540         [ #  # ]:           0 :     if (!isupper( UCINT *p ))
    2541                 :             :     {
    2542                 :           0 :         p = szString;
    2543                 :           0 :         goto exit_function; /* not an abc-number */
    2544                 :             :     }
    2545   [ #  #  #  # ]:           0 :     val = __MYTOLOWER( *p ) - ALPHA_ONE + 1;
    2546                 :           0 :     p++;
    2547         [ #  # ]:           0 :     while (*p)
    2548                 :             :     {
    2549         [ #  # ]:           0 :         if (islower( UCINT *p ))
    2550                 :             :         {
    2551                 :           0 :             val *= ALPHA_BASE;
    2552                 :           0 :             val += *p - ALPHA_ONE + 1;
    2553                 :             :         }
    2554                 :             :         else
    2555         [ #  # ]:           0 :             if (*p == ALPHA_ZERO)
    2556                 :             :             {
    2557                 :             :                 /*^^^ 1.06 */
    2558         [ #  # ]:           0 :                 if (val > treshold)
    2559                 :             :                 {
    2560                 :           0 :                     p = pp;
    2561                 :           0 :                     val = 0;
    2562                 :           0 :                     goto exit_function;
    2563                 :             :                 }
    2564                 :             :                 else
    2565                 :             :                 /* Software version 1.07 ^^^*/
    2566                 :           0 :                     val *= ALPHA_BASE;  /* @1.06 fuzz testing caused overflow here! */
    2567                 :             :             }
    2568                 :             :             else
    2569                 :             :             {
    2570                 :           0 :                 break;
    2571                 :             :             }
    2572                 :           0 :         p++;
    2573                 :             :     }
    2574                 :             : 
    2575                 :           0 : exit_function:
    2576         [ #  # ]:           0 :     if (q)
    2577                 :             :     {
    2578                 :           0 :         *q = (char *) p;  /* cast deliberately discards const qualifier */
    2579                 :             :     }
    2580                 :             : 
    2581                 :           0 :     return val;
    2582                 :             : #undef __MYTOLOWER
    2583                 :             : }
    2584                 :             : 
    2585                 :             : 
    2586                 :             : /********************************************************/
    2587                 :           0 : long inchi_strtol(const char *str, const char **p, int base)
    2588                 :             : {
    2589         [ #  # ]:           0 :     if (base == ALPHA_BASE) {
    2590                 :           0 :         return abctol(str, (char **)p); /* cast deliberately discards const qualifier */
    2591                 :             :     }
    2592                 :             :     else {
    2593                 :           0 :         return strtol(str, (char **)p, base); /* cast deliberately discards const qualifier */
    2594                 :             :     }
    2595                 :             : }
    2596                 :             : #endif /* #if ( READ_INCHI_STRING == 1 ) */
    2597                 :             : 
    2598                 :             : #undef ALPHA_BASE
    2599                 :             : #undef ALPHA_MINUS
    2600                 :             : #undef ALPHA_ZERO_VAL
    2601                 :             : #undef ALPHA_ONE
    2602                 :             : #undef ALPHA_ZERO
    2603                 :             : 
    2604                 :             : 
    2605                 :             : /****************************************************************************/
    2606                 :           0 : double inchi_strtod(const char *str, const char **p)
    2607                 :             : {
    2608                 :           0 :     return strtod( str, (char **) p );
    2609                 :             : }
    2610                 :             : 
    2611                 :             : 
    2612                 :             : /****************************************************************************
    2613                 :             :   MakeDecNumber( ... )
    2614                 :             : 
    2615                 :             :     Produce a decimal number
    2616                 :             : 
    2617                 :             :     szString length nStringLen includes 1 byte for zero termination
    2618                 :             :     Return Value: length without zero termination; -1 means not enough room
    2619                 :             : ****************************************************************************/
    2620                 :        2024 : int MakeDecNumber( char        *szString,
    2621                 :             :                    int         nStringLen,
    2622                 :             :                    const char  *szLeadingDelim,
    2623                 :             :                    int         nValue )
    2624                 :             : {
    2625                 :             : #define DECIMAL_BASE     10
    2626                 :             : #define DECIMAL_MINUS    '-'
    2627                 :             : #define DECIMAL_ZERO_VAL '0'
    2628                 :             : #define DECIMAL_ONE      '1'
    2629                 :             : #define DECIMAL_ZERO     '0'
    2630                 :             : 
    2631                 :        2024 :     char *p = szString;
    2632                 :             :     char *q;
    2633                 :             :     int  nChar;
    2634                 :             : 
    2635         [ -  + ]:        2024 :     if (nStringLen < 2)
    2636                 :             :     {
    2637                 :           0 :         return -1;
    2638                 :             :     }
    2639   [ +  +  +  +  :        3115 :     while (szLeadingDelim && *szLeadingDelim && --nStringLen)
                   +  - ]
    2640                 :             :     {
    2641                 :        1091 :         *p++ = *szLeadingDelim++; /* djb-rwth: GCC 14 false positive */
    2642                 :             :     }
    2643         [ -  + ]:        2024 :     if (nStringLen < 2)
    2644                 :             :     {
    2645                 :           0 :         return -1;
    2646                 :             :     }
    2647         [ -  + ]:        2024 :     if (!nValue)
    2648                 :             :     {
    2649                 :           0 :         *p++ = DECIMAL_ZERO_VAL;  /*  zero value (cannot use 0) */
    2650                 :           0 :         *p = '\0';
    2651                 :           0 :         return (int) ( p - szString );
    2652                 :             :     }
    2653         [ +  + ]:        2024 :     if (nValue < 0)
    2654                 :             :     {
    2655                 :           3 :         *p++ = DECIMAL_MINUS;
    2656                 :           3 :         nStringLen--;
    2657                 :           3 :         nValue = -nValue;
    2658                 :             :     }
    2659   [ +  +  +  - ]:        4382 :     for (q = p; nValue && --nStringLen; nValue /= DECIMAL_BASE)
    2660                 :             :     {
    2661         [ +  + ]:        2358 :         if ((nChar = nValue % DECIMAL_BASE)) /* djb-rwth: addressing LLVM warning */
    2662                 :             :         {
    2663                 :        2286 :             nChar = DECIMAL_ONE + nChar - 1;
    2664                 :             :         }
    2665                 :             :         else
    2666                 :             :         {
    2667                 :          72 :             nChar = DECIMAL_ZERO;
    2668                 :             :         }
    2669                 :        2358 :         *q++ = nChar;
    2670                 :             :     }
    2671         [ -  + ]:        2024 :     if (nStringLen <= 0)
    2672                 :             :     {
    2673                 :           0 :         return -1;
    2674                 :             :     }
    2675                 :        2024 :     *q = '\0';
    2676                 :        2024 :     mystrrev( p );
    2677                 :             : 
    2678                 :        2024 :     return (int) ( q - szString );
    2679                 :             : 
    2680                 :             : #undef DECIMAL_BASE
    2681                 :             : #undef DECIMAL_MINUS
    2682                 :             : #undef DECIMAL_ZERO_VAL
    2683                 :             : #undef DECIMAL_ONE
    2684                 :             : #undef DECIMAL_ZERO
    2685                 :             : }
    2686                 :             : 
    2687                 :             : 
    2688                 :             : /****************************************************************************
    2689                 :             :   Print out num[0..n-1] separated with commas
    2690                 :             :     For shortness, compress consecutive numbers (>2 members in a series)
    2691                 :             :     to a range:
    2692                 :             :     '1,2,5, 7-10' means 1,2,5,7,8,9,10'
    2693                 :             : ****************************************************************************/
    2694                 :           0 : void print_sequence_of_nums_compressing_ranges( int n,
    2695                 :             :                                                 int *num,
    2696                 :             :                                                 INCHI_IOS_STRING *strbuf )
    2697                 :             : {
    2698                 :             :     int k, range;
    2699                 :             : 
    2700                 :           0 :     range = 0;
    2701         [ #  # ]:           0 :     for (k = 0; k < n - 1; k++)
    2702                 :             :     {
    2703         [ #  # ]:           0 :         if (num[k + 1] == num[k] + 1)
    2704                 :             :         {
    2705         [ #  # ]:           0 :             if (range)
    2706                 :             :             {
    2707                 :           0 :                 range++;
    2708                 :             :             }
    2709                 :             :             else
    2710                 :             :             {
    2711                 :           0 :                 inchi_strbuf_printf( strbuf, "%d-", num[k] );
    2712                 :           0 :                 range = 1;
    2713                 :             :             }
    2714                 :             :         }
    2715                 :             :         else
    2716                 :             :         {
    2717         [ #  # ]:           0 :             if (range)
    2718                 :             :             {
    2719                 :           0 :                 range = 0;
    2720                 :             :             }
    2721                 :           0 :             inchi_strbuf_printf( strbuf, "%d,", num[k] );
    2722                 :             :         }
    2723                 :             :     }
    2724                 :           0 :     inchi_strbuf_printf( strbuf, "%d", num[n - 1] );
    2725                 :             : 
    2726                 :           0 :     return;
    2727                 :             : }
        

Generated by: LCOV version 2.0-1