Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
#include "FWCore/ParameterSet/interface/VParameterSetEntry.h"
#include "FWCore/ParameterSet/interface/ParameterSet.h"
#include "FWCore/ParameterSet/src/split.h"
#include "FWCore/Utilities/interface/Digest.h"

#include <cassert>
#include <ostream>
#include <sstream>

namespace edm {

  VParameterSetEntry::VParameterSetEntry() : tracked_(false), theVPSet_(), theIDs_() {}

  VParameterSetEntry::VParameterSetEntry(std::vector<ParameterSet> const& vpset, bool isTracked)
      : tracked_(isTracked), theVPSet_(new std::vector<ParameterSet>(vpset)), theIDs_() {}

  VParameterSetEntry::VParameterSetEntry(std::string_view rep)
      : tracked_(rep[0] == '+'), theVPSet_(), theIDs_(new std::vector<ParameterSetID>) {
    assert(rep[0] == '+' || rep[0] == '-');
    std::vector<std::string_view> temp;
    // need a substring that starts at the '{'
    std::string_view bracketedRepr = rep.substr(2);
    split(std::back_inserter(temp), bracketedRepr, '{', ',', '}');
    theIDs_->reserve(temp.size());
    for (auto const& id : temp) {
      theIDs_->emplace_back(std::string(id));
    }
  }

  void VParameterSetEntry::toString(std::string& result) const {
    assert(theIDs_);
    result += tracked_ ? "+q" : "-q";
    result += '{';
    std::string start;
    std::string const between(",");
    for (std::vector<ParameterSetID>::const_iterator i = theIDs_->begin(), e = theIDs_->end(); i != e; ++i) {
      result += start;
      i->toString(result);
      start = between;
    }
    result += '}';
  }

  void VParameterSetEntry::toDigest(cms::Digest& digest) const {
    assert(theIDs_);
    digest.append(tracked_ ? "+q{" : "-q{", 3);
    bool started = false;
    for (std::vector<ParameterSetID>::const_iterator i = theIDs_->begin(), e = theIDs_->end(); i != e; ++i) {
      if (started)
        digest.append(",", 1);
      i->toDigest(digest);
      started = true;
    }
    digest.append("}", 1);
  }

  std::string VParameterSetEntry::toString() const {
    std::string result;
    toString(result);
    return result;
  }

  std::vector<ParameterSet> const& VParameterSetEntry::vpset() const {
    fillVPSet();
    return *theVPSet_;
  }

  // NOTE: This function, and other non-const functions of this class
  // that expose internals, may be used in a way that causes the cached
  // "theVPSet_" and "theIDs_" to be inconsistent.
  // THIS PROBLEM NEEDS TO BE ADDRESSED
  std::vector<ParameterSet>& VParameterSetEntry::vpsetForUpdate() {
    fillVPSet();
    return *theVPSet_;
  }

  void VParameterSetEntry::fillVPSet() const {
    if (nullptr == theVPSet_.load()) {
      auto tmp = std::make_unique<std::vector<ParameterSet>>();
      tmp->reserve(theIDs_->size());
      for (auto const& theID : *theIDs_) {
        tmp->push_back(getParameterSet(theID));
      }
      VParameterSet* expected = nullptr;
      if (theVPSet_.compare_exchange_strong(expected, tmp.get())) {
        // theVPSet_ was equal to nullptr and now is equal to tmp.get()
        tmp.release();
      }
    }
  }

  // NOTE: This function, and other non-const functions of this class
  // that expose internals, may be used in a way that causes the cached
  // "theVPSet_" and "theIDs_" to be inconsistent.
  // THIS PROBLEM NEEDS TO BE ADDRESSED
  ParameterSet& VParameterSetEntry::psetInVector(int i) {
    assert(theVPSet_);
    return theVPSet_->at(i);
  }

  std::vector<ParameterSet>::size_type VParameterSetEntry::size() const {
    return theIDs_ ? theIDs_->size() : (theVPSet_ ? vpset().size() : 0);
  }

  void VParameterSetEntry::registerPsetsAndUpdateIDs() {
    fillVPSet();
    theIDs_ = value_ptr<std::vector<ParameterSetID>>(new std::vector<ParameterSetID>);
    theIDs_->resize(theVPSet_->size());
    for (std::vector<ParameterSet>::iterator i = theVPSet_->begin(), e = theVPSet_->end(); i != e; ++i) {
      if (!i->isRegistered()) {
        i->registerIt();
      }
      theIDs_->at(i - theVPSet_->begin()) = i->id();
    }
  }

  std::string VParameterSetEntry::dump(unsigned int indent) const {
    std::string indentation(indent, ' ');
    std::ostringstream os;
    std::vector<ParameterSet> const& vps = vpset();
    os << "VPSet " << (isTracked() ? "tracked" : "untracked") << " = ({" << std::endl;
    std::string start;
    std::string const between(",\n");
    for (std::vector<ParameterSet>::const_iterator i = vps.begin(), e = vps.end(); i != e; ++i) {
      os << start << indentation << i->dump(indent);
      start = between;
    }
    if (!vps.empty()) {
      os << std::endl;
    }
    os << indentation << "})";
    return os.str();
  }

  std::ostream& operator<<(std::ostream& os, VParameterSetEntry const& vpsetEntry) {
    os << vpsetEntry.dump();
    return os;
  }
}  // namespace edm