void CmfLoader::loadMolecule()

in core/indigo-core/molecule/src/cmf_loader.cpp [406:715]


void CmfLoader::loadMolecule(Molecule& mol)
{
    int code;

    mol.clear();

    QS_DEF(Array<int>, cycle_numbers);
    QS_DEF(Array<int>, atom_stack);

    _atoms.clear();
    _bonds.clear();
    _pseudo_labels.clear();
    _attachments.clear();
    cycle_numbers.clear();
    atom_stack.clear();

    bool first_atom = true;

    if (!_getNextCode(code))
        return;

    bool has_ext_part = false;

    /* Main loop */
    do
    {
        _BondDesc* bond = 0;

        if (code > CMF_ALPHABET_SIZE)
            throw Error("unexpected code");

        if (code == CMF_TERMINATOR)
            break;

        if (code == CMF_EXT)
        {
            has_ext_part = true;
            // Ext part has to be read till CMF_TERMINATOR
            break;
        }

        if (!first_atom)
        {
            int number;

            while (_readCycleNumber(code, number))
            {
                while (cycle_numbers.size() <= number)
                    cycle_numbers.push(-1);

                if (cycle_numbers[number] >= 0)
                    throw Error("cycle #%d already in use", number);

                cycle_numbers[number] = atom_stack.top();

                if (!_getNextCode(code))
                    break;
            }
        }

        if (code == CMF_SEPARATOR)
        {
            atom_stack.pop();
            first_atom = true;

            if (!_getNextCode(code))
                break;

            continue;
        }

        if (code == CMF_OPEN_BRACKET)
        {
            atom_stack.push(atom_stack.top());

            if (!_getNextCode(code))
                break;

            continue;
        }

        if (code == CMF_CLOSE_BRACKET)
        {
            atom_stack.pop();

            if (!_getNextCode(code))
                break;

            continue;
        }

        if (!first_atom)
        {
            bond = &_bonds.push();
            bond->beg = atom_stack.top();
        }

        if (bond != 0)
        {
            _readBond(code, *bond);

            int number;

            if (_readCycleNumber(code, number))
            {
                if (cycle_numbers[number] < 0)
                    throw Error("bad cycle number after bond symbol");

                bond->end = cycle_numbers[number];
                cycle_numbers[number] = -1;

                if (!_getNextCode(code))
                    break;

                continue;
            }
        }

        _AtomDesc& atom = _atoms.push();

        if (!first_atom)
            atom_stack.pop();

        atom_stack.push(_atoms.size() - 1);

        first_atom = false;

        if (bond != 0)
            bond->end = _atoms.size() - 1;

        memset(&atom, 0, sizeof(_AtomDesc));
        atom.hydrogens = -1;
        atom.valence = -1;
        atom.pseudo_atom_idx = -1;
        atom.rsite = false;

        if (code > 0 && (code < ELEM_MAX || code == CMF_PSEUDOATOM || code == CMF_RSITE || code == CMF_RSITE_EXT))
        {
            if (!_readAtom(code, atom, _atoms.size() - 1))
                break;
            continue;
        }

        if (!_getNextCode(code))
            break;

    } while (true);

    // if have internal decoder, finish it
    /*   if (_decoder_obj.get() != 0)
          _decoder_obj->finish(); */

    /* Reading finished, filling molecule */

    int i;

    for (i = 0; i < _atoms.size(); i++)
    {
        mol.addAtom(_atoms[i].label);

        if (_atoms[i].pseudo_atom_idx >= 0)
            mol.setPseudoAtom(i, _pseudo_labels.at(_atoms[i].pseudo_atom_idx));

        if (_atoms[i].rsite_bits > 0)
            mol.setRSiteBits(i, _atoms[i].rsite_bits);

        mol.setAtomCharge(i, _atoms[i].charge);
        mol.setAtomIsotope(i, _atoms[i].isotope);
        if (_atoms[i].hydrogens >= 0)
            mol.setImplicitH(i, _atoms[i].hydrogens);
        mol.setAtomRadical(i, _atoms[i].radical);

        if (_atoms[i].highlighted)
            mol.highlightAtom(i);
    }

    for (i = 0; i < _bonds.size(); i++)
    {
        int type = _bonds[i].type;
        int beg = _bonds[i].beg;
        int end = _bonds[i].end;

        if (_bonds[i].swap)
            std::swap(beg, end);

        int idx = mol.addBond_Silent(beg, end, type);

        if (_bonds[i].in_ring)
            mol.setEdgeTopology(idx, TOPOLOGY_RING);
        else
            mol.setEdgeTopology(idx, TOPOLOGY_CHAIN);

        if (_bonds[i].direction != 0)
            mol.setBondDirection(idx, _bonds[i].direction);

        if (_bonds[i].highlighted)
            mol.highlightBond(idx);
    }

    for (i = 0; i < _attachments.size(); i++)
        mol.addAttachmentPoint(_attachments[i].index, _attachments[i].atom);

    mol.validateEdgeTopologies();

    if (has_ext_part)
        _readExtSection(mol);

    if (atom_flags != 0)
    {
        atom_flags->clear();

        for (i = 0; i < _atoms.size(); i++)
            atom_flags->push(_atoms[i].flags);
    }

    if (bond_flags != 0)
    {
        bond_flags->clear();

        for (i = 0; i < _bonds.size(); i++)
            bond_flags->push(_bonds[i].flags);
    }

    if (!skip_cistrans)
    {
        for (i = 0; i < _bonds.size(); i++)
        {
            if (_bonds[i].cis_trans != 0)
            {
                int parity = _bonds[i].cis_trans;
                if (parity > 0)
                    mol.cis_trans.setParity(i, _bonds[i].cis_trans);
                else
                    mol.cis_trans.ignore(i);
                mol.restoreSubstituents(i);
            }
        }
    }

    if (!skip_valence)
    {
        for (i = 0; i < _atoms.size(); i++)
        {
            if (_atoms[i].valence >= 0)
                mol.setValence(i, _atoms[i].valence);
        }
    }

    if (!skip_stereocenters)
    {
        for (i = 0; i < _atoms.size(); i++)
        {
            if (_atoms[i].stereo_type != 0)
                mol.addStereocenters(i, _atoms[i].stereo_type, _atoms[i].stereo_group, _atoms[i].stereo_invert_pyramid);
        }
    }

    for (i = 0; i < _atoms.size(); i++)
    {
        if (_atoms[i].allene_stereo_parity != 0)
        {
            int left, right, subst[4];
            bool pure_h[4];
            int parity = _atoms[i].allene_stereo_parity;

            if (!MoleculeAlleneStereo::possibleCenter(mol, i, left, right, subst, pure_h))
                throw Error("invalid molecule allene stereo marker");

            if (subst[1] != -1 && subst[1] < subst[0])
                std::swap(subst[1], subst[0]);

            if (subst[3] != -1 && subst[3] < subst[2])
                std::swap(subst[3], subst[2]);

            if (pure_h[0])
            {
                std::swap(subst[1], subst[0]);
                parity = 3 - parity;
            }
            if (pure_h[2])
            {
                std::swap(subst[2], subst[3]);
                parity = 3 - parity;
            }

            mol.allene_stereo.add(i, left, right, subst, parity);
        }
    }

    // for loadXyz()
    _mol = &mol;

    // Check if atom mapping was used
    if (has_mapping)
    {
        // Compute inv_atom_mapping_to_restore
        inv_atom_mapping_to_restore.clear_resize(atom_mapping_to_restore.size());
        for (i = 0; i < atom_mapping_to_restore.size(); i++)
            inv_atom_mapping_to_restore[atom_mapping_to_restore[i]] = i;

        // Compute inv_bond_mapping_to_restore
        inv_bond_mapping_to_restore.clear_resize(bond_mapping_to_restore.size());
        for (i = 0; i < bond_mapping_to_restore.size(); i++)
            inv_bond_mapping_to_restore[bond_mapping_to_restore[i]] = i;

        QS_DEF(Molecule, tmp);
        tmp.makeEdgeSubmolecule(mol, atom_mapping_to_restore, bond_mapping_to_restore, NULL);
        mol.clone(tmp, NULL, NULL);
    }
}