reading an IP address from argv forces me to convert it to uint32_t
this function will do so:
uint32_t convert_string_ip_to_uint32_t (const string & string_ip)
{
stringstream s(string_ip) ;
uint16_t a,b,c,d; //to store the 4 ints
char ch; //to temporarily store the '.'
s >> a >> ch >> b >> ch >> c >> ch >> d ;
std::cout << a << " " << b << " " << c << " "<< d << std::flush;;
return ((uint32_t) a << 24 | b << 16 | c << 8 | d);
}
But when I change the data type of a,b,c and d to uint8_t, the result will be rubish. Why?
e.g. string_ip = '192.168.1.10'
Related
I am trying to create a text generator which shall generate following output:
localparam OR_CHANNEL_DATA_WIDTH = 2;
localparam RQ_CHANNEL_DATA_WIDTH = 18;
localparam RSP_CHANNEL_DATA_WIDTH = 8;
localparam VIN_CHANNEL_DATA_WIDTH = 43;
localparam VOUT_CHANNEL_DATA_WIDTH = 123;
I used std::stringstream to build the stream:
std::stringstream ss;
ss << "localparam OR_CHANNEL_DATA_WIDTH" << std::right << std::setw(80) << " = " << Sth::get() << ";\n";
ss << "localparam RQ_CHANNEL_DATA_WIDTH" << std::right << std::setw(80) << " = " << Sth::get() << ";\n";
ss << "localparam RSP_CHANNEL_DATA_WIDTH" << std::right << std::setw(80) << " = " << Sth::get() << ";\n";
Sth::get() will return number. There are many such lines that needs to be generated. But the text in the middle is not fixed. How can I achieve the above output
I am not sure you can do it in a simple streaming operation, but easily write a small function that does the job:
#include <iostream>
#include <sstream>
#include <iomanip>
const std::string adjust_width(const std::string& s, int width)
{
std::stringstream temp;
temp << std::left << std::setw(width) << s;
return temp.str();
}
int main()
{
std::stringstream ss;
ss << adjust_width("localparam OR_CHANNEL_DATA_WIDTH", 80) << " = " << 1 << ";\n";
ss << adjust_width("localparam RQ_CHANNEL_DATA_WIDTH", 80) << " = " << 12 << ";\n";
ss << adjust_width("localparam RSP_CHANNEL_DATA_WIDTH", 80) << " = " << 123 << ";\n";
ss << adjust_width("localparam VIN_CHANNEL_DATA_WIDTH", 80) << " = " << 1234 << ";\n";
std::cout << ss.str();
return 0;
}
I have created 2 Publishers connecting to the same static location .
Publisher1
dummyFrontEnd::dummyFrontEnd():context(1),socket(context,ZMQ_PUB) {
}
void dummyFrontEnd::Init()
{
socket.connect("tcp://127.0.0.1:5555");
cout << "Connecting .... " << endl;
}
void dummyFrontEnd::SendTwoTables()
{
cout << "In SendTwoTables" <<endl;
while(1) {
canlogreq canLogObj = canlogreq::default_instance();
canLogObj.set_fromhours(11);
canLogObj.set_fromminutes(7);
canLogObj.set_fromseconds(2);
canLogObj.set_fromday(16);
canLogObj.set_frommonth(5);
canLogObj.set_fromyear(2020);
canLogObj.set_tohours(12);
canLogObj.set_tominutes(7);
canLogObj.set_toseconds(4);
canLogObj.set_today(17);
canLogObj.set_tomonth(5);
canLogObj.set_toyear(2020);
zmq::message_t logsnippetmsg(canLogObj.ByteSizeLong() + sizeof(uint16_t));
*((uint16_t*)logsnippetmsg.data()) = 20;
canLogObj.SerializeToArray(logsnippetmsg.data()+sizeof(uint16_t), canLogObj.ByteSizeLong());
socket.send(logsnippetmsg);
usleep(1);
canLogObj.clear_fromhours();
canLogObj.clear_fromminutes();
canLogObj.clear_fromseconds();
canLogObj.clear_fromday();
canLogObj.clear_frommonth();
canLogObj.clear_fromyear();
canLogObj.clear_tohours();
canLogObj.clear_tominutes();
canLogObj.clear_toseconds();
canLogObj.clear_today();
canLogObj.clear_tomonth();
canLogObj.clear_toyear();
}
}
Publisher2:
dummyFrontEnd::dummyFrontEnd():context(1),socket(context,ZMQ_PUB) {
}
void dummyFrontEnd::Init()
{
socket.connect("tcp://127.0.0.1:5555");
cout << "Connecting .... " << endl;
}
void dummyFrontEnd:: SendData() {
while (std::getline(file, line_str)) {
std::stringstream ss(line_str);
double tdiff;
int i;
char J;
int _1939;
int pgn;
char p;
int priority;
char _0;
int source;
char dash;
std::string direction;
char d;
int length;
int data[8];
ss >> tdiff >> i >> J >> _1939 >> pgn >> p >> priority >> _0 >> source
>> dash >> direction >> d >> length >> data[0] >> data[1] >> data[2]
>> data[3] >> data[4] >> data[5] >> data[6] >> data[7];
timestamp += tdiff;
while (gcl_get_time_ms() - start_time <
uint64_t(timestamp * 1000.0) - first_time) { usleep(1); }
if (arguments.verbose) {
std::cout << timestamp << " " << i << " " << J << " " << _1939 << " "
<< pgn << " " << p << " " << priority << " " << _0 << " " << source
<< " " << dash << " " << direction << " " << d << " " << length
<< " " << data[0] << " " << data[1] << " " << data[2] << " "
<< data[3] << " " << data[4] << " " << data[5] << " " << data[6]
<< " " << data[7] << std::endl;
}
uint64_t timestamp_ms = (uint64_t)(timestamp * 1000.0);
protoTable.add_columnvalues(uint64ToString(timestamp_ms) /* timestamp */);
protoTable.add_columnvalues(intToString(pgn) /* PGN */);
protoTable.add_columnvalues(intToString(priority) /* Priority */);
protoTable.add_columnvalues(intToString(source) /* Source */);
protoTable.add_columnvalues(direction /* Direction */);
protoTable.add_columnvalues(intToString(length) /* Length */);
protoTable.add_columnvalues(intToString(data[0]) /* data1 */);
protoTable.add_columnvalues(intToString(data[1]) /* data2 */);
protoTable.add_columnvalues(intToString(data[2]) /* data3 */);
protoTable.add_columnvalues(intToString(data[3]) /* data4 */);
protoTable.add_columnvalues(intToString(data[4]) /* data5 */);
protoTable.add_columnvalues(intToString(data[5]) /* data6 */);
protoTable.add_columnvalues(intToString(data[6]) /* data7 */);
protoTable.add_columnvalues(intToString(data[7]) /* data8 */);
zmq::message_t create_values(protoTable.ByteSizeLong()+sizeof(uint16_t));
*((uint16_t*)create_values.data()) = TABLEMSG_ID; // ID
protoTable.SerializeToArray(create_values.data()+sizeof(uint16_t), protoTable.ByteSizeLong());
socket.send(create_values);
protoTable.clear_columnvalues();
usleep(1);
}
}
Subscriber
TransportLayer::TransportLayer():context(1),socket(context,ZMQ_SUB){ }
void TransportLayer::Init()
{
socket.bind("tcp://*:5555");
socket.setsockopt(ZMQ_SUBSCRIBE, "", 0);
}
void TransportLayer::Receive()
{
cout <<"TransportLayer::Receive " << " I m in server " << endl;
static int count = 1 ;
// Producer thread.
while ( true ){
zmq::message_t request;
string protoBuf;
socket.recv(&request);
uint16_t id = *((uint16_t*)request.data());
cout <<"TransportLayer : "<<"request.data: "<< request.data() << endl;
cout << "TransportLayer: count " << count<< endl; count = count+1 ;
cout <<"TransportLayer : request.data.size "<< request.size() << endl;
protoBuf = std::string(static_cast<char*>(request.data()+sizeof(uint16_t)), request.size()-sizeof(uint16_t));
cout << "ProtoBuf : " << protoBuf << endl;
InterfaceLayer *interfaceLayObj = InterfaceLayer::getInstance();
switch(id) {
case TABLEMSG_ID: cout << "Canlyser" << endl;
interfaceLayObj->ParseProtoBufTable(protoBuf);
break;
case LOGSNIPPET_ID:cout << "LogSnip" << endl;
interfaceLayObj->ParseProtoBufLogSnippet(protoBuf);
interfaceLayObj->logsnippetSignal(); // publish the signal
break;
default:
break;
}
usleep(1);
}
}
Observation :
I)
Execution Order .
1. Started Subscriber
2. Started Publisher1 ( it sent only one data value)
Subscriber missed to receive this data.
II) modified Publisher1 to send the same data in a while loop
Execution Order
1. Started Subscriber
2. Started Publisher1
3. Started Publsiher2 .
Now I see that Subscriber is receiving the data from both publishers .
This gives me an indication that there is a possibility for data loss.
How do I ensure there is absolutely no data loss.
Thanks
Your producer may be sending its one message before the subscription handshaking has completed. As a result, the publish socket discards the message because there is no subscription registered.
If you use an XPUB socket (ZMQ_XPUB -- see http://api.zeromq.org/4-2:zmq-socket) instead of a PUB socket, your program can wait for a subscribe message, so that it knows that someone is listening, before sending its message(s).
I think this is best explained with an example:
#include <iostream>
struct A
{
int a;
};
struct B
{
A a;
int b;
};
struct C: A
{
int c;
};
static inline std::ostream& operator<< (std::ostream& os, const A& a)
{ return os << a.a; }
static inline std::ostream& operator<< (std::ostream& os, const B& b)
{ return os << b.a << " " << b.b; }
static inline std::ostream& operator<< (std::ostream& os, const C& c)
{ return os << c.a << " " << c.c; }
static_assert(std::is_pod<B>::value, "B");
static_assert(std::is_pod<A>::value, "A");
static_assert(std::is_trivial<C>::value, "C");
//static_assert(std::is_pod<C>::value, "C");
int main()
{
std::cout << "sizeof(A) " << sizeof(A) << std::endl;
std::cout << "sizeof(B) " << sizeof(B) << std::endl;
std::cout << "sizeof(C) " << sizeof(C) << std::endl;
B b = B{14,42};
std::cout << "b " << b << std::endl;
C c; c.a=15; c.c=43;
std::cout << "c " << c << std::endl;
B* bp = &b;
std::cout << "(C)b " << *(C*)(bp) << std::endl;
C* cp = &c;
std::cout << "(B)c " << *(B*)(cp) << std::endl;
return 0;
}
Output:
sizeof(A) 4
sizeof(B) 8
sizeof(C) 8
b 14 42
c 15 43
(C)b 14 42
(B)c 15 43
Why does C not qualify as standard_layout. As I would expect it has the same memory layout as B. What could potentially differ?
I was trying to insert a data struct into a vector everytime a match is detected, but i am failing even in compiling. The code is next:
#include <string>
#include <boost/xpressive/xpressive.hpp>
#include <boost/xpressive/regex_actions.hpp>
using namespace boost::xpressive;
struct Data
{
int integer;
double real;
std::string str;
Data(const int _integer, const double _real, const std::string& _str) : integer(_integer), real(_real), str(_str) { }
};
int main()
{
std::vector<Data> container;
std::string input = "Int: 0 - Real: 18.8 - Str: ABC-1005\nInt: 0 - Real: 21.3 - Str: BCD-1006\n";
sregex parser = ("Int: " >> (s1 = _d) >> " - Real: " >> (s2 = (repeat<1,2>(_d) >> '.' >> _d)) >> " - Str: " >> (s3 = +set[alnum | '-']) >> _n)
[::ref(container)->*push_back(Data(as<int>(s1), as<double>(s2), s3))];
sregex_iterator cur(input.begin(), input.end(), parser);
sregex_iterator end;
for(; cur != end; ++cur)
smatch const &what = *cur;
return 0;
}
It is failing in compile the "push_back" semantic action due to I am using a Data object inside and it is not able to use it lazinessly (I guess, I am not really sure).
Please, could anyone help me with this?
Note- I am unluckily tied to MS VS 2010 (not fully c++11 compliant), so please don't use variadic templates and emplace_back solutions. Thank you.
Using Xpressive
You should make the action a lazy actor. Your Data constructor call isn't.
Live On Coliru
#include <string>
#include <boost/xpressive/xpressive.hpp>
#include <boost/xpressive/regex_actions.hpp>
namespace bex = boost::xpressive;
struct Data {
int integer;
double real;
std::string str;
Data(int integer, double real, std::string str) : integer(integer), real(real), str(str) { }
};
#include <iostream>
int main() {
std::vector<Data> container;
std::string const& input = "Int: 0 - Real: 18.8 - Str: ABC-1005\nInt: 0 - Real: 21.3 - Str: BCD-1006\n";
using namespace bex;
bex::sregex const parser = ("Int: " >> (s1 = _d) >> " - Real: " >> (s2 = (repeat<1,2>(_d) >> '.' >> _d)) >> " - Str: " >> (s3 = +set[alnum | '-']) >> _n)
[bex::ref(container)->*bex::push_back(bex::construct<Data>(as<int>(s1), as<double>(s2), s3))];
bex::sregex_iterator cur(input.begin(), input.end(), parser), end;
for (auto const& what : boost::make_iterator_range(cur, end)) {
std::cout << what.str() << "\n";
}
for(auto& r : container) {
std::cout << "[ " << r.integer << "; " << r.real << "; " << r.str << " ]\n";
}
}
Prints
Int: 0 - Real: 18.8 - Str: ABC-1005
Int: 0 - Real: 21.3 - Str: BCD-1006
[ 0; 18.8; ABC-1005 ]
[ 0; 21.3; BCD-1006 ]
Using Spirit
I'd use spirit for this. Spirit has the primitives to directly parse to underlying data types, which is less error prone and more efficient.
Spirit Qi (V2)
Using Phoenix, it's pretty similar: Live On Coliru
Using Fusion adaptation, it gets more interesting, and a lot simpler:
Live On Coliru
Now imagine:
You wanted to match the keywords case insensitive
You wanted to make whitespace insignificant
You wanted to accept empty lines, but not random data in between
How would you do that in Xpressive? Here's how you'd do it with Spirit. Note how the additional constraints do not change the grammar, essentially. Contrast that with regex-based parsers.
Live On Coliru
#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/adapted/struct.hpp>
namespace qi = boost::spirit::qi;
struct Data {
int integer;
double real;
std::string str;
};
BOOST_FUSION_ADAPT_STRUCT(Data, integer, real, str);
#include <iostream>
int main() {
std::vector<Data> container;
using It = std::string::const_iterator;
std::string const& input = "iNT: 0 - Real: 18.8 - Str: ABC-1005\n\nInt: 1-Real:21.3 -sTR:BCD-1006\n\n";
qi::rule<It, Data(), qi::blank_type> parser = qi::no_case[
qi::lit("int") >> ':' >> qi::auto_ >> '-'
>> "real" >> ':' >> qi::auto_ >> '-'
>> "str" >> ':' >> +(qi::alnum|qi::char_('-')) >> +qi::eol
];
It f = input.begin(), l = input.end();
if (parse(f, l, qi::skip(qi::blank)[*parser], container)) {
std::cout << "Parsed:\n";
for(auto& r : container) {
std::cout << "[ " << r.integer << "; " << r.real << "; " << r.str << " ]\n";
}
} else {
std::cout << "Parse failed\n";
}
if (f != l) {
std::cout << "Remaining input: '" << std::string(f,l) << "'\n";
}
}
Still prints
Parsed:
[ 0; 18.8; ABC-1005 ]
[ 1; 21.3; BCD-1006 ]
Further thoughts: how would you
Parse scientific notation? Negative numbers?
Parse decimal numbers correctly (assuming you are really parsing financial amounts, you may not wish inexact floating point representations)
Spirit X3
If you can use c++14, Spirit X3 can be more efficient, and compile a lot faster than either the Spirit Qi or the Xpressive approach:
Live On Coliru
#include <boost/spirit/home/x3.hpp>
#include <boost/fusion/adapted/struct.hpp>
struct Data {
int integer;
double real;
std::string str;
};
BOOST_FUSION_ADAPT_STRUCT(Data, integer, real, str);
namespace Parsers {
using namespace boost::spirit::x3;
static auto const data
= rule<struct Data_, ::Data> {}
= no_case[
lit("int") >> ':' >> int_ >> '-'
>> "real" >> ':' >> double_ >> '-'
>> "str" >> ':' >> +(alnum|char_('-')) >> +eol
];
static auto const datas = skip(blank)[*data];
}
#include <iostream>
int main() {
std::vector<Data> container;
std::string const& input = "iNT: 0 - Real: 18.8 - Str: ABC-1005\n\nInt: 1-Real:21.3 -sTR:BCD-1006\n\n";
auto f = input.begin(), l = input.end();
if (parse(f, l, Parsers::datas, container)) {
std::cout << "Parsed:\n";
for(auto& r : container) {
std::cout << "[ " << r.integer << "; " << r.real << "; " << r.str << " ]\n";
}
} else {
std::cout << "Parse failed\n";
}
if (f != l) {
std::cout << "Remaining input: '" << std::string(f,l) << "'\n";
}
}
Prints (it's getting boring):
Parsed:
[ 0; 18.8; ABC-1005 ]
[ 1; 21.3; BCD-1006 ]
int main() {
int x = 3613;
std::cout << "x= " << x << std::endl;
std::string xBin = std::bitset<16>(x).to_string();
std::cout << xBin << std::endl;
unsigned long xDecimal = std::bitset<16>(xBin).to_ulong();
std::cout << xDecimal << std::endl;
std::cout << std::endl << std::endl;
int b01 = 0b11001;
std::cout << "b01= " << b01 << std::endl;
int b02 = 0b1010;
std::cout << "b02= " << b02 << std::endl;
int b03 = b01 + b02;
std::cout << "int b03 = b01 + b02 = " << b03 << std::endl;
return 0;
}
Output:
x= 3613
0000111000011101
3613
b01= 25
b02= 10
int b03 = b01 + b02 = 35
With binary literals we can do normal arithmetic operations, while with the strings obtained with std::bitset<> this is not possible.
So...the question is: how to "compose" the binary literals, for example through the conversion from decimal to binary as obtained using std::bitset<> ?
Looking forward to your kind help. Marco
You shouldn't operate on bitsets by converting them to string and back - that's missing the point of bitsets... Instead you operate on them by using binary operators: &, |, ^, ... (just like you would on usual integers).
std::cout << std::bitset<3>(4) << " or "
<< std::bitset<3>(2) << " = "
<< (std::bitset<3>(4) | std::bitset<3>(2)) << std::endl;
Prints: 100 or 010 = 110
You can find all operators on wiki: http://en.cppreference.com/w/cpp/utility/bitset