Coverage Report

Created: 2026-09-04 07:10

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openbabel/src/formats/cccformat.cpp
Line
Count
Source
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
17
#include <openbabel/obmolecformat.h>
18
#include <openbabel/mol.h>
19
#include <openbabel/atom.h>
20
#include <openbabel/elements.h>
21
#include <cstdlib>
22
23
24
using namespace std;
25
namespace OpenBabel
26
{
27
28
class CCCFormat : public OBMoleculeFormat
29
{
30
public:
31
    //Register this format type ID
32
    CCCFormat()
33
12
    {
34
12
        OBConversion::RegisterFormat("ccc",this);
35
12
    }
36
37
    const char* Description() override  // required
38
0
    {
39
0
        return
40
0
          "CCC 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
13
    {
51
13
        return NOTWRITABLE;
52
13
    }
53
54
    ////////////////////////////////////////////////////
55
    /// The "API" interface functions
56
    bool ReadMolecule(OBBase* pOb, OBConversion* pConv) override;
57
58
 };
59
60
//Make an instance of the format class
61
CCCFormat theCCCFormat;
62
63
/////////////////////////////////////////////////////////////////
64
bool CCCFormat::ReadMolecule(OBBase* pOb, OBConversion* pConv)
65
0
{
66
67
0
    OBMol* pmol = pOb->CastAndClear<OBMol>();
68
0
    if (pmol == nullptr)
69
0
        return false;
70
71
    //Define some references so we can use the old parameter names
72
0
    istream &ifs = *pConv->GetInStream();
73
0
    OBMol &mol = *pmol;
74
0
    mol.SetTitle( pConv->GetTitle()); //default title is the filename
75
76
0
    char buffer[BUFF_SIZE];
77
0
    ifs.getline(buffer,BUFF_SIZE);
78
79
0
    if (strlen(buffer) > 5)
80
0
        mol.SetTitle(&buffer[5]);
81
0
    mol.SetEnergy(0.0);
82
83
0
    int natoms = 0;
84
0
    ifs.getline(buffer,BUFF_SIZE);
85
0
    sscanf(buffer,"%*s%d",&natoms);
86
0
    if (natoms < 1 || natoms >= 100000000)
87
0
      return(false);
88
0
    mol.ReserveAtoms(natoms);
89
0
    mol.BeginModify();
90
91
0
    int end,order;
92
0
    double x,y,z;
93
0
    OBAtom atom;
94
0
    vector3 v;
95
0
    vector<string> vs;
96
0
    char element[3];
97
0
    element[2] = '\0';
98
99
0
    for (int i = 1;i <= natoms;i++)
100
0
    {
101
0
        if (!ifs.getline(buffer,BUFF_SIZE))
102
0
            return(false);
103
        // This is a fixed-column format: the element symbol is in columns
104
        // 0-1, the coordinates start at column 15, and the bond list starts
105
        // at column 60.  Bounds-check the line length before indexing so we
106
        // never parse past the end of the (terminated) line into stale memory.
107
0
        size_t linelen = strlen(buffer);
108
0
        if (linelen < 15)
109
0
        {
110
0
            obErrorLog.ThrowError(__FUNCTION__,
111
0
                                  "Problems reading a CCC file: truncated atom "
112
0
                                  "record (missing coordinates).", obError);
113
0
            return(false);
114
0
        }
115
0
        atom.Clear();
116
0
        element[0] = buffer[0];
117
0
        element[1] = (buffer[1] != ' ') ? buffer[1]:'\0';
118
0
        atom.SetAtomicNum(OBElements::GetAtomicNum(element));
119
0
        x = y = z = 0.0;
120
0
        if (sscanf(&buffer[15],"%lf%lf%lf",&x,&y,&z) != 3)
121
0
        {
122
0
            obErrorLog.ThrowError(__FUNCTION__,
123
0
                                  "Problems reading a CCC file: could not parse "
124
0
                                  "atom coordinates.", obError);
125
0
            return(false);
126
0
        }
127
0
        v.Set(x,y,z);
128
0
        atom.SetVector(v);
129
130
0
        if (!mol.AddAtom(atom))
131
0
            return(false);
132
        // The bond list is optional; only parse it when the line is long
133
        // enough, and clear vs otherwise so bonds do not leak across atoms.
134
0
        vs.clear();
135
0
        if (linelen > 60)
136
0
            tokenize(vs,&buffer[60]);
137
0
        vector<string>::iterator j;
138
139
0
        for (j = vs.begin();j != vs.end();++j)
140
0
            if (!j->empty())
141
0
            {
142
                //get the bond order
143
0
                switch((char)(*j)[j->size()-1])
144
0
                {
145
0
                case 'S':
146
0
                    order = 1;
147
0
                    break;
148
0
                case 'D':
149
0
                    order = 2;
150
0
                    break;
151
0
                case 'T':
152
0
                    order = 3;
153
0
                    break;
154
0
                default:
155
0
                    order = 1;
156
0
                }
157
0
                (*j)[j->size()-1] = ' ';
158
0
                end = atoi(j->c_str());
159
0
                if (i>end)
160
0
                    mol.AddBond(i,end,order);
161
0
            }
162
0
    }
163
164
0
    mol.EndModify();
165
0
    return(true);
166
0
}
167
168
} //namespace OpenBabel