Update of /cvsroot/objecthandler/ObjectHandler/ohxl
In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv20729/ohxl
Modified Files:
callingrange.cpp callingrange.hpp functioncall.cpp
functioncall.hpp objecthandlerxl.cpp objecthandlerxl.hpp
Added Files:
objhandlerxl.hpp
Log Message:
- allow nesting of QL & non-QL functions
- support for permanent objects
Index: objecthandlerxl.cpp
===================================================================
RCS file: /cvsroot/objecthandler/ObjectHandler/ohxl/objecthandlerxl.cpp,v
retrieving revision 1.5
retrieving revision 1.6
diff -C2 -d -r1.5 -r1.6
*** objecthandlerxl.cpp 9 Jun 2006 18:58:27 -0000 1.5
--- objecthandlerxl.cpp 11 Jun 2006 12:38:22 -0000 1.6
***************
*** 29,33 ****
# undef BOOST_LIB_DIAGNOSTIC
#endif
- #include <iostream>
#include <iomanip>
#include <sstream>
--- 29,32 ----
***************
*** 48,58 ****
return *ret;
else
! throw std::exception("Attempt to reference uninitialized ObjectHandlerXL object");
} else
! throw std::exception("Attempt to reference uninitialized ObjectHandlerXL object");
}
boost::shared_ptr < CallingRange > ObjectHandlerXL::getCallingRange() {
!
// XLOPERs which might need freeing in the event of an exception
--- 47,57 ----
return *ret;
else
! throw Exception("Attempt to reference uninitialized ObjectHandlerXL object");
} else
! throw Exception("Attempt to reference uninitialized ObjectHandlerXL object");
}
boost::shared_ptr < CallingRange > ObjectHandlerXL::getCallingRange() {
!
// XLOPERs which might need freeing in the event of an exception
***************
*** 81,85 ****
} else {
callingRange = i->second;
! callingRange->update();
}
}
--- 80,84 ----
} else {
callingRange = i->second;
! //callingRange->update();
}
}
***************
*** 103,107 ****
void ObjectHandlerXL::resetCaller() {
! getCallingRange();
}
--- 102,108 ----
void ObjectHandlerXL::resetCaller() {
! boost::shared_ptr < CallingRange > callingRange = getCallingRange();
! if (callingRange)
! callingRange->update();
}
***************
*** 115,129 ****
callingRanges_[callingRange->getKey()] = callingRange;
}
std::string instanceNameDerived;
! if (instanceName.empty())
instanceNameDerived = generateInstanceName();
! else
instanceNameDerived = instanceName;
checkName(instanceNameDerived);
- callingRange->registerObject(instanceNameDerived);
-
std::string instanceNameCounter = ObjectHandler::storeObject(instanceNameDerived, object);
return instanceNameCounter + "#" + callingRange->updateCount();
--- 116,132 ----
callingRanges_[callingRange->getKey()] = callingRange;
}
+ callingRange->update();
std::string instanceNameDerived;
! if (instanceName.empty()) {
instanceNameDerived = generateInstanceName();
! object->setAnonymous(true);
! } else {
instanceNameDerived = instanceName;
+ }
+ callingRange->registerObject(instanceNameDerived, object);
checkName(instanceNameDerived);
std::string instanceNameCounter = ObjectHandler::storeObject(instanceNameDerived, object);
return instanceNameCounter + "#" + callingRange->updateCount();
***************
*** 161,165 ****
boost::shared_ptr < CallingRange > callingRange = iter_previous->second;
if (!callingRange->isValid()) {
! callingRange->clear();
callingRanges_.erase(key);
}
--- 164,168 ----
boost::shared_ptr < CallingRange > callingRange = iter_previous->second;
if (!callingRange->isValid()) {
! callingRange->clearAll();
callingRanges_.erase(key);
}
***************
*** 167,173 ****
}
! void ObjectHandlerXL::deleteAllObjects() {
! callingRanges_.clear();
! ObjectHandler::deleteAllObjects();
}
--- 170,177 ----
}
! void ObjectHandlerXL::deleteAllObjects(const bool &deletePermanent) {
! if (deletePermanent)
! callingRanges_.clear();
! ObjectHandler::deleteAllObjects(deletePermanent);
}
Index: objecthandlerxl.hpp
===================================================================
RCS file: /cvsroot/objecthandler/ObjectHandler/ohxl/objecthandlerxl.hpp,v
retrieving revision 1.5
retrieving revision 1.6
diff -C2 -d -r1.5 -r1.6
*** objecthandlerxl.hpp 9 Jun 2006 18:58:27 -0000 1.5
--- objecthandlerxl.hpp 11 Jun 2006 12:38:22 -0000 1.6
***************
*** 58,62 ****
virtual boost::shared_ptr < Object > retrieveObjectImpl(const std::string &instanceName) const;
virtual void collectGarbage();
! virtual void deleteAllObjects();
//! Reset the calling cell.
--- 58,62 ----
virtual boost::shared_ptr < Object > retrieveObjectImpl(const std::string &instanceName) const;
virtual void collectGarbage();
! virtual void deleteAllObjects(const bool &deletePermanent = false);
//! Reset the calling cell.
Index: callingrange.hpp
===================================================================
RCS file: /cvsroot/objecthandler/ObjectHandler/ohxl/callingrange.hpp,v
retrieving revision 1.2
retrieving revision 1.3
diff -C2 -d -r1.2 -r1.3
*** callingrange.hpp 2 Jun 2006 13:59:05 -0000 1.2
--- callingrange.hpp 11 Jun 2006 12:38:22 -0000 1.3
***************
*** 24,27 ****
--- 24,28 ----
#include <oh/object.hpp>
+ #include <map>
namespace ObjHandler {
***************
*** 35,40 ****
return key_;
}
! void registerObject(const std::string &instanceName);
! void clear();
void update();
std::string updateCount();
--- 36,43 ----
return key_;
}
! void registerObject(const std::string &instanceName,
! boost::shared_ptr<Object> object);
! void clearAnonymous();
! void clearAll();
void update();
std::string updateCount();
***************
*** 44,51 ****
static std::string getKeyCount();
std::string key_;
- std::vector < std::string > residentObjects_;
bool busy_;
int updateCount_;
std::string getAddressString() const;
};
--- 47,56 ----
static std::string getKeyCount();
std::string key_;
bool busy_;
int updateCount_;
std::string getAddressString() const;
+ void setInvocationCount();
+ int invocationCount_;
+ std::map<std::string, boost::shared_ptr<Object> > residentObjects_;
};
Index: functioncall.cpp
===================================================================
RCS file: /cvsroot/objecthandler/ObjectHandler/ohxl/functioncall.cpp,v
retrieving revision 1.5
retrieving revision 1.6
diff -C2 -d -r1.5 -r1.6
*** functioncall.cpp 8 Jun 2006 09:37:27 -0000 1.5
--- functioncall.cpp 11 Jun 2006 12:38:22 -0000 1.6
***************
*** 27,34 ****
FunctionCall *FunctionCall::instance_ = 0;
- // FIXME these values need to be configured at runtime
- const std::string libFunctionSignature = "=ql";
- const std::string libName = "QuantLib";
-
FunctionCall::FunctionCall(const std::string functionName)
: functionName_(functionName), callerDimensions_(Uninitialized) {
--- 27,30 ----
***************
*** 36,41 ****
throw Exception("Multiple attempts to initialize global FunctionCall object");
instance_ = this;
! xCaller.xltype = 0;
! xReftext.xltype = 0;
address_ = "";
}
--- 32,38 ----
throw Exception("Multiple attempts to initialize global FunctionCall object");
instance_ = this;
! xCaller_.xltype = 0;
! xReftext_.xltype = 0;
! xMulti_.xltype = 0;
address_ = "";
}
***************
*** 43,48 ****
FunctionCall::~FunctionCall() {
instance_ = 0;
! if (xCaller.xltype) Excel(xlFree, 0, 1, &xCaller);
! if (xReftext.xltype) Excel(xlFree, 0, 1, &xReftext);
}
--- 40,46 ----
FunctionCall::~FunctionCall() {
instance_ = 0;
! if (xCaller_.xltype) Excel(xlFree, 0, 1, &xCaller_);
! if (xReftext_.xltype) Excel(xlFree, 0, 1, &xReftext_);
! if (xMulti_.xltype) Excel(xlFree, 0, 1, &xMulti_);
}
***************
*** 55,65 ****
const XLOPER *FunctionCall::getCallerReference() {
! if (!xCaller.xltype) Excel(xlfCaller, &xCaller, 0);
! return &xCaller;
}
const XLOPER *FunctionCall::getCallerAddress() {
! if (!xReftext.xltype) Excel(xlfReftext, &xReftext, 1, getCallerReference());
! return &xReftext;
}
--- 53,68 ----
const XLOPER *FunctionCall::getCallerReference() {
! if (!xCaller_.xltype) Excel(xlfCaller, &xCaller_, 0);
! return &xCaller_;
}
const XLOPER *FunctionCall::getCallerAddress() {
! if (!xReftext_.xltype) Excel(xlfReftext, &xReftext_, 1, getCallerReference());
! return &xReftext_;
! }
!
! const XLOPER *FunctionCall::getCallerArray() {
! if (!xMulti_.xltype) Excel(xlCoerce, &xMulti_, 2, getCallerReference(), TempInt(xltypeMulti));
! return &xMulti_;
}
***************
*** 104,143 ****
}
- bool FunctionCall::outerFunction() {
-
- // exit if calling cell is #VALUE
- //XLOPER xValue;
- //Excel(xlfGetCell, &xValue, 2, TempNum(5), getCallerReference());
- //if (xValue.xltype & (xltypeErr | xltypeMissing)) {
- // return false;
- //}
- //Excel(xlFree, 0, 1, &xValue);
-
- std::string formula = getFormula();
- std::string functionNameCompare = "=" + functionName_ + "(";
- if (formula.substr(0, functionNameCompare.length()) == functionNameCompare) {
- if (formula.find(functionName_, functionNameCompare.length()) != std::string::npos) {
- std::ostringstream err;
- err << "Function '" << functionName_ << "' appears in formula '" << formula
- << "' as both the outermost function and as an inner function. "
- << "ObjectHandler cannot handle cell formulas in which a given function "
- << "is nested within itself as this circumvents garbage collection. "
- << "Please split this formula into separate cells.";
- throw Exception(err.str());
- }
- return true;
- } else {
- if (formula.substr(0, libFunctionSignature.length()) != libFunctionSignature) {
- std::ostringstream err;
- err << "in formula '" << formula << "' - " << libName << " function '" << functionName_
- << "' is nested within a non-" << libName << " function. ObjectHandler cannot handle "
- << "library functions nested within non-library functions as this circumvents garbage "
- << "collection. Please split this formula into separate cells.";
- throw Exception(err.str());
- }
- return false;
- }
- }
-
CallerDimensions FunctionCall::getCallerDimensions() {
// determine dimensions of calling range
--- 107,110 ----
***************
*** 145,157 ****
// this could be extended to detect scalar / matrix
if (callerDimensions_ == Uninitialized) {
! const XLOPER *xRef = getCallerReference();
! // xRef might be xltypeRef/xltypeSRef so coerce it to xltypeMulti
! XLOPER xMulti;
! Excel(xlCoerce, &xMulti, 2, xRef, TempInt(xltypeMulti));
! if (xMulti.val.array.rows == 1 && xMulti.val.array.columns > 1)
callerDimensions_ = Row;
else
callerDimensions_ = Column;
- Excel(xlFree, 0, 1, &xMulti);
}
return callerDimensions_;
--- 112,120 ----
// this could be extended to detect scalar / matrix
if (callerDimensions_ == Uninitialized) {
! const XLOPER *xMulti = getCallerArray();
! if (xMulti->val.array.rows == 1 && xMulti->val.array.columns > 1)
callerDimensions_ = Row;
else
callerDimensions_ = Column;
}
return callerDimensions_;
Index: functioncall.hpp
===================================================================
RCS file: /cvsroot/objecthandler/ObjectHandler/ohxl/functioncall.hpp,v
retrieving revision 1.3
retrieving revision 1.4
diff -C2 -d -r1.3 -r1.4
*** functioncall.hpp 8 Jun 2006 09:37:27 -0000 1.3
--- functioncall.hpp 11 Jun 2006 12:38:22 -0000 1.4
***************
*** 45,56 ****
const XLOPER *getCallerReference();
const XLOPER *getCallerAddress();
const std::string &getAddressString();
const std::string &getFormula();
! bool outerFunction();
CallerDimensions getCallerDimensions();
private:
static FunctionCall *instance_;
! XLOPER xCaller;
! XLOPER xReftext;
std::string address_;
std::string formula_;
--- 45,58 ----
const XLOPER *getCallerReference();
const XLOPER *getCallerAddress();
+ const XLOPER *getCallerArray();
const std::string &getAddressString();
const std::string &getFormula();
! //bool outerFunction();
CallerDimensions getCallerDimensions();
private:
static FunctionCall *instance_;
! XLOPER xCaller_;
! XLOPER xReftext_;
! XLOPER xMulti_;
std::string address_;
std::string formula_;
--- NEW FILE: objhandlerxl.hpp ---
/*
Copyright (C) 2006 Eric Ehlers
This file is part of QuantLib, a free-software/open-source library
for financial quantitative analysts and developers - http://quantlib.org/
QuantLib is free software: you can redistribute it and/or modify it under the
terms of the QuantLib license. You should have received a copy of the
license along with this program; if not, please email qua...@li...
The license is also available online at http://quantlib.org/html/license.html
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the license for more details.
*/
#ifndef oh_objhandlerxl_hpp
#define oh_objhandlerxl_hpp
#include <oh/objhandler.hpp>
#include <ohxl/objecthandlerxl.hpp>
#include <ohxl/conversions.hpp>
#include <ohxl/functioncall.hpp>
#include <ohxl/callingrange.hpp>
#endif
Index: callingrange.cpp
===================================================================
RCS file: /cvsroot/objecthandler/ObjectHandler/ohxl/callingrange.cpp,v
retrieving revision 1.2
retrieving revision 1.3
diff -C2 -d -r1.2 -r1.3
*** callingrange.cpp 2 Jun 2006 13:59:05 -0000 1.2
--- callingrange.cpp 11 Jun 2006 12:38:22 -0000 1.3
***************
*** 28,31 ****
--- 28,34 ----
namespace ObjHandler {
+ // FIXME this value needs to be configured at runtime
+ const std::string libFunctionSignature = "ql";
+
int CallingRange::keyCount_ = 0;
***************
*** 61,75 ****
}
! void CallingRange::clear() {
! std::vector < std::string >::const_iterator i;
! for (i = residentObjects_.begin(); i != residentObjects_.end(); i++) {
! std::string instanceName = *i;
! ObjectHandler::instance().deleteObject(instanceName);
}
residentObjects_.clear();
}
! void CallingRange::registerObject(const std::string &instanceName) {
! residentObjects_.push_back(instanceName);
}
--- 64,97 ----
}
! void CallingRange::clearAnonymous() {
! std::map<std::string, boost::shared_ptr<Object> >::const_iterator iter_current, iter_previous;
! iter_current = residentObjects_.begin();
! while (iter_current != residentObjects_.end()) {
! iter_previous = iter_current;
! iter_current++;
! if (iter_previous->second->anonymous()) {
! ObjectHandler::instance().deleteObject(iter_previous->first);
! residentObjects_.erase(iter_previous->first);
! }
}
+ }
+
+ void CallingRange::clearAll() {
+ std::map<std::string, boost::shared_ptr<Object> >::const_iterator i;
+ for (i = residentObjects_.begin(); i != residentObjects_.end(); i++)
+ ObjectHandler::instance().deleteObject(i->first);
residentObjects_.clear();
}
! void CallingRange::registerObject(
! const std::string &instanceName,
! boost::shared_ptr<Object> object) {
! std::map<std::string, boost::shared_ptr<Object> >::const_iterator i;
! i = residentObjects_.find(instanceName);
! if (i != residentObjects_.end()) {
! ObjectHandler::instance().deleteObject(i->first);
! residentObjects_.erase(i->first);
! }
! residentObjects_[instanceName] = object;
}
***************
*** 138,141 ****
--- 160,179 ----
}
+ // FIXME use boost::regex here
+ void CallingRange::setInvocationCount() {
+ std::string formula = FunctionCall::instance().getFormula();
+ invocationCount_ = -1;
+ unsigned int index = 0;
+ while (index < formula.length()) {
+ index = formula.find(libFunctionSignature, index);
+ if (index == std::string::npos) {
+ return;
+ } else {
+ invocationCount_++;
+ index++;
+ }
+ }
+ }
+
void CallingRange::update() {
/*
***************
*** 146,162 ****
- final call - mark calling range as "not busy"
*/
! if (FunctionCall::instance().outerFunction()) {
! if (busy_) {
busy_ = false;
- } else {
- clear();
- }
} else {
! if (busy_) {
! return;
! } else {
busy_ = true;
! clear();
! }
}
}
--- 184,196 ----
- final call - mark calling range as "not busy"
*/
! if (busy_) {
! invocationCount_--;
! if (!invocationCount_)
busy_ = false;
} else {
! setInvocationCount();
! if (invocationCount_)
busy_ = true;
! clearAnonymous();
}
}
***************
*** 173,181 ****
out << "reference: " << callingRange.getAddressString() << std::endl;
out << "valid: " << (callingRange.isValid() ? "TRUE" : "FALSE") << std::endl;
out << "update count: " << callingRange.updateCount_ << std::endl;
out << "resident objects: " << callingRange.residentObjects_.size() << std::endl;
! std::vector < std::string >::const_iterator i;
for (i = callingRange.residentObjects_.begin(); i != callingRange.residentObjects_.end(); i++)
! out << " instance name: " << *i << std::endl;
out << std::endl;
return out;
--- 207,217 ----
out << "reference: " << callingRange.getAddressString() << std::endl;
out << "valid: " << (callingRange.isValid() ? "TRUE" : "FALSE") << std::endl;
+ out << "busy: " << (callingRange.busy_ ? "TRUE" : "FALSE") << std::endl;
out << "update count: " << callingRange.updateCount_ << std::endl;
+ out << "invocation count: " << callingRange.invocationCount_ << std::endl;
out << "resident objects: " << callingRange.residentObjects_.size() << std::endl;
! std::map<std::string, boost::shared_ptr<Object> >::const_iterator i;
for (i = callingRange.residentObjects_.begin(); i != callingRange.residentObjects_.end(); i++)
! out << " instance name: " << i->first << std::endl;
out << std::endl;
return out;
|