bool CmfLoader::_readAtom()

in core/indigo-core/molecule/src/cmf_loader.cpp [89:284]


bool CmfLoader::_readAtom(int& code, _AtomDesc& atom, int atom_idx)
{
    if (code > 0 && code < ELEM_MAX)
        atom.label = code;
    else if (code == CMF_PSEUDOATOM)
    {
        int len;

        if (!_getNextCode(len))
            throw Error("pseudo-atom identifier must be followed by length");

        if (len < 1)
            throw Error("empty pseudo-atom");

        atom.pseudo_atom_idx = _pseudo_labels.add(len + 1);
        char* label = _pseudo_labels.at(atom.pseudo_atom_idx);

        for (int i = 0; i < len; i++)
        {
            int c;
            if (!_getNextCode(c))
                throw Error("pseudo-atom label is incomplete");
            label[i] = static_cast<char>(c);
        }

        label[len] = 0;
    }
    else if (code == CMF_RSITE)
    {
        atom.label = ELEM_RSITE;
        _getNextCode(atom.rsite_bits);
    }
    else if (code == CMF_RSITE_EXT)
    {
        atom.label = ELEM_RSITE;
        atom.rsite_bits = (int)_scanner->readPackedUInt();
    }
    else
        throw Error("bad atom number: %d", code);

    if (!_getNextCode(code))
        return false;

    if (code >= CMF_CHARGES && code < CMF_CHARGES + CMF_NUM_OF_CHARGES && code != CMF_SEPARATOR)
    {
        int charge = code - CMF_CHARGES;

        charge += CMF_MIN_CHARGE;

        atom.charge = charge;

        if (!_getNextCode(code))
            return false;
    }

    if (code == CMF_CHARGE_EXT)
    {
        int charge;
        _getNextCode(charge);
        charge -= 128;
        atom.charge = charge;

        if (!_getNextCode(code))
            return false;
    }

    if (code >= CMF_ISOTOPE_ZERO && code <= CMF_ISOTOPE_OTHER)
    {
        int deviation;

        if (code == CMF_ISOTOPE_ZERO)
            deviation = 0;
        else if (code == CMF_ISOTOPE_PLUS1)
            deviation = 1;
        else if (code == CMF_ISOTOPE_PLUS2)
            deviation = 2;
        else if (code == CMF_ISOTOPE_MINUS1)
            deviation = -1;
        else if (code == CMF_ISOTOPE_MINUS2)
            deviation = -2;
        else // CMF_ISOTOPE_OTHER
        {
            if (!_getNextCode(code))
                throw Error("expecting mass difference");

            deviation = code - 100;
        }

        atom.isotope = Element::getDefaultIsotope(atom.label) + deviation;

        if (!_getNextCode(code))
            return false;
    }

    if (code >= CMF_RADICAL_SINGLET && code <= CMF_RADICAL_TRIPLET)
    {
        if (code == CMF_RADICAL_SINGLET)
            atom.radical = RADICAL_SINGLET;
        else if (code == CMF_RADICAL_DOUBLET)
            atom.radical = RADICAL_DOUBLET;
        else // code == CMF_RADICAL_TRIPLET
            atom.radical = RADICAL_TRIPLET;

        if (!_getNextCode(code))
            return false;
    }

    if (code >= CMF_STEREO_ANY && code <= CMF_STEREO_ABS_1)
    {
        if (code >= CMF_STEREO_AND_1)
        {
            /* CMF_STEREO_*_1 -> CMF_STEREO_*_0 */
            code -= CMF_MAX_STEREOGROUPS * 2 + 1;
            atom.stereo_invert_pyramid = true;
        }

        if (code == CMF_STEREO_ANY)
            atom.stereo_type = MoleculeStereocenters::ATOM_ANY;
        else if (code == CMF_STEREO_ABS_0)
            atom.stereo_type = MoleculeStereocenters::ATOM_ABS;
        else if (code < CMF_STEREO_OR_0)
        {
            atom.stereo_type = MoleculeStereocenters::ATOM_AND;
            atom.stereo_group = code - CMF_STEREO_AND_0 + 1;
        }
        else
        {
            atom.stereo_type = MoleculeStereocenters::ATOM_OR;
            atom.stereo_group = code - CMF_STEREO_OR_0 + 1;
        }
        if (!_getNextCode(code))
            return false;
    }

    if (code == CMF_STEREO_ALLENE_0 || code == CMF_STEREO_ALLENE_1)
    {
        if (code == CMF_STEREO_ALLENE_0)
            atom.allene_stereo_parity = 1;
        else
            atom.allene_stereo_parity = 2;
        if (!_getNextCode(code))
            return false;
    }

    if (code >= CMF_IMPLICIT_H && code <= CMF_IMPLICIT_H + CMF_MAX_IMPLICIT_H)
    {
        atom.hydrogens = code - CMF_IMPLICIT_H;
        if (!_getNextCode(code))
            return false;
    }

    if (code >= CMF_VALENCE && code <= CMF_VALENCE + CMF_MAX_VALENCE)
    {
        atom.valence = code - CMF_VALENCE;
        if (!_getNextCode(code))
            return false;
    }

    if (code == CMF_VALENCE_EXT)
    {
        atom.valence = (int)_scanner->readPackedUInt();
        if (!_getNextCode(code))
            return false;
    }

    while (code == CMF_ATTACHPT)
    {
        int aidx;

        if (!_getNextCode(aidx))
            throw Error("expected attachment index");

        _AttachmentDesc& att = _attachments.push();
        att.atom = atom_idx;
        att.index = aidx;

        if (!_getNextCode(code))
            return false;
    }

    while (code >= CMF_ATOM_FLAGS && code < CMF_ATOM_FLAGS + CMF_NUM_OF_ATOM_FLAGS)
    {
        atom.flags |= (1 << (code - CMF_ATOM_FLAGS));
        if (!_getNextCode(code))
            return false;
    }

    if (code == CMF_HIGHLIGHTED)
    {
        atom.highlighted = true;
        if (!_getNextCode(code))
            return false;
    }

    return true;
}