// Read the documentation to learn more about C++ code generator // versioning. // %X% %Q% %Z% %W% #include // DummyResponse #include // XSutility #include // ResponseContainer #include #include #include #include #include #include #include #include #include #include namespace XSContainer { ResponseContainer* responses = 0; // Class XSContainer::ResponseContainer ResponseContainer* ResponseContainer::s_instance = 0; ResponseContainer::ResponseContainer (DummyResponse* dummy) { m_responseList.insert(ResponseMap::value_type(DUMMY_RSP,dummy)); XSstream& xscout = static_cast(tcout); if (std::min(xscout.consoleChatterLevel(),xscout.logChatterLevel()) > 25) { tcout << "ResponseContainer Initialization: eMin: " << dummy->eLow() << " eMax: " << dummy->eHigh() << " nE: " << dummy->numEnergies() << " ln: ? " << std::boolalpha << dummy->isLog() << std::endl; } } ResponseContainer::~ResponseContainer() { clear(); } ResponseContainer* ResponseContainer::Instance (DummyResponse* dummy) { if (s_instance == 0) {s_instance = new ResponseContainer(dummy);} return s_instance; } void ResponseContainer::addToList (const string& name, Response* newResponse) { // supplying a released auto_ptr would be a better way perhaps. responseList(name,newResponse); addToParamMap(newResponse); } void ResponseContainer::clear (bool deleteObj) { // The boolean deleteObj is now obsolete. Response objects // are no longer deleted anywhere in ResponseContainer // functions. It's now up to SpectralData to have the honors. if (!m_responseList.empty()) { ResponseMapIter itRl(m_responseList.begin()); // non-const. while (itRl != m_responseList.end()) { if ( (*itRl).first != DUMMY_RSP) { m_responseList.erase(itRl++); } else ++itRl; } // ResponseParam pointers are not owned here, simply erase them. m_parameterMap.clear(); // reference counted. Since we are deleting everything, one of the // iterators will call delete on the pointer value. m_RMFmap.clear(); } } void ResponseContainer::addToList (const RefCountPtr& newRMF) { RMFmap(newRMF->name(), RefCountPtr(newRMF)); } const Response* ResponseContainer::responseList (const string& name, size_t index) const { return internalFind(name,index); } Response* ResponseContainer::responseList (const string& name, size_t index) { return internalFind(name,index); } void ResponseContainer::responseList (const string& name, Response* value) { m_responseList.insert(ResponseMap::value_type(name,value)); } void ResponseContainer::RMFmap (const string& name, const RefCountPtr& rmf) { m_RMFmap.insert(RMFMap::value_type(name,rmf)); } size_t ResponseContainer::numberOfResponses () const { return m_responseList.size(); } void ResponseContainer::removeByToken (const std::vector& doomed, size_t sourceNum) { size_t n(doomed.size()); // If sourceNum is 0 (default), remove all responses in the vector, // else just remove that specified by sourceNum. for (size_t j = (sourceNum==0 ? 0 : sourceNum-1); j < n; ++j) { ResponseMapIter d(m_responseList.begin()); ResponseMapIter dEnd(m_responseList.end()); while (d != dEnd) { Response* current(d->second); if (current == doomed[j]) { // No longer calling delete on current. The SpectralData // obj and NOT ResponseContainer will now be responsible // for Response memory (Jan 06). //remove from list of RMFs. m_responseList.erase(d); // and remove any response params from the global list removeFromParamMap(doomed[j]); break; } else ++d; } if (sourceNum != 0) break; } } void ResponseContainer::removeByToken (const RefCountPtr& doomed) throw () { // associative container erase functions are guaranteed by // the standard not to throw. This function will be called by // RealResponse's dtor. RMFMapIter m(m_RMFmap.begin()); RMFMapIter mEnd(m_RMFmap.end()); while ( m != mEnd ) { RefCountPtr& current( (*m).second); if ( *current == *doomed ) { m_RMFmap.erase(m); break; } else ++m; } } Response* ResponseContainer::internalFind (const string& name, size_t index) const { size_t N = m_responseList.count(name); if (N == 0) return 0; else { ResponseMapConstIter f = m_responseList.lower_bound(name); if (N == 1) { return (*f).second; } else { ResponseMapConstIter g = m_responseList.upper_bound(name); while ( f != g) { if ( ((*f).second)->index() != index ) { ++f; } else { return (*f).second; } } return 0; } } } Response* ResponseContainer::swapResponses (Response* inResponse, Response* outResponse) { ResponseMapIter itResp(m_responseList.begin()); ResponseMapIter itRespEnd(m_responseList.end()); bool isFound = false; while (itResp != itRespEnd) { if (itResp->second == outResponse) { // Must reconstruct the global map name key for the inReponse: string nameKey; if (const RealResponse* rr = inResponse->toRealResponse()) nameKey = rr->rmfName(); else if (inResponse->toUserDummyResponse()) nameKey = USR_DUMMY_RSP; else if (const MultiResponse* mr = inResponse->toMultiResponse()) { for (size_t i=0; irmfNames().size(); ++i) nameKey += mr->rmfNames()[i] + " "; } m_responseList.insert(ResponseMap::value_type(nameKey,inResponse)); m_responseList.erase(itResp); removeFromParamMap(outResponse); addToParamMap(inResponse); isFound = true; break; } ++itResp; } return isFound ? outResponse : static_cast(0); } void ResponseContainer::clearParameters () { // Intended to remove all pointers from parameterMap AND destroy the responseParameters // themselves. // This is somewhat convoluted, but safe. For each responsePar in map, call // on its response parent to delete it, which in turn calls removeFromParamMap // by way of responsePar's destructor. This also relies on the ASSUMPTION that // a Response has NO MORE THAN ONE responsePar of a given type. ResponseParamMapIter it = m_parameterMap.begin(); while (it != m_parameterMap.end()) { ResponseParam* rp = it->second; // This is where above assumption matters: rp->responseParent()->removeGainParam(rp->parType()); it = m_parameterMap.begin(); } } void ResponseContainer::removeFromParamMap (size_t respIndex, const ResponseParam* param) throw () { //NOTE: This function is meant to be called from ResponseParam's // destructor, so IT BETTER NOT THROW. Also, not all destroyed responseParams // will be found here, such as those created from cloning. In those cases, this // should do nothing. std::pair iters = m_parameterMap.equal_range(respIndex); ResponseParamMapIter it = iters.first; while (it != iters.second) { if (it->second == param) { // m_parameter map does not own the parameters, so no delete call. m_parameterMap.erase(it); break; } ++it; } } void ResponseContainer::addToParamMap (size_t respIndex, ResponseParam* param) { // Meant to be called from ResponseParam's ctor. (but not copy ctor) m_parameterMap.insert(ResponseParamMap::value_type(respIndex, param)); } void ResponseContainer::removeFromParamMap (const Response* resp) { // Function does nothing if Response contains no gain fit parameters. if (resp->getConstGain()) removeFromParamMap(resp->index(), resp->getConstGain()); if (resp->getLinearGain()) removeFromParamMap(resp->index(), resp->getLinearGain()); } void ResponseContainer::addToParamMap (Response* resp) { // Function does nothing if Response contains no gain fit parameters. // Bending the const rules to allow us to copy the (const) ResponseParam // pointers into a map of non-const pointers. It doesn't seem worth // it to provide non-const public get functions in Response class // just for this one limited case. if (resp->getConstGain()) { ResponseParam* ncRespPar = const_cast(resp->getConstGain()); addToParamMap(resp->index(), ncRespPar); } if (resp->getLinearGain()) { ResponseParam* ncRespPar = const_cast(resp->getLinearGain()); addToParamMap(resp->index(), ncRespPar); } } ResponseMap& ResponseContainer::responseList () { return m_responseList; } // Additional Declarations } // namespace XSContainer