How can I validate a subset of a RapidJSON document? - rapidjson

I'm using RapidJSON to parse messages that (roughly) conform to JSON-RPC. Here's an example of one such message:
{
"method": "increment",
"params": [ { "count": 42 } ]
}
The content of params depends on the value of method, so... I need to validate against a different schema for each possible value of method. As a step towards this goal, I created a map of schema documents, keyed by the method name:
std::unordered_map<std::string, rapidjson::SchemaDocument> schemas;
My intention was to do something like this (after parsing the received JSON into a RapidJSON document, doc):
if (schemas.find(doc["method"]) != schemas.end()) {
validate(doc, schemas[doc]);
}
My problem is: I know how to validate a rapidjson::Document, but not a GenericValue instance (which is, I gather, what doc["method"] returns).
How can I validate a fragment or 'sub-document' of a RapidJSON document?
UPDATE/EXPLANATION: Thanks to #wsxedcrfv's answer, I now realize that my statement saying "I know how to validate a rapidjson::Document wasn't entirely accurate. I knew one way of validating a rapidjson::Document. But there's more than one way to do it, apparently. To clean up this question a bit for posterity, here's the validate() function that was missing from my original question:
bool validate(
rj::SchemaDocument const& schema,
rj::Document *doc,
std::string const& jsonMsg
)
{
bool valid = false;
rj::StringStream ss(jsonMsg.c_str());
rj::SchemaValidatingReader<
rj::kParseDefaultFlags,
rj::StringStream,
rj::UTF8<>
> reader(ss, schema);
doc->Populate(reader);
if (!reader.GetParseResult()) {
if (!reader.IsValid()) {
rj::StringBuffer sb;
reader.GetInvalidSchemaPointer().StringifyUriFragment(sb);
printf("Message does not conform to schema!\n");
printf("--------------------------------------------------------------------\n");
printf("Invalid schema: %s\n", sb.GetString());
printf("Invalid keyword: %s\n", reader.GetInvalidSchemaKeyword());
sb.Clear();
reader.GetInvalidDocumentPointer().StringifyUriFragment(sb);
printf("Invalid document: %s\n", sb.GetString());
printf("--------------------------------------------------------------------\n");
}
else {
printf("Message JSON is not well-formed!\n");
}
}
else {
valid = true;
}
return valid;
}
As #wsxedcrfv points out, another option is to create a SchemaValidator instance and pass it to the Accept() method of the (sub-)document:
#include "rapidjson/document.h"
#include <rapidjson/schema.h>
#include <iostream>
namespace rj = rapidjson;
namespace
{
std::string testMsg = R"msg({ "root": { "method": "control", "params": [ { "icc_delta_vol": 5 } ] } })msg";
std::string msgSchema = R"schema(
{
"type": "object",
"properties": {
"method": { "$ref": "#/definitions/method" },
"params": { "$ref": "#/definitions/paramsList" }
},
"required": [ "method", "params" ],
"additionalProperties": false,
"definitions": {
// Omitted in the interest of brevity
...
}
})schema";
} // End anonymous namespace
int main()
{
rj::Document schemaDoc;
if (schemaDoc.Parse(::msgSchema.c_str()).HasParseError()) {
std::cout << "Schema contains invalid JSON, aborting...\n";
exit(EXIT_FAILURE);
}
rj::SchemaDocument schema(schemaDoc);
rj::SchemaValidator validator(schema);
rj::Document doc;
doc.Parse(::testMsg.c_str());
std::cout << "doc.Accept(validator) = " << doc["root"].Accept(validator) << '\n';
return 0;
Now that I know about this alternate method, I can easily use it to do context-specific validation of sub-documents/fragments...

I guess this answer is a bit late for you, but this works for me:
char json[] = "{ \"a\" : 1, \"b\" : 1.2 } ";
rapidjson::Document d;
std::cout << "parse json error? " << d.Parse(json).HasParseError() << "\n";
char schema[] = "{ \"type\" : \"integer\" } ";
rapidjson::Document sd;
std::cout << "parse schema error? " << sd.Parse(schema).HasParseError() << "\n";
rapidjson::SchemaDocument s{sd}; //sd may now be deleted
rapidjson::SchemaValidator vali{s};
std::cout << "json " << d.Accept(vali) << "\n"; // 0
vali.Reset();
std::cout << "a " << d.GetObject()["a"].Accept(vali) << "\n"; // 1
vali.Reset();
std::cout << "b " << d.GetObject()["b"].Accept(vali) << "\n"; // 0
I don't know which validate function you are using, but a Document is a GenericValue and the GenericValue provides Accept.

Related

Moving a sprite using keyboard

I'm trying to move playerSpaceShip by keyboard. The function is changing its position (checked in the console by getcoordinates()) but it's not displaying it on the screen(sprite is not moving). Anyone can figure out why?
player.cpp
void player::movePlayer(sf::Vector2f distance)
{
playerSpaceShipSprite.move(playerMoveSpeed * distance.x, playerMoveSpeed * distance.y);
}
void player::render(sf::RenderTarget* target)
{
target->draw(playerSpaceShipSprite);
}
game.cpp
void game::update()
{
while (window->isOpen())
{
while (window->pollEvent(sfEvent))
{
if (sfEvent.type == sf::Event::Closed)
window->close();
playerMovement(sfEvent);
}
}
}
void game::renderPlayer()
{
if (Player)
Player->render(window);
}
void game::render()
{
window->clear();
renderBackground();
renderPlayer();
renderBlueAlien();
window->display();
}
void game::playerMovement(sf::Event sfEvent)
{
if (sfEvent.type == sf::Event::EventType::KeyPressed)
{
switch (sfEvent.key.code)
{
case sf::Keyboard::Left:
{
Player->movePlayer(sf::Vector2f(-1,0));
std::cout << "Left key pressed\n";
break;
}
case sf::Keyboard::Right:
{
Player->movePlayer(sf::Vector2f(1, 0));
std::cout << "Right key pressed\n";
break;
}
case sf::Keyboard::Up:
{
Player->movePlayer(sf::Vector2f(0, -1));
std::cout << "Up key pressed\n";
break;
}
case sf::Keyboard::Down:
{
Player->movePlayer(sf::Vector2f(0, 1));
std::cout << "Down key pressed\n";
break;
}
case sf::Keyboard::Space:
{
std::cout << "Space key pressed\n";
break;
}
}
}
}
void game::run()
{
while (window->isOpen())
{
render();
update();
}
}
void game::update() has while (window->isOpen()) at the start.
This means that the update function never returns back to void game::run(), where your second while (window->isOpen()) statement is, and since it never returns to there, void game::render() never gets called again.
The player is moving, but the screen is not updating to show the player moving. Getting rid of while (window->isOpen()) in void game::update() solves the problem.
I solved this using a debugger, setting a breakpoint inside void player::movePlayer(sf::Vector2f distance), and stepping through the code until I came across the problem.

mock a function with pointer as argument

I want to mock a function which has a pointer argument
class I_Shaft
{
public:
virtual ~I_Shaft() {
}
virtual void GetFloor(I_Floor* FloorPointer) = 0;
};
the mocked interface:
class Mock_I_Shaft : public I_Shaft
{
public:
MOCK_METHOD1(GetFloor, void(I_Floor* FloorPointer));
};
the mocked interface Mock_I_Floor which needs a default and a copy constructor (otherwise it won't get compiled):
class Mock_I_Floor : public I_Floor
{
public:
Mock_I_Floor() {}
Mock_I_Floor(const Mock_I_Floor& f) {}
virtual ~Mock_I_Floor() {};
MOCK_METHOD0(GetPosition, uint16_t());
};
the implementation that is to be tested:
C_HZS::C_HZS(I_Shaft& refShaft) : //constructor initializing refShaft
refShaft(refShaft)
{
}
void C_HZS::run(void)
{
I_Floor* ptrFloor = NULL;
refShaft.GetFloor(ptrFloor);
if(ptrFloor == NULL){
std::cerr << "there is no valid pointer" <<std::endl;
return;
}
floorPosition = ptrFloor->GetPosition();
std::cout << "floorPosition: " << floorPosition << std::endl;
}
and here is my test:
TEST(HZS, testFloorPosition) {
Mock_I_Shaft shaft;
Mock_I_Floor floor;
Mock_I_Floor* pFloorMocked= &floor;
C_HZS dutObj(shaft);
EXPECT_CALL(shaft, GetFloor(_))
.Times(AtLeast(1))
.WillOnce(SetArgPointee<0>(*pFloorMocked)
);
dutObj.run();
EXPECT_FALSE(...);
}
The problem is: I am not able to inject pFloorMocked into the mocked function. Within the run() function ptrFloor always stays NULL. What is the reason for this? Is there another way to mock this function?

How to make it as parallel processing using OpenMP flag?

How can we use all processor at a time to run below code using openmp flag?
If I am converting while loop as for loop using for(;!xml.atEnd();) it is showing error:
need to initialisation and increment/decrements
//Need parallel processing for this code.
while (!xml.atEnd()) {
// cerr <<"while loop";
xml.readNext();
if (xml.isStartElement()) {
currentXmlElement = xml.name();
if (xml.name() == "sample") {
QString fname = xml.attributes().value("filename").toString();
QString sname = xml.attributes().value("name").toString();
QString setname = xml.attributes().value("setName").toString();
QString sampleOrder = xml.attributes().value("sampleOrder").toString();
QString isSelected = xml.attributes().value("isSelected").toString();
//_mainwindow->setStatusText(tr("Loading sample: %1").arg(sname));
//_mainwindow->setProgressBar(tr("Loading Sample Number %1").arg(++currentSampleCount),currentSampleCount,currentSampleCount+1);
bool checkLoaded=false;
Q_FOREACH(mzSample* loadedFile, _mainwindow->getSamples()) {
if (QString(loadedFile->fileName.c_str())== fname) checkLoaded=true;
}
if(checkLoaded == true) continue; // skip files that have been loaded already
// #pragma omp critical {
qDebug() << "Checking:" << fname;
QFileInfo sampleFile(fname);
if (!sampleFile.exists()) {
Q_FOREACH(QString path, pathlist) {
fname= path + QDir::separator() + sampleFile.fileName();
qDebug() << "Checking if exists:" << fname;
if (sampleFile.exists()) break;
}
}
if ( !fname.isEmpty() ) {
// mzFileIO* fileLoader = new mzFileIO(this);
// fileLoader->setMainWindow(_mainwindow);
// mzSample* sample = fileLoader->loadSample(fname);
// delete(fileLoader);
mzSample* sample = _mainwindow->fileLoader->loadSample(fname);
if (sample) {
_mainwindow->addSample(sample);
currentSample=sample;
if (!sname.isEmpty() ) sample->sampleName = sname.toStdString();
if (!setname.isEmpty() ) sample->setSetName(setname.toStdString());
if (!sampleOrder.isEmpty()) sample->setSampleOrder(sampleOrder.toInt());
if (!isSelected.isEmpty()) sample->isSelected = isSelected.toInt();
} else {
currentSample=NULL;
}
}
}
//change sample color
if (xml.name() == "color" && currentSample) {
currentSample->color[0] = xml.attributes().value("red").toString().toDouble();
currentSample->color[1] = xml.attributes().value("blue").toString().toDouble();
currentSample->color[2] = xml.attributes().value("green").toString().toDouble();
currentSample->color[3] = xml.attributes().value("alpha").toString().toDouble();
}
//polynomialAlignmentTransformation vector
if (xml.name() == "polynomialAlignmentTransformation" && currentSample) {
vector<double>transform;
Q_FOREACH(QXmlStreamAttribute coef, xml.attributes() ) {
double coefValue =coef.value().toString().toDouble();
transform.push_back(coefValue);
}
qDebug() << "polynomialAlignmentTransformation: "; printF(transform);
currentSample->polynomialAlignmentTransformation = transform;
currentSample->saveOriginalRetentionTimes();
currentSample->applyPolynomialTransform();
}
}
if (xml.isCharacters() && currentXmlElement == "projectDescription") {
projectDescription.append( xml.text() );
}
}
OpenMP doesn't really deal with arbitrary objects. Besides, the OpenMP model won't suit you here. The basic idea for OpenMP is to farm out single iterations of a for loop to different threads. This isn't going to work well for reading XML data, which by its very nature has to be read serially to preserve ordering.
In your case, suppose you could use OpenMP, parallelizing the outer loop. Suppose there are 8 OpenMP threads running. Each is going to execute the xml.readNext(); line. I can almost guarantee that the readNext function isn't thread-safe, which is going to give you undefined results. Even if it were thread-safe, it would have to read one full item (not sure what it's reading since I don't know the type of xml) atomically which would make your code mostly serial anyway.

Use iXMLHttpRequest2 to download zip file

I am trying to port cocos2dx application for Windows phone 8. I am trying to use iXMLHTTPRequest class to perform Network calls in C++.
I am trying to download zip file using this but dont know what and where I am doing wrong. Here is my code which I am using, Please help me to figure out the issue and what I should do to make it working.
void HTTPRequest::sendRequest(){
m_cancelHttpRequestSource = cancellation_token_source();
// Set up the GET request parameters.
std::string s_str = std::string(urlString);
std::wstring wid_str = std::wstring(s_str.begin(), s_str.end());
const wchar_t* w_char = wid_str.c_str();
auto uri = ref new Uri( ref new String(w_char));
String ^temp = uri->AbsoluteUri;
auto token = m_cancelHttpRequestSource.get_token();
// Send the request and then update the UI.
onHttpRequestCompleted(m_httpRequest.GetAsync(uri, token));
}
void HTTPRequest::onHttpRequestCompleted(concurrency::task httpRequest)
{
httpRequest.then([this](task previousTask)
{
try
{
wstring response = previousTask.get();
if (m_httpRequest.GetStatusCode() == 200)
{
size_t strSize;
FILE* fileHandle;
auto local = Windows::Storage::ApplicationData::Current->LocalFolder;
auto localFileNamePlatformString = local->Path + "\\test1.zip";
// Create an the xml file in text and Unicode encoding mode.
if ((fileHandle = _wfopen(localFileNamePlatformString->Data(), L"wb")) == NULL) // C4996
// Note: _wfopen is deprecated; consider using _wfopen_s instead
{
wprintf(L"_wfopen failed!\n");
return(0);
}
// Write a string into the file.
strSize = wcslen(response.c_str());
if (fwrite(response.c_str(), sizeof(wchar_t), strSize, fileHandle) != strSize)
{
wprintf(L"fwrite failed!\n");
}
// Close the file.
if (fclose(fileHandle))
{
wprintf(L"fclose failed!\n");
}
}
else
{
// The request failed. Show the status code and reason.
wstringstream ss;
ss << L"The server returned "
<< m_httpRequest.GetStatusCode()
<< L" ("
<< m_httpRequest.GetReasonPhrase()
<< L')';
//String ^responseText = ref new String(ss.str().c_str());
m_delegate->parserError(requestType->getCString(), "Print Status Code later");
}
}
catch (const task_canceled&)
{
// Indicate that the operation was canceled.
//String ^responseText = "The operation was canceled";
m_delegate->parserError(requestType->getCString(), "Operation has canceled");
}
catch (Exception^ e)
{
// Indicate that the operation failed.
//String ^responseText = "The operation failed";
m_delegate->parserError(requestType->getCString(), "The operation failed");
// TODO: Handle the error further.
(void)e;
}
}, task_continuation_context::use_current());
}

Volume backup using VSS in vc++

Can anyone suggest me how to do volume backup?
below is my code. Creating shapshot of C: drive and tryinh to backed up and using CopyFile to backup file by file. Is their any way to backup valume?
cout<<"=============Begin Initialize=========="<<endl;
if(FAILED(CoInitializeEx(NULL,0)))
{
cout << "CoInitialize() failed\n";
return(0);
}
if(FAILED(CoInitializeSecurity(
NULL,
-1,
NULL,
NULL,
RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
RPC_C_IMP_LEVEL_IDENTIFY,
NULL,
EOAC_NONE,
NULL)))
{
cout << "CoInitializeSecurity() failed\n";
return(0);
}
if(FAILED(CreateVssBackupComponents(&m_pVssObject)))
{
cout << "CreateVssBackupComponents() failed\n";
return(0);
}
if(FAILED(m_pVssObject->InitializeForBackup()))
{
cout << "IVssBackupComponents->InitializeForBackup() failed\n";
return(0);
}
// if(FAILED(m_pVssObject->SetContext(dwContext)))
if(FAILED(m_pVssObject->SetContext(VSS_CTX_BACKUP | VSS_CTX_APP_ROLLBACK)))
{
cout << "IVssBackupComponents->SetContext() failed\n";
return(0);
}
if(FAILED(m_pVssObject->SetBackupState(true,true,VSS_BT_FULL,false)))
{
cout << "IVssBackupComponents->SetContext() failed\n";
return(0);
}
cout<<"=============End Initialize=========="<<endl;
// Start the shadow set
CHECK_COM(m_pVssObject->StartSnapshotSet(&m_latestSnapshotSetID))
GetVolumePathNameW((LPCWSTR)wstrVolume.c_str(),wszVolumePathName, MAX_PATH);
CHECK_COM(m_pVssObject->IsVolumeSupported(GUID_NULL, wszVolumePathName, &supported));
// Add the specified volumes to the shadow set
VSS_ID SnapshotID;
CHECK_COM(m_pVssObject->AddToSnapshotSet(wszVolumePathName, GUID_NULL, &SnapShotId));
m_latestSnapshotIdList.push_back(SnapshotID);
cout<<"Prepare the shadow for backup\n";
CHECK_COM(m_pVssObject->PrepareForBackup(&pPrepare));
cout<<"Waiting for the asynchronous operation to finish..."<<endl;
CHECK_COM(pPrepare->Wait());
HRESULT hrReturned = S_OK;
CHECK_COM(pPrepare->QueryStatus(&hrReturned, NULL));
// Check if the async operation succeeded...
if(FAILED(hrReturned))
{
cout<<"Error during the last asynchronous operation."<<endl;
}
pPrepare->Release();
cout<<"Creating the shadow (DoSnapshotSet) ... "<<endl;
CHECK_COM(m_pVssObject->DoSnapshotSet(&pDoShadowCopy));
cout<<"Waiting for the asynchronous operation to finish..."<<endl;
CHECK_COM(pDoShadowCopy->Wait());
hrReturned = S_OK;
CHECK_COM(pDoShadowCopy->QueryStatus(&hrReturned, NULL));
// Check if the async operation succeeded...
if(FAILED(hrReturned))
{
cout<<"Error during the last asynchronous operation."<<endl;
}
pDoShadowCopy->Release();
HRESULT result;
//CHECK_COM(m_pVssObject->GetSnapshotProperties(SnapShotId,&props));
result=m_pVssObject->GetSnapshotProperties(SnapShotId,&props);
if(result== S_OK)
{
_tprintf (_T(" Snapshot Id :") WSTR_GUID_FMT _T("\n"), GUID_PRINTF_ARG( props.m_SnapshotId));
_tprintf (_T(" Snapshot Set ID :") WSTR_GUID_FMT _T("\n"), GUID_PRINTF_ARG( props.m_SnapshotSetId));
_tprintf (_T(" Provider ID :") WSTR_GUID_FMT _T("\n"), GUID_PRINTF_ARG( props.m_ProviderId));
_tprintf (_T(" OriginalVolumeName : %ls\n"),props.m_pwszOriginalVolumeName);
if(props.m_pwszExposedPath != NULL) _tprintf (_T(" Exposed Path : %ls\n"),props.m_pwszExposedPath);
if(props.m_pwszExposedName != NULL) _tprintf (_T(" Exposed Path Name : %ls\n"),props.m_pwszExposedName);
if(props.m_pwszSnapshotDeviceObject != NULL) _tprintf (_T(" SnapShot device object: %ls\n"),props.m_pwszSnapshotDeviceObject);
SYSTEMTIME stUTC, stLocal;
FILETIME ftCreate;
ftCreate.dwHighDateTime = HILONG(props.m_tsCreationTimestamp);
ftCreate.dwLowDateTime = LOLONG(props.m_tsCreationTimestamp);
FileTimeToSystemTime(&ftCreate, &stUTC);
SystemTimeToTzSpecificLocalTime(NULL, &stUTC, &stLocal);
_tprintf (TEXT("Created : %02d/%02d/%d %02d:%02d \n"), stLocal.wMonth, stLocal.wDay, stLocal.wYear, stLocal.wHour, stLocal.wMinute );
_tprintf (_T("\n"));
}
WCHAR sam_file[1024];
wsprintf(sam_file,L"%s%s",props.m_pwszSnapshotDeviceObject,L"\\WINDOWS\\System32\\Config\\SAM");
CopyFile(sam_file,L"c:\\temp\\dbg_sm_bkup",FALSE);
VssFreeSnapshotProperties(&props);
m_pVssObject->Release();
Thanks in Advance
You can do volume shadow copy using vshadow tool. Source code also available online also with sdks. Go through the following link,
http://msdn.microsoft.com/en-us/library/windows/desktop/bb530725(v=vs.85).aspx

Resources