Coverage Report

Created: 2025-08-26 06:55

/src/openbabel/src/formats/chemdrawct.cpp
Line
Count
Source (jump to first uncovered line)
1
/**********************************************************************
2
Copyright (C) 1998-2001 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
#include <openbabel/obmolecformat.h>
17
#include <openbabel/mol.h>
18
#include <openbabel/atom.h>
19
#include <openbabel/bond.h>
20
#include <openbabel/elements.h>
21
22
#include <cstdlib>
23
24
using namespace std;
25
namespace OpenBabel
26
{
27
28
  class ChemDrawFormat : public OBMoleculeFormat
29
  {
30
  public:
31
    //Register this format type ID
32
    ChemDrawFormat()
33
6
    {
34
6
      OBConversion::RegisterFormat("ct",this);
35
6
    }
36
37
    const char* Description() override  // required
38
0
    {
39
0
      return
40
0
        "ChemDraw Connection Table format\n"
41
0
        "No comments yet\n";
42
0
    }
43
44
    const char* SpecificationURL() override
45
0
    { return ""; }  // optional
46
47
    //Flags() can return be any the following combined by | or be omitted if none apply
48
    // NOTREADABLE  READONEONLY  NOTWRITABLE  WRITEONEONLY
49
    unsigned int Flags() override
50
6
    {
51
6
      return READONEONLY | WRITEONEONLY;
52
6
    }
53
54
    //*** This section identical for most OBMol conversions ***
55
    ////////////////////////////////////////////////////
56
    /// The "API" interface functions
57
    bool ReadMolecule(OBBase* pOb, OBConversion* pConv) override;
58
    bool WriteMolecule(OBBase* pOb, OBConversion* pConv) override;
59
  };
60
  //***
61
62
  //Make an instance of the format class
63
  ChemDrawFormat theChemDrawFormat;
64
65
  ////////////////////////////////////////////////////////////////
66
67
  bool ChemDrawFormat::WriteMolecule(OBBase* pOb, OBConversion* pConv)
68
0
  {
69
0
    OBMol* pmol = dynamic_cast<OBMol*>(pOb);
70
0
    if (pmol == nullptr)
71
0
      return false;
72
73
    //Define some references so we can use the old parameter names
74
0
    ostream &ofs = *pConv->GetOutStream();
75
0
    OBMol &mol = *pmol;
76
77
0
    char buffer[BUFF_SIZE];
78
79
0
    ofs << mol.GetTitle() << endl;
80
0
    ofs << " " << mol.NumAtoms() << " " << mol.NumBonds() << endl;
81
82
0
    OBAtom *atom;
83
0
    vector<OBAtom*>::iterator i;
84
85
0
    for(atom = mol.BeginAtom(i);atom;atom = mol.NextAtom(i))
86
0
      {
87
0
        snprintf(buffer, BUFF_SIZE, " %9.4f %9.4f    0.0000 %-1s",
88
0
                 atom->x(),
89
0
                 atom->y(),
90
0
                 OBElements::GetSymbol(atom->GetAtomicNum()));
91
0
        ofs << buffer << endl;
92
0
      }
93
94
0
    OBBond *bond;
95
0
    vector<OBBond*>::iterator j;
96
97
0
    for(bond = mol.BeginBond(j);bond;bond = mol.NextBond(j))
98
0
      {
99
0
        snprintf(buffer, BUFF_SIZE, "%3d%3d%3d%3d",
100
0
                 bond->GetBeginAtomIdx(),
101
0
                 bond->GetEndAtomIdx(),
102
0
                 bond->GetBondOrder(), bond->GetBondOrder());
103
0
        ofs << buffer << endl;
104
0
      }
105
0
    return(true);
106
0
  }
107
108
  bool ChemDrawFormat::ReadMolecule(OBBase* pOb, OBConversion* pConv)
109
0
  {
110
0
    OBMol* pmol = pOb->CastAndClear<OBMol>();
111
0
    if (pmol == nullptr)
112
0
      return false;
113
114
    //Define some references so we can use the old parameter names
115
0
    istream &ifs = *pConv->GetInStream();
116
0
    OBMol &mol = *pmol;
117
0
    const char* title = pConv->GetTitle();
118
119
0
    char buffer[BUFF_SIZE];
120
0
    unsigned int natoms, nbonds;
121
0
    unsigned int bgn, end, order;
122
0
    vector<string> vs;
123
0
    OBAtom *atom;
124
0
    double x, y, z;
125
126
0
    mol.SetDimension(2);
127
0
    mol.BeginModify();
128
129
0
    ifs.getline(buffer,BUFF_SIZE);
130
0
    if (strlen(buffer) == 0)
131
0
      mol.SetTitle(buffer);
132
0
    else
133
0
      mol.SetTitle(title);
134
135
0
    ifs.getline(buffer,BUFF_SIZE);
136
0
    sscanf(buffer," %d %d", &natoms, &nbonds);
137
138
0
    for (unsigned int i = 1; i <= natoms; i ++)
139
0
      {
140
0
        if (!ifs.getline(buffer,BUFF_SIZE)) return(false);
141
0
        tokenize(vs,buffer);
142
0
        if (vs.size() != 4) return(false);
143
0
        atom = mol.NewAtom();
144
145
0
        x = atof((char*)vs[0].c_str());
146
0
        y = atof((char*)vs[1].c_str());
147
0
        z = atof((char*)vs[2].c_str());
148
149
0
        atom->SetVector(x,y,z); //set coordinates
150
0
        atom->SetAtomicNum(OBElements::GetAtomicNum(vs[3].c_str()));
151
0
      }
152
153
0
    if (nbonds != 0)
154
0
      for (unsigned int i = 0; i < nbonds; i++)
155
0
        {
156
0
          if (!ifs.getline(buffer,BUFF_SIZE)) return(false);
157
0
          tokenize(vs,buffer);
158
0
          if (vs.size() != 4) return(false);
159
0
          if (!sscanf(buffer,"%d%d%d%*d",&bgn,&end,&order)) return (false);
160
0
          mol.AddBond(bgn,end,order);
161
0
        }
162
163
    // clean out remaining blank lines
164
0
    std::streampos ipos;
165
0
    do
166
0
    {
167
0
      ipos = ifs.tellg();
168
0
      ifs.getline(buffer,BUFF_SIZE);
169
0
    }
170
0
    while(strlen(buffer) == 0 && !ifs.eof() );
171
0
    ifs.seekg(ipos);
172
173
0
    mol.EndModify();
174
0
    return(true);
175
0
  }
176
177
178
} //namespace OpenBabel