From e376641a51d84f541593ea6a37c6fa8058089132 Mon Sep 17 00:00:00 2001 From: Dirk Eddelbuettel Date: Thu, 5 Dec 2024 07:28:35 -0600 Subject: [PATCH 1/2] Use Rcpp::stop instead of throw (closes #401) --- ChangeLog | 11 +++++++++++ src/bdh.cpp | 10 +++++----- src/bdp.cpp | 14 +++++++------- src/bds.cpp | 6 +++--- src/beqs.cpp | 4 ++-- src/blpapi_utils.cpp | 44 ++++++++++++++++++++++---------------------- src/bsrch.cpp | 4 ++-- src/lookup.cpp | 2 +- src/subscribe.cpp | 4 ++-- 9 files changed, 55 insertions(+), 44 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4781e305..532aabb5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2024-12-05 Dirk Eddelbuettel + + * src/bdh.cpp: Use Rcpp::stop instead of throw + * src/bdp.cpp: Idem + * src/bds.cpp: Idem + * src/beqs.cpp: Idem + * src/blpapi_utils.cpp: Idem + * src/bsrch.cpp: Idem + * src/lookup.cpp: Idem + * src/subscribe.cpp: Idem + 2024-12-04 Dirk Eddelbuettel * DESCRIPTION (Version, Date): Roll micro version and date diff --git a/src/bdh.cpp b/src/bdh.cpp index 1ca56b72..d7a144cf 100644 --- a/src/bdh.cpp +++ b/src/bdh.cpp @@ -43,13 +43,13 @@ using BloombergLP::blpapi::Name; std::string getSecurityName(Event& event) { MessageIterator msgIter(event); if (!msgIter.next()) { - throw std::logic_error("Not a valid MessageIterator."); + Rcpp::stop("Not a valid MessageIterator."); } Message msg = msgIter.message(); Element response = msg.asElement(); if(std::strcmp(response.name().string(),"HistoricalDataResponse")) { - throw std::logic_error("Not a valid HistoricalDataResponse."); + Rcpp::stop("Not a valid HistoricalDataResponse."); } Element securityData = response.getElement(Name{"securityData"}); @@ -61,14 +61,14 @@ Rcpp::List HistoricalDataResponseToDF(Event& event, const std::vector& rtypes, bool verbose=FALSE) { MessageIterator msgIter(event); if (!msgIter.next()) { - throw std::logic_error("Not a valid MessageIterator."); + Rcpp::stop("Not a valid MessageIterator."); } Message msg = msgIter.message(); Element response = msg.asElement(); if (verbose) response.print(Rcpp::Rcout); if (std::strcmp(response.name().string(),"HistoricalDataResponse")) { - throw std::logic_error("Not a valid HistoricalDataResponse."); + Rcpp::stop("Not a valid HistoricalDataResponse."); } Element securityData = response.getElement(Name{"securityData"}); Element fieldData = securityData.getElement(Name{"fieldData"}); @@ -81,7 +81,7 @@ Rcpp::List HistoricalDataResponseToDF(Event& event, const std::vector& securities, const std::vector& colnames, const std::vector& rtypes, bool verbose) { MessageIterator msgIter(event); if (!msgIter.next()) { - throw std::logic_error("Not a valid MessageIterator."); + Rcpp::stop("Not a valid MessageIterator."); } Message msg = msgIter.message(); Element response = msg.asElement(); if (verbose) response.print(Rcpp::Rcout); if (std::strcmp(response.name().string(),"ReferenceDataResponse")) { - throw std::logic_error("Not a valid ReferenceDataResponse."); + Rcpp::stop("Not a valid ReferenceDataResponse."); } const Name responseError("responseError"); @@ -65,7 +65,7 @@ void getBDPResult(Event& event, Rcpp::List& res, const std::vector& errMsg = errorElement.getElementAsString(messageTag); } Rcpp::Rcerr << "REQUEST FAILED: " << errorElement << std::endl; - throw std::logic_error("bdp result: a responseError was received with message: (" + errMsg + ")"); + Rcpp::stop("bdp result: a responseError was received with message: (" + errMsg + ")"); } Element securityData = response.getElement(Name{"securityData"}); @@ -76,14 +76,14 @@ void getBDPResult(Event& event, Rcpp::List& res, const std::vector& // check that the seqNum matches the order of the securities vector (it's a grave error to screw this up) if(securities[row_index].compare(this_security.getElementAsString(Name{"security"}))!=0) { - throw std::logic_error("mismatched Security sequence, please report a bug."); + Rcpp::stop("mismatched Security sequence, please report a bug."); } Element fieldData = this_security.getElement(Name{"fieldData"}); for(size_t j = 0; j < fieldData.numElements(); ++j) { Element e = fieldData.getElement(j); auto col_iter = std::find(colnames.begin(), colnames.end(), e.name().string()); if (col_iter == colnames.end()) { - throw std::logic_error(std::string("column is not expected: ") + e.name().string()); + Rcpp::stop(std::string("column is not expected: ") + e.name().string()); } size_t col_index = std::distance(colnames.begin(),col_iter); populateDfRow(res[col_index],row_index,e,rtypes[col_index]); @@ -98,7 +98,7 @@ Rcpp::List bdp_Impl(SEXP con_, std::vector securities, std::vector< SEXP options_, SEXP overrides_, bool verbose, SEXP identity_) { // via Rcpp Attributes we get a try/catch block with error propagation to R "for free" - Session* session = + Session* session = reinterpret_cast(checkExternalPointer(con_, "blpapi::Session*")); // get the field info @@ -114,7 +114,7 @@ Rcpp::List bdp_Impl(SEXP con_, std::vector securities, std::vector< if (!session->openService(rdsrv.c_str())) { Rcpp::stop("Failed to open " + rdsrv); } - + Service refDataService = session->getService(rdsrv.c_str()); Request request = refDataService.createRequest("ReferenceDataRequest"); createStandardRequest(request, securities, fields, options_, overrides_); diff --git a/src/bds.cpp b/src/bds.cpp index 610beff9..c0359bf5 100644 --- a/src/bds.cpp +++ b/src/bds.cpp @@ -99,7 +99,7 @@ void populateDfRowBDS(Rcpp::RObject ans, R_len_t row_index, Element& e) { case BLPAPI_DATATYPE_CORRELATION_ID: INTEGER(ans)[row_index] = e.getValueAsInt32(); break; default: - throw std::logic_error("Unsupported datatype outside of api blpapi_DataType_t scope."); + Rcpp::stop("Unsupported datatype outside of api blpapi_DataType_t scope."); } } @@ -218,14 +218,14 @@ Rcpp::List bulkArrayToDf(Element& fieldData) { Rcpp::List BulkDataResponseToDF(Event& event, std::string& requested_field, std::string response_type, bool verbose) { MessageIterator msgIter(event); if(!msgIter.next()) { - throw std::logic_error("Not a valid MessageIterator."); + Rcpp::stop("Not a valid MessageIterator."); } Message msg = msgIter.message(); Element response = msg.asElement(); if (verbose) response.print(Rcpp::Rcout); if(std::strcmp(response.name().string(),response_type.c_str())) { - throw std::logic_error("Not a valid " + response_type + "."); + Rcpp::stop("Not a valid " + response_type + "."); } Element securityData = response.getElement(Name{"securityData"}); diff --git a/src/beqs.cpp b/src/beqs.cpp index 8dcee6fa..3ba2d7d9 100644 --- a/src/beqs.cpp +++ b/src/beqs.cpp @@ -56,14 +56,14 @@ using BloombergLP::blpapi::Name; Rcpp::DataFrame processResponseEvent(Event event, const bool verbose) { MessageIterator msgIter(event); // create message iterator - if (!msgIter.next()) throw std::logic_error("Not a valid MessageIterator."); + if (!msgIter.next()) Rcpp::stop("Not a valid MessageIterator."); Message msg = msgIter.message(); // get message if (verbose) msg.print(Rcpp::Rcout); Element response = msg.asElement(); // view as element if (std::strcmp(response.name().string(), "BeqsResponse") != 0) - throw std::logic_error("Not a valid EQSDataResponse."); + Rcpp::stop("Not a valid EQSDataResponse."); Element data = msg.getElement(Name{"data"}); // get data payload, extract field with display units Element fieldDisplayUnits = data.getElement(Name{"fieldDisplayUnits"}); diff --git a/src/blpapi_utils.cpp b/src/blpapi_utils.cpp index 1dee1146..76bbbf25 100644 --- a/src/blpapi_utils.cpp +++ b/src/blpapi_utils.cpp @@ -50,31 +50,31 @@ using BloombergLP::blpapi::Name; void* checkExternalPointer(SEXP xp_, const char* valid_tag) { if(xp_ == R_NilValue) { - throw std::logic_error("External pointer is NULL."); + Rcpp::stop("External pointer is NULL."); } if(TYPEOF(xp_) != EXTPTRSXP) { - throw std::logic_error("Not an external pointer."); + Rcpp::stop("Not an external pointer."); } if(R_ExternalPtrTag(xp_)==R_NilValue) { - throw std::logic_error("External pointer tag is NULL."); + Rcpp::stop("External pointer tag is NULL."); } const char* xp_tag = CHAR(PRINTNAME(R_ExternalPtrTag(xp_))); if(!xp_tag) { - throw std::logic_error("External pointer tag is blank."); + Rcpp::stop("External pointer tag is blank."); } if(std::strcmp(xp_tag,valid_tag) != 0) { - throw std::logic_error("External pointer tag does not match."); + Rcpp::stop("External pointer tag does not match."); } if(R_ExternalPtrAddr(xp_)==NULL) { - throw std::logic_error("External pointer address is null."); + Rcpp::stop("External pointer address is null."); } return R_ExternalPtrAddr(xp_); } const int bbgDateToRDate(const Datetime& bbg_date) { if(bbg_date.hasParts(DatetimeParts::TIME)) { - throw std::logic_error("Attempt to convert a Datetime with time parts set to an R Date."); + Rcpp::stop("Attempt to convert a Datetime with time parts set to an R Date."); } const boost::gregorian::date r_epoch(1970,1,1); boost::gregorian::date bbg_boost_date(bbg_date.year(),bbg_date.month(),bbg_date.day()); @@ -84,10 +84,10 @@ const int bbgDateToRDate(const Datetime& bbg_date) { const int bbgDateToRDate(const double yyyymmdd_date) { if(yyyymmdd_date < 0) { - throw std::logic_error("Attempt to convert a negative double value to an R Date."); + Rcpp::stop("Attempt to convert a negative double value to an R Date."); } if(trunc(yyyymmdd_date)!=yyyymmdd_date) { - throw std::logic_error("Attempt to convert a double value with time parts set to an R Date."); + Rcpp::stop("Attempt to convert a double value with time parts set to an R Date."); } const boost::gregorian::date r_epoch(1970,1,1); @@ -149,17 +149,17 @@ void appendOptionsToRequest(Request& request, SEXP options_) { Rcpp::CharacterVector options(options_); if(!options.hasAttribute("names")) { - throw std::logic_error("Request options must be named."); + Rcpp::stop("Request options must be named."); } if(options.attr("names") == R_NilValue) { - throw std::logic_error("Request optionnames must not be null."); + Rcpp::stop("Request optionnames must not be null."); } Rcpp::CharacterVector options_names(options.attr("names")); if(options.length() && options_names.length()==0) { - throw std::logic_error("Request options must be non empty and named."); + Rcpp::stop("Request options must be non empty and named."); } for(R_len_t i = 0; i < options.length(); i++) { @@ -172,13 +172,13 @@ void appendOverridesToRequest(Request& request, SEXP overrides_) { Rcpp::CharacterVector overrides(overrides_); if(!overrides.hasAttribute("names") || overrides.attr("names") == R_NilValue) { - throw std::logic_error("Request overrides must be named."); + Rcpp::stop("Request overrides must be named."); } Rcpp::CharacterVector overrides_names(overrides.attr("names")); if(overrides.length() && overrides_names.length()==0) { - throw std::logic_error("Request overrides must be non empty and named."); + Rcpp::stop("Request overrides must be non empty and named."); } Element request_overrides = request.getElement(Name{"overrides"}); @@ -367,25 +367,25 @@ FieldInfo getFieldType(Session *session, Service& fieldInfoService, const std::s //msg.asElement().print(std::cout); Element fields = msg.getElement(Name{"fieldData"}); if(fields.numValues() > 1) { - throw std::logic_error("getFieldType: too many fields returned."); + Rcpp::stop("getFieldType: too many fields returned."); } Element field = fields.getValueAsElement(0); if (!field.hasElement(Name{"id"})) { - throw std::logic_error("Did not find 'id' in repsonse."); + Rcpp::stop("Did not find 'id' in repsonse."); } if (field.hasElement(Name{"fieldError"})) { std::ostringstream err; err << "Bad field: " << field.getElementAsString(Name{"id"}) << std::endl; - throw std::logic_error(err.str()); + Rcpp::stop(err.str()); } if (!field.hasElement(Name{"fieldInfo"})) { - throw std::logic_error("Did not find fieldInfo in repsonse."); + Rcpp::stop("Did not find fieldInfo in repsonse."); } Element fieldInfo = field.getElement(Name{"fieldInfo"}); if (!fieldInfo.hasElement(Name{"mnemonic"}) || !fieldInfo.hasElement(Name{"datatype"}) || !fieldInfo.hasElement(Name{"ftype"})) { - throw std::logic_error("fieldInfo missing info mnemonic/datatype/ftype."); + Rcpp::stop("fieldInfo missing info mnemonic/datatype/ftype."); } ans.id = field.getElementAsString(Name{"id"}); ans.mnemonic = fieldInfo.getElementAsString(Name{"mnemonic"}); @@ -404,7 +404,7 @@ std::vector getFieldTypes(Session *session, const std::vector &fields) { const std::string APIFLDS_SVC("//blp/apiflds"); if (!session->openService(APIFLDS_SVC.c_str())) { - throw std::logic_error(std::string("Failed to open " + APIFLDS_SVC)); + Rcpp::stop(std::string("Failed to open " + APIFLDS_SVC)); } Service fieldInfoService = session->getService(APIFLDS_SVC.c_str()); std::vector ans; @@ -417,7 +417,7 @@ std::vector getFieldTypes(Session *session, Rcpp::List allocateDataFrame(const vector& rownames, const vector& colnames, vector& coltypes) { if(colnames.size() != coltypes.size()) { - throw std::logic_error("colnames size inconsistent with column types size."); + Rcpp::stop("colnames size inconsistent with column types size."); } Rcpp::List ans(colnames.size()); @@ -433,7 +433,7 @@ Rcpp::List allocateDataFrame(const vector& rownames, const vector& colnames, const vector& coltypes) { if(colnames.size() != coltypes.size()) { - throw std::logic_error("colnames size inconsistent with column types size."); + Rcpp::stop("colnames size inconsistent with column types size."); } Rcpp::List ans(colnames.size()); diff --git a/src/bsrch.cpp b/src/bsrch.cpp index c05fc6c3..3f051dfb 100644 --- a/src/bsrch.cpp +++ b/src/bsrch.cpp @@ -54,14 +54,14 @@ using BloombergLP::blpapi::Name; Rcpp::DataFrame processBsrchResponse(Event event, const bool verbose) { MessageIterator msgIter(event); // create message iterator - if (!msgIter.next()) throw std::logic_error("Not a valid MessageIterator."); + if (!msgIter.next()) Rcpp::stop("Not a valid MessageIterator."); Message msg = msgIter.message(); // get message if (verbose) msg.print(Rcpp::Rcout); Element response = msg.asElement(); // view as element if (std::strncmp(response.name().string(), "GridResponse", std::strlen("GridResponse")) != 0) - throw std::logic_error("Not a valid GridResponse."); + Rcpp::stop("Not a valid GridResponse."); // exrsvc provides a grid in the form of DataRecords // Extract the dimensions and key attributes before processing diff --git a/src/lookup.cpp b/src/lookup.cpp index 8adc57ec..eadafd50 100644 --- a/src/lookup.cpp +++ b/src/lookup.cpp @@ -51,7 +51,7 @@ void processMessage(bbg::Message &msg, InstrumentListResults &matches, const boo bbg::Element response = msg.asElement(); if (verbose) response.print(Rcpp::Rcout); if (std::strcmp(response.name().string(),"InstrumentListResponse")) { - throw std::logic_error("Not a valid InstrumentListResponse."); + Rcpp::stop("Not a valid InstrumentListResponse."); } bbg::Element data = response.getElement(bbg::Name{"results"}); diff --git a/src/subscribe.cpp b/src/subscribe.cpp index bb1a22ac..42755178 100644 --- a/src/subscribe.cpp +++ b/src/subscribe.cpp @@ -170,7 +170,7 @@ SEXP subscribe_Impl(SEXP con_, std::vector securities, std::vector< SEXP options_, SEXP identity_) { // via Rcpp Attributes we get a try/catch block with error propagation to R "for free" - Session* session = + Session* session = reinterpret_cast(checkExternalPointer(con_, "blpapi::Session*")); const std::string mdsrv = "//blp/mktdata"; @@ -214,7 +214,7 @@ SEXP subscribe_Impl(SEXP con_, std::vector securities, std::vector< Rcpp::List ans; auto it = BlpapiEventToString.find(event.eventType()); if(it==BlpapiEventToString.end()) { - throw Rcpp::exception("Unknown event type."); + Rcpp::stop("Unknown event type."); } ans["event.type"] = it->second; size_t cid(msg.correlationId().asInteger()); From 9e62aff920053d6d22bfa6d9f58aa1c995fc54c4 Mon Sep 17 00:00:00 2001 From: Dirk Eddelbuettel Date: Sat, 7 Dec 2024 14:48:14 -0600 Subject: [PATCH 2/2] Update NEWS.Rd --- inst/NEWS.Rd | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/inst/NEWS.Rd b/inst/NEWS.Rd index 7afa59aa..6ae114cb 100644 --- a/inst/NEWS.Rd +++ b/inst/NEWS.Rd @@ -4,6 +4,14 @@ \newcommand{\ghpr}{\href{https://github.com/Rblp/Rblpapi/pull/#1}{##1}} \newcommand{\ghit}{\href{https://github.com/Rblp/Rblpapi/issues/#1}{##1}} +\section{Changes in Rblpapi version 0.3.16 (2025-xx-yy)}{ + \itemize{ + \item A quoto error message is now improved (Rodolphe Duge in \ghpr{400}) + \item Convert remaining \code{throw} into \code{Rcpp::stop} (Dirk in + \ghpr{402} fixing \ghit{401}) + } +} + \section{Changes in Rblpapi version 0.3.15 (2024-09-18)}{ \itemize{ \item A warning is now issued if more than 1000 results are returned