Qt XML validation Errorhandling - c++

I'm trying to find a solution that in case that a validation is not successful because there is more then one error in the XML file the Qt MessageHandler(line, column, description etc. ) is able to show every error in the XML data not just the first one that occurs in the XML file.
Example:
I have an error in line: 65 (see pic)
but there are also errors in line :78,83,95 but it dose not show it only shows the first one.
Is there a solution for this case? And if yes how?
My Code looks like this:
MessageHandler messageHandler;
QFile xsdfile("....xsd");
xsdfile.open(QIODevice::ReadOnly);
QXmlSchema schema;
schema.setMessageHandler(&messageHandler);
bool errorOccurred = false;
if (schema.load(&xsdfile, QUrl::fromLocalFile(xsdfile.fileName())) == false)
errorOccurred = true;
else
{
QXmlSchemaValidator xmlvalidator(schema);
QFile xmlfile("......xml");
xmlfile.open(QIODevice::ReadOnly);
if (!xmlvalidator.validate(&xmlfile, QUrl::fromLocalFile(xmlfile.fileName())))
errorOccurred = true;
xmlfile.close();
}
xsdfile.close();
if (errorOccurred) {
QString qs = messageHandler.statusMessage();
cout << "Line: " << messageHandler.line() << "\n" << "Row: " << messageHandler.column() << "\n" << "ErrorMessage: ";
std::cout << qs.toUtf8().constData() << std::endl;
return -1;
}
else {
return 0;
}
And my MessageHandler class looks like this:
class MessageHandler : public QAbstractMessageHandler
{
public:
MessageHandler()
: QAbstractMessageHandler(0)
{
}
QString statusMessage() const
{
return m_description;
}
int line() const
{
return m_sourceLocation.line();
}
int column() const
{
return m_sourceLocation.column();
}
protected:
virtual void handleMessage(QtMsgType type, const QString &description,
const QUrl &identifier, const QSourceLocation &sourceLocation)
{
Q_UNUSED(type);
Q_UNUSED(identifier);
m_description = description;
m_sourceLocation = sourceLocation;
}
private:
QString m_description;
QSourceLocation m_sourceLocation;
};
Thanks :)

I think you need to write a custom validator to catch all errors. You can modify this example code to catch all errors.
struct NodeProperties
{
NodeProperties()
{
values.resize(names.size());
}
std::vector<int> values;
static QStringList names;
static QString rootName;
static QString childName;
};
QString NodeProperties::rootName = "static_route";
QString NodeProperties::childName = "molenet";
QStringList NodeProperties::names = QList<QString>() << "node_id"
<< "nextHop_id"
<< "sink_id"
<< "delay_before_send"
<< "delay_before_sleep";
QList<NodeProperties> nodesProperties;
bool parseXMLFile()
{
QXmlStreamReader xmlStreamReader;
QString xmlFile;
xmlFile = QFileDialog::getOpenFileName(this,
tr("Open XML file"), QDir::currentPath(), tr("XML (*.xml)"));
if(xmlFile.isEmpty())
return false;
QFile file(xmlFile);
if (!file.open(QFile::ReadOnly | QFile::Text))
{
QMessageBox::warning(this,tr("Error: Cannot read file ..."),
(xmlFile+" " + file.errorString() ));
return false;
}
nodesProperties.clear();
xmlStreamReader.setDevice(&file);
xmlStreamReader.readNext();
while(!xmlStreamReader.atEnd())
{
if(xmlStreamReader.isStartElement())
{
if(xmlStreamReader.name() == NodeProperties::rootName)
xmlStreamReader.readNext();
if(xmlStreamReader.name() == NodeProperties::childName)
{
xmlStreamReader.readNext();
if(xmlStreamReader.isCharacters() )
xmlStreamReader.readNext();
if(xmlStreamReader.isStartElement())
{
NodeProperties prop;
for(int i = 0; i < NodeProperties::names.size(); ++i)
{
if(xmlStreamReader.isCharacters() )
{
xmlStreamReader.readNext();
--i;
continue;
}
if(xmlStreamReader.name() == NodeProperties::names[i])
{
prop.values[i] = xmlStreamReader.readElementText().toInt();
}
xmlStreamReader.readNext();
}
nodesProperties.push_back(prop);
}
}
}
xmlStreamReader.readNext();
}
file.close();
if (xmlStreamReader.hasError())
{
QMessageBox::warning(this,tr("Error: Failed to parse file "),
(xmlFile+" " + xmlStreamReader.errorString() ));
nodesProperties.pop_back();
}
else if (file.error() != QFile::NoError)
{
qDebug() << "Error: Cannot read file " << qPrintable(xmlFile)
<< ": " << qPrintable(file.errorString());
}
//createGraphVizFile(xmlFile);
this->xmlFile = xmlFile;
return true;
}
The XML file is:
<?xml version="1.0"?>
<static_route>
<molenet>
<node_id> 1 </node_id>
<nextHop_id> 2 </nextHop_id>
<sink_id> 254 </sink_id>
<delay_before_send> 2 </delay_before_send>
<delay_before_sleep> 30 </delay_before_sleep>
</molenet>
<molenet>
<node_id> 2 </node_id>
<nextHop_id> 3 </nextHop_id>
<sink_id> 254 </sink_id>
<delay_before_send> 4 </delay_before_send>
<delay_before_sleep> 30 </delay_before_sleep>
</molenet>
</static_route>

Related

How to manage 16208 registers from a txt file to sort them?

I'm a beginner in programming & now I'm trying to sort and search data from a .txt file with C++, the file has 16208 lines, and each line is a register so, Idk how could I manage an array or ony other data structure, first to sort and then to search data of the file, how could I do It? implement an a dynamic array with resize or something like that?
This is from CArchivo.h
#pragma once
#include <bits/stdc++.h>
class CArchivo{
public:
errno_t error; // Opcional
FILE* archivo;
char cadena[75];
//char* resultadoString;
void abrirArchivo(const char nombreArchivo[15]);
void cerrarArchivo();
void imprimirArchivo();
void ordenarRegistros();
void guardarRegistros();
void buscarRegistros(std::string fechaInicial, std::string fechaFinal );
int contarRegistros();
CArchivo();
~CArchivo();
};
This is from CArchivo.cpp
#include "CArchivo.h"
void CArchivo::abrirArchivo(const char nombreArchivo[15]) {
error = fopen_s(&archivo, nombreArchivo, "r");
error == 0 ? std::cout << "The file has open\n" : std::cout << "Failed to open the file\n";
}
void CArchivo::cerrarArchivo() {
error = fclose(archivo);
error == 0 ? std::cout << "\nThe file is closed\n" : std::cout << "\nThe file isn't closed\n";
}
void CArchivo::imprimirArchivo() {
if (error != 0)
{
printf("Error en la apertura/creacion del archivo");
}
else {
do {
fgets(cadena, 75, archivo);
printf("%s", cadena);
} while (!feof(archivo));
}
}
void CArchivo::ordenarRegistros() {
std::string stringResult = "";
int sizeArr = 0;
//const int contArr = contarRegistros();
//std::string* dataArr = new std::string[contArr];
do
{
fgets(cadena, 75, archivo);
printf(cadena);
//std::cout << stringResult;
//dataArr[sizeArr] = stringResult;
//sizeArr += 1;
} while (!feof(archivo));
//std::cout << dataArr[0];
//delete[] dataArr;
}
void CArchivo::guardarRegistros() {
}
void CArchivo::buscarRegistros(std::string fechaInicial, std::string fechaFinal) {
}
int CArchivo::contarRegistros() {
int sizeArr = 0;
//Count the number of registers
if (error != 0)
{
printf("Error en la apertura/creacion del archivo");
}
else {
do {
fgets(cadena, 75, archivo);
sizeArr++;
} while (!feof(archivo));
}
return sizeArr;
}
CArchivo::CArchivo() {
error = NULL;
//resultadoString = NULL;
cadena[74] = NULL;
archivo = NULL;
}
CArchivo::~CArchivo() {}```

Input Available Logs in wxWidgets socket example with for-loop in Client.cpp OnTest2 function

I am beginning to learn about sockets in wxWidgets, and run on Windows 10 (latest version), CodeBlocks 20.03 with mingw2 (gnu 11.2), and wxWidgets 3.15.
The socket sample compiles and run OK.
Because I will be sending many wxStrings (up to 7000 in one session) from the client to the server, I added a for-loop in the client.cpp OnTest2 function (see below).
Where the single transfer of the original socket sample runs OK every time, the adapted client.cpp OnTest2 function always logs Input-Available events at various locations.
For some reason "Input-Available" is logged on all sends.
The Server receives everything, so I am not worried that much about the future content.
Still, these Input-Available Log messages should not happen, I think.
I read somewhere that calling wxThread::Yield() prior to calling WaitForRead() would help, but it did not.
Is something wrong in my "simple" approach of adding a for-loop?
I hope someone can help me understand why these Input-Available log message appear,
and help me find a solution.
Edit:
I have reduced the wxWidgets socket examples to the smallest of my 'beginners' abilities.
minclient.cpp
#include "wx/wxprec.h"
#ifndef WX_PRECOMP
# include "wx/wx.h"
#endif
#include "wx/socket.h"
#include "wx/sstream.h"
class MyApp : public wxApp
{
public:
virtual bool OnInit() wxOVERRIDE;
};
class MyFrame : public wxFrame
{
public:
MyFrame();
~MyFrame();
void OnQuit(wxCommandEvent& event);
void OnOpenConnection(wxCommandEvent& event);
void OnCloseConnection(wxCommandEvent& event);
void OpenConnection(wxSockAddress::Family family);
void OnSocketEvent(wxSocketEvent& event);
void OnTest(wxCommandEvent& event);
private:
wxSocketClient *m_sock;
wxMenu *m_menuFile;
wxMenu *m_menuSocket;
wxMenuBar *m_menuBar;
wxDECLARE_EVENT_TABLE();
};
enum
{
CLIENT_QUIT = wxID_EXIT,
CLIENT_ABOUT = wxID_ABOUT,
CLIENT_OPEN = 100,
CLIENT_TEST,
CLIENT_CLOSE,
SOCKET_ID
};
wxBEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_MENU(CLIENT_QUIT, MyFrame::OnQuit)
EVT_MENU(CLIENT_OPEN, MyFrame::OnOpenConnection)
EVT_MENU(CLIENT_TEST, MyFrame::OnTest)
EVT_MENU(CLIENT_CLOSE, MyFrame::OnCloseConnection)
EVT_SOCKET(SOCKET_ID, MyFrame::OnSocketEvent)
wxEND_EVENT_TABLE()
wxIMPLEMENT_APP(MyApp);
bool MyApp::OnInit()
{
if ( !wxApp::OnInit() )
return false;
MyFrame *frame = new MyFrame();
frame->Show(true);
return true;
}
MyFrame::MyFrame() : wxFrame((wxFrame *)NULL, wxID_ANY,
_("wxSocket demo: Client"),
wxDefaultPosition, wxSize(300, 200))
{
m_menuFile = new wxMenu();
m_menuFile->AppendSeparator();
m_menuFile->Append(CLIENT_QUIT, _("E&xit\tAlt-X"), _("Quit client"));
m_menuSocket = new wxMenu();
m_menuSocket->Append(CLIENT_OPEN, _("&Open session\tCtrl-O"), _("Connect to server"));
m_menuSocket->AppendSeparator();
m_menuSocket->Append(CLIENT_TEST, _("Test &2\tCtrl-F2"), _("Test ReadMsg and WriteMsg"));
m_menuSocket->AppendSeparator();
m_menuSocket->Append(CLIENT_CLOSE, _("&Close session\tCtrl-C"), _("Close connection"));
m_menuBar = new wxMenuBar();
m_menuBar->Append(m_menuFile, _("&File"));
m_menuBar->Append(m_menuSocket, _("&TCP"));
SetMenuBar(m_menuBar);
m_sock = new wxSocketClient();
m_sock->SetEventHandler(*this, SOCKET_ID);
m_sock->SetNotify(wxSOCKET_CONNECTION_FLAG | wxSOCKET_INPUT_FLAG | wxSOCKET_LOST_FLAG);
m_sock->Notify(true);
}
MyFrame::~MyFrame()
{
delete m_sock;
}
void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
{
Close(true);
}
void MyFrame::OnOpenConnection(wxCommandEvent& WXUNUSED(event))
{
OpenConnection(wxSockAddress::IPV4);
}
void MyFrame::OpenConnection(wxSockAddress::Family family)
{
wxIPaddress * addr;
wxIPV4address addr4;
addr = &addr4;
m_menuSocket->Enable(CLIENT_OPEN, false);
m_menuSocket->Enable(CLIENT_CLOSE, false);
wxString hostname = "localhost";
addr->Hostname(hostname);
addr->Service(3000);
m_sock->Connect(*addr, false);
}
void MyFrame::OnCloseConnection(wxCommandEvent& WXUNUSED(event))
{
m_sock->Close();
}
void MyFrame::OnSocketEvent(wxSocketEvent& event)
{
switch ( event.GetSocketEvent() )
{
case wxSOCKET_INPUT:
std::cout << "Input available on the socket.\n";
break;
case wxSOCKET_LOST:
std::cout << "Socket connection was unexpectedly lost.\n";
break;
case wxSOCKET_CONNECTION:
std::cout << "... socket is now connected.\n";
break;
default:
std::cout << "Unknown socket event!\n";
break;
}
}
void MyFrame::OnTest(wxCommandEvent& WXUNUSED(event))
{
for(int f = 0; f < 2; f++)
{
unsigned char c = 0xCE;
m_sock->Write(&c, 1);
m_sock->SetFlags(wxSOCKET_WAITALL);
wxString s = "This is my string to send";
const wxScopedCharBuffer msg1(s.utf8_str());
size_t len = wxStrlen(msg1) + 1;
wxCharBuffer msg2(wxStrlen(msg1));
m_sock->WriteMsg(msg1, len);
if(m_sock->Error())
{ std::cout << " Write failed !\n"; }
m_sock->WaitForRead(2);
if (m_sock->IsData())
{
m_sock->ReadMsg(msg2.data(), len);
if(m_sock->Error())
{ std::cout << " Read failed !\n"; }
else
{
if (memcmp(msg1, msg2, len) != 0)
{ std::cout << "Test failed !\n"; }
else
{ std::cout << "Returned msg: \"" << msg2 << "\"" << std::endl; }
}
}
else
{ std::cout << "Timeout ! Test failed.\n"; }
}
}
minserver.cpp
#include "wx/wxprec.h"
#ifndef WX_PRECOMP
# include "wx/wx.h"
#endif
#include "wx/socket.h"
typedef wxIPV4address IPaddress;
class MyApp : public wxApp
{
public:
virtual bool OnInit() wxOVERRIDE;
};
class MyFrame : public wxFrame
{
public:
MyFrame();
~MyFrame();
void OnQuit(wxCommandEvent& event);
void OnServerEvent(wxSocketEvent& event);
void OnSocketEvent(wxSocketEvent& event);
void Test(wxSocketBase *sock);
private:
wxSocketServer *m_server;
wxMenu *m_menuFile;
wxMenuBar *m_menuBar;
int m_numClients;
wxDECLARE_EVENT_TABLE();
};
enum
{
SERVER_QUIT = wxID_EXIT,
SERVER_ID = 100,
SOCKET_ID
};
wxBEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_MENU(SERVER_QUIT, MyFrame::OnQuit)
EVT_SOCKET(SERVER_ID, MyFrame::OnServerEvent)
EVT_SOCKET(SOCKET_ID, MyFrame::OnSocketEvent)
wxEND_EVENT_TABLE()
wxIMPLEMENT_APP(MyApp);
bool MyApp::OnInit()
{
if ( !wxApp::OnInit() )
return false;
MyFrame *frame = new MyFrame();
frame->Show(true);
return true;
}
MyFrame::MyFrame() : wxFrame((wxFrame *)NULL, wxID_ANY,
_("wxSocket demo: Server"),
wxDefaultPosition, wxSize(300, 200))
{
m_menuFile = new wxMenu();
m_menuFile->Append(SERVER_QUIT, _("E&xit\tAlt-X"), _("Quit server"));
m_menuBar = new wxMenuBar();
m_menuBar->Append(m_menuFile, _("&File"));
SetMenuBar(m_menuBar);
IPaddress addr;
addr.Service(3000);
m_server = new wxSocketServer(addr);
if (! m_server->IsOk())
{
std::cout << "Could not listen at the specified port !\n";
return;
}
IPaddress addrReal;
if ( !m_server->GetLocal(addrReal) )
{ std::cout << "ERROR: couldn't get the address we bound to.\n"; }
else
{ std::cout << "Server listening at " << addrReal.IPAddress() << ": " << addrReal.Service() << std::endl; }
m_server->SetEventHandler(*this, SERVER_ID);
m_server->SetNotify(wxSOCKET_CONNECTION_FLAG);
m_server->Notify(true);
m_numClients = 0;
}
MyFrame::~MyFrame()
{
delete m_server;
}
void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
{
Close(true);
}
void MyFrame::OnServerEvent(wxSocketEvent& event)
{
wxString s = "OnServerEvent: ";
wxSocketBase *sock;
switch(event.GetSocketEvent())
{
case wxSOCKET_CONNECTION:
s.Append("wxSOCKET_CONNECTION");
break;
default:
s.Append("Unexpected event !");
break;
}
std::cout << s << std::endl;
sock = m_server->Accept(false);
if (sock)
{
IPaddress addr;
if ( !sock->GetPeer(addr) )
{ std::cout << "New connection from unknown client accepted.\n"; }
else
{ std::cout << "New client connection from " << addr.IPAddress() << ":" << addr.Service() << " accepted\n"; }
}
else
{
std::cout << "Error: couldn't accept a new connection\n";
return;
}
sock->SetEventHandler(*this, SOCKET_ID);
sock->SetNotify(wxSOCKET_INPUT_FLAG | wxSOCKET_LOST_FLAG);
sock->Notify(true);
m_numClients++;
}
void MyFrame::OnSocketEvent(wxSocketEvent& event)
{
wxString s = "OnSocketEvent: ";
wxSocketBase *sock = event.GetSocket();
switch(event.GetSocketEvent())
{
case wxSOCKET_INPUT:
s.Append(_("wxSOCKET_INPUT"));
break;
case wxSOCKET_LOST:
s.Append(_("wxSOCKET_LOST"));
break;
default:
s.Append(_("Unexpected event !"));
break;
}
std::cout << s << std::endl;
switch(event.GetSocketEvent())
{
case wxSOCKET_INPUT:
{
sock->SetNotify(wxSOCKET_LOST_FLAG);
unsigned char c;
sock->Read(&c, 1);
switch (c)
{
case 0xCE:
Test(sock);
break;
default:
std::cout << "Unknown test id received from client\n";
}
sock->SetNotify(wxSOCKET_LOST_FLAG | wxSOCKET_INPUT_FLAG);
break;
}
case wxSOCKET_LOST:
{
m_numClients--;
std::cout << "Deleting socket.\n";
sock->Destroy();
break;
}
default: ;
}
}
void MyFrame::Test(wxSocketBase *sock)
{
char buf[4096];
wxUint32 len = sock->ReadMsg(buf, sizeof(buf)).LastCount();
if ( !len )
{
std::cout << "Failed to read message.\n";
return;
}
std::cout << "Received: \"" << wxString::FromUTF8(buf, len) << "\" , Returning it\n";
sock->WriteMsg(buf, len);
}
The below message on the client happens at every 'test'. (Also when the for loop is removed.)
Input available on the socket
I searched for socket libraries, and found only 8 sort of current ones.
(Boos.ASIO, beej, bestofcpp, netlib, and others)
They were either to complicated for me to start with, or had python dependency.
I appreciate suggestions for easy to learn alternative libraries.

Wrong donwloaded filesize in Qt 5.6

I used a DownloadManager class like that but the problem is that for large file I have a wrong size 65536KB instead of 51328022 bytes. There are something wrong in the saveDisk method.
ps: I used Qt 5.6 cuz I need to run the app on Windows Vista & XP
bool DownloadManager::saveToDisk(const QString &filename, QIODevice *data)
{
LogManager* logmgr = LogManager::GetInstance();
FileManager* filemgr = FileManager::GetInstance();
QFileInfo fileinfo(filename);
QString dirpath = fileinfo.absoluteDir().absolutePath();
if (!filemgr->DirectoryIsPresent(dirpath))
{
if (!filemgr->CreateDirectory(dirpath)) {
logmgr->Log(LOG_LEVEL_ERROR, QString("cannot create directory (") + dirpath + ")");
}
}
QFile file(filename);
if (!file.open(QIODevice::WriteOnly)) {
const QString errorText = QString("Could not open ") + filename + QString(" for writing:") + file.errorString();
logmgr->Log(LOG_LEVEL_ERROR, errorText);
return false;
}
file.write(data->readAll());
file.close();
return true;
}
void DownloadManager::downloadFinished(QNetworkReply *reply)
{
LogManager* logmgr = LogManager::GetInstance();
if (m_currentDownloads.contains(reply))
{
QUrl url = reply->url();
if (reply->error() != QNetworkReply::NoError) {
m_nbFailedDownload++;
const QString errorText = QString("Download of ")+ url.toString() +" failed: " + reply->errorString() + " (" + QString::number(reply->error()) + ")";
logmgr->Log(LOG_LEVEL_ERROR, errorText);
} else {
m_nbSucceededDownload++;
QString filename = saveFileName(url);
if (saveToDisk(filename, reply))
{
const QString infoText = QString("Download of ") + url.toString() + " succeeded (saved to " + filename + ")";
logmgr->Log(LOG_LEVEL_INFO, infoText);
}
}
m_currentDownloads.removeAll(reply);
reply->deleteLater();
}
int total = m_nbTotalDownload == 0? 1:m_nbTotalDownload;
emit onProgress((m_nbFailedDownload + m_nbSucceededDownload) * 100 / total);
if (m_currentDownloads.isEmpty()){
logmgr->Log(LOG_LEVEL_INFO, "DownloadManager downloads finished");
emit onFinished();
}
}
You should call DownloadManager::saveToDisk by signal QNetworkReply::readyRead
void DownloadManager::onDownloadReadyRead( QNetworkReply *reply )
{
...
saveToDisk( filename, reply );
...
}
void DownloadManager::saveToDisk( QNetworkReply* reply )
{
...
file.write( reply->read( reply_->bytesAvailable() ) );
...
}
It's ok. I replaced this line :
file.write(data->readAll());
file.close();
return true;
by
ByteArray ba = data->readAll();
int nbTries = 99;
int n = ba.size();
int idx = 0;
while (n > 0 && nbTries > 0)
{
int ret = file.write(ba.data() + idx, std::min(16*1024, n));
if (ret > 0)
{
n -= ret;
idx += ret;
}
else
{
nbTries --;
}
}
file.close();
return nbTries > 0;
I wrote several chunks instead of one big

ZeroMQ PUB/SUB bind subscriber

I'm studying ZeroMQ with myself.
I tested PUB as a server(bind), SUB as a client(connect) and worked fine. Opposite (PUB as a client(connect), SUB as a server(bind)) also works fine.
When I connect a another SUB socket as client something goes wrong without any exception or errors.
here's my example code.
#include <zmq.hpp>
#include <string>
#include <iostream>
#include <unistd.h>
#include <thread>
class ZMQSock
{
public:
ZMQSock(const char* addr)
{
if (addr != NULL)
{
mctx = new zmq::context_t(1);
mszAddr = new char[strlen(addr) + 1];
snprintf(mszAddr, strlen(addr) + 1, "%s", addr);
}
}
virtual ~ZMQSock()
{
if (msock != nullptr)
delete msock;
if (mctx != nullptr)
delete mctx;
if (mszAddr != nullptr)
delete [] mszAddr;
}
int zbind()
{
if (msock != nullptr)
msock->bind(mszAddr);
else return -1;
return 0;
}
int zconnect()
{
if (msock != nullptr)
msock->connect(mszAddr);
else return -1;
return 0;
}
void start()
{
if (mbthread != false)
return ;
mbthread = true;
mhthread = std::thread(std::bind(&ZMQSock::run, this));
}
virtual void stop()
{
if (mbthread == false)
return ;
mbthread = false;
if (mhthread.joinable())
mhthread.join();
}
virtual void run() = 0;
protected:
char* mszAddr{nullptr};
zmq::context_t* mctx{nullptr};
zmq::socket_t* msock{nullptr};
bool mbthread{false};
std::thread mhthread;
};
class ZPublisher : public ZMQSock
{
public:
ZPublisher(const char* addr) : ZMQSock(addr)
{
if (msock == nullptr)
{
msock = new zmq::socket_t(*mctx, ZMQ_PUB);
}
}
virtual ~ZPublisher()
{
}
bool zsend(const char* data, const unsigned int length, bool sendmore=false)
{
zmq::message_t msg(length);
memcpy(msg.data(), data, length);
if (sendmore)
return msock->send(msg, ZMQ_SNDMORE);
return msock->send(msg);
}
void run()
{
if (mszAddr == nullptr)
return ;
if (strlen(mszAddr) < 6)
return ;
const char* fdelim = "1";
const char* first = "it sends to first. two can not recv this sentence!\0";
const char* sdelim = "2";
const char* second = "it sends to second. one can not recv this sentence!\0";
while (mbthread)
{
zsend(fdelim, 1, true);
zsend(first, strlen(first));
zsend(sdelim, 1, true);
zsend(second, strlen(second));
usleep(1000 * 1000);
}
}
};
class ZSubscriber : public ZMQSock
{
public:
ZSubscriber(const char* addr) : ZMQSock(addr)
{
if (msock == nullptr)
{
msock = new zmq::socket_t(*mctx, ZMQ_SUB);
}
}
virtual ~ZSubscriber()
{
}
void setScriberDelim(const char* delim, const int length)
{
msock->setsockopt(ZMQ_SUBSCRIBE, delim, length);
mdelim = std::string(delim, length);
}
std::string zrecv()
{
zmq::message_t msg;
msock->recv(&msg);
return std::string(static_cast<char*>(msg.data()), msg.size());
}
void run()
{
if (mszAddr == nullptr)
return ;
if (strlen(mszAddr) < 6)
return ;
while (mbthread)
{
std::cout << "MY DELIM IS [" << mdelim << "] - MSG : ";
std::cout << zrecv() << std::endl;
usleep(1000 * 1000);
}
}
private:
std::string mdelim;
};
int main ()
{
ZPublisher pub("tcp://localhost:5252");
ZSubscriber sub1("tcp://localhost:5252");
ZSubscriber sub2("tcp://*:5252");
pub.zconnect();
sub1.zconnect();
sub2.zbind();
sub1.setScriberDelim("1", 1);
sub2.setScriberDelim("2", 1);
pub.start();
std::cout << "PUB Server has been started.." << std::endl;
usleep(1000 * 1000);
sub1.start();
std::cout << "SUB1 Start." << std::endl;
sub2.start();
std::cout << "SUB2 Start." << std::endl;
int i = 0;
std::cout << "< Press any key to exit program. >" << std::endl;
std::cin >> i;
std::cout << "SUB1 STOP START" << std::endl;
sub1.stop();
std::cout << "SUB2 STOP START" << std::endl;
sub2.stop();
std::cout << "PUB STOP START" << std::endl;
pub.stop();
std::cout << "ALL DONE" << std::endl;
return 0;
}
What causes this? or Am I using PUB/SUB illegally?
You are connecting a SUB socket to a SUB socket, that is an invalid connection. In your case the PUB should bind and the SUBs should connect.

Custom class to XML using QSettings

I'd like to save custom class to XML using QSettings. But I always get XML without structure members.
#include <QCoreApplication>
#include <QtCore/qdatastream.h>
#include <qxmlstream.h>
#include <qdebug.h>
#include <QtCore/QSettings>
#include <QMetaType>
struct Interface_struct
{
QString name;
QString ip;
};
Q_DECLARE_METATYPE(Interface_struct)
QDataStream& operator <<(QDataStream& out, const Interface_struct& s)
{
out << s.name << s.ip;
return out;
}
QDataStream& operator >>(QDataStream& in, Interface_struct& s)
{
in >> s.name;
in >> s.ip;
return in;
}
static bool readXmlFile(QIODevice &device, QSettings::SettingsMap &map)
{
qDebug()<< "read";
QXmlStreamReader reader(&device);
QString key;
while(!reader.atEnd())
{
reader.readNext();
if( reader.isStartElement() && reader.tokenString() != "Settings")
{
if( reader.text().isNull() )
{
// key = Settings
if(key.isEmpty())
{
key = reader.tokenString();
}
// key = Settings/Intervall
else
{
key += "/" + reader.tokenString();
}
}
else
{
map.insert(key, reader.text().data());
}
}
}
return true;
}
static bool writeXmlFile(QIODevice &device, const QSettings::SettingsMap &map)
{
qDebug()<< "write";
QXmlStreamWriter writer(&device);
writer.writeStartDocument("1.0");
writer.writeStartElement("Settings");
foreach(QString key, map.keys())
{
foreach(QString elementKey, key.split("/"))
{
writer.writeStartElement(elementKey);
}
writer.writeCharacters(map.value(key).toString());
writer.writeEndElement();
}
writer.writeEndElement();
writer.writeEndDocument();
return true;
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
qRegisterMetaType<Interface_struct>("Interface_struct");
qRegisterMetaTypeStreamOperators<Interface_struct>("Interface_struct");
{
Interface_struct s;
s.name = QString("br03000");
s.ip = QString("172.16.222.5");
const QSettings::Format xml_format =
QSettings::registerFormat("xml", readXmlFile, writeXmlFile);
if(xml_format == QSettings::InvalidFormat)
{
qDebug() << "InvalidFormat!";
return 0;
}
QSettings::setPath(xml_format, QSettings::UserScope, "/home/farit/test/");
QSettings settings(xml_format, QSettings::UserScope, "xml_cfg");
settings.setValue("network", QVariant::fromValue(s));
}
{
QSettings::Format xml_format =
QSettings::registerFormat("xml", readXmlFile, writeXmlFile);
QSettings::setPath(xml_format, QSettings::UserScope, "/home/farit/test/");
QSettings settings(xml_format, QSettings::UserScope, "xml_cfg");
QVariant value = settings.value("network");
Interface_struct interface = value.value<Interface_struct>();
qDebug() << "TEST: " << interface.name << interface.ip;
}
return 0;
}
I get this output:
read
write
read
TEST: "" ""
Press <RETURN> to close this window...
And XML looks like this:
<?xml version="1.0" encoding="UTF-8"?><Settings><network></network></Settings>
How can I save structure members of custom class to XML using QSettings?
UPDATE: I'm sorry, I forgot to mention, that is supposed to be done in Qt4.