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
#include "DataFormats/Provenance/interface/processingOrderMerge.h"
#include "DataFormats/Provenance/interface/ProcessHistory.h"
#include "FWCore/Utilities/interface/Exception.h"
#include <algorithm>

namespace edm {
  namespace {
    [[noreturn]] void throwIncompatibleOrdering(std::string const& msg) {
      throw cms::Exception("IncompatibleProcessHistoryOrdering")
          << "Incompatible process history ordering during merge: " << msg << "\n";
    }

    template <typename Iter>
    Iter foundLaterIn(Iter itBegin, Iter it, Iter itEnd, std::string const& name) {
      auto itFind = std::find(itBegin, itEnd, name);
      if (itFind < it) {
        throwIncompatibleOrdering("process " + name + " found earlier in other list");
      }
      return itFind;
    }
  }  // namespace

  void processingOrderMerge(ProcessHistory const& iHistory, std::vector<std::string>& processNames) {
    if (processNames.empty()) {
      for (auto it = iHistory.rbegin(); it != iHistory.rend(); ++it) {
        processNames.push_back(it->processName());
      }
    } else {
      std::vector<std::string> fromHistory;
      fromHistory.reserve(iHistory.size());
      for (auto it = iHistory.rbegin(); it != iHistory.rend(); ++it) {
        fromHistory.push_back(it->processName());
      }
      processingOrderMerge(fromHistory, processNames);
    }
  }

  void processingOrderMerge(std::vector<std::string> const& iHistory, std::vector<std::string>& processNames) {
    if (processNames.empty()) {
      processNames = iHistory;
    } else {
      std::vector<std::string> tempNames;
      tempNames.reserve(processNames.size() > iHistory.size() ? processNames.size() : iHistory.size());
      auto itNew = iHistory.begin();
      auto itNewEnd = iHistory.end();
      auto itOld = processNames.begin();
      auto itOldEnd = processNames.end();
      while (itNew != itNewEnd && itOld != itOldEnd) {
        if (*itNew == *itOld) {
          tempNames.push_back(*itOld);
          ++itNew;
          ++itOld;
        } else {
          //see if we can find it in the old list
          auto itFindOld = foundLaterIn(processNames.begin(), itOld, itOldEnd, *itNew);
          auto itFindNew = foundLaterIn(iHistory.begin(), itNew, itNewEnd, *itOld);
          if (itFindOld != itOldEnd) {
            if (itFindNew != itNewEnd) {
              throwIncompatibleOrdering("process " + *itNew + " and " + *itOld + " are out of order");
            }
            //found it, copy over everything up to and including it
            while (itOld != itFindOld) {
              tempNames.push_back(*itOld);
              ++itOld;
            }
            tempNames.push_back(*itOld);
            ++itOld;
            ++itNew;
          } else {
            if (itFindNew == itNewEnd) {
              throwIncompatibleOrdering("process " + *itOld + " and " + *itNew + " are independent");
            }
            while (itNew != itFindNew) {
              tempNames.push_back(*itNew);
              ++itNew;
            }
            //not found, add the new one
            tempNames.push_back(*itNew);
            ++itNew;
            ++itOld;
          }
        }
      }
      //copy over any remaining old names
      while (itOld != itOldEnd) {
        tempNames.push_back(*itOld);
        ++itOld;
      }
      while (itNew != itNewEnd) {
        tempNames.push_back(*itNew);
        ++itNew;
      }
      processNames.swap(tempNames);
    }
  }
}  // namespace edm