Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 12:55:07

0001 #include "DetectorDescription/Parser/src/DDLMap.h"
0002 #include "DetectorDescription/Core/interface/ClhepEvaluator.h"
0003 #include "DetectorDescription/Parser/interface/DDLElementRegistry.h"
0004 
0005 // Boost parser, spirit, for parsing the std::vector elements.
0006 #include "boost/spirit/home/classic/core/non_terminal/grammar.hpp"
0007 #include "boost/spirit/include/classic.hpp"
0008 
0009 #include <cstddef>
0010 #include <utility>
0011 
0012 class DDCompactView;
0013 
0014 class MapPair {
0015 public:
0016   MapPair(DDLMap* iMap) : map_{iMap} {};
0017   void operator()(char const* str, char const* end) const;
0018 
0019 private:
0020   DDLMap* map_;
0021 };
0022 
0023 class MapMakeName {
0024 public:
0025   MapMakeName(DDLMap* iMap) : map_{iMap} {};
0026   void operator()(char const* str, char const* end) const;
0027 
0028 private:
0029   DDLMap* map_;
0030 };
0031 
0032 class MapMakeDouble {
0033 public:
0034   MapMakeDouble(DDLMap* iMap) : map_{iMap} {};
0035   void operator()(char const* str, char const* end) const;
0036 
0037 private:
0038   DDLMap* map_;
0039 };
0040 
0041 class Mapper : public boost::spirit::classic::grammar<Mapper> {
0042 public:
0043   Mapper(DDLMap* iMap) : map_{iMap} {};
0044   template <typename ScannerT>
0045   struct definition;
0046 
0047   MapPair mapPair() const { return MapPair(map_); }
0048   MapMakeName mapMakeName() const { return MapMakeName(map_); }
0049   MapMakeDouble mapMakeDouble() const { return MapMakeDouble(map_); }
0050 
0051 private:
0052   DDLMap* map_;
0053 };
0054 
0055 namespace boost {
0056   namespace spirit {
0057     namespace classic {}
0058   }  // namespace spirit
0059 }  // namespace boost
0060 
0061 using namespace boost::spirit::classic;
0062 
0063 DDLMap::DDLMap(DDLElementRegistry* myreg) : DDXMLElement(myreg) {}
0064 
0065 template <typename ScannerT>
0066 struct Mapper::definition {
0067   definition(Mapper const& self) {
0068     mapSet = ppair[self.mapPair()] >> *((',' >> ppair)[self.mapPair()]);
0069 
0070     ppair = name >> ch_p('=') >> value;
0071 
0072     name = (alpha_p >> *alnum_p)[self.mapMakeName()];
0073 
0074     value = (+(anychar_p - ','))[self.mapMakeDouble()];
0075   }
0076 
0077   rule<ScannerT> mapSet, ppair, name, value;
0078 
0079   rule<ScannerT> const& start() const { return mapSet; }
0080 };
0081 
0082 void MapPair::operator()(char const* str, char const* end) const { map_->do_pair(str, end); }
0083 
0084 void MapMakeName::operator()(char const* str, char const* end) const { map_->do_makeName(str, end); }
0085 
0086 void MapMakeDouble::operator()(char const* str, char const* end) const { map_->do_makeDouble(str, end); }
0087 
0088 void DDLMap::preProcessElement(const std::string& name, const std::string& nmspace, DDCompactView& cpv) {
0089   pName = "";
0090   pMap.clear();
0091   //pMapMap.clear(); only the DDLAlgorithm is allowed to clear this guy!
0092   pDouble = 0.0;
0093   pNameSpace = nmspace;
0094 }
0095 
0096 void DDLMap::processElement(const std::string& name, const std::string& nmspace, DDCompactView& cpv) {
0097   std::string tTextToParse = getText();
0098   DDXMLAttribute atts = getAttributeSet();
0099   std::string tName = atts.find("name")->second;
0100 
0101   if (tTextToParse.empty()) {
0102     errorOut("No std::string to parse!");
0103   }
0104 
0105   // NOT IMPLEMENTED YET
0106   if (atts.find("type") != atts.end() && atts.find("type")->second == "string") {
0107     errorOut("Map of type std::string is not supported yet.");
0108   }
0109 
0110   Mapper mapGrammar{this};
0111 
0112   pMap.clear();
0113 
0114   parse_info<> info = boost::spirit::classic::parse(tTextToParse.c_str(), mapGrammar >> end_p, space_p);
0115   if (!info.full) {
0116     errorOut("Does not conform to name=value, name=value... etc. of ddl Map element.");
0117   }
0118 
0119   if (parent() == "Algorithm" || parent() == "SpecPar") {
0120     pMapMap[tName] = pMap;
0121   } else if (parent() == "ConstantsSection" || parent() == "DDDefinition") {
0122     dd_map_type tMap;
0123     for (std::map<std::string, double>::const_iterator it = pMap.begin(); it != pMap.end(); ++it) {
0124       tMap[it->first] = it->second;
0125     }
0126     DDMap m(getDDName(pNameSpace), std::make_unique<dd_map_type>(tMap));
0127     // clear the map of maps, because in these elements we only have ONE at a time.
0128     pMapMap.clear();
0129   }
0130 
0131   std::string nEntries = atts.find("nEntries")->second;
0132   if (pMap.size() != size_t(myRegistry_->evaluator().eval(pNameSpace, nEntries))) {
0133     errorOut("Number of entries found in Map text does not match number in attribute nEntries.");
0134   }
0135   clear();
0136 }
0137 
0138 void DDLMap::do_pair(char const* str, char const* end) { pMap[pName] = pDouble; }
0139 
0140 void DDLMap::do_makeName(char const* str, char const* end) { pName = std::string(str, end); }
0141 
0142 void DDLMap::do_makeDouble(char const* str, char const* end) {
0143   std::string ts(str, end);
0144   pDouble = myRegistry_->evaluator().eval(pNameSpace, ts);
0145 }
0146 
0147 void DDLMap::errorOut(const char* str) {
0148   std::string msg("\nDDLMap: Failed to parse the following: \n");
0149   msg += std::string(str);
0150   msg += "\n as a Map element (comma separated list of name=value).";
0151   throwError(msg);
0152 }
0153 
0154 ReadMapType<std::map<std::string, double> >& DDLMap::getMapOfMaps(void) { return pMapMap; }