Coverage Report

Created: 2025-10-10 06:56

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
6
    {
36
6
      OBConversion::RegisterFormat("hin",this, "chemical/x-hin");
37
6
    }
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
19
  {
65
66
19
    OBMol* pmol = pOb->CastAndClear<OBMol>();
67
19
    if (pmol == nullptr)
68
0
      return false;
69
70
    //Define some references so we can use the old parameter names
71
19
    istream &ifs = *pConv->GetInStream();
72
19
    OBMol &mol = *pmol;
73
19
    const char* title = pConv->GetTitle();
74
75
    // Right now only read in the first molecule
76
19
    int i;
77
19
    int max, bo;
78
19
    char buffer[BUFF_SIZE];
79
19
    string str,str1;
80
19
    double x,y,z;
81
19
    OBAtom *atom;
82
19
    vector<string> vs;
83
84
19
    ifs.getline(buffer, BUFF_SIZE);
85
750
    while (ifs.good() && (strstr(buffer, "mol") == nullptr || buffer[0] == ';')) //The "mol" in comment line should be ignored.
86
745
      {
87
745
        ifs.getline(buffer, BUFF_SIZE);
88
745
        if (ifs.peek() == EOF || !ifs.good())
89
14
          return false;
90
745
      }
91
5
    ifs.getline(buffer, BUFF_SIZE);
92
5
    if (!ifs.good())
93
0
      return false; // ended early
94
95
5
    mol.BeginModify();
96
91
    while (ifs.good() && strstr(buffer, "endmol") == nullptr)
97
86
      {
98
86
  if(buffer[0]==';'){
99
1
     ifs.getline(buffer, BUFF_SIZE);
100
1
     continue; //The comment Line in HIN should be ignored.
101
1
  }
102
103
85
        tokenize(vs,buffer); // Don't really know how long it'll be
104
85
        if (vs.size() < 11)
105
85
          {
106
85
            ifs.getline(buffer, BUFF_SIZE);
107
85
            continue;
108
85
          }
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
0
        max = 11 + 2 * atoi((char *)vs[10].c_str());
119
0
        for (i = 11; i < max; i+=2)
120
0
          {
121
0
            switch(((char*)vs[i+1].c_str())[0]) // First char in next token
122
0
              {
123
0
              case 's':
124
0
                bo = 1;
125
0
                break;
126
0
              case 'd':
127
0
                bo = 2;
128
0
                break;
129
0
              case 't':
130
0
                bo = 3;
131
0
                break;
132
0
              case 'a':
133
0
                bo = 5;
134
0
                break;
135
0
              default :
136
0
                bo = 1;
137
0
                break;
138
0
              }
139
0
            mol.AddBond(mol.NumAtoms(), atoi((char *)vs[i].c_str()), bo);
140
0
          }
141
0
        ifs.getline(buffer, BUFF_SIZE);
142
0
      }
143
144
    // clean out remaining blank lines
145
    // blank lines cleaning codes rewritten for avoiding peek() and tellg() bugs
146
    // https://github.com/openbabel/openbabel/issues/1569
147
5
    std::streampos ipos;
148
5
    do
149
5
    {
150
5
      ipos = ifs.tellg();
151
5
      ifs.getline(buffer,BUFF_SIZE);
152
5
    }
153
5
    while(strlen(buffer) == 0 && !ifs.eof() );
154
5
    ifs.seekg(ipos);
155
156
157
5
    mol.EndModify();
158
159
5
    mol.SetTitle(title);
160
5
    mol.SetPartialChargesPerceived();
161
162
5
    return(true);
163
5
  }
164
165
  ////////////////////////////////////////////////////////////////
166
167
  bool HINFormat::WriteMolecule(OBBase* pOb, OBConversion* pConv)
168
232
  {
169
232
    OBMol* pmol = dynamic_cast<OBMol*>(pOb);
170
232
    if (pmol == nullptr)
171
0
      return false;
172
173
    //Define some references so we can use the old parameter names
174
232
    ostream &ofs = *pConv->GetOutStream();
175
232
    OBMol &mol = *pmol;
176
177
232
    unsigned int i, file_num = 1;
178
232
    string str,str1;
179
232
    char buffer[BUFF_SIZE];
180
232
    OBAtom *atom;
181
232
    OBBond *bond;
182
232
    vector<OBBond*>::iterator j;
183
232
    char bond_char;
184
185
    // make sure to escape titles in double quotes
186
    // PR#1501694
187
232
    ofs << "mol " << file_num << " \"" << mol.GetTitle() << "\"\n";
188
189
12.9k
    for(i = 1;i <= mol.NumAtoms(); i++)
190
12.7k
      {
191
12.7k
        atom = mol.GetAtom(i);
192
12.7k
        snprintf(buffer, BUFF_SIZE, "atom %d - %-3s **  - %8.5f %8.5f  %8.5f  %8.5f %d ",
193
12.7k
                i,
194
12.7k
                OBElements::GetSymbol(atom->GetAtomicNum()),
195
12.7k
                atom->GetPartialCharge(),
196
12.7k
                atom->GetX(),
197
12.7k
                atom->GetY(),
198
12.7k
                atom->GetZ(),
199
12.7k
                atom->GetExplicitDegree());
200
12.7k
        ofs << buffer;
201
37.3k
        for (bond = atom->BeginBond(j); bond; bond = atom->NextBond(j))
202
24.6k
          {
203
24.6k
            switch(bond->GetBondOrder())
204
24.6k
              {
205
22.4k
              case 1 :
206
22.4k
                bond_char = 's';
207
22.4k
                break;
208
2.23k
              case 2 :
209
2.23k
                bond_char = 'd';
210
2.23k
                break;
211
2
              case 3 :
212
2
                bond_char = 't';
213
2
                break;
214
0
              case 5 :
215
0
                bond_char = 'a';
216
0
                break;
217
0
              default:
218
0
                bond_char = 's';
219
0
                break;
220
24.6k
              }
221
24.6k
            if (bond->IsAromatic())
222
2.57k
              bond_char = 'a';
223
224
24.6k
            snprintf(buffer,BUFF_SIZE, "%d %c ", (bond->GetNbrAtom(atom))->GetIdx(), bond_char);
225
24.6k
            ofs << buffer;
226
24.6k
          }
227
12.7k
        ofs << endl;
228
12.7k
      }
229
232
    ofs << "endmol " << file_num << endl;
230
232
    return(true);
231
232
  }
232
233
} //namespace OpenBabel