Added support for sending JSON::Values over a socket in DTMI format without needing to convert in advance.
This commit is contained in:
parent
558123e11e
commit
7d5942adf1
2 changed files with 116 additions and 5 deletions
116
lib/json.cpp
116
lib/json.cpp
|
@ -475,7 +475,7 @@ const JSON::Value & JSON::Value::operator[](unsigned int i) const{
|
||||||
/// Packs to a std::string for transfer over the network.
|
/// Packs to a std::string for transfer over the network.
|
||||||
/// If the object is a container type, this function will call itself recursively and contain all contents.
|
/// If the object is a container type, this function will call itself recursively and contain all contents.
|
||||||
/// As a side effect, this function clear the internal buffer of any object-types.
|
/// As a side effect, this function clear the internal buffer of any object-types.
|
||||||
std::string JSON::Value::toPacked(){
|
std::string JSON::Value::toPacked() const{
|
||||||
std::string r;
|
std::string r;
|
||||||
if (isInt() || isNull() || isBool()){
|
if (isInt() || isNull() || isBool()){
|
||||||
r += 0x01;
|
r += 0x01;
|
||||||
|
@ -500,7 +500,7 @@ std::string JSON::Value::toPacked(){
|
||||||
if (isObject()){
|
if (isObject()){
|
||||||
r += 0xE0;
|
r += 0xE0;
|
||||||
if (objVal.size() > 0){
|
if (objVal.size() > 0){
|
||||||
for (JSON::ObjIter it = objVal.begin(); it != objVal.end(); it++){
|
for (JSON::ObjConstIter it = objVal.begin(); it != objVal.end(); it++){
|
||||||
if (it->first.size() > 0){
|
if (it->first.size() > 0){
|
||||||
r += it->first.size() / 256;
|
r += it->first.size() / 256;
|
||||||
r += it->first.size() % 256;
|
r += it->first.size() % 256;
|
||||||
|
@ -512,11 +512,10 @@ std::string JSON::Value::toPacked(){
|
||||||
r += (char)0x0;
|
r += (char)0x0;
|
||||||
r += (char)0x0;
|
r += (char)0x0;
|
||||||
r += (char)0xEE;
|
r += (char)0xEE;
|
||||||
strVal.clear();
|
|
||||||
}
|
}
|
||||||
if (isArray()){
|
if (isArray()){
|
||||||
r += 0x0A;
|
r += 0x0A;
|
||||||
for (JSON::ArrIter it = arrVal.begin(); it != arrVal.end(); it++){
|
for (JSON::ArrConstIter it = arrVal.begin(); it != arrVal.end(); it++){
|
||||||
r += it->toPacked();
|
r += it->toPacked();
|
||||||
}
|
}
|
||||||
r += (char)0x0;
|
r += (char)0x0;
|
||||||
|
@ -527,6 +526,115 @@ std::string JSON::Value::toPacked(){
|
||||||
}
|
}
|
||||||
//toPacked
|
//toPacked
|
||||||
|
|
||||||
|
/// Packs and transfers over the network.
|
||||||
|
/// If the object is a container type, this function will call itself recursively for all contents.
|
||||||
|
void JSON::Value::sendTo(Socket::Connection & socket) const{
|
||||||
|
if (isInt() || isNull() || isBool()){
|
||||||
|
socket.SendNow("\001", 1);
|
||||||
|
int tmpHalf = htonl((int)(intVal >> 32));
|
||||||
|
socket.SendNow((char*)&tmpHalf, 4);
|
||||||
|
tmpHalf = htonl((int)(intVal & 0xFFFFFFFF));
|
||||||
|
socket.SendNow((char*)&tmpHalf, 4);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (isString()){
|
||||||
|
socket.SendNow("\002", 1);
|
||||||
|
int tmpVal = htonl((int)strVal.size());
|
||||||
|
socket.SendNow((char*)&tmpVal, 4);
|
||||||
|
socket.SendNow(strVal);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (isObject()){
|
||||||
|
if (isMember("trackid") && isMember("time")){
|
||||||
|
unsigned int trackid = objVal.find("trackid")->second.asInt();
|
||||||
|
long long time = objVal.find("time")->second.asInt();
|
||||||
|
unsigned int size = 16;
|
||||||
|
if (objVal.size() > 0){
|
||||||
|
for (JSON::ObjConstIter it = objVal.begin(); it != objVal.end(); it++){
|
||||||
|
if (it->first.size() > 0 && it->first != "trackid" && it->first != "time" && it->first != "datatype"){
|
||||||
|
size += 2+it->first.size()+it->second.packedSize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
socket.SendNow("DTP2", 4);
|
||||||
|
size = htonl(size);
|
||||||
|
socket.SendNow((char*)&size, 4);
|
||||||
|
trackid = htonl(trackid);
|
||||||
|
socket.SendNow((char*)&trackid, 4);
|
||||||
|
int tmpHalf = htonl((int)(time >> 32));
|
||||||
|
socket.SendNow((char*)&tmpHalf, 4);
|
||||||
|
tmpHalf = htonl((int)(time & 0xFFFFFFFF));
|
||||||
|
socket.SendNow((char*)&tmpHalf, 4);
|
||||||
|
socket.SendNow("\340", 1);
|
||||||
|
if (objVal.size() > 0){
|
||||||
|
for (JSON::ObjConstIter it = objVal.begin(); it != objVal.end(); it++){
|
||||||
|
if (it->first.size() > 0 && it->first != "trackid" && it->first != "time" && it->first != "datatype"){
|
||||||
|
char sizebuffer[2] = {0, 0};
|
||||||
|
sizebuffer[0] = (it->first.size() >> 8) & 0xFF;
|
||||||
|
sizebuffer[1] = it->first.size() & 0xFF;
|
||||||
|
socket.SendNow(sizebuffer, 2);
|
||||||
|
socket.SendNow(it->first);
|
||||||
|
it->second.sendTo(socket);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
socket.SendNow("\000\000\356", 3);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
socket.SendNow("\340", 1);
|
||||||
|
if (objVal.size() > 0){
|
||||||
|
for (JSON::ObjConstIter it = objVal.begin(); it != objVal.end(); it++){
|
||||||
|
if (it->first.size() > 0){
|
||||||
|
char sizebuffer[2] = {0, 0};
|
||||||
|
sizebuffer[0] = (it->first.size() >> 8) & 0xFF;
|
||||||
|
sizebuffer[1] = it->first.size() & 0xFF;
|
||||||
|
socket.SendNow(sizebuffer, 2);
|
||||||
|
socket.SendNow(it->first);
|
||||||
|
it->second.sendTo(socket);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
socket.SendNow("\000\000\356", 3);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (isArray()){
|
||||||
|
socket.SendNow("\012", 1);
|
||||||
|
for (JSON::ArrConstIter it = arrVal.begin(); it != arrVal.end(); it++){
|
||||||
|
it->sendTo(socket);
|
||||||
|
}
|
||||||
|
socket.SendNow("\000\000\356", 3);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}//sendTo
|
||||||
|
|
||||||
|
/// Returns the packed size of this Value.
|
||||||
|
unsigned int JSON::Value::packedSize() const{
|
||||||
|
if (isInt() || isNull() || isBool()){
|
||||||
|
return 9;
|
||||||
|
}
|
||||||
|
if (isString()){
|
||||||
|
return 5 + strVal.size();
|
||||||
|
}
|
||||||
|
if (isObject()){
|
||||||
|
unsigned int ret = 4;
|
||||||
|
if (objVal.size() > 0){
|
||||||
|
for (JSON::ObjConstIter it = objVal.begin(); it != objVal.end(); it++){
|
||||||
|
if (it->first.size() > 0){
|
||||||
|
ret += 2+it->first.size()+it->second.packedSize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
if (isArray()){
|
||||||
|
unsigned int ret = 4;
|
||||||
|
for (JSON::ArrConstIter it = arrVal.begin(); it != arrVal.end(); it++){
|
||||||
|
ret += it->packedSize();
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}//packedSize
|
||||||
|
|
||||||
/// Pre-packs any object-type JSON::Value to a std::string for transfer over the network, including proper DTMI header.
|
/// Pre-packs any object-type JSON::Value to a std::string for transfer over the network, including proper DTMI header.
|
||||||
/// Non-object-types will print an error to stderr.
|
/// Non-object-types will print an error to stderr.
|
||||||
/// The internal buffer is guaranteed to be up-to-date after this function is called.
|
/// The internal buffer is guaranteed to be up-to-date after this function is called.
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <istream>
|
#include <istream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include "socket.h"
|
||||||
|
|
||||||
//empty definition of DTSC::Stream so it can be a friend.
|
//empty definition of DTSC::Stream so it can be a friend.
|
||||||
namespace DTSC {
|
namespace DTSC {
|
||||||
|
@ -73,7 +74,9 @@ namespace JSON {
|
||||||
const Value & operator[](const char * i) const;
|
const Value & operator[](const char * i) const;
|
||||||
const Value & operator[](unsigned int i) const;
|
const Value & operator[](unsigned int i) const;
|
||||||
//handy functions and others
|
//handy functions and others
|
||||||
std::string toPacked();
|
std::string toPacked() const;
|
||||||
|
void sendTo(Socket::Connection & socket) const;
|
||||||
|
unsigned int packedSize() const;
|
||||||
void netPrepare();
|
void netPrepare();
|
||||||
std::string & toNetPacked();
|
std::string & toNetPacked();
|
||||||
std::string toString() const;
|
std::string toString() const;
|
||||||
|
|
Loading…
Add table
Reference in a new issue