Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 13:27:09

0001 // -*- C++ -*-
0002 //
0003 // Package:     Core
0004 // Class  :     FWConfiguration
0005 //
0006 // Implementation:
0007 //     <Notes on implementation>
0008 //
0009 // Original Author:  Chris Jones
0010 //         Created:  Fri Feb 22 15:54:29 EST 2008
0011 //
0012 
0013 // system include files
0014 #include <memory>
0015 
0016 #include <stdexcept>
0017 #include <algorithm>
0018 #include <functional>
0019 // user include files
0020 #include "Fireworks/Core/interface/FWConfiguration.h"
0021 
0022 //
0023 // constants, enums and typedefs
0024 //
0025 
0026 //
0027 // static data member definitions
0028 //
0029 
0030 //
0031 // constructors and destructor
0032 //
0033 //FWConfiguration::FWConfiguration()
0034 //{
0035 //}
0036 
0037 FWConfiguration::FWConfiguration(const FWConfiguration& rhs)
0038     : m_stringValues(rhs.m_stringValues ? new std::vector<std::string>(*(rhs.m_stringValues)) : nullptr),
0039       m_keyValues(rhs.m_keyValues ? new KeyValues(*(rhs.m_keyValues)) : nullptr),
0040       m_version(rhs.m_version) {}
0041 
0042 FWConfiguration::~FWConfiguration() {}
0043 
0044 //
0045 // assignment operators
0046 //
0047 FWConfiguration& FWConfiguration::operator=(const FWConfiguration& rhs) {
0048   //An exception safe implementation is
0049   FWConfiguration temp(rhs);
0050   swap(temp);
0051 
0052   return *this;
0053 }
0054 
0055 //
0056 // member functions
0057 //
0058 FWConfiguration& FWConfiguration::addKeyValue(const std::string& iKey, const FWConfiguration& iConfig) {
0059   if (m_stringValues) {
0060     throw std::runtime_error("adding key/value to configuration containing string values");
0061   }
0062   if (not m_keyValues) {
0063     m_keyValues = std::make_unique<KeyValues>(1, std::make_pair(iKey, iConfig));
0064   } else {
0065     m_keyValues->push_back(std::make_pair(iKey, iConfig));
0066   }
0067   return *this;
0068 }
0069 FWConfiguration& FWConfiguration::addKeyValue(const std::string& iKey, FWConfiguration& iConfig, bool iDoSwap) {
0070   if (m_stringValues) {
0071     throw std::runtime_error("adding key/value to configuration containing string values");
0072   }
0073   if (m_stringValues) {
0074     throw std::runtime_error("adding key/value to configuration containing string values");
0075   }
0076   if (not m_keyValues) {
0077     if (not iDoSwap) {
0078       m_keyValues = std::make_unique<KeyValues>(1, std::make_pair(iKey, iConfig));
0079     } else {
0080       m_keyValues = std::make_unique<KeyValues>(1, std::make_pair(iKey, FWConfiguration()));
0081       m_keyValues->back().second.swap(iConfig);
0082     }
0083   } else {
0084     if (not iDoSwap) {
0085       m_keyValues->push_back(std::make_pair(iKey, iConfig));
0086     } else {
0087       m_keyValues->push_back(std::make_pair(iKey, FWConfiguration()));
0088       m_keyValues->back().second.swap(iConfig);
0089     }
0090   }
0091   return *this;
0092 }
0093 
0094 FWConfiguration& FWConfiguration::addValue(const std::string& iValue) {
0095   if (m_keyValues) {
0096     throw std::runtime_error("adding string value to configuration containing key/value pairs");
0097   }
0098   if (not m_stringValues) {
0099     m_stringValues = std::make_unique<std::vector<std::string>>(1, iValue);
0100   } else {
0101     m_stringValues->push_back(iValue);
0102   }
0103   return *this;
0104 }
0105 
0106 void FWConfiguration::swap(FWConfiguration& iRHS) {
0107   std::swap(m_version, iRHS.m_version);
0108   m_stringValues.swap(iRHS.m_stringValues);
0109   m_keyValues.swap(iRHS.m_keyValues);
0110 }
0111 
0112 //
0113 // const member functions
0114 //
0115 const std::string& FWConfiguration::value(unsigned int iIndex) const {
0116   if (not m_stringValues) {
0117     throw std::runtime_error("no string values set");
0118   }
0119   return m_stringValues->at(iIndex);
0120 }
0121 
0122 const FWConfiguration* FWConfiguration::valueForKey(const std::string& iKey) const {
0123   if (m_stringValues) {
0124     throw std::runtime_error("valueFoKey fails because configuration containing string values");
0125   }
0126   if (not m_keyValues) {
0127     throw std::runtime_error("valueForKey fails becuase no key/values set");
0128   }
0129   KeyValues::iterator itFind =
0130       std::find_if(m_keyValues->begin(),
0131                    m_keyValues->end(),
0132                    std::bind(std::equal_to<void>(),
0133                              std::bind(&std::pair<std::string, FWConfiguration>::first, std::placeholders::_1),
0134                              iKey));
0135   if (itFind == m_keyValues->end()) {
0136     return nullptr;
0137   }
0138   return &(itFind->second);
0139 }
0140 
0141 /** Helper function to make sure we escape correctly xml entities embedded in
0142     the string @a value.
0143   */
0144 std::string attrEscape(std::string value) {
0145   std::string::size_type index = 0;
0146   index = 0;
0147   while (std::string::npos != (index = value.find('&', index))) {
0148     value.replace(index, 1, "&amp;", 5);
0149     // Do not check "&quot;" for quotes.
0150     index += 5;
0151   }
0152 
0153   while (std::string::npos != (index = value.find('"', index))) {
0154     value.replace(index, 1, "&quot;", 6);
0155     // Do not check "&quot;" for quotes.
0156     index += 6;
0157   }
0158 
0159   index = 0;
0160   while (std::string::npos != (index = value.find('<', index))) {
0161     value.replace(index, 1, "&lt;", 4);
0162     // Do not check "&quot;" for quotes.
0163     index += 4;
0164   }
0165 
0166   index = 0;
0167   while (std::string::npos != (index = value.find('>', index))) {
0168     value.replace(index, 1, "&gt;", 4);
0169     // Do not check "&quot;" for quotes.
0170     index += 4;
0171   }
0172 
0173   return value;
0174 }
0175 
0176 /** Streaming FWConfiguration objects to xml.
0177 
0178     Example of dump is:
0179     
0180     <config name="top" version="1">
0181       <string value="S1">
0182       <string value="S2">
0183       ...
0184       <string value="SN">
0185       <config name="c1">
0186          ...
0187       </configuration>
0188       <config name="c2">
0189          ...
0190       </config>
0191       ...
0192     </config>
0193    
0194     Streaming the top level configuration item will stream all its children.
0195   */
0196 void FWConfiguration::streamTo(std::ostream& oTo, const FWConfiguration& iConfig, const std::string& name) {
0197   static int recursionLevel = -1;
0198   recursionLevel += 1;
0199   std::string indentation(recursionLevel, ' ');
0200   oTo << indentation << "<config name=\"" << name << "\" version=\"" << iConfig.version() << "\">\n";
0201   if (iConfig.stringValues()) {
0202     for (FWConfiguration::StringValues::const_iterator it = iConfig.stringValues()->begin();
0203          it != iConfig.stringValues()->end();
0204          ++it) {
0205       oTo << indentation << "  <string>" << attrEscape(*it) << "</string>\n";
0206     }
0207   }
0208   if (iConfig.keyValues()) {
0209     for (FWConfiguration::KeyValues::const_iterator it = iConfig.keyValues()->begin(); it != iConfig.keyValues()->end();
0210          ++it) {
0211       FWConfiguration::streamTo(oTo, it->second, attrEscape(it->first));
0212     }
0213   }
0214   oTo << indentation << "</config>" << std::endl;
0215   recursionLevel -= 1;
0216 }
0217 
0218 //
0219 // static member functions
0220 //