Coverage Report

Created: 2026-10-17 06:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openbabel/src/formats/hinformat.cpp
Line
Count
Source
1
/**********************************************************************
2
Copyright (C) 2000 by OpenEye Scientific Software, Inc.
3
Some portions Copyright (C) 2001-2006 by Geoffrey R. Hutchison
4
Some portions Copyright (C) 2004 by Chris Morley
5
6
This program is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation version 2 of the License.
9
10
This program is distributed in the hope that it will be useful,
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
GNU General Public License for more details.
14
***********************************************************************/
15
#include <openbabel/babelconfig.h>
16
17
#include <openbabel/obmolecformat.h>
18
#include <openbabel/mol.h>
19
#include <openbabel/atom.h>
20
#include <openbabel/bond.h>
21
#include <openbabel/obiter.h>
22
#include <openbabel/elements.h>
23
24
#include <cstdlib>
25
26
using namespace std;
27
namespace OpenBabel
28
{
29
30
  class HINFormat : public OBMoleculeFormat
31
  {
32
  public:
33
    //Register this format type ID
34
    HINFormat()
35
12
    {
36
12
      OBConversion::RegisterFormat("hin",this, "chemical/x-hin");
37
12
    }
38
39
    const char* Description() override  // required
40
0
    {
41
0
      return "HyperChem HIN format\n"
42
0
             "No comments yet\n";
43
0
    }
44
45
    const char* SpecificationURL() override
46
0
    { return ""; }  // optional
47
48
    const char* GetMIMEType() override
49
0
    { return "chemical/x-hin"; }  // optional
50
51
    //*** This section identical for most OBMol conversions ***
52
    ////////////////////////////////////////////////////
53
    /// The "API" interface functions
54
    bool ReadMolecule(OBBase* pOb, OBConversion* pConv) override;
55
    bool WriteMolecule(OBBase* pOb, OBConversion* pConv) override;
56
  };
57
  //***
58
59
  //Make an instance of the format class
60
  HINFormat theHINFormat;
61
62
  /////////////////////////////////////////////////////////////////
63
  bool HINFormat::ReadMolecule(OBBase* pOb, OBConversion* pConv)
64
0
  {
65
66
0
    OBMol* pmol = pOb->CastAndClear<OBMol>();
67
0
    if (pmol == nullptr)
68
0
      return false;
69
70
    //Define some references so we can use the old parameter names
71
0
    istream &ifs = *pConv->GetInStream();
72
0
    OBMol &mol = *pmol;
73
0
    const char* title = pConv->GetTitle();
74
75
    // Right now only read in the first molecule
76
0
    int i;
77
0
    int max, bo;
78
0
    char buffer[BUFF_SIZE];
79
0
    string str,str1;
80
0
    double x,y,z;
81
0
    OBAtom *atom;
82
0
    vector<string> vs;
83
84
0
    ifs.getline(buffer, BUFF_SIZE);
85
0
    while (ifs.good() && (strstr(buffer, "mol") == nullptr || buffer[0] == ';')) //The "mol" in comment line should be ignored.
86
0
      {
87
0
        ifs.getline(buffer, BUFF_SIZE);
88
0
        if (ifs.peek() == EOF || !ifs.good())
89
0
          return false;
90
0
      }
91
0
    ifs.getline(buffer, BUFF_SIZE);
92
0
    if (!ifs.good())
93
0
      return false; // ended early
94
95
0
    mol.BeginModify();
96
0
    while (ifs.good() && strstr(buffer, "endmol") == nullptr)
97
0
      {
98
0
  if(buffer[0]==';'){
99
0
     ifs.getline(buffer, BUFF_SIZE);
100
0
     continue; //The comment Line in HIN should be ignored.
101
0
  }
102
103
0
        tokenize(vs,buffer); // Don't really know how long it'll be
104
0
        if (vs.size() < 11)
105
0
          {
106
0
            ifs.getline(buffer, BUFF_SIZE);
107
0
            continue;
108
0
          }
109
110
0
        atom = mol.NewAtom();
111
0
        atom->SetAtomicNum(OBElements::GetAtomicNum(vs[3].c_str()));
112
0
        atom->SetPartialCharge(atof(vs[6].c_str()));
113
0
        x = atof((char*)vs[7].c_str());
114
0
        y = atof((char*)vs[8].c_str());
115
0
        z = atof((char*)vs[9].c_str());
116
0
        atom->SetVector(x,y,z);
117
118
        // Bond count comes straight from the file; clamp it to what the
119
        // line actually holds so a huge or negative value can't overflow
120
        // "max" or send the loop below reading past the end of vs[].
121
0
        int numbonds = atoi((char *)vs[10].c_str());
122
0
        if (numbonds < 0)
123
0
          numbonds = 0;
124
0
        if (numbonds > ((int)vs.size() - 11) / 2)
125
0
          numbonds = ((int)vs.size() - 11) / 2;
126
0
        max = 11 + 2 * numbonds;
127
0
        for (i = 11; i < max; i+=2)
128
0
          {
129
0
            switch(((char*)vs[i+1].c_str())[0]) // First char in next token
130
0
              {
131
0
              case 's':
132
0
                bo = 1;
133
0
                break;
134
0
              case 'd':
135
0
                bo = 2;
136
0
                break;
137
0
              case 't':
138
0
                bo = 3;
139
0
                break;
140
0
              case 'a':
141
0
                bo = 5;
142
0
                break;
143
0
              default :
144
0
                bo = 1;
145
0
                break;
146
0
              }
147
0
            mol.AddBond(mol.NumAtoms(), atoi((char *)vs[i].c_str()), bo);
148
0
          }
149
0
        ifs.getline(buffer, BUFF_SIZE);
150
0
      }
151
152
    // clean out remaining blank lines
153
    // blank lines cleaning codes rewritten for avoiding peek() and tellg() bugs
154
    // https://github.com/openbabel/openbabel/issues/1569
155
0
    std::streampos ipos;
156
0
    do
157
0
    {
158
0
      ipos = ifs.tellg();
159
0
      ifs.getline(buffer,BUFF_SIZE);
160
0
    }
161
0
    while(strlen(buffer) == 0 && !ifs.eof() );
162
0
    ifs.seekg(ipos);
163
164
165
0
    mol.EndModify();
166
167
0
    mol.SetTitle(title);
168
0
    mol.SetPartialChargesPerceived();
169
170
0
    return(true);
171
0
  }
172
173
  ////////////////////////////////////////////////////////////////
174
175
  bool HINFormat::WriteMolecule(OBBase* pOb, OBConversion* pConv)
176
2.04k
  {
177
2.04k
    OBMol* pmol = dynamic_cast<OBMol*>(pOb);
178
2.04k
    if (pmol == nullptr)
179
0
      return false;
180
181
    //Define some references so we can use the old parameter names
182
2.04k
    ostream &ofs = *pConv->GetOutStream();
183
2.04k
    OBMol &mol = *pmol;
184
185
2.04k
    unsigned int i, file_num = 1;
186
2.04k
    string str,str1;
187
2.04k
    char buffer[BUFF_SIZE];
188
2.04k
    OBAtom *atom;
189
2.04k
    OBBond *bond;
190
2.04k
    vector<OBBond*>::iterator j;
191
2.04k
    char bond_char;
192
193
    // make sure to escape titles in double quotes
194
    // PR#1501694
195
2.04k
    ofs << "mol " << file_num << " \"" << mol.GetTitle() << "\"\n";
196
197
2.04k
    for(i = 1;i <= mol.NumAtoms(); i++)
198
0
      {
199
0
        atom = mol.GetAtom(i);
200
0
        snprintf(buffer, BUFF_SIZE, "atom %d - %-3s **  - %8.5f %8.5f  %8.5f  %8.5f %d ",
201
0
                i,
202
0
                OBElements::GetSymbol(atom->GetAtomicNum()),
203
0
                atom->GetPartialCharge(),
204
0
                atom->GetX(),
205
0
                atom->GetY(),
206
0
                atom->GetZ(),
207
0
                atom->GetExplicitDegree());
208
0
        ofs << buffer;
209
0
        for (bond = atom->BeginBond(j); bond; bond = atom->NextBond(j))
210
0
          {
211
0
            switch(bond->GetBondOrder())
212
0
              {
213
0
              case 1 :
214
0
                bond_char = 's';
215
0
                break;
216
0
              case 2 :
217
0
                bond_char = 'd';
218
0
                break;
219
0
              case 3 :
220
0
                bond_char = 't';
221
0
                break;
222
0
              case 5 :
223
0
                bond_char = 'a';
224
0
                break;
225
0
              default:
226
0
                bond_char = 's';
227
0
                break;
228
0
              }
229
0
            if (bond->IsAromatic())
230
0
              bond_char = 'a';
231
232
0
            snprintf(buffer,BUFF_SIZE, "%d %c ", (bond->GetNbrAtom(atom))->GetIdx(), bond_char);
233
0
            ofs << buffer;
234
0
          }
235
0
        ofs << endl;
236
0
      }
237
2.04k
    ofs << "endmol " << file_num << endl;
238
2.04k
    return(true);
239
2.04k
  }
240
241
} //namespace OpenBabel