Error creating user issued assets - create_assets - Bitshares Graphene network - c++

Blockchain server: Ubuntu 14.04
C++ server: C++ 11
When I tried to create a user issued assets on Bitshare, I need to construct a json object as one of the parameter, see instructions here: https://steemit.com/bitshares/#adinda/update-bitshares-how-to-creating-a-new-uia-asset-manually
Official API documentation here: http://docs.bitshares.org/api/wallet-api.html
Search for "create_asset", then you can find it!
Because I am creating a cpp server, I made a c++ version of it, I use jsoncpp for constructing json. But after testing, it reports parsing error:
4 parse_error_exception: Parse Error
Unexpected char '111' in "options"
{"c":111,"s":"options"}
th_a json.cpp:454 variant_from_stream
Attempting to parse array ["nathan","SYMBOL",3]
{"array":["nathan","SYMBOL",3]}
th_a json.cpp:261 arrayFromStreamBase
Error parsing object
{}
th_a json.cpp:224 objectFromStreamBase
{"str":"{\"jsonrpc\": \"2.0\", \"id\":\"2\", \"method\": \"create_asset\", \"params\": [\"nathan\", \"SYMBOL\", 3, options, {}, true] }"}
th_a json.cpp:463 from_string
Process finished with exit code 0
Here is my code:
#include <stdlib.h>
#include <cstring>
#include <curl/curl.h>
#include <iostream>
#include <string>
#include <json/json.h>
#include <json/value.h>
using namespace std;
int main() {
CURL *curl = curl_easy_init();
struct curl_slist *headers = NULL;
if (curl) {
cout << "curl initialized." << endl;
}
//Initialize Json.
Json::Value perm;
perm["charge_market_fee"] = 0x01;
perm["white_list"] = 0x02;
perm["override_authority"] = 0x04;
perm["transfer_restricted"] = 0x08;
perm["disable_force_settle"] = 0x10;
perm["global_settle"] = 0x20;
perm["disable_confidential"] = 0x40;
perm["witness_fed_asset"] = 0x80;
perm["committee_fed_asset"] = 0x100;
Json::Value permissions;
permissions["charge_market_fee"] = true;
permissions["white_list"] = true;
permissions["override_authority"] = true;
permissions["transfer_restricted"] = true;
permissions["disable_force_settle"] = true;
permissions["global_settle"] = true;
permissions["disable_confidential"] = true;
permissions["witness_fed_asset"] = true;
permissions["committee_fed_asset"] = true;
Json::Value flags;
flags["charge_market_fee"] = false;
flags["white_list"] = false;
flags["override_authority"] = false;
flags["transfer_restricted"] = false;
flags["disable_force_settle"] = false;
flags["global_settle"] = false;
flags["disable_confidential"] = false;
flags["witness_fed_asset"] = false;
flags["committee_fed_asset"] = false;
int permissions_int = 0;
for (Json::Value::iterator itr = permissions.begin(); itr != permissions.end(); itr++) {
if(*itr)
permissions_int += perm[itr.key().asString()].asInt();
}
cout << "permissions_int: " << permissions_int << endl;
int flags_int = 0;
for (Json::Value::iterator itr = permissions.begin(); itr != permissions.end(); itr++) {
if (*itr)
flags_int += perm[itr.key().asString()].asInt();
}
cout << "flags_int: " << flags_int << endl;
Json::Value core_ext;
Json::Value minParameters;
Json::Value minParameters_new;
minParameters["amount"] = 10;
minParameters["asset_id"] = "1.3.0";
minParameters_new["amount"] = 10;
minParameters_new["asset_id"] = "1.3.1";
core_ext["base"] = minParameters;
core_ext["quote"] = minParameters_new;
cout << "core_ext: " << core_ext << endl;
Json::Value options;
options["max_supply"] = 10000;
options["market_fee_percent"] = 0;
options["max_market_fee"] = 0;
options["issuer_permissions"] = permissions_int;
options["flags"] = flags_int;
options["core_exchange_rate"] = core_ext;
options["whitelist_authorities"] = Json::Value(Json::arrayValue);
options["blacklist_authorities"] = Json::Value(Json::arrayValue);
options["whitelist_markets"] = Json::Value(Json::arrayValue);
options["blacklist_markets"] = Json::Value(Json::arrayValue);
options["description"] = "My fancy description";
cout << "options: " << endl << options.toStyledString() << endl;
// Preparing data.
const char *data =
"{\"jsonrpc\": \"2.0\", \"id\":\"2\", \"method\": \"create_asset\", \"params\": [\"nathan\", \"SYMBOL\", 3, options, {}, true] }";
headers = curl_slist_append(headers, "content-type: text/plain;");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_URL, "http://127.0.0.1:8090/");
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (long) strlen(data));
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data);
//curl_easy_setopt(curl, CURLOPT_USERPWD,"bitcoinrpcUSERNAME:bitcoinrpcPASSWORD");
curl_easy_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_TRY);
curl_easy_perform(curl);
return 0;
}
I verified my 'options' object which I sent through curl, it's output is:
{
"blacklist_authorities" : [],
"blacklist_markets" : [],
"core_exchange_rate" :
{
"base" :
{
"amount" : 10,
"asset_id" : "1.3.0"
},
"quote" :
{
"amount" : 10,
"asset_id" : "1.3.1"
}
},
"description" : "My fancy description",
"flags" : 511,
"issuer_permissions" : 511,
"market_fee_percent" : 0,
"max_market_fee" : 0,
"max_supply" : 10000,
"whitelist_authorities" : [],
"whitelist_markets" : []
}
I didn't find any char '111' in "options", that's why I am confused. Could anyone please offer any suggestions? I would be greatly appreciate it!
Updates:
Thanks for the suggestions, now I constructed a new json holding all the information in the original *data, see code below:
Json::Value data;
Json::Value params_new = Json::arrayValue;
params_new.append("nathan");
params_new.append("SYMBOL");
params_new.append(3);
params_new.append(options);
params_new.append({});
params_new.append(true);
data["jsonrpc"] = 2.0;
data["id"] = 2;
data["method"] = "create_asset";
data["params"] = params_new;
cout << "data: " << data << endl;
cout << "to c_str: " << data.toStyledString().c_str() << endl;
I sent data.toStyledString().c_str() as *data thourgh curl, now after sending it, I got followings:
4 parse_error_exception: Parse Error
Unexpected EOF: 11 eof_exception: End Of File
stringstream
{}
th_a sstream.cpp:66 readsome
while parsing token 'par'
{"token":"par\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000"}
th_a json.cpp:131 stringFromStream
{"e":"11 eof_exception: End Of File\nstringstream\n {}\n th_a sstream.cpp:66 readsome\nwhile parsing token 'par\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000'\n {\"token\":\"par\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\"}\n th_a json.cpp:131 stringFromStream"}
th_a json.cpp:219 objectFromStreamBase
{"str":"{\n\t\"id\" : 2,\n\t\"jsonrpc\" : 2.0,\n\t\"method\" : \"create_asset\",\n\t\"par\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000"}
th_a json.cpp:463 from_string
Process finished with exit code 0
This is such a weird problem, I verified the content in data.toStyledString().c_str() - which I sent through curl:
{
"id" : 2,
"jsonrpc" : 2.0,
"method" : "create_asset",
"params" :
[
"nathan",
"SYMBOL",
3,
{
"blacklist_authorities" : [],
"blacklist_markets" : [],
"core_exchange_rate" :
{
"base" :
{
"amount" : 10,
"asset_id" : "1.3.0"
},
"quote" :
{
"amount" : 10,
"asset_id" : "1.3.1"
}
},
"description" : "My fancy description",
"flags" : 511,
"issuer_permissions" : 511,
"market_fee_percent" : 0,
"max_market_fee" : 0,
"max_supply" : 10000,
"whitelist_authorities" : [],
"whitelist_markets" : []
},
null,
true
]
}
And it is a valid json, could anyone offer any ideas? Thanks so much!

Related

http response from recv() is missing raw/binary data in the body C++ sockets

working on a http client that downloads data from a website using HTTP/1.1 (not https on port 443). The program is working for the most part, but when I attempt to write the data to a file, the data in the file does not match with the data when I physically save the file from a browser. Here is the code below:
#include <fstream>
#include <iostream>
#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string>
#include <cstring>
using namespace std;
string resolveToIPAddress(string, string);
int getPortNum(string);
string getUrlPath(string);
string getDomain(string);
string getDomainWithFile(string);
string getUrlWithNoPort(string);
string getFileFromURL(string);
string getFilePath(string);
bool hasHTTPProtocol(string);
bool hasPortNum(string);
bool checkIfValidProtocol(string);
int main(int argc, char ** argv) {
//Create a file to be opened for output
ofstream out_file;
out_file.open("output", ios::out | ios::binary);
int connection_port = 0, send_req, recv_req;
string ip_addr = "", domain = "", ipFromDomain = "", file_to_get = "", http_response = "";
ip_addr = argv[1]; //point ip address argument to the 2nd indice in the arguments
//Check if http is valid
if(hasHTTPProtocol(ip_addr) == true) {
//if there is a port number, Get port number (extract it from URL)
if(hasPortNum(ip_addr)) {
connection_port = getPortNum(ip_addr);
domain = getDomain(ip_addr);
}
//if there is no port number, set default port number = 80 and set domain to truncated ip address
else {
connection_port = 80;
domain = getDomain(ip_addr);
}
file_to_get = getFileFromURL(ip_addr);
//For Testing purposes only
//cout << "Domain: " << domain << endl;
//cout << getDomainWithFile(ip_addr) << endl;
//cout << "URL without port: " << getUrlWithNoPort(ip_addr) << endl;
//cout << "URL Path: " << getUrlPath(ip_addr);
//cout << "Path and File: " << getFilePath(ip_addr) << endl;
//cout << "Domain and File: " << getDomainWithFile(ip_addr) << endl;
// cout << "Port Number: " << connection_port << endl;
// cout << "File requested: " << file_to_get << endl;
//resolve domain to ipAddress
ipFromDomain = resolveToIPAddress(domain, to_string(connection_port));
//Connect to iP Address with port and return metadata
//Create the socket
int http_client_socket = socket(AF_INET, SOCK_STREAM, 0);
// connect address and contain socket
struct sockaddr_in connection_addr;
connection_addr.sin_family = AF_INET; //set the addressfamily type to INET
connection_addr.sin_port = htons(connection_port); //set socket to parsed port number
//cout << "ip address: " << ipFromDomain << endl; //checking to see if ip address is well converted
inet_aton(ipFromDomain.c_str(), &connection_addr.sin_addr); //convert ip address from IPV4 notation string and store it into structure
//Connect to server address
if(connect(http_client_socket, (struct sockaddr *) &connection_addr, sizeof(connection_addr)) != 0) {
out_file << "NOCONNECTION" << endl;
out_file.close();
exit(0);
}
//Logic for HTTP GET Request
string http_request = "GET /" + getFilePath(ip_addr) + " HTTP/1.1\r\nHost:" + domain + "\r\nConnection: close\r\n\r\n";
//cout << http_request << endl;
send_req = send(http_client_socket, http_request.c_str(), http_request.length(), 0);
if ( send_req != http_request.length() ) { std::cerr << "Oops on send\n"; }
char buff[BUFSIZ];
int n;
while ( (n=recv(http_client_socket, buff, sizeof(buff), 0)) > 0 ) {
http_response.append(buff, n);
}
//Testing
//cout << http_response << endl;
//Test for 404, if there is a 404 then close the program and exit with "FILENOTFOUND" in output file
if(http_response.find("HTTP/1.1 404") != string::npos) {
out_file << "FILENOTFOUND" << endl;
out_file.close();
exit(0);
}
const char * http_body_data = strstr(http_response.c_str(), "\r\n\r\n");
if(http_body_data) {
http_body_data += 4;
}
//out_file << http_response;
//close the file
out_file << http_body_data;
out_file.close();
//close the socket
close(http_client_socket);
} else {
out_file << "INVALIDPROTOCOL" << endl;
out_file.close();
exit(0);
}
return 0;
}
string getUrlWithNoPort(string url) {
if(hasHTTPProtocol(url))
return url.substr(7, url.length() - 7);
return url;
}
//Get URL without port and path
string getDomain(string url) {
string urlWithoutPortandPath = "";
int i = 0;
//Check if full URL has a protocol
if (hasHTTPProtocol(url)) {
//if it has a protocol truncate the protocol from FQDN
i = 7;
while (url[i] != '/') {
//for (int i = 7; i < url.length(); i++) {
if (url[i] == ':') {
break;
}
urlWithoutPortandPath += url[i];
i++;
//}
}
return urlWithoutPortandPath;
}
//if it does not have a protocol remove port number and path
while (url[i] != '/') {
//for (int i = 0; i < url.length(); i++) {
if (url[i] == ':') {
break;
}
urlWithoutPortandPath += url[i];
i++;
}
return urlWithoutPortandPath;
}
string getDomainWithFile(string url) {
string urlWithoutPortandPath = "";
//Check if full URL has a protocol
if (hasHTTPProtocol(url)) {
//if it has a protocol truncate the protocol from FQDN
for (int i = 7; i < url.length(); i++) {
if (url[i] == ':') {
break;
}
urlWithoutPortandPath += url[i];
}
return urlWithoutPortandPath;
}
//if it does not have a protocol remove port number and path
for (int i = 0; i < url.length(); i++) {
if (url[i] == ':') {
break;
}
urlWithoutPortandPath += url[i];
}
return urlWithoutPortandPath;
}
bool hasHTTPProtocol(string url) {
string httpProtocol = url.substr(0, 7);
if(httpProtocol == "http://")
return true;
return false;
}
int getPortNum(string url) {
string port = "";
int portNum, portIdx = 0, pathIdx = 0, portEndIdx = 0;
if(hasHTTPProtocol(url)) {
for(int i = 7; i < url.length(); i++) {
if (url[i] == ':')
portIdx = i + 1;
}
}
string fromPortToPath = url.substr(portIdx, url.length() - portIdx);
//cout << "Port to Path: " << fromPortToPath << endl;
for (int i = 0; i < fromPortToPath.length(); i++) {
if (fromPortToPath[i] == '/') {
pathIdx = i + 1;
portEndIdx = i;
break;
}
}
port = fromPortToPath.substr(0, portEndIdx);
portNum = stoi(port);
return portNum;
}
string getUrlPath(string url) {
string urlPath = "";
int pathIdx = 0, portIdx = 0, portEndIdx = 0;
if(hasHTTPProtocol(url)) {
for(int i = 7; i < url.length(); i++) {
if (url[i] == ':')
portIdx = i + 1;
}
}
string fromPortToPath = url.substr(portIdx, url.length() - portIdx);
cout << "Port to Path: " << fromPortToPath << endl;
for (int i = 0; i < fromPortToPath.length(); i++) {
if (fromPortToPath[i] == '/') {
pathIdx = i + 1;
portEndIdx = i;
break;
}
}
urlPath = fromPortToPath.substr(portEndIdx + 1, fromPortToPath.length() - pathIdx );
return urlPath;
}
bool hasPortNum(string url) {
if(hasHTTPProtocol(url)) {
for (int i = 7; i < url.length(); i++) {
if (url[i] == ':')
return true;
}
} else {
for (int i = 0; i < url.length(); i++) {
if (url[i] == ':')
return true;
}
}
return false;
}
//Resolves a string hostname e.g. google.com into an ipaddress (practically a DNS function)
string resolveToIPAddress(string urlString, string portNum) {
struct addrinfo hints, *results;
struct addrinfo *result;
int error, sock_id;
string numericalIPS[100];
//set all bits in hints to zero
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
if((error = getaddrinfo(urlString.c_str(), portNum.c_str(), &hints, &results)) != 0) {
cout << "error " << error << ":" << gai_strerror(error) << endl;
}
int i = 0;
//loop through results
for(result = results; result != nullptr; result = result->ai_next) {
struct sockaddr_in *ip_addr;
ip_addr = (struct sockaddr_in *)result->ai_addr;
numericalIPS[i] = inet_ntoa(ip_addr->sin_addr);
i++;
}
return numericalIPS[0];
}
string getFileFromURL(string url) {
int idxToFile;
string file_request;
string path_to_file = getDomainWithFile(url);
for (int i = 0; i < path_to_file.length(); i++) {
if(path_to_file[i] == '/') {
idxToFile = i + 1;
}
}
file_request = path_to_file.substr(idxToFile, path_to_file.length() - idxToFile);
return file_request;
}
string getFilePath(string url) {
string domainPathAndFile = getDomainWithFile(url);
string pathAndFile;
int idxToPath;
for (int i = 0; i < domainPathAndFile.length(); i++) {
if(domainPathAndFile[i] == '/') {
idxToPath = i + 1;
break;
}
}
pathAndFile = domainPathAndFile.substr(idxToPath, domainPathAndFile.length() - idxToPath);
return pathAndFile;
}
I used this website as a testing medium: http://www.testingmcafeesites.com/testcat_ac.html
When I do the following:
wget http://www.testingmcafeesites.com/testcat_ac.html
I get the following:
<html>
<head>
<title>URL for testing - Category Art/Culure</title>
</head>
<body>
<code>
http://www.testingmcafeesites.com/testcat_ac.html<br>
<br>
This is an example URL which should be categorized as an art/culture website with a minimal risk reputation score.<br>
This page simply displays this text without any specific content on it, it is just for testing purpose.<br>
<br>
<b>If you can see this text, it was not blocked by any filter!</b><br>
<br>
</code>
</body>
</html>
However, with my program, I get the following and there are spaces as well in the first couple of lines:
<html>
<head>
<title>URL for testing - Category Art/Culure</title>
</head>
<body>
<code>
http://www.testingmcafeesites.com/testcat_ac.html<br>
<br>
This is an example URL which should be categorized as an art/culture website with a minimal risk reputation score.<br>
This page simply displays this text without any specific content on it, it is just for testing purpose.<br>
<br>
<b>If you can see this text, it was not blocked by any filter!</b><br>
<br>
</code>
</body>
Sadly, this platform does not illustrate the spaces. What can I do to improve the body of the http response in my code. I was able to remove the header of the response with strstr but I feel as if I am missing something else. Thanks!
I suggest that you use
wget http://www.testingmcafeesites.com/testcat_ac.html -O testcat_ac.html
Open the file testcat_ac.html in a hex editor and you see it contains a lot of unprintable characters, null bytes. Dealing with such data as a C string http_response.c_str() is not productive. Use std::string equivalent functions.

Webservice call using IXMLHttpRequest undesired response Text

Using IXMLHttpRequest to fetch the data from the webservice.(actually, java servlets file). Using below code to send request and get response from webservice
IXMLHTTPRequestPtr pIXMLHTTPRequest = NULL;
CoInitialize(nullptr);
String usBuffer;
CATTry
{
hr = pIXMLHTTPRequest.CreateInstance("Msxml2.XMLHTTP.6.0");
if (SUCCEEDED(hr) && (pIXMLHTTPRequest != NULL))
{
hr = pIXMLHTTPRequest->open("POST", "URL", false);
if (SUCCEEDED(hr))
{
String lsusHeaderName;
lsusHeaderName.Append("Content-Type: application/x-www-form-urlencoded");
lsusHeaderName.Append("Accept: */*");
lsusHeaderName.Append("ticket: " + "ticketvalue");
lsusHeaderName.Append("Context: " + "securityvalue");
for (int i = 1; i <= ilsusHeaderName.Size(); i++)
{
BSTR bstrHeaderName;
BSTR bstrHeaderValue;
ilsusHeaderName[i].ConvertToBSTR(&bstrHeaderName);
hr = pIXMLHTTPRequest->setRequestHeader(bstrHeaderName, bstrHeaderValue);
}
String iusRequestParam = "Type=xxxx&Name=xxxxytr&Revision=09";
if (iusRequestParam != "")
{
hr = pIXMLHTTPRequest->send(iusRequestParam.ConvertToChar());
}
else
{
hr = pIXMLHTTPRequest->send();
}
{
struct __timeb64 t_stime;
struct __timeb64 t_ctime;
long lProcTime = 0;
memset(&t_stime, 0, sizeof(struct __timeb64));
memset(&t_ctime, 0, sizeof(struct __timeb64));
long nRedyState = READYSTATE_UNINITIALIZED;
_ftime64(&t_stime);
while (nRedyState != READYSTATE_COMPLETE)
{
_ftime64(&t_ctime);
lProcTime = (long)(1000 * (t_ctime.time - t_stime.time) + (t_ctime.millitm - t_stime.millitm));
if (lProcTime > HTTP_TIMEOUT)
{
break;
}
nRedyState = pIXMLHTTPRequest->readyState;
}
}
std::cout << "Request status : " << pIXMLHTTPRequest->status << std::endl;
if ((pIXMLHTTPRequest->status == 200))
{
_bstr_t spbstrResponse = pIXMLHTTPRequest->responseText;
BSTR bstrString = NULL;
bstrString = spbstrResponse.GetBSTR();
usBuffer.BuildFromBSTR(bstrString);
usOutput = usBuffer;
std::cout << "Output : " << usBuffer << std::endl;
bstrString = NULL;
}
else
{
std::cout << "Failed to send GET/POST Method." << std::endl;
}
}
else
{
hr = E_FAIL;
}
}
}
}
CATCatch(CATError, pError)
{
std::cout << "Failed to query XMLHTTP 6.0. Perhaps MSXML 6.0 is not exists." << std::endl;
}
CATEndTry;
This webservice call returns 200 status code, but response text is not good.It returns some html,javascript code as response text.
Expected result is one of the attribute value of the passed object. Example output:
{
"logy": "646F916E00005E78609AC53D0000974F"
}
Couldn't locate the issue in this code, why it returns html,javascript code.As I am new to WINAPI concepts, your help is highly appreciated.
Edit:
Checked webservice via postman and it returns expected result.
Header should be passed in this way. This solved the issue.
CATListOfCATUnicodeString lsusHeaderName;
CATListOfCATUnicodeString lsusHeaderValue;
lsusHeaderName.Append("Content-Type");
lsusHeaderValue.Append("application/x-www-form-urlencoded");
lsusHeaderName.Append("Login-ticket");
lsusHeaderValue.Append(usLoginTicket);
lsusHeaderName.Append("SecurityContext");
lsusHeaderValue.Append(usSecurityContext);

Get device path based on USB VID:PID in Linux

If I plug in a device, say /dev/ttyUSB0 and I want to get the number 0 based on its VID:PID (found with lsusb), how could I do that in C++ Linux? I have this code to find one printer device, if it's helpful at all:
int printer_open (void)
{
char printer_location[] = "/dev/usb/lpX";
struct stat buf;
// continuously try all numbers until stat returns true for the connected printer
for (int i = 0; i < 10; i++)
{
printer_location[11] = '0' + i;
if (!stat (printer_location, &buf))
break;
}
return 0;
}
You could use libusb
apt-get install build-essential libudev-dev
Here is a good example: http://www.dreamincode.net/forums/topic/148707-introduction-to-using-libusb-10/
and here is the lib description: http://libusb.sourceforge.net/api-1.0/
int main() {
libusb_context *context = NULL;
libusb_device **list = NULL;
int rc = 0;
ssize_t count = 0;
rc = libusb_init(&context);
assert(rc == 0);
count = libusb_get_device_list(context, &list);
assert(count > 0);
for (size_t idx = 0; idx < count; ++idx) {
libusb_device *device = list[idx];
libusb_device_descriptor desc = {0};
rc = libusb_get_device_descriptor(device, &desc);
assert(rc == 0);
printf("Vendor:Device = %04x:%04x\n", desc.idVendor, desc.idProduct);
}
}
And if you compile your code don't forget to add the lib reference -I/usr/include/libusb-1.0/ and - lusb-1.0
libusb can't get it actually. So look at this file instead: /proc/bus/input/devices
Example line from the file:
I: Bus=0003 Vendor=1a2c Product=0c23 Version=0110
N: Name="USB USB Keyboard"
P: Phys=usb-0000:00:14.0-3/input0
S: Sysfs=/devices/pci0000:00/0000:00:14.0/usb1/1-3/1-3:1.0/0003:1A2C:0C23.0015/input/input30
U: Uniq=
H: Handlers=sysrq kbd event10 leds
B: PROP=0
B: EV=120013
B: KEY=1000000000007 ff800000000007ff febeffdff3cfffff fffffffffffffffe
B: MSC=10
B: LED=7
This function gets the event number from the device with the matching VID:PID:
#include <string>
#include <iostream>
#include <fstream>
void open_device (std::string device_vid, std::string device_pid)
{
try
{
std::ifstream file_input;
std::size_t pos;
std::string device_path, current_line, search_str, event_str;
std::string device_list_file = "/proc/bus/input/devices";
bool vid_pid_found = false;
int fd = 0;
bool debug = true;
// 1. open device list file
file_input.open(device_list_file.c_str());
if (!file_input.is_open())
{
std::cerr << "file_input.open >> " << std::strerror(errno) << std::endl;
throw -2;
}
// 2. search for first VID:PID and get event number
search_str = "Vendor=" + device_vid + " Product=" + device_pid;
while (getline(file_input, current_line))
{
if (!vid_pid_found)
{
pos = current_line.find(search_str, 0);
if (pos != std::string::npos)
{
vid_pid_found = true;
search_str = "event";
}
}
else
{
pos = current_line.find(search_str, 0);
if (pos != std::string::npos)
{
event_str = current_line.substr(pos);
// find space and substring event##
pos = event_str.find(' ', 0);
event_str = event_str.substr(0, pos);
break;
}
}
}
// 3. build device path
device_path = "/dev/input/" + event_str;
if (debug) std::cout << "device_path = " << device_path << std::endl;
// 4. connect to device
fd = open (device_path.c_str(), O_RDONLY);
if (fd < 0)
{
std::cerr << "open >> errno = " << std::strerror(errno) << std::endl;
throw -3;
}
}
catch (const std::exception &e)
{
std::cerr << "e.what() = " << e.what() << std::endl;
throw -1;
}
return;
}

Write nested arrays with rapidjson the "SAX" way

I'm trying to write a json structure using rapidjson the sax way. Here's what I do:
StringBuffer sb;
PrettyWriter<StringBuffer> writer(sb);
writer.StartObject();
writer.Key("user");
writer.StartArray();
OperatorAcPtrList::iterator xIt;
for (xIt = userList.begin(); xIt != userList.end(); xIt++)
{
writer.Key("userId");
writer.Uint((*xIt)->id);
writer.Key("productIdList");
writer.StartArray();
ProductIdList::iterator xPrdIdIt;
for (xPrdIdIt = ((*xIt)->productList).begin();
xPrdIdIt != ((*xIt)->productList).end(); xPrdIdIt++)
{
writer.Uint(*xPrdIdIt);
}
writer.EndArray();
}
writer.EndArray();
writer.EndObject();
But the result is not what I'd expect, it's:
{
"userList": [
"userId",
20,
"productIdList",
[
1,
2
],
"userId",
21,
"productIdList",
[
1,
2
]
]
}
It looks like everything inside the first StartArray EndArray becomes an array element. What I'd like to obtain instead is:
{
"userList": [
{
"userId" : 20,
"productIdList" : [1, 2],
},
{
"userId" : 21,
"productIdList" : [1, 2]
}
]
}
Am I doing something wrong or what I want is not supported at all?
Before you call writer.Key("userId"); in the for loop, add writer.StartObject();, and add writer.EndObject(); correspondingly. Here is an example:
#include "rapidjson/writer.h"
#include "rapidjson/stringbuffer.h"
#include <iostream>
using namespace rapidjson;
using namespace std;
int main() {
StringBuffer s;
Writer<StringBuffer> writer(s);
writer.StartObject();
writer.Key("userList");
writer.StartArray();
writer.StartObject();
writer.Key("userId");
writer.Uint(20);
writer.Key("productIdList");
writer.StartArray();
for (unsigned i = 1; i < 3; i++)
writer.Uint(i);
writer.EndArray();
writer.EndObject();
writer.StartObject();
writer.Key("userId");
writer.Uint(21);
writer.Key("productIdList");
writer.StartArray();
for (unsigned i = 1; i < 3; i++)
writer.Uint(i);
writer.EndArray();
writer.EndObject();
writer.EndArray();
writer.EndObject();
cout << s.GetString() << endl;
}

XercesC 2.7 failes to get a DOMWriter

I'm writing a server and I wanted to use XML with my Java client. I'm using CygWin with XercesC 3.1.1 for my development test and this works fine (I looped 30000 with this function and had no crash). However, on my target machine it's running HP-UX with XercesC 2.7. To implement the differences in the XercesC implementation I wrote a separate class to handle each version.
When I try to run the code with XercesC 2.7. I always get a NULL pointer when I try to create the DOMWriter, and a SIGABORT when trying again.
Since I couldn't find anyything on google I hope that someone can shed some light on what I'm doing wrong here. I've been looking at the sample code provided with the XercesC souorce, and I also have some production code from fellow programmers, and I can't see any difference for the live of it.
I tried to create an SSCE which is a bit long, but it is the shortest sample that I could create.
xml_serialize.h
#ifndef XML_SERIALIZE_H_
#define XML_SERIALIZE_H_
#include <string>
#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/util/XMLString.hpp>
#include <xercesc/dom/DOM.hpp>
#if defined(XERCES_NEW_IOSTREAMS)
#include <iostream>
#else
#include <iostream.h>
#endif
#include <xercesc/util/OutOfMemoryException.hpp>
class XStr
{
public :
// -----------------------------------------------------------------------
// Constructors and Destructor
// -----------------------------------------------------------------------
XStr(const char* const toTranscode)
{
// Call the private transcoding method
fUnicodeForm = xercesc::XMLString::transcode(toTranscode);
}
~XStr()
{
xercesc::XMLString::release(&fUnicodeForm);
}
// -----------------------------------------------------------------------
// Getter methods
// -----------------------------------------------------------------------
const XMLCh* unicodeForm() const
{
return fUnicodeForm;
}
private :
// -----------------------------------------------------------------------
// Private data members
//
// fUnicodeForm
// This is the Unicode XMLCh format of the string.
// -----------------------------------------------------------------------
XMLCh* fUnicodeForm;
};
#define X(str) XStr(str).unicodeForm()
std::string fromXMLString(XMLCh *oXMLString);
class XMLSerialize
{
private:
xercesc::DOMImplementation *mImpl;
protected:
xercesc::DOMImplementation *getDOMImplementation(void);
public:
XMLSerialize(void);
virtual ~XMLSerialize(void);
public:
/**
* Creates an empty DOM
*/
xercesc::DOMDocument *createDocument(const std::string &oDocumentName);
/**
* Parses an XML from a string.
*/
xercesc::DOMDocument *parseDocument(const std::string &oDocumentName, std::string const &oReferenceId);
/**
* Serializes the document into a string
*/
int serialize(xercesc::DOMDocument *oDocument, std::string &oXMLOut, bool bDocumentRelease = true);
};
#endif /* XML_SERIALIZE_H_ */
xml_serialize.cpp
#include <xercesc/util/XMLString.hpp>
#include <xercesc/dom/DOM.hpp>
#include <xercesc/util/TransService.hpp>
#include <xercesc/framework/MemBufFormatTarget.hpp>
#include <xercesc/util/OutOfMemoryException.hpp>
#include <sstream>
#include <vector>
#include <iostream>
#include "xml_serialize.h"
int serializeEnvironment(void);
XMLSerialize *serializer = NULL;
XMLSerialize::XMLSerialize()
{
mImpl = xercesc::DOMImplementationRegistry::getDOMImplementation(X("Core"));
}
XMLSerialize::~XMLSerialize()
{
}
xercesc::DOMDocument *XMLSerialize::createDocument(const std::string &oDocumentName)
{
if(mImpl == NULL)
return NULL;
xercesc::DOMDocument *doc = mImpl->createDocument(
0, // root element namespace URI.
X(oDocumentName.c_str()), // root element name
0); // document type object (DTD).
if(doc == NULL)
return NULL;
return doc;
}
int XMLSerialize::serialize(xercesc::DOMDocument *oDocument, std::string &oXMLOut, bool bDocumentRelease)
{
int result = 0;
XMLCh *xmlUnicode = NULL;
char *strXML = NULL;
xercesc::DOMWriter *serializer = NULL;
if(mImpl == NULL)
{
oXMLOut = "ERROR: XercesC DOMImplementationRegistry not initialized";
result = 1;
goto Quit;
}
serializer = ((xercesc::DOMImplementationLS*)mImpl)->createDOMWriter();
if(serializer == NULL)
{
oXMLOut = "ERROR: XercesC unable to instantiate a DOMWriter!";
result = 2;
goto Quit;
}
xmlUnicode = serializer->writeToString(*oDocument);
strXML = xercesc::XMLString::transcode(xmlUnicode);
oXMLOut = strXML;
if(bDocumentRelease == true)
oDocument->release();
result = 0;
Quit:
if(strXML != NULL)
xercesc::XMLString::release(&strXML);
if(xmlUnicode != NULL)
xercesc::XMLString::release(&xmlUnicode);
if(serializer != NULL)
serializer->release();
return result;
}
int serializeEnvironment(void)
{
int errorCode = 0;
xercesc::DOMElement *rootElem = NULL;
xercesc::DOMElement *item = NULL;
xercesc::DOMElement *element = NULL;
xercesc::DOMText *nameNode = NULL;
xercesc::DOMCDATASection *dataNode = NULL;
std::string xml;
try
{
xercesc::DOMDocument *doc = serializer->createDocument("EnvironmentList");
if(doc == NULL)
return 1;
rootElem = doc->getDocumentElement();
std::vector<std::pair<std::string, std::string> > env;
for(int i = 0; i < 5; i++)
{
std::string key;
std::string value;
std::stringstream ss;
ss << "KEY";
ss << i;
ss >> key;
ss.clear();
ss << "VALUE";
ss << i;
ss >> value;
ss.clear();
env.push_back(std::make_pair(key, value));
}
for(std::vector<std::pair<std::string, std::string> >::const_iterator it = env.begin(); it != env.end(); ++it)
{
std::pair<std::string, std::string>entry = *it;
std::string name = entry.first;
std::string value = entry.second;
if(value.empty())
value = "";
item = doc->createElement(X("item"));
rootElem->appendChild(item);
element = doc->createElement(X("item"));
nameNode = doc->createTextNode(X(name.c_str()));
item->appendChild(element);
element->appendChild(nameNode);
element = doc->createElement(X("item"));
dataNode = doc->createCDATASection(X(value.c_str()));
item->appendChild(element);
element->appendChild(dataNode);
}
errorCode = serializer->serialize(doc, xml);
std::cout << xml << std::endl;
doc->release();
errorCode = 0;
}
catch (const xercesc::OutOfMemoryException&)
{
XERCES_STD_QUALIFIER cerr << "OutOfMemoryException" << XERCES_STD_QUALIFIER endl;
errorCode = 2;
}
catch (const xercesc::DOMException& e)
{
XERCES_STD_QUALIFIER cerr << "DOMException code is: " << e.code << XERCES_STD_QUALIFIER endl;
errorCode = 3;
}
catch (...)
{
XERCES_STD_QUALIFIER cerr << "An error occurred creating the document" << XERCES_STD_QUALIFIER endl;
errorCode = 4;
}
return errorCode;
}
int main()
{
xercesc::XMLPlatformUtils::Initialize();
serializer = new XMLSerialize();
int error = 0;
for(int i = 0; i < 2; i++)
{
std::cout << "Serializing:" << i << " ... " << std::endl;
if((error = serializeEnvironment()) != 0)
std::cout << "ERROR" << error << std::endl;
std::cout << "Done" << std::endl;
}
xercesc::XMLPlatformUtils::Terminate();
return 0;
}
output
Serializing:0 ...
ERROR: XercesC unable to instantiate a DOMWriter!
Done
Serializing:1 ...
aCC runtime: pure virtual function called for class "xercesc_2_7::DOMImplementationLS".
Abort(coredump)
update
I finally managed to compile 2.7 for cygwin and tested the above code there. This works fine, so there must be some problem with the HP-UX environment.
I was compiling the code with gcc and aparently the xerces library was compiled with aCC. So nopw I switched to aCC in my makefile and now it works.
One should expect that the produced libraries are compatible, but apparently this is not the case. So the above code is actually correct.