void MoleculeCdxmlSaver::writeBinaryValue()

in core/indigo-core/molecule/src/molecule_cdxml_saver.cpp [135:351]


void MoleculeCdxmlSaver::writeBinaryValue(const XMLAttribute* pAttr, int16_t tag, ECDXType cdx_type)
{
    _output.writeBinaryUInt16(tag);
    switch (cdx_type)
    {
    case ECDXType::CDXString: {
        std::string val = pAttr->Value();
        uint16_t styles = 0;
        _output.writeBinaryUInt16(static_cast<uint16_t>(val.size() + sizeof(styles)));
        _output.writeBinaryUInt16(styles);
        _output.write(val.data(), static_cast<int>(val.size()));
    }
    break;

    case ECDXType::CDXUINT8:
    case ECDXType::CDXINT8: {
        int8_t val;
        switch (tag)
        {
        case kCDXProp_CaptionJustification:
        case kCDXProp_Justification:
        case kCDXProp_LabelJustification:
            val = kTextJustificationStrToInt.at(pAttr->Value());
            break;
        case kCDXProp_LabelAlignment:
        case kCDXProp_Node_LabelDisplay:
            val = kLabelAlignmentStrToInt.at(pAttr->Value());
            break;
        case kCDXProp_Atom_Radical:
            val = static_cast<int8_t>(kRadicalStrToId.at(pAttr->Value()));
            break;
        case kCDXProp_Bond_CIPStereochemistry:
            val = kCIPBondStereochemistryIndexToChar.at(pAttr->Value()[0]);
            break;
        case kCDXProp_Atom_CIPStereochemistry:
            val = kCIPStereochemistryCharToIndex.at(pAttr->Value()[0]);
            break;
        case kCDXProp_Arrow_Type:
            val = static_cast<int8_t>(kCDXProp_Arrow_TypeStrToID.at(pAttr->Value()));
            break;
        case kCDXProp_Atom_Geometry:
            val = static_cast<int8_t>(KGeometryTypeNameToInt.at(pAttr->Value()));
            break;
        case kCDXProp_Atom_EnhancedStereoType:
            val = static_cast<int8_t>(kCDXEnhancedStereoStrToID.at(pAttr->Value()));
            break;
        default:
            val = static_cast<int8_t>(pAttr->IntValue());
            break;
        }
        _output.writeBinaryUInt16(sizeof(val));
        _output.writeByte(val);
    }
    break;

    case ECDXType::CDXINT16:
    case ECDXType::CDXUINT16: {
        int16_t val = static_cast<int16_t>(pAttr->IntValue());
        switch (tag)
        {
        case kCDXProp_Node_Type:
            val = static_cast<int16_t>(KNodeTypeNameToInt.at(pAttr->Value()));
            break;
        case kCDXProp_Graphic_Type:
            val = static_cast<int16_t>(kCDXPropGraphicTypeStrToID.at(pAttr->Value()));
            break;
        case kCDXProp_Rectangle_Type: {
            auto vecs = split(pAttr->Value(), ' ');
            for (auto str_val : vecs)
                val |= kRectangleTypeStrToInt.at(str_val);
        }
        break;
        case kCDXProp_BondSpacing:
            val *= kBondSpacingMultiplier;
            break;
        case kCDXProp_Line_Type:
            val = static_cast<int16_t>(kLineTypeStrToInt.at(pAttr->Value()));
            break;
        case kCDXProp_Arrow_Type:
            val = static_cast<int16_t>(kCDXProp_Arrow_TypeStrToID.at(pAttr->Value()));
            break;
        case kCDXProp_Arrow_ArrowHead_Head:
        case kCDXProp_Arrow_ArrowHead_Tail:
            val = kCDXProp_Arrow_ArrowHeadStrToInt.at(pAttr->Value());
            break;
        case kCDXProp_Arrowhead_Type: {
            auto it = kCDXProp_Arrow_ArrowHeadTypeStrToInt.find(pAttr->Value());
            if (it != kCDXProp_Arrow_ArrowHeadTypeStrToInt.end())
                val = it->second;
            break;
        }
        case kCDXProp_Symbol_Type: {
            auto it = kCDXPropSymbolTypeStrToID.find(pAttr->Value());
            if (it != kCDXPropSymbolTypeStrToID.end())
                val = it->second;
            break;
        }
        case kCDXProp_Bond_Display:
        case kCDXProp_Bond_Display2:
            val = static_cast<int16_t>(kCDXProp_Bond_DisplayStrToID.at(pAttr->Value()));
            break;
        case kCDXProp_Bond_Order: {
            auto vals = split(pAttr->Value(), ' ');
            val = 0;
            for (auto& value : vals)
            {
                val |= static_cast<int16_t>(kBondOrderStrToId.at(value));
            }
            if (val == 0)
                val = -1;
        }
        break;
        }

        _output.writeBinaryUInt16(sizeof(val));
        _output.writeBinaryUInt16(val);
    }
    break;

    case ECDXType::CDXINT32:
    case ECDXType::CDXUINT32: {
        int32_t val = pAttr->IntValue();
        if (tag == kCDXProp_ChainAngle)
            val <<= 16;
        _output.writeBinaryUInt16(sizeof(val));
        _output.writeBinaryInt(val);
    }
    break;

    case ECDXType::CDXPoint3D:
    case ECDXType::CDXPoint2D:
    case ECDXType::CDXRectangle: {
        std::string values = pAttr->Value();
        auto vec_strs = split(values, ' ');
        if (vec_strs.size() % 2 == 0)
        {
            for (size_t i = 0; i < vec_strs.size(); i += 2)
                std::swap(vec_strs[i], vec_strs[i + 1]);
        }

        _output.writeBinaryUInt16(static_cast<uint16_t>(sizeof(int32_t) * vec_strs.size()));

        for (const auto& v : vec_strs)
        {
            int32_t coord = static_cast<int32_t>(std::stof(v) * (1 << 16));
            _output.writeBinaryInt(coord);
        }
    }
    break;

    case ECDXType::CDXCoordinate: {
        int32_t coord = static_cast<int32_t>(pAttr->FloatValue() * (1 << 16));
        _output.writeBinaryUInt16(sizeof(coord));
        _output.writeBinaryInt(coord);
    }
    break;

    case ECDXType::CDXBooleanImplied:
    case ECDXType::CDXBoolean: {
        uint8_t val = std::string(pAttr->Value()) == "yes" ? 1 : 0;
        _output.writeBinaryUInt16(sizeof(val));
        _output.writeByte(val);
    }
    break;

    case ECDXType::CDXObjectID: {
        uint32_t val = pAttr->IntValue();
        _output.writeBinaryUInt16(sizeof(val));
        _output.writeBinaryInt(val);
    }
    break;
    case ECDXType::CDXUnformatted: {
        std::string values = pAttr->Value();
        std::vector<uint8_t> bytes_vector;
        for (size_t i = 0; i < values.size(); i += 2)
        {
            uint32_t val;
            std::string hex_str = values.substr(i, 2);
            std::stringstream converter;
            converter << std::hex << hex_str;
            converter >> val;
            bytes_vector.push_back(static_cast<uint8_t>(val));
        }
        _output.writeBinaryUInt16(static_cast<uint16_t>(bytes_vector.size()));
        _output.write(bytes_vector.data(), static_cast<int>(bytes_vector.size()));
    }
    break;

    case ECDXType::CDXObjectIDArray: {
        std::string values = pAttr->Value();
        auto vals = split(values, ' ');
        _output.writeBinaryUInt16(static_cast<uint16_t>(vals.size() * sizeof(int32_t)));
        for (const auto& val : vals)
            _output.writeBinaryInt(std::stoi(val));
    }
    break;

    case ECDXType::CDXDate:
    case ECDXType::CDXRepresentsProperty:
    case ECDXType::CDXFontTable:
    case ECDXType::CDXColorTable:
    case ECDXType::CDXElementList:
    case ECDXType::CDXFormula:
    case ECDXType::CDXObjectIDArrayWithCounts:
    case ECDXType::CDXGenericList:
    case ECDXType::CDXFLOAT64:
    case ECDXType::CDXINT16ListWithCounts:
    case ECDXType::CDXCurvePoints:
    case ECDXType::CDXCurvePoints3D:
    case ECDXType::CDXvaries:
    case ECDXType::CDXFontStyle:
        throw Error("Unsupported type: %d", cdx_type);
        break;
    default:
        break;
    }
}