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.
|
||||
/// 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.
|
||||
std::string JSON::Value::toPacked(){
|
||||
std::string JSON::Value::toPacked() const{
|
||||
std::string r;
|
||||
if (isInt() || isNull() || isBool()){
|
||||
r += 0x01;
|
||||
|
@ -500,7 +500,7 @@ std::string JSON::Value::toPacked(){
|
|||
if (isObject()){
|
||||
r += 0xE0;
|
||||
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){
|
||||
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)0xEE;
|
||||
strVal.clear();
|
||||
}
|
||||
if (isArray()){
|
||||
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 += (char)0x0;
|
||||
|
@ -527,6 +526,115 @@ std::string JSON::Value::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.
|
||||
/// Non-object-types will print an error to stderr.
|
||||
/// The internal buffer is guaranteed to be up-to-date after this function is called.
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include <map>
|
||||
#include <istream>
|
||||
#include <vector>
|
||||
#include "socket.h"
|
||||
|
||||
//empty definition of DTSC::Stream so it can be a friend.
|
||||
namespace DTSC {
|
||||
|
@ -73,7 +74,9 @@ namespace JSON {
|
|||
const Value & operator[](const char * i) const;
|
||||
const Value & operator[](unsigned int i) const;
|
||||
//handy functions and others
|
||||
std::string toPacked();
|
||||
std::string toPacked() const;
|
||||
void sendTo(Socket::Connection & socket) const;
|
||||
unsigned int packedSize() const;
|
||||
void netPrepare();
|
||||
std::string & toNetPacked();
|
||||
std::string toString() const;
|
||||
|
|
Loading…
Add table
Reference in a new issue