failed to get values of XML elements in pugixml using node.value() - c++

I have below simple XML template in my C++ source code. Within below code block I need to get values for <scannerID> and <subscannerID>. both elements are children of pugixml document root.
xml_document doc;
xml_parse_result r;
std::string sXml = "<inArgs><scannerID>1</scannerID><subScannerID>2</subScannerID></inArgs>";
r = doc.load_buffer(sXml.c_str(), sXml.length());
if (!r) {
return false;
}
xml_node root = doc.child("inArgs");
if (!root) {
return false;
}
std::cout << "root = " << root.name() << std::endl;
xml_node scanner_node = root.child("scannerID");
if (scanner_node) {
std::cout << "scannerID = " << scanner_node.name() << std::endl;
std::cout << "scannerID = " << scanner_node.value() << std::endl;
}
xml_node sub_scanner_node = root.child("subscannerID");
if (scanner_node) {
std::cout << "sub_scanner_node = " << sub_scanner_node.name() << std::endl;
std::cout << "sub_scanner_node = " << sub_scanner_node.value() << std::endl;
}
this code portion giving an output like below. I can get the node's names correctly but failed to retrieve the values.
Out put: values are empty strings.
root = inArgs
scannerID = scannerID
scannerID =
subscannerID = subscannerID
subscannerID =
Edited to add modification for the approach in the answer
node = root.child("scannerID");
if (!node) {
return false;
}
std::cout << "nodeName = %s" << node.name() << std::endl;
std::cout << "text value: " << node.child_value() << std::endl;
but still the output is the same. I saw something different while reading the documents in

The data is in the pcdata child of your element_nodes.
Try scanner_node.child_value()
see the Getting node data section for further examples and explanation.
see node_element
see node_pcdata

Related

c++ filesystem out of root

I`l trying to catch wrong paths in input args in my code and found that behavior.
code example:
#include <iostream>
#include <filesystem>
using namespace std;
namespace fs = std::filesystem;
int main() {
fs::path p = "/home";
cout << p << endl; // "/home"
cout << fs::exists(p) << endl; // 1
try {
p = p / "../..";
cout << p << endl; // "/home/../.."
cout << fs::exists(p) << endl; // 1
} catch (...) {
cout << "catched" << endl;
}
p = fs::canonical(p);
cout << p << endl; // "/"
cout << fs::exists(p) << endl; // 1
return 0;
}
How to catch out of bounds of the root with the standard capabilities? Is this a bug or a feature?
Like everyone else said, you cannot "go out of bounds" with relative parent directory (..).
That said, you can check the depth of a given path:
The path can be traversed element-wise via iterators returned by the begin() and end() functions, which views the path in generic format and iterates over root name, root directory, and the subsequent file name elements (directory separators are skipped except the one that identifies the root directory). If the very last element in the path is a directory separator, the last iterator will dereference to an empty element.
Live On Coliru
#include <filesystem>
#include <iostream>
namespace fs = std::filesystem;
int main()
{
std::cout << std::boolalpha;
for (fs::path p :
{
"/home",
"/home/sehe",
"/home/",
"//home/",
"/home/sehe/",
}) //
{
try {
p = canonical(absolute(p));
std::cout << " -- " << p << " (" << exists(p) << ")\n";
std::cout << "elements:";
for (auto& el : p) {
std::cout << " " << el << ";";
}
std::cout << "\n";
if (std::distance(p.begin(), p.end()) < 3) {
std::cout << "Does not have two unique parents\n";
} else {
p = p / "../..";
std::cout << "Up two: " << p << " (" << exists(p) << ")\n";
}
} catch (std::exception const& e) {
std::cout << "error " << e.what() << "\n";
}
}
}
On my machine prints:
-- "/home" (true)
elements: "/"; "home";
Does not have two unique parents
-- "/home/sehe" (true)
elements: "/"; "home"; "sehe";
Up two: "/home/sehe/../.." (true)
-- "/home" (true)
elements: "/"; "home";
Does not have two unique parents
-- "/home" (true)
elements: "/"; "home";
Does not have two unique parents
-- "/home/sehe" (true)
elements: "/"; "home"; "sehe";
Up two: "/home/sehe/../.." (true)

Value passed to function doubling inside call

I'm currently having an issue with a function call of get_set() for a doubly-linked list class I am making. The function returns a vector of all the elements within the list from position_from to position_to. For the tests I am sending
dll_UT->get_set( dll_UT->size()/2+1 , dll_UT->size()-1)
however, the value of dll_UT->size() somehow doubles within the call. When called directly before in my COUT statement, it shows the correct value of 100, but when inside the function this turns to 200. I've left console logs below as well as screenshots of the test.cpp and doubly_linked_list.cpp.
Any help on this is greatly appreciated as I've never seen this type of behavior before and would like to understand why such a thing is occuring.
Doubly_linked_list get_set(unsigned position_from, unsigned_position to){
std::cout << "\n\t__NEW TEST__\nSize of size/2+1 = " << this->size()/2+1 << "\nSize of size()-1 = " << this->size()-1 << std::endl;
std::cout << "position_from = " << position_from << "\nposition_to = " << position_to << std::endl;
//value of position_from == 200, should be == this->size()/2+1 which = 100
std::vector<int> temp;
temp.reserve(position_to - position_from);
while(position_from < position_to){
temp.push_back( this->get_data(position_from) );
position_from++;
}
temp.push_back(this->get_data(position_to));
std::cout << "Size of position_from = " << position_from << "\nSize of position_to = " << position_to << "\n\t__END TEST__" << std::endl;
return temp;```
}
Test.cpp {
```std::cout << "\nTEST.cpp::: dll_UT-size() = " << dll_UT->size() <<
"\nTEST.cpp::: dll_UT-size()/2+1 = " << dll_UT->size()/2+1 << std::endl;
//assuring dll_UT->size()/2+1 = 100
std::cout << "\nTEST.cpp::: expected_set.size() = " << expected_set.size() <<
"\nTEST.cpp::: expected_set.begin()+expected_set.size()/2+1 = " << expected_set.size()/2+1 << std::endl;
ASSERT_EQ(std::vector<int> (expected_set.begin()+expected_set.size()/2+1,expected_set.end()),
dll_UT->get_set( dll_UT->size()/2+1 , dll_UT->size()-1));//second half of data
// ^first operand doubled, ^second operand fine
//actually value sent is 200. dll_UT->size() is somehow doubling and equaling 400 but only for first operand of get_set(unsigned, unsigned)
Updated Caputre

Not sure where the segmentation fault is

I'm getting problem with segmentation fault when trying to compile a C++ program, but not sure where the problem lies. I suspect that the problem lies with the .find() ..... could it be the iterator operator < and == which are the comparators for find() that is the issue? I hope that someone can point out to me where they think the problem lies.
The following is part of test01.cpp, where I run it to test the code and use print statements to find out where the problem is:
bool confirmEverythingMatches(const btree<long>& testContainer, const set<long>& stableContainer) {
cout << "Confirms the btree and the set "
"contain exactly the same values..." << endl;
for (long i = kMinInteger; i <= kMaxInteger; i++) {
cout << "Start of for-loop to find iterator for comparisons..." << endl;
if (stableContainer.find(i) != stableContainer.end()) {
cout << "can find i (" << i << ") in stableContainer!" << endl;
} else {
cout << "cannot find i (" << i << ") in stableContainer!" << endl;
}
cout << "In between finding i in stable and testContainers..." << endl;
if (testContainer.find(i) != testContainer.end()) {
cout << "can find i (" << i << ") in testContainer!" << endl;
} else {
cout << "cannot find i (" << i << ") in testContainer!" << endl;
}
cout << "Before assigning the find to boolean variables..." << endl;
bool foundInTree = (testContainer.find(i) != testContainer.end());
cout << "testContainer.find(i) != testContainer.end()" << endl;
bool foundInSet = (stableContainer.find(i) != stableContainer.end());
cout << "stableContainer.find(i) != stableContainer.end()" << endl;
if (foundInTree != foundInSet) {
cout << "- btree and set don't contain the same data!" << endl;
cout << "Mismatch at element: " << i << endl;
return false;
} else {cout << "foundInTree == foundInSet!!!" << i << endl;}
}
cout << "- btree checks out just fine." << endl;
return true;
}
} // namespace close
/**
* Codes for testing various bits and pieces. Most of the code is commented out
* you should uncomment it as appropriate.
**/
int main(void) {
// initialise random number generator with 'random' seed
initRandom();
cout << "after initRandom().." << endl;
// insert lots of random numbers and compare with a known correct container
btree<long> testContainer(99);
cout << "after specifying max node elements in testContainer.." << endl;
set<long> stableContainer;
cout << "after constructing stableContainer.." << endl;
insertRandomNumbers(testContainer, stableContainer, 1000000);
cout << "after inserting random numbers into testContainer and for success inserts, also into stableContainer.." << endl;
btree<long> btcpy = testContainer;
cout << "after copy assigning a copy of testContainer to btcopy.." << endl;
confirmEverythingMatches(btcpy, stableContainer);
cout << "after confirming everything internally matches between testContainer and stableContainer.." << endl;
return 0;
}
The output I get when running the program (No problem when compiling) is this:
Confirms the btree and the set contain exactly the same values...
Start of for-loop to find iterator for comparisons...
cannot find i (1000000) in stableContainer!
In between finding i in stable and testContainers...
ASAN:DEADLYSIGNAL
=================================================================
==7345==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000018 (pc 0x000108d132a8 bp 0x000000000000 sp 0x7fff56eee6f0 T0)
#0 0x108d132a7 in btree<long>::find(long const&) const (test01+0x1000022a7)
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV (test01+0x1000022a7) in btree<long>::find(long const&) const
==7345==ABORTING
Abort trap: 6
I also got this error when I tried to run it on another machine:
==29936==ERROR: AddressSanitizer failed to allocate 0x200000 (2097152) bytes of SizeClassAllocator32: 12
I found that when it goes into the find(), it will have the segmentation fault:
/**
* Identical in functionality to the non-const version of find,
* save the fact that what's pointed to by the returned iterator
* is deemed as const and immutable.
*
* #param elem the client element we are trying to match.
* #return an iterator to the matching element, or whatever the
* const end() returns if no such match was ever found.
*/
template<typename T> typename btree<T>::const_iterator
btree<T>::find(const T& elem) const {
std::cout << "CONST ITERATOR'S FIND" << std::endl;
Node *tmp_ = root_;
std::cout << "1" << std::endl;
while(true) {
std::cout << "2" << std::endl;
size_t i;
std::cout << "3" << std::endl;
// go through all elements from root to tail
for (i = 0; i < tmp_->__occupied_size_; ++i) {
std::cout << "4" << std::endl;
if (tmp_->__elem_[i] == elem) {
std::cout << "5" << std::endl;
// find the elem, return an iterator
return const_iterator(tmp_, i, this);
std::cout << "6" << std::endl;
} else if (tmp_->__elem_[i] > elem) {
std::cout << "7" << std::endl;
// elem is not in current Node, go to descendants
// for the elem.
if (tmp_->__descendants_ == nullptr) {
std::cout << "8" << std::endl;
return cend();
std::cout << "9" << std::endl;
} else {
std::cout << "10" << std::endl;
tmp_ = tmp_->__descendants_[i];
std::cout << "11" << std::endl;
break;
}
}
}
// handling boundaries cases
if (i == tmp_->__occupied_size_) {
std::cout << "12" << std::endl;
if (tmp_->__descendants_[i] == nullptr) {
std::cout << "13" << std::endl;
return cend();
std::cout << "14" << std::endl;
} else {
std::cout << "15" << std::endl;
tmp_ = tmp_->__descendants_[i];
}
}
}
}
The print statements for this find is:
CONST ITERATOR'S FIND
1
2
3
4
4
7
10
11
2
3
4
7
10
11
ASAN:DEADLYSIGNAL
Ok, so based on the implementation of this find function, I think the problem might be located in
if (tmp_->__descendants_ == nullptr) {
std::cout << "8" << std::endl;
return cend();
std::cout << "9" << std::endl;
} else {
std::cout << "10" << std::endl;
tmp_ = tmp_->__descendants_[i];
std::cout << "11" << std::endl;
break;
}
and then
// handling boundaries cases
if (i == tmp_->__occupied_size_) {
std::cout << "12" << std::endl;
if (tmp_->__descendants_[i] == nullptr) {
std::cout << "13" << std::endl;
return cend();
std::cout << "14" << std::endl;
} else {
std::cout << "15" << std::endl;
tmp_ = tmp_->__descendants_[i];
}
}
So, You are checking if tmp->__descendants_ is not null. If it is not, then you set tmp_ = tmp_->descendants_[i];
Note: you are just checking __descendants_ pointer to be null or not, you are not checking the __descendants_ [i] if it is null!
What if the tmp->__descendants_[i] is null (or gets out of the descendants array)?
If that value is null, then tmp_->occupied_size_ might give you segfault.
Note2: For some reason you are using same index "i" for iterating through __elem_ and __descendants_. I am not sure, how descendants are created, but it might be also a problem here.
This is why debuggers exist. Run your program in the debugger, let the program fail, and then the debugger will tell you where and why it's gone wrong.
It looks like you've got potentially a lot of code to trawl through, which no one here will really want to do as it's not a concise question.
Good luck!

Using Hbase Thrift2 API in C++

I've been using the Thrift API for HBase in C++ (example usage here), but now I have a need to use Thrift2 instead. I know there are examples for using Thrift2 in other languages, such as C#, Python, and Java, but I can't find documentation for C++.
Here's my current code for calling the Thrift API:
transport->open();
std::string t("demo_table");
/ Scan all tables, look for the demo table and delete it. /
std::cout << "scanning tables..." << std::endl;
StrVec tables;
client.getTableNames(tables);
for (StrVec::const_iterator it = tables.begin(); it != tables.end(); ++it) {
std::cout << " found: " << *it << std::endl;
if (t == *it) {
if (client.isTableEnabled(*it)) {
std::cout << " disabling table: " << *it << std::endl;
client.disableTable(*it);
}
std::cout << " deleting table: " << *it << std::endl;
client.deleteTable(*it);
}
}
Now this fails after switching to Thrift2. For example, client.getTableNames() no longer works (the function doesn't exist).
Some functions are removed from hbase thrift2 interface. If you just want to get list of table names in hbase, you can use get children of /hbase/table in zookeeper.
struct String_vector paths;
int ret = zoo_get_children(zkhandle,"/hbase/table", 0,&paths);//
if(ret)
{
std::cout << "zoo_get_children error " << ret << std::endl;
} else {
for(i = 0;i < paths.count;i++)
printf("/hbase/table/%s\n",paths.data[i]);
free_vector(&paths);
}

Bloomberg Equity Option Chain through API

I am currently working on a project that should help me create an implied volatility surface for a given stock. For this purpose, I am writing a script that will download all the available options for this specific stock - from what I've gathered, this is possible by sending a request through the Bloomberg API using bulks fields/overrides. Here is my current code:
d_host = "localhost";
d_port = 8194;
SessionOptions sessionOptions;
sessionOptions.setServerHost(d_host.c_str());
sessionOptions.setServerPort(d_port);
Session session(sessionOptions);
Service refDataService = session.getService("//blp/refdata");
Request request = refDataService.createRequest("ReferenceDataRequest");
request.append("securities", "MSFT US EQUITY");
request.append("fields", "CHAIN_TICKERS");
// add overrides
Element overrides = request.getElement("overrides");
Element override1 = overrides.appendElement();
override1.setElement("fieldId", "CHAIN_PUT_CALL_TYPE_OVRD");
override1.setElement("value", "C");
Element override2 = overrides.appendElement();
override2.setElement("fieldId", "CHAIN_POINTS_OVRD");
override2.setElement("value", 100);
Element override3 = overrides.appendElement();
override3.setElement("fieldId", "CHAIN_EXP_DT_OVRD");
override3.setElement("value", "20250203");
std::cout << "Sending Request: " << request << std::endl;
CorrelationId cid(this);
session.sendRequest(request, cid);
(followed by event handling)
Now I have several issues/questions:
The code compiles without problems, but when running it on the Bloomberg terminal,the following error is printed:
How would I go about fixing this problem? I assume I made a mistake somewhere in the override fields..
How would I need to adjust my code to download all options available given a specific maturity, i.e. I want to get a list of all the options until today + 15 years.
How would I then download the implied volatility for each option? Would I need to store the tickers in an array and then send a request for the field "IVOL_MID" for each option or is there some kind of way to obtain all the volatilities at once?
Edit: Here is the code of my event handler, since that seems to be the problem.
session.sendRequest(request, cid);
while (true)
{
Event event = session.nextEvent();
MessageIterator msgIter(event);
while (msgIter.next()) {
Message msg = msgIter.message();
if (msg.correlationId() == cid) {
processMessage(msg);
}
}
if (event.eventType() == Event::RESPONSE) {
break;
}
}
void processMessage(Message &msg)
{
Element securityDataArray = msg.getElement(SECURITY_DATA);
int numSecurities = securityDataArray.numValues();
for (int i = 0; i < numSecurities; ++i) {
Element securityData = securityDataArray.getValueAsElement(i);
std::cout << securityData.getElementAsString(SECURITY)
<< std::endl;
const Element fieldData = securityData.getElement(FIELD_DATA);
for (size_t j = 0; j < fieldData.numElements(); ++j) {
Element field = fieldData.getElement(j);
if (!field.isValid()) {
std::cout << field.name() << " is NULL." << std::endl;
}
else {
std::cout << field.name() << " = "
<< field.getValueAsString() << std::endl;
}
}
Element fieldExceptionArray =
securityData.getElement(FIELD_EXCEPTIONS);
for (size_t k = 0; k < fieldExceptionArray.numValues(); ++k) {
Element fieldException =
fieldExceptionArray.getValueAsElement(k);
std::cout <<
fieldException.getElement(ERROR_INFO).getElementAsString(
"category")
<< ": " << fieldException.getElementAsString(FIELD_ID);
}
std::cout << std::endl;
}
The problem is in the event handling code that you are not showing. You are probably parsing it incorrectly.
Running your query I get the following result:
MSFT US 01/20/17 C23
MSFT US 01/20/17 C25
MSFT US 01/20/17 C30
MSFT US 01/20/17 C33
MSFT US 01/20/17 C35
MSFT US 01/20/17 C38
MSFT US 01/20/17 C40
MSFT US 01/20/17 C43
MSFT US 01/20/17 C45
MSFT US 01/20/17 C47
MSFT US 01/20/17 C50
MSFT US 01/20/17 C52.5
MSFT US 01/20/17 C55
MSFT US 01/20/17 C57.5
MSFT US 01/20/17 C60
MSFT US 01/20/17 C65
MSFT US 01/20/17 C70
Note: I'm using the Java API but it is essentially the same.
UPDATE:
your code does not parse the field data array element properly: the returned data contains an array of sequences so you need to parse it in two steps. Instead of field.getValueAsString(), you should have a code that looks like this (it's in Java and not tested):
//...
for (int i = 0; i < field.numValues(); i++) {
Element sequence = field.getValueAsElement(i);
ElementIterator it = sequence.elementIterator();
while (it.hasNext()) {
Element e = it.next();
System.out.println(e.getValueAsString());
}
If that does not work I suggest you debug your code step by step and inspect the type of data you receive and handle it accordingly.
For more details you should read the Developer's guide, in particular A.2.3.
As seen in the other answer, the problem lies in the event handling so I've rewritten that part using some examples from the Bloomberg API emulator.
session.sendRequest(request, cid);
bool continueToLoop = true;
while (continueToLoop)
{
Event evt = session.nextEvent();
switch (evt.eventType())
{
case Event::RESPONSE:
continueToLoop = false; //fall through
case Event::PARTIAL_RESPONSE:
ProcessReferenceDataEvent(evt);
break;
}
}
void ProcessReferenceDataEvent(Event evt)
{
const string level1 = "";
const string level2 = "\t";
const string level3 = "\t\t";
const string level4 = "\t\t\t";
std::cout << endl << endl;
std::cout << level1 << "EventType = " << evt.eventType();
MessageIterator iter(evt);
while (iter.next())
{
Message msg = iter.message();
std::cout << endl << endl;
std::cout << level1 << "correlationID = " << msg.correlationId().asInteger() << endl;
std::cout << level1 << "messageType = " << msg.messageType().string() << endl;
std::cout << endl << endl;
Element SecurityDataArray = msg.getElement(SECURITY_DATA);
int numSecurities = SecurityDataArray.numValues();
for (int valueIndex = 0; valueIndex < numSecurities; valueIndex++)
{
Element SecurityData = SecurityDataArray.getValueAsElement(valueIndex);
string Security = SecurityData.getElementAsString(SECURITY);
std::cout << level2 << Security << endl;
bool hasFieldErrors = SecurityData.hasElement("fieldExceptions", true);
if (hasFieldErrors)
{
Element FieldErrors = SecurityData.getElement(FIELD_EXCEPTIONS);
for (size_t errorIndex = 0; errorIndex < FieldErrors.numValues(); errorIndex++)
{
Element fieldError = FieldErrors.getValueAsElement(errorIndex);
string fieldId = fieldError.getElementAsString(FIELD_ID);
Element errorInfo = fieldError.getElement(ERROR_INFO);
string source = errorInfo.getElementAsString("source");
int code = errorInfo.getElementAsInt32("code");
string category = errorInfo.getElementAsString("category");
string strMessage = errorInfo.getElementAsString("message");
string subCategory = errorInfo.getElementAsString("subcategory");
cerr << level3 << "field error:" << endl;
cerr << level4 << "fieldId = " << fieldId << endl;
cerr << level4 << "source = " << source << endl;
cerr << level4 << "code = " << code << endl;
cerr << level4 << "category = " << category << endl;
cerr << level4 << "errorMessage = " << strMessage << endl;
cerr << level4 << "subCategory = " << subCategory << endl;
}
}
bool isSecurityError = SecurityData.hasElement("securityError", true);
if (isSecurityError)
{
Element secError = SecurityData.getElement("securityError");
string source = secError.getElementAsString("source");
int code = secError.getElementAsInt32("code");
string category = secError.getElementAsString("category");
string errorMessage = secError.getElementAsString("message");
string subCategory = secError.getElementAsString("subcategory");
cerr << level3 << "security error:" << endl;
cerr << level4 << "source = " << source << endl;
cerr << level4 << "code = " << code << endl;
cerr << level4 << "category = " << category << endl;
cerr << level4 << "errorMessage = " << errorMessage << endl;
cerr << level4 << "subCategory = " << subCategory << endl;
}
else
{
Element FieldData = SecurityData.getElement(FIELD_DATA);
double pxLast = FieldData.getElementAsFloat64("PX_LAST");
double bid = FieldData.getElementAsFloat64("BID");
double ask = FieldData.getElementAsFloat64("ASK");
string ticker = FieldData.getElementAsString("TICKER");
std::cout << level3 << "fields: " << endl;
std::cout << level4 << "PX_LAST = " << pxLast << endl;
std::cout << level4 << "BID = " << bid << endl;
std::cout << level4 << "ASK = " << ask << endl;
std::cout << level4 << "TICKER = " << ticker << endl;
bool excludeNullElements = true;
if (FieldData.hasElement("CHAIN_TICKERS", excludeNullElements))
{
Element chainTickers = FieldData.getElement("CHAIN_TICKERS");
for (size_t chainTickerValueIndex = 0; chainTickerValueIndex < chainTickers.numValues(); chainTickerValueIndex++)
{
Element chainTicker = chainTickers.getValueAsElement(chainTickerValueIndex);
string strChainTicker = chainTicker.getElementAsString("Ticker");
std::cout << level4 << "CHAIN_TICKER = " << strChainTicker << endl;
}
}
else
{
std::cout << level4 << "NO CHAIN_TICKER information" << endl;
}
}
}
}
}
Regarding the second question, the Bloomberg support staff recommended me to just pick an arbitarily high number so that all options would be downloaded, i.e.
override2.setElement("fieldId", "CHAIN_POINTS_OVRD");
override2.setElement("value", 50000);
For the third question, it is possible to download the chain tickers for all maturities by setting the "CHAIN_EXP_DT_OVRD" override to 'ALL' (this part is currently untested):
Element override3 = overrides.appendElement();
override3.setElement("fieldId", "CHAIN_EXP_DT_OVRD");
override3.setElement("value", 'ALL');