Made JSON library non-recursive.
Co-authored with Diederick.
This commit is contained in:
parent
7905bb2bda
commit
16d38459b6
14 changed files with 503 additions and 328 deletions
135
lib/config.cpp
135
lib/config.cpp
|
@ -84,11 +84,11 @@ void Util::Config::addOption(std::string optname, JSON::Value option) {
|
||||||
vals[optname].removeMember("default");
|
vals[optname].removeMember("default");
|
||||||
}
|
}
|
||||||
long_count = 0;
|
long_count = 0;
|
||||||
for (JSON::ObjIter it = vals.ObjBegin(); it != vals.ObjEnd(); it++) {
|
jsonForEach(vals, it) {
|
||||||
if (it->second.isMember("long")) {
|
if (it->isMember("long")) {
|
||||||
long_count++;
|
long_count++;
|
||||||
}
|
}
|
||||||
if (it->second.isMember("long_off")) {
|
if (it->isMember("long_off")) {
|
||||||
long_count++;
|
long_count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -98,33 +98,33 @@ void Util::Config::addOption(std::string optname, JSON::Value option) {
|
||||||
void Util::Config::printHelp(std::ostream & output) {
|
void Util::Config::printHelp(std::ostream & output) {
|
||||||
unsigned int longest = 0;
|
unsigned int longest = 0;
|
||||||
std::map<long long int, std::string> args;
|
std::map<long long int, std::string> args;
|
||||||
for (JSON::ObjIter it = vals.ObjBegin(); it != vals.ObjEnd(); it++) {
|
jsonForEach(vals, it) {
|
||||||
unsigned int current = 0;
|
unsigned int current = 0;
|
||||||
if (it->second.isMember("long")) {
|
if (it->isMember("long")) {
|
||||||
current += it->second["long"].asString().size() + 4;
|
current += (*it)["long"].asString().size() + 4;
|
||||||
}
|
}
|
||||||
if (it->second.isMember("short")) {
|
if (it->isMember("short")) {
|
||||||
current += it->second["short"].asString().size() + 3;
|
current += (*it)["short"].asString().size() + 3;
|
||||||
}
|
}
|
||||||
if (current > longest) {
|
if (current > longest) {
|
||||||
longest = current;
|
longest = current;
|
||||||
}
|
}
|
||||||
current = 0;
|
current = 0;
|
||||||
if (it->second.isMember("long_off")) {
|
if (it->isMember("long_off")) {
|
||||||
current += it->second["long_off"].asString().size() + 4;
|
current += (*it)["long_off"].asString().size() + 4;
|
||||||
}
|
}
|
||||||
if (it->second.isMember("short_off")) {
|
if (it->isMember("short_off")) {
|
||||||
current += it->second["short_off"].asString().size() + 3;
|
current += (*it)["short_off"].asString().size() + 3;
|
||||||
}
|
}
|
||||||
if (current > longest) {
|
if (current > longest) {
|
||||||
longest = current;
|
longest = current;
|
||||||
}
|
}
|
||||||
if (it->second.isMember("arg_num")) {
|
if (it->isMember("arg_num")) {
|
||||||
current = it->first.size() + 3;
|
current = it.key().size() + 3;
|
||||||
if (current > longest) {
|
if (current > longest) {
|
||||||
longest = current;
|
longest = current;
|
||||||
}
|
}
|
||||||
args[it->second["arg_num"].asInt()] = it->first;
|
args[(*it)["arg_num"].asInt()] = it.key();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
output << "Usage: " << getString("cmd") << " [options]";
|
output << "Usage: " << getString("cmd") << " [options]";
|
||||||
|
@ -136,54 +136,54 @@ void Util::Config::printHelp(std::ostream & output) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
output << std::endl << std::endl;
|
output << std::endl << std::endl;
|
||||||
for (JSON::ObjIter it = vals.ObjBegin(); it != vals.ObjEnd(); it++) {
|
jsonForEach(vals, it) {
|
||||||
std::string f;
|
std::string f;
|
||||||
if (it->second.isMember("long") || it->second.isMember("short")) {
|
if (it->isMember("long") || it->isMember("short")) {
|
||||||
if (it->second.isMember("long") && it->second.isMember("short")) {
|
if (it->isMember("long") && it->isMember("short")) {
|
||||||
f = "--" + it->second["long"].asString() + ", -" + it->second["short"].asString();
|
f = "--" + (*it)["long"].asString() + ", -" + (*it)["short"].asString();
|
||||||
} else {
|
} else {
|
||||||
if (it->second.isMember("long")) {
|
if (it->isMember("long")) {
|
||||||
f = "--" + it->second["long"].asString();
|
f = "--" + (*it)["long"].asString();
|
||||||
}
|
}
|
||||||
if (it->second.isMember("short")) {
|
if (it->isMember("short")) {
|
||||||
f = "-" + it->second["short"].asString();
|
f = "-" + (*it)["short"].asString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (f.size() < longest) {
|
while (f.size() < longest) {
|
||||||
f.append(" ");
|
f.append(" ");
|
||||||
}
|
}
|
||||||
if (it->second.isMember("arg")) {
|
if (it->isMember("arg")) {
|
||||||
output << f << "(" << it->second["arg"].asString() << ") " << it->second["help"].asString() << std::endl;
|
output << f << "(" << (*it)["arg"].asString() << ") " << (*it)["help"].asString() << std::endl;
|
||||||
} else {
|
} else {
|
||||||
output << f << it->second["help"].asString() << std::endl;
|
output << f << (*it)["help"].asString() << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (it->second.isMember("long_off") || it->second.isMember("short_off")) {
|
if (it->isMember("long_off") || it->isMember("short_off")) {
|
||||||
if (it->second.isMember("long_off") && it->second.isMember("short_off")) {
|
if (it->isMember("long_off") && it->isMember("short_off")) {
|
||||||
f = "--" + it->second["long_off"].asString() + ", -" + it->second["short_off"].asString();
|
f = "--" + (*it)["long_off"].asString() + ", -" + (*it)["short_off"].asString();
|
||||||
} else {
|
} else {
|
||||||
if (it->second.isMember("long_off")) {
|
if (it->isMember("long_off")) {
|
||||||
f = "--" + it->second["long_off"].asString();
|
f = "--" + (*it)["long_off"].asString();
|
||||||
}
|
}
|
||||||
if (it->second.isMember("short_off")) {
|
if (it->isMember("short_off")) {
|
||||||
f = "-" + it->second["short_off"].asString();
|
f = "-" + (*it)["short_off"].asString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (f.size() < longest) {
|
while (f.size() < longest) {
|
||||||
f.append(" ");
|
f.append(" ");
|
||||||
}
|
}
|
||||||
if (it->second.isMember("arg")) {
|
if (it->isMember("arg")) {
|
||||||
output << f << "(" << it->second["arg"].asString() << ") " << it->second["help"].asString() << std::endl;
|
output << f << "(" << (*it)["arg"].asString() << ") " << (*it)["help"].asString() << std::endl;
|
||||||
} else {
|
} else {
|
||||||
output << f << it->second["help"].asString() << std::endl;
|
output << f << (*it)["help"].asString() << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (it->second.isMember("arg_num")) {
|
if (it->isMember("arg_num")) {
|
||||||
f = it->first;
|
f = it.key();
|
||||||
while (f.size() < longest) {
|
while (f.size() < longest) {
|
||||||
f.append(" ");
|
f.append(" ");
|
||||||
}
|
}
|
||||||
output << f << "(" << it->second["arg"].asString() << ") " << it->second["help"].asString() << std::endl;
|
output << f << "(" << (*it)["arg"].asString() << ") " << (*it)["help"].asString() << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -197,42 +197,43 @@ bool Util::Config::parseArgs(int & argc, char ** & argv) {
|
||||||
int long_i = 0;
|
int long_i = 0;
|
||||||
int arg_count = 0;
|
int arg_count = 0;
|
||||||
if (vals.size()) {
|
if (vals.size()) {
|
||||||
for (JSON::ObjIter it = vals.ObjBegin(); it != vals.ObjEnd(); it++) {
|
jsonForEach(vals, it) {
|
||||||
if (it->second.isMember("short")) {
|
if (it->isMember("short")) {
|
||||||
shortopts += it->second["short"].asString();
|
shortopts += (*it)["short"].asString();
|
||||||
if (it->second.isMember("arg")) {
|
if (it->isMember("arg")) {
|
||||||
shortopts += ":";
|
shortopts += ":";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (it->second.isMember("short_off")) {
|
if (it->isMember("short_off")) {
|
||||||
shortopts += it->second["short_off"].asString();
|
shortopts += (*it)["short_off"].asString();
|
||||||
if (it->second.isMember("arg")) {
|
if (it->isMember("arg")) {
|
||||||
shortopts += ":";
|
shortopts += ":";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (it->second.isMember("long")) {
|
if (it->isMember("long")) {
|
||||||
longOpts[long_i].name = it->second["long"].asString().c_str();
|
longOpts[long_i].name = (*it)["long"].asStringRef().c_str();
|
||||||
longOpts[long_i].val = it->second["short"].asString()[0];
|
longOpts[long_i].val = (*it)["short"].asString()[0];
|
||||||
if (it->second.isMember("arg")) {
|
if (it->isMember("arg")) {
|
||||||
longOpts[long_i].has_arg = 1;
|
longOpts[long_i].has_arg = 1;
|
||||||
}
|
}
|
||||||
long_i++;
|
long_i++;
|
||||||
}
|
}
|
||||||
if (it->second.isMember("long_off")) {
|
if (it->isMember("long_off")) {
|
||||||
longOpts[long_i].name = it->second["long_off"].asString().c_str();
|
longOpts[long_i].name = (*it)["long_off"].asStringRef().c_str();
|
||||||
longOpts[long_i].val = it->second["short_off"].asString()[0];
|
longOpts[long_i].val = (*it)["short_off"].asString()[0];
|
||||||
if (it->second.isMember("arg")) {
|
if (it->isMember("arg")) {
|
||||||
longOpts[long_i].has_arg = 1;
|
longOpts[long_i].has_arg = 1;
|
||||||
}
|
}
|
||||||
long_i++;
|
long_i++;
|
||||||
}
|
}
|
||||||
if (it->second.isMember("arg_num") && !(it->second.isMember("value") && it->second["value"].size())) {
|
if (it->isMember("arg_num") && !(it->isMember("value") && (*it)["value"].size())) {
|
||||||
if (it->second["arg_num"].asInt() > arg_count) {
|
if ((*it)["arg_num"].asInt() > arg_count) {
|
||||||
arg_count = it->second["arg_num"].asInt();
|
arg_count = (*it)["arg_num"].asInt();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((opt = getopt_long(argc, argv, shortopts.c_str(), longOpts, 0)) != -1) {
|
while ((opt = getopt_long(argc, argv, shortopts.c_str(), longOpts, 0)) != -1) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 'h':
|
case 'h':
|
||||||
|
@ -253,17 +254,17 @@ bool Util::Config::parseArgs(int & argc, char ** & argv) {
|
||||||
exit(1);
|
exit(1);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
for (JSON::ObjIter it = vals.ObjBegin(); it != vals.ObjEnd(); it++) {
|
jsonForEach(vals, it) {
|
||||||
if (it->second.isMember("short") && it->second["short"].asString()[0] == opt) {
|
if (it->isMember("short") && (*it)["short"].asString()[0] == opt) {
|
||||||
if (it->second.isMember("arg")) {
|
if (it->isMember("arg")) {
|
||||||
it->second["value"].append((std::string)optarg);
|
(*it)["value"].append((std::string)optarg);
|
||||||
} else {
|
} else {
|
||||||
it->second["value"].append((long long int)1);
|
(*it)["value"].append((long long int)1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (it->second.isMember("short_off") && it->second["short_off"].asString()[0] == opt) {
|
if (it->isMember("short_off") && (*it)["short_off"].asString()[0] == opt) {
|
||||||
it->second["value"].append((long long int)0);
|
(*it)["value"].append((long long int)0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -272,9 +273,9 @@ bool Util::Config::parseArgs(int & argc, char ** & argv) {
|
||||||
free(longOpts); //free the long options array
|
free(longOpts); //free the long options array
|
||||||
long_i = 1; //re-use long_i as an argument counter
|
long_i = 1; //re-use long_i as an argument counter
|
||||||
while (optind < argc) { //parse all remaining options, ignoring anything unexpected.
|
while (optind < argc) { //parse all remaining options, ignoring anything unexpected.
|
||||||
for (JSON::ObjIter it = vals.ObjBegin(); it != vals.ObjEnd(); it++) {
|
jsonForEach(vals, it) {
|
||||||
if (it->second.isMember("arg_num") && it->second["arg_num"].asInt() == long_i) {
|
if (it->isMember("arg_num") && (*it)["arg_num"].asInt() == long_i) {
|
||||||
it->second["value"].append((std::string)argv[optind]);
|
(*it)["value"].append((std::string)argv[optind]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1207,9 +1207,10 @@ namespace DTSC {
|
||||||
if (meta.isMember("buffer_window")) {
|
if (meta.isMember("buffer_window")) {
|
||||||
bufferWindow = meta["buffer_window"].asInt();
|
bufferWindow = meta["buffer_window"].asInt();
|
||||||
}
|
}
|
||||||
for (JSON::ObjIter it = meta["tracks"].ObjBegin(); it != meta["tracks"].ObjEnd(); it++) {
|
//for (JSON::ObjIter it = meta["tracks"].ObjBegin(); it != meta["tracks"].ObjEnd(); it++) {
|
||||||
if (it->second["trackid"].asInt()) {
|
jsonForEach(meta["tracks"], it) {
|
||||||
tracks[it->second["trackid"].asInt()] = Track(it->second);
|
if ((*it)["trackid"].asInt()) {
|
||||||
|
tracks[(*it)["trackid"].asInt()] = Track((*it));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (meta.isMember("moreheader")) {
|
if (meta.isMember("moreheader")) {
|
||||||
|
|
402
lib/json.cpp
402
lib/json.cpp
|
@ -9,6 +9,140 @@
|
||||||
#include <string.h> //for memcpy
|
#include <string.h> //for memcpy
|
||||||
#include <arpa/inet.h> //for htonl
|
#include <arpa/inet.h> //for htonl
|
||||||
|
|
||||||
|
/// Construct from a root Value to iterate over.
|
||||||
|
JSON::Iter::Iter(Value & root){
|
||||||
|
myType = root.myType;
|
||||||
|
i = 0;
|
||||||
|
r = &root;
|
||||||
|
if (!root.size()){myType = JSON::EMPTY;}
|
||||||
|
if (myType == JSON::ARRAY){
|
||||||
|
aIt = root.arrVal.begin();
|
||||||
|
}
|
||||||
|
if (myType == JSON::OBJECT){
|
||||||
|
oIt = root.objVal.begin();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Dereferences into a Value reference.
|
||||||
|
/// If invalid iterator, returns an empty reference and prints a warning message.
|
||||||
|
JSON::Value & JSON::Iter::operator*() const{
|
||||||
|
if (myType == JSON::ARRAY && aIt != r->arrVal.end()){
|
||||||
|
return **aIt;
|
||||||
|
}
|
||||||
|
if (myType == JSON::OBJECT && oIt != r->objVal.end()){
|
||||||
|
return *(oIt->second);
|
||||||
|
}
|
||||||
|
static JSON::Value error;
|
||||||
|
WARN_MSG("Dereferenced invalid JSON iterator");
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Dereferences into a Value reference.
|
||||||
|
/// If invalid iterator, returns an empty reference and prints a warning message.
|
||||||
|
JSON::Value * JSON::Iter::operator->() const{
|
||||||
|
return &(operator*());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// True if not done iterating.
|
||||||
|
JSON::Iter::operator bool() const{
|
||||||
|
return ((myType == JSON::ARRAY && aIt != r->arrVal.end()) || (myType == JSON::OBJECT && oIt != r->objVal.end()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Go to next iteration.
|
||||||
|
JSON::Iter & JSON::Iter::operator++(){
|
||||||
|
if (*this){
|
||||||
|
++i;
|
||||||
|
if (myType == JSON::ARRAY){
|
||||||
|
++aIt;
|
||||||
|
}
|
||||||
|
if (myType == JSON::OBJECT){
|
||||||
|
++oIt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the name of the current indice.
|
||||||
|
const std::string & JSON::Iter::key() const{
|
||||||
|
if (myType == JSON::OBJECT && *this){
|
||||||
|
return oIt->first;
|
||||||
|
}
|
||||||
|
static const std::string empty;
|
||||||
|
WARN_MSG("Got key from invalid JSON iterator");
|
||||||
|
return empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the number of the current indice.
|
||||||
|
unsigned int JSON::Iter::num() const{
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct from a root Value to iterate over.
|
||||||
|
JSON::ConstIter::ConstIter(const Value & root){
|
||||||
|
myType = root.myType;
|
||||||
|
i = 0;
|
||||||
|
r = &root;
|
||||||
|
if (!root.size()){myType = JSON::EMPTY;}
|
||||||
|
if (myType == JSON::ARRAY){
|
||||||
|
aIt = root.arrVal.begin();
|
||||||
|
}
|
||||||
|
if (myType == JSON::OBJECT){
|
||||||
|
oIt = root.objVal.begin();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Dereferences into a Value reference.
|
||||||
|
/// If invalid iterator, returns an empty reference and prints a warning message.
|
||||||
|
const JSON::Value & JSON::ConstIter::operator*() const{
|
||||||
|
if (myType == JSON::ARRAY && aIt != r->arrVal.end()){
|
||||||
|
return **aIt;
|
||||||
|
}
|
||||||
|
if (myType == JSON::OBJECT && oIt != r->objVal.end()){
|
||||||
|
return *(oIt->second);
|
||||||
|
}
|
||||||
|
static JSON::Value error;
|
||||||
|
WARN_MSG("Dereferenced invalid JSON iterator");
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Dereferences into a Value reference.
|
||||||
|
/// If invalid iterator, returns an empty reference and prints a warning message.
|
||||||
|
const JSON::Value * JSON::ConstIter::operator->() const{
|
||||||
|
return &(operator*());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// True if not done iterating.
|
||||||
|
JSON::ConstIter::operator bool() const{
|
||||||
|
return ((myType == JSON::ARRAY && aIt != r->arrVal.end()) || (myType == JSON::OBJECT && oIt != r->objVal.end()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Go to next iteration.
|
||||||
|
JSON::ConstIter & JSON::ConstIter::operator++(){
|
||||||
|
if (*this){
|
||||||
|
++i;
|
||||||
|
if (myType == JSON::ARRAY){
|
||||||
|
++aIt;
|
||||||
|
}
|
||||||
|
if (myType == JSON::OBJECT){
|
||||||
|
++oIt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the name of the current indice.
|
||||||
|
const std::string & JSON::ConstIter::key() const{
|
||||||
|
if (myType == JSON::OBJECT && *this){
|
||||||
|
return oIt->first;
|
||||||
|
}
|
||||||
|
static const std::string empty;
|
||||||
|
WARN_MSG("Got key from invalid JSON iterator");
|
||||||
|
return empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the number of the current indice.
|
||||||
|
unsigned int JSON::ConstIter::num() const{
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
static inline char c2hex(char c) {
|
static inline char c2hex(char c) {
|
||||||
if (c >= '0' && c <= '9') return c - '0';
|
if (c >= '0' && c <= '9') return c - '0';
|
||||||
if (c >= 'a' && c <= 'f') return c - 'a' + 10;
|
if (c >= 'a' && c <= 'f') return c - 'a' + 10;
|
||||||
|
@ -142,6 +276,16 @@ JSON::Value::Value() {
|
||||||
null();
|
null();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sets this JSON::Value to null
|
||||||
|
JSON::Value::~Value() {
|
||||||
|
null();
|
||||||
|
}
|
||||||
|
|
||||||
|
JSON::Value::Value(const Value & rhs) {
|
||||||
|
null();
|
||||||
|
*this = rhs;
|
||||||
|
}
|
||||||
|
|
||||||
/// Sets this JSON::Value to read from this position in the std::istream
|
/// Sets this JSON::Value to read from this position in the std::istream
|
||||||
JSON::Value::Value(std::istream & fromstream) {
|
JSON::Value::Value(std::istream & fromstream) {
|
||||||
null();
|
null();
|
||||||
|
@ -271,6 +415,16 @@ JSON::Value::Value(long long int val) {
|
||||||
intVal = val;
|
intVal = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sets this JSON::Value to the given integer.
|
||||||
|
JSON::Value::Value(bool val) {
|
||||||
|
myType = BOOL;
|
||||||
|
if (val){
|
||||||
|
intVal = 1;
|
||||||
|
}else{
|
||||||
|
intVal = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Compares a JSON::Value to another for equality.
|
/// Compares a JSON::Value to another for equality.
|
||||||
bool JSON::Value::operator==(const JSON::Value & rhs) const {
|
bool JSON::Value::operator==(const JSON::Value & rhs) const {
|
||||||
if (myType != rhs.myType) return false;
|
if (myType != rhs.myType) return false;
|
||||||
|
@ -285,11 +439,11 @@ bool JSON::Value::operator==(const JSON::Value & rhs) const {
|
||||||
}
|
}
|
||||||
if (myType == OBJECT) {
|
if (myType == OBJECT) {
|
||||||
if (objVal.size() != rhs.objVal.size()) return false;
|
if (objVal.size() != rhs.objVal.size()) return false;
|
||||||
for (std::map<std::string, Value>::const_iterator it = objVal.begin(); it != objVal.end(); ++it) {
|
for (std::map<std::string, Value*>::const_iterator it = objVal.begin(); it != objVal.end(); ++it) {
|
||||||
if (!rhs.isMember(it->first)) {
|
if (!rhs.isMember(it->first)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (it->second != rhs.objVal.find(it->first)->second) {
|
if (*(it->second) != rhs.objVal.find(it->first)->second) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -298,8 +452,8 @@ bool JSON::Value::operator==(const JSON::Value & rhs) const {
|
||||||
if (myType == ARRAY) {
|
if (myType == ARRAY) {
|
||||||
if (arrVal.size() != rhs.arrVal.size()) return false;
|
if (arrVal.size() != rhs.arrVal.size()) return false;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (std::deque<Value>::const_iterator it = arrVal.begin(); it != arrVal.end(); ++it) {
|
for (std::deque<Value*>::const_iterator it = arrVal.begin(); it != arrVal.end(); ++it) {
|
||||||
if (*it != rhs.arrVal[i]) {
|
if (**it != *(rhs.arrVal[i])) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
|
@ -314,6 +468,38 @@ bool JSON::Value::operator!=(const JSON::Value & rhs) const {
|
||||||
return !((*this) == rhs);
|
return !((*this) == rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Completely clears the contents of this value,
|
||||||
|
/// changing its type to NULL in the process.
|
||||||
|
void JSON::Value::null() {
|
||||||
|
shrink(0);
|
||||||
|
strVal.clear();
|
||||||
|
intVal = 0;
|
||||||
|
myType = EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets this JSON::Value to be equal to the given JSON::Value.
|
||||||
|
JSON::Value & JSON::Value::operator=(const JSON::Value & rhs) {
|
||||||
|
null();
|
||||||
|
myType = rhs.myType;
|
||||||
|
if (myType == STRING){
|
||||||
|
strVal = rhs.strVal;
|
||||||
|
}
|
||||||
|
if (myType == BOOL || myType == INTEGER){
|
||||||
|
intVal = rhs.intVal;
|
||||||
|
}
|
||||||
|
if (myType == OBJECT){
|
||||||
|
jsonForEachConst(rhs, i){
|
||||||
|
(*this)[i.key()] = *i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (myType == ARRAY){
|
||||||
|
jsonForEachConst(rhs, i){
|
||||||
|
append(*i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
/// Sets this JSON::Value to the given boolean.
|
/// Sets this JSON::Value to the given boolean.
|
||||||
JSON::Value & JSON::Value::operator=(const bool & rhs) {
|
JSON::Value & JSON::Value::operator=(const bool & rhs) {
|
||||||
null();
|
null();
|
||||||
|
@ -445,7 +631,12 @@ JSON::Value & JSON::Value::operator[](const std::string i) {
|
||||||
null();
|
null();
|
||||||
myType = OBJECT;
|
myType = OBJECT;
|
||||||
}
|
}
|
||||||
return objVal[i];
|
Value * pntr = objVal[i];
|
||||||
|
if (!pntr){
|
||||||
|
objVal[i] = new JSON::Value();
|
||||||
|
pntr = objVal[i];
|
||||||
|
}
|
||||||
|
return *pntr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieves or sets the JSON::Value at this position in the object.
|
/// Retrieves or sets the JSON::Value at this position in the object.
|
||||||
|
@ -455,7 +646,12 @@ JSON::Value & JSON::Value::operator[](const char * i) {
|
||||||
null();
|
null();
|
||||||
myType = OBJECT;
|
myType = OBJECT;
|
||||||
}
|
}
|
||||||
return objVal[i];
|
Value * pntr = objVal[i];
|
||||||
|
if (!pntr){
|
||||||
|
objVal[i] = new JSON::Value();
|
||||||
|
pntr = objVal[i];
|
||||||
|
}
|
||||||
|
return *pntr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieves or sets the JSON::Value at this position in the array.
|
/// Retrieves or sets the JSON::Value at this position in the array.
|
||||||
|
@ -466,27 +662,27 @@ JSON::Value & JSON::Value::operator[](unsigned int i) {
|
||||||
myType = ARRAY;
|
myType = ARRAY;
|
||||||
}
|
}
|
||||||
while (i >= arrVal.size()) {
|
while (i >= arrVal.size()) {
|
||||||
append(JSON::Value());
|
append(new JSON::Value());
|
||||||
}
|
}
|
||||||
return arrVal[i];
|
return *arrVal[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieves the JSON::Value at this position in the object.
|
/// Retrieves the JSON::Value at this position in the object.
|
||||||
/// Fails horribly if that values does not exist.
|
/// Fails horribly if that values does not exist.
|
||||||
const JSON::Value & JSON::Value::operator[](const std::string i) const {
|
const JSON::Value & JSON::Value::operator[](const std::string i) const {
|
||||||
return objVal.find(i)->second;
|
return *objVal.find(i)->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieves the JSON::Value at this position in the object.
|
/// Retrieves the JSON::Value at this position in the object.
|
||||||
/// Fails horribly if that values does not exist.
|
/// Fails horribly if that values does not exist.
|
||||||
const JSON::Value & JSON::Value::operator[](const char * i) const {
|
const JSON::Value & JSON::Value::operator[](const char * i) const {
|
||||||
return objVal.find(i)->second;
|
return *objVal.find(i)->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieves the JSON::Value at this position in the array.
|
/// Retrieves the JSON::Value at this position in the array.
|
||||||
/// Fails horribly if that values does not exist.
|
/// Fails horribly if that values does not exist.
|
||||||
const JSON::Value & JSON::Value::operator[](unsigned int i) const {
|
const JSON::Value & JSON::Value::operator[](unsigned int i) const {
|
||||||
return arrVal[i];
|
return *arrVal[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Packs to a std::string for transfer over the network.
|
/// Packs to a std::string for transfer over the network.
|
||||||
|
@ -517,12 +713,12 @@ std::string JSON::Value::toPacked() const {
|
||||||
if (isObject()) {
|
if (isObject()) {
|
||||||
r += 0xE0;
|
r += 0xE0;
|
||||||
if (objVal.size() > 0) {
|
if (objVal.size() > 0) {
|
||||||
for (JSON::ObjConstIter it = objVal.begin(); it != objVal.end(); it++) {
|
jsonForEachConst(*this, i){
|
||||||
if (it->first.size() > 0) {
|
if (i.key().size() > 0) {
|
||||||
r += it->first.size() / 256;
|
r += i.key().size() / 256;
|
||||||
r += it->first.size() % 256;
|
r += i.key().size() % 256;
|
||||||
r += it->first;
|
r += i.key();
|
||||||
r += it->second.toPacked();
|
r += i->toPacked();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -532,8 +728,8 @@ std::string JSON::Value::toPacked() const {
|
||||||
}
|
}
|
||||||
if (isArray()) {
|
if (isArray()) {
|
||||||
r += 0x0A;
|
r += 0x0A;
|
||||||
for (JSON::ArrConstIter it = arrVal.begin(); it != arrVal.end(); it++) {
|
jsonForEachConst(*this, i){
|
||||||
r += it->toPacked();
|
r += i->toPacked();
|
||||||
}
|
}
|
||||||
r += (char)0x0;
|
r += (char)0x0;
|
||||||
r += (char)0x0;
|
r += (char)0x0;
|
||||||
|
@ -563,13 +759,13 @@ void JSON::Value::sendTo(Socket::Connection & socket) const {
|
||||||
}
|
}
|
||||||
if (isObject()) {
|
if (isObject()) {
|
||||||
if (isMember("trackid") && isMember("time")) {
|
if (isMember("trackid") && isMember("time")) {
|
||||||
unsigned int trackid = objVal.find("trackid")->second.asInt();
|
unsigned int trackid = objVal.find("trackid")->second->asInt();
|
||||||
long long time = objVal.find("time")->second.asInt();
|
long long time = objVal.find("time")->second->asInt();
|
||||||
unsigned int size = 16;
|
unsigned int size = 16;
|
||||||
if (objVal.size() > 0) {
|
if (objVal.size() > 0) {
|
||||||
for (JSON::ObjConstIter it = objVal.begin(); it != objVal.end(); it++) {
|
jsonForEachConst(*this, i){
|
||||||
if (it->first.size() > 0 && it->first != "trackid" && it->first != "time" && it->first != "datatype") {
|
if (i.key().size() > 0 && i.key() != "trackid" && i.key() != "time" && i.key() != "datatype") {
|
||||||
size += 2 + it->first.size() + it->second.packedSize();
|
size += 2 + i.key().size() + i->packedSize();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -584,14 +780,14 @@ void JSON::Value::sendTo(Socket::Connection & socket) const {
|
||||||
socket.SendNow((char *)&tmpHalf, 4);
|
socket.SendNow((char *)&tmpHalf, 4);
|
||||||
socket.SendNow("\340", 1);
|
socket.SendNow("\340", 1);
|
||||||
if (objVal.size() > 0) {
|
if (objVal.size() > 0) {
|
||||||
for (JSON::ObjConstIter it = objVal.begin(); it != objVal.end(); it++) {
|
jsonForEachConst(*this, i){
|
||||||
if (it->first.size() > 0 && it->first != "trackid" && it->first != "time" && it->first != "datatype") {
|
if (i.key().size() > 0 && i.key() != "trackid" && i.key() != "time" && i.key() != "datatype") {
|
||||||
char sizebuffer[2] = {0, 0};
|
char sizebuffer[2] = {0, 0};
|
||||||
sizebuffer[0] = (it->first.size() >> 8) & 0xFF;
|
sizebuffer[0] = (i.key().size() >> 8) & 0xFF;
|
||||||
sizebuffer[1] = it->first.size() & 0xFF;
|
sizebuffer[1] = i.key().size() & 0xFF;
|
||||||
socket.SendNow(sizebuffer, 2);
|
socket.SendNow(sizebuffer, 2);
|
||||||
socket.SendNow(it->first);
|
socket.SendNow(i.key());
|
||||||
it->second.sendTo(socket);
|
i->sendTo(socket);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -605,14 +801,14 @@ void JSON::Value::sendTo(Socket::Connection & socket) const {
|
||||||
}
|
}
|
||||||
socket.SendNow("\340", 1);
|
socket.SendNow("\340", 1);
|
||||||
if (objVal.size() > 0) {
|
if (objVal.size() > 0) {
|
||||||
for (JSON::ObjConstIter it = objVal.begin(); it != objVal.end(); it++) {
|
jsonForEachConst(*this, i){
|
||||||
if (it->first.size() > 0) {
|
if (i.key().size() > 0) {
|
||||||
char sizebuffer[2] = {0, 0};
|
char sizebuffer[2] = {0, 0};
|
||||||
sizebuffer[0] = (it->first.size() >> 8) & 0xFF;
|
sizebuffer[0] = (i.key().size() >> 8) & 0xFF;
|
||||||
sizebuffer[1] = it->first.size() & 0xFF;
|
sizebuffer[1] = i.key().size() & 0xFF;
|
||||||
socket.SendNow(sizebuffer, 2);
|
socket.SendNow(sizebuffer, 2);
|
||||||
socket.SendNow(it->first);
|
socket.SendNow(i.key());
|
||||||
it->second.sendTo(socket);
|
i->sendTo(socket);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -621,8 +817,8 @@ void JSON::Value::sendTo(Socket::Connection & socket) const {
|
||||||
}
|
}
|
||||||
if (isArray()) {
|
if (isArray()) {
|
||||||
socket.SendNow("\012", 1);
|
socket.SendNow("\012", 1);
|
||||||
for (JSON::ArrConstIter it = arrVal.begin(); it != arrVal.end(); it++) {
|
jsonForEachConst(*this, i){
|
||||||
it->sendTo(socket);
|
i->sendTo(socket);
|
||||||
}
|
}
|
||||||
socket.SendNow("\000\000\356", 3);
|
socket.SendNow("\000\000\356", 3);
|
||||||
return;
|
return;
|
||||||
|
@ -640,9 +836,9 @@ unsigned int JSON::Value::packedSize() const {
|
||||||
if (isObject()) {
|
if (isObject()) {
|
||||||
unsigned int ret = 4;
|
unsigned int ret = 4;
|
||||||
if (objVal.size() > 0) {
|
if (objVal.size() > 0) {
|
||||||
for (JSON::ObjConstIter it = objVal.begin(); it != objVal.end(); it++) {
|
jsonForEachConst(*this, i){
|
||||||
if (it->first.size() > 0) {
|
if (i.key().size() > 0) {
|
||||||
ret += 2 + it->first.size() + it->second.packedSize();
|
ret += 2 + i.key().size() + i->packedSize();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -650,8 +846,8 @@ unsigned int JSON::Value::packedSize() const {
|
||||||
}
|
}
|
||||||
if (isArray()) {
|
if (isArray()) {
|
||||||
unsigned int ret = 4;
|
unsigned int ret = 4;
|
||||||
for (JSON::ArrConstIter it = arrVal.begin(); it != arrVal.end(); it++) {
|
jsonForEachConst(*this, i){
|
||||||
ret += it->packedSize();
|
ret += i->packedSize();
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -669,20 +865,20 @@ void JSON::Value::netPrepare() {
|
||||||
std::string packed = toPacked();
|
std::string packed = toPacked();
|
||||||
//insert proper header for this type of data
|
//insert proper header for this type of data
|
||||||
int packID = -1;
|
int packID = -1;
|
||||||
long long unsigned int time = objVal["time"].asInt();
|
long long unsigned int time = (*this)["time"].asInt();
|
||||||
std::string dataType;
|
std::string dataType;
|
||||||
if (isMember("datatype") || isMember("trackid")) {
|
if (isMember("datatype") || isMember("trackid")) {
|
||||||
dataType = objVal["datatype"].asString();
|
dataType = (*this)["datatype"].asString();
|
||||||
if (isMember("trackid")) {
|
if (isMember("trackid")) {
|
||||||
packID = objVal["trackid"].asInt();
|
packID = (*this)["trackid"].asInt();
|
||||||
} else {
|
} else {
|
||||||
if (objVal["datatype"].asString() == "video") {
|
if ((*this)["datatype"].asString() == "video") {
|
||||||
packID = 1;
|
packID = 1;
|
||||||
}
|
}
|
||||||
if (objVal["datatype"].asString() == "audio") {
|
if ((*this)["datatype"].asString() == "audio") {
|
||||||
packID = 2;
|
packID = 2;
|
||||||
}
|
}
|
||||||
if (objVal["datatype"].asString() == "meta") {
|
if ((*this)["datatype"].asString() == "meta") {
|
||||||
packID = 3;
|
packID = 3;
|
||||||
}
|
}
|
||||||
//endmark and the likes...
|
//endmark and the likes...
|
||||||
|
@ -696,9 +892,9 @@ void JSON::Value::netPrepare() {
|
||||||
}
|
}
|
||||||
removeMember("trackid");
|
removeMember("trackid");
|
||||||
packed = toPacked();
|
packed = toPacked();
|
||||||
objVal["time"] = (long long int)time;
|
(*this)["time"] = (long long int)time;
|
||||||
objVal["datatype"] = dataType;
|
(*this)["datatype"] = dataType;
|
||||||
objVal["trackid"] = packID;
|
(*this)["trackid"] = packID;
|
||||||
strVal.resize(packed.size() + 20);
|
strVal.resize(packed.size() + 20);
|
||||||
memcpy((void *)strVal.c_str(), "DTP2", 4);
|
memcpy((void *)strVal.c_str(), "DTP2", 4);
|
||||||
} else {
|
} else {
|
||||||
|
@ -771,9 +967,9 @@ std::string JSON::Value::toString() const {
|
||||||
case ARRAY: {
|
case ARRAY: {
|
||||||
std::string tmp = "[";
|
std::string tmp = "[";
|
||||||
if (arrVal.size() > 0) {
|
if (arrVal.size() > 0) {
|
||||||
for (ArrConstIter it = ArrBegin(); it != ArrEnd(); it++) {
|
jsonForEachConst(*this, i){
|
||||||
tmp += it->toString();
|
tmp += i->toString();
|
||||||
if (it + 1 != ArrEnd()) {
|
if (i.num()+1 != arrVal.size()) {
|
||||||
tmp += ",";
|
tmp += ",";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -785,12 +981,10 @@ std::string JSON::Value::toString() const {
|
||||||
case OBJECT: {
|
case OBJECT: {
|
||||||
std::string tmp2 = "{";
|
std::string tmp2 = "{";
|
||||||
if (objVal.size() > 0) {
|
if (objVal.size() > 0) {
|
||||||
ObjConstIter it3 = ObjEnd();
|
jsonForEachConst(*this, i){
|
||||||
--it3;
|
tmp2 += string_escape(i.key()) + ":";
|
||||||
for (ObjConstIter it2 = ObjBegin(); it2 != ObjEnd(); it2++) {
|
tmp2 += i->toString();
|
||||||
tmp2 += string_escape(it2->first) + ":";
|
if (i.num()+1 != objVal.size()) {
|
||||||
tmp2 += it2->second.toString();
|
|
||||||
if (it2 != it3) {
|
|
||||||
tmp2 += ",";
|
tmp2 += ",";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -828,9 +1022,9 @@ std::string JSON::Value::toPrettyString(int indentation) const {
|
||||||
case ARRAY: {
|
case ARRAY: {
|
||||||
if (arrVal.size() > 0) {
|
if (arrVal.size() > 0) {
|
||||||
std::string tmp = "[\n" + std::string(indentation + 2, ' ');
|
std::string tmp = "[\n" + std::string(indentation + 2, ' ');
|
||||||
for (ArrConstIter it = ArrBegin(); it != ArrEnd(); it++) {
|
jsonForEachConst(*this, i){
|
||||||
tmp += it->toPrettyString(indentation + 2);
|
tmp += i->toPrettyString(indentation + 2);
|
||||||
if (it + 1 != ArrEnd()) {
|
if (i.num() + 1 != arrVal.size()) {
|
||||||
tmp += ", ";
|
tmp += ", ";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -848,12 +1042,10 @@ std::string JSON::Value::toPrettyString(int indentation) const {
|
||||||
shortMode = true;
|
shortMode = true;
|
||||||
}
|
}
|
||||||
std::string tmp2 = "{" + std::string((shortMode ? "" : "\n"));
|
std::string tmp2 = "{" + std::string((shortMode ? "" : "\n"));
|
||||||
ObjConstIter it3 = ObjEnd();
|
jsonForEachConst(*this, i){
|
||||||
--it3;
|
tmp2 += (shortMode ? std::string("") : std::string(indentation + 2, ' ')) + string_escape(i.key()) + ":";
|
||||||
for (ObjConstIter it2 = ObjBegin(); it2 != ObjEnd(); it2++) {
|
tmp2 += i->toPrettyString(indentation + 2);
|
||||||
tmp2 += (shortMode ? std::string("") : std::string(indentation + 2, ' ')) + string_escape(it2->first) + ":";
|
if (i.num() + 1 != objVal.size()) {
|
||||||
tmp2 += it2->second.toPrettyString(indentation + 2);
|
|
||||||
if (it2 != it3) {
|
|
||||||
tmp2 += "," + std::string((shortMode ? " " : "\n"));
|
tmp2 += "," + std::string((shortMode ? " " : "\n"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -878,7 +1070,7 @@ void JSON::Value::append(const JSON::Value & rhs) {
|
||||||
null();
|
null();
|
||||||
myType = ARRAY;
|
myType = ARRAY;
|
||||||
}
|
}
|
||||||
arrVal.push_back(rhs);
|
arrVal.push_back(new JSON::Value(rhs));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Prepends the given value to the beginning of this JSON::Value array.
|
/// Prepends the given value to the beginning of this JSON::Value array.
|
||||||
|
@ -888,7 +1080,7 @@ void JSON::Value::prepend(const JSON::Value & rhs) {
|
||||||
null();
|
null();
|
||||||
myType = ARRAY;
|
myType = ARRAY;
|
||||||
}
|
}
|
||||||
arrVal.push_front(rhs);
|
arrVal.push_front(new JSON::Value(rhs));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// For array and object JSON::Value objects, reduces them
|
/// For array and object JSON::Value objects, reduces them
|
||||||
|
@ -898,25 +1090,24 @@ void JSON::Value::prepend(const JSON::Value & rhs) {
|
||||||
/// do anything if the size is already lower or equal to the
|
/// do anything if the size is already lower or equal to the
|
||||||
/// given size.
|
/// given size.
|
||||||
void JSON::Value::shrink(unsigned int size) {
|
void JSON::Value::shrink(unsigned int size) {
|
||||||
if (myType == ARRAY) {
|
|
||||||
while (arrVal.size() > size) {
|
while (arrVal.size() > size) {
|
||||||
|
delete arrVal.front();
|
||||||
arrVal.pop_front();
|
arrVal.pop_front();
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (myType == OBJECT) {
|
|
||||||
while (objVal.size() > size) {
|
while (objVal.size() > size) {
|
||||||
|
delete objVal.begin()->second;
|
||||||
objVal.erase(objVal.begin());
|
objVal.erase(objVal.begin());
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// For object JSON::Value objects, removes the member with
|
/// For object JSON::Value objects, removes the member with
|
||||||
/// the given name, if it exists. Has no effect otherwise.
|
/// the given name, if it exists. Has no effect otherwise.
|
||||||
void JSON::Value::removeMember(const std::string & name) {
|
void JSON::Value::removeMember(const std::string & name) {
|
||||||
|
if (objVal.count(name)){
|
||||||
|
delete objVal[name];
|
||||||
objVal.erase(name);
|
objVal.erase(name);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// For object JSON::Value objects, returns true if the
|
/// For object JSON::Value objects, returns true if the
|
||||||
/// given name is a member. Returns false otherwise.
|
/// given name is a member. Returns false otherwise.
|
||||||
|
@ -954,61 +1145,11 @@ bool JSON::Value::isNull() const {
|
||||||
return (myType == EMPTY);
|
return (myType == EMPTY);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns an iterator to the begin of the object map, if any.
|
|
||||||
JSON::ObjIter JSON::Value::ObjBegin() {
|
|
||||||
return objVal.begin();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns an iterator to the end of the object map, if any.
|
|
||||||
JSON::ObjIter JSON::Value::ObjEnd() {
|
|
||||||
return objVal.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns an iterator to the begin of the array, if any.
|
|
||||||
JSON::ArrIter JSON::Value::ArrBegin() {
|
|
||||||
return arrVal.begin();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns an iterator to the end of the array, if any.
|
|
||||||
JSON::ArrIter JSON::Value::ArrEnd() {
|
|
||||||
return arrVal.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns an iterator to the begin of the object map, if any.
|
|
||||||
JSON::ObjConstIter JSON::Value::ObjBegin() const {
|
|
||||||
return objVal.begin();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns an iterator to the end of the object map, if any.
|
|
||||||
JSON::ObjConstIter JSON::Value::ObjEnd() const {
|
|
||||||
return objVal.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns an iterator to the begin of the array, if any.
|
|
||||||
JSON::ArrConstIter JSON::Value::ArrBegin() const {
|
|
||||||
return arrVal.begin();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns an iterator to the end of the array, if any.
|
|
||||||
JSON::ArrConstIter JSON::Value::ArrEnd() const {
|
|
||||||
return arrVal.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the total of the objects and array size combined.
|
/// Returns the total of the objects and array size combined.
|
||||||
unsigned int JSON::Value::size() const {
|
unsigned int JSON::Value::size() const {
|
||||||
return objVal.size() + arrVal.size();
|
return objVal.size() + arrVal.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Completely clears the contents of this value,
|
|
||||||
/// changing its type to NULL in the process.
|
|
||||||
void JSON::Value::null() {
|
|
||||||
objVal.clear();
|
|
||||||
arrVal.clear();
|
|
||||||
strVal.clear();
|
|
||||||
intVal = 0;
|
|
||||||
myType = EMPTY;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Converts a std::string to a JSON::Value.
|
/// Converts a std::string to a JSON::Value.
|
||||||
JSON::Value JSON::fromString(std::string json) {
|
JSON::Value JSON::fromString(std::string json) {
|
||||||
std::istringstream is(json);
|
std::istringstream is(json);
|
||||||
|
@ -1101,8 +1242,9 @@ void JSON::fromDTMI(const unsigned char * data, unsigned int len, unsigned int &
|
||||||
case 0x0A: { //array
|
case 0x0A: { //array
|
||||||
++i;
|
++i;
|
||||||
while (data[i] + data[i + 1] != 0 && i < len) { //while not encountering 0x0000 (we assume 0x0000EE)
|
while (data[i] + data[i + 1] != 0 && i < len) { //while not encountering 0x0000 (we assume 0x0000EE)
|
||||||
ret.append(JSON::Value());
|
JSON::Value tval;
|
||||||
fromDTMI(data, len, i, *--ret.ArrEnd()); //add content, recursively parsed, updating i
|
fromDTMI(data, len, i, tval); //add content, recursively parsed, updating i
|
||||||
|
ret.append(tval);
|
||||||
}
|
}
|
||||||
i += 3; //skip 0x0000EE
|
i += 3; //skip 0x0000EE
|
||||||
return;
|
return;
|
||||||
|
|
61
lib/json.h
61
lib/json.h
|
@ -21,27 +21,24 @@ namespace JSON {
|
||||||
EMPTY, BOOL, INTEGER, STRING, ARRAY, OBJECT
|
EMPTY, BOOL, INTEGER, STRING, ARRAY, OBJECT
|
||||||
};
|
};
|
||||||
|
|
||||||
class Value;
|
|
||||||
//forward declaration for below typedef
|
|
||||||
|
|
||||||
typedef std::map<std::string, Value>::iterator ObjIter;
|
|
||||||
typedef std::deque<Value>::iterator ArrIter;
|
|
||||||
typedef std::map<std::string, Value>::const_iterator ObjConstIter;
|
|
||||||
typedef std::deque<Value>::const_iterator ArrConstIter;
|
|
||||||
|
|
||||||
/// A JSON::Value is either a string or an integer, but may also be an object, array or null.
|
/// A JSON::Value is either a string or an integer, but may also be an object, array or null.
|
||||||
class Value {
|
class Value {
|
||||||
|
friend class Iter;
|
||||||
|
friend class ConstIter;
|
||||||
private:
|
private:
|
||||||
ValueType myType;
|
ValueType myType;
|
||||||
long long int intVal;
|
long long int intVal;
|
||||||
std::string strVal;
|
std::string strVal;
|
||||||
std::deque<Value> arrVal;
|
std::deque<Value*> arrVal;
|
||||||
std::map<std::string, Value> objVal;
|
std::map<std::string, Value*> objVal;
|
||||||
public:
|
public:
|
||||||
//friends
|
//friends
|
||||||
friend class DTSC::Stream; //for access to strVal
|
friend class DTSC::Stream; //for access to strVal
|
||||||
//constructors
|
//constructors/destructors
|
||||||
Value();
|
Value();
|
||||||
|
~Value();
|
||||||
|
Value(const Value & rhs);
|
||||||
Value(std::istream & fromstream);
|
Value(std::istream & fromstream);
|
||||||
Value(const std::string & val);
|
Value(const std::string & val);
|
||||||
Value(const char * val);
|
Value(const char * val);
|
||||||
|
@ -51,6 +48,7 @@ namespace JSON {
|
||||||
bool operator==(const Value & rhs) const;
|
bool operator==(const Value & rhs) const;
|
||||||
bool operator!=(const Value & rhs) const;
|
bool operator!=(const Value & rhs) const;
|
||||||
//assignment operators
|
//assignment operators
|
||||||
|
Value & operator=(const Value & rhs);
|
||||||
Value & operator=(const std::string & rhs);
|
Value & operator=(const std::string & rhs);
|
||||||
Value & operator=(const char * rhs);
|
Value & operator=(const char * rhs);
|
||||||
Value & operator=(const long long int & rhs);
|
Value & operator=(const long long int & rhs);
|
||||||
|
@ -92,14 +90,6 @@ namespace JSON {
|
||||||
bool isObject() const;
|
bool isObject() const;
|
||||||
bool isArray() const;
|
bool isArray() const;
|
||||||
bool isNull() const;
|
bool isNull() const;
|
||||||
ObjIter ObjBegin();
|
|
||||||
ObjIter ObjEnd();
|
|
||||||
ArrIter ArrBegin();
|
|
||||||
ArrIter ArrEnd();
|
|
||||||
ObjConstIter ObjBegin() const;
|
|
||||||
ObjConstIter ObjEnd() const;
|
|
||||||
ArrConstIter ArrBegin() const;
|
|
||||||
ArrConstIter ArrEnd() const;
|
|
||||||
unsigned int size() const;
|
unsigned int size() const;
|
||||||
void null();
|
void null();
|
||||||
};
|
};
|
||||||
|
@ -115,6 +105,41 @@ namespace JSON {
|
||||||
void fromDTMI(std::string & data, Value & ret);
|
void fromDTMI(std::string & data, Value & ret);
|
||||||
void fromDTMI(const unsigned char * data, unsigned int len, unsigned int & i, Value & ret);
|
void fromDTMI(const unsigned char * data, unsigned int len, unsigned int & i, Value & ret);
|
||||||
|
|
||||||
|
class Iter {
|
||||||
|
public:
|
||||||
|
Iter(Value & root);///<Construct from a root Value to iterate over.
|
||||||
|
Value & operator*() const;///< Dereferences into a Value reference.
|
||||||
|
Value* operator->() const;///< Dereferences into a Value reference.
|
||||||
|
operator bool() const;///< True if not done iterating.
|
||||||
|
Iter & operator++();///<Go to next iteration.
|
||||||
|
const std::string & key() const;///<Return the name of the current indice.
|
||||||
|
unsigned int num() const;///<Return the number of the current indice.
|
||||||
|
private:
|
||||||
|
ValueType myType;
|
||||||
|
Value * r;
|
||||||
|
unsigned int i;
|
||||||
|
std::deque<Value*>::iterator aIt;
|
||||||
|
std::map<std::string, Value*>::iterator oIt;
|
||||||
|
};
|
||||||
|
class ConstIter {
|
||||||
|
public:
|
||||||
|
ConstIter(const Value & root);///<Construct from a root Value to iterate over.
|
||||||
|
const Value & operator*() const;///< Dereferences into a Value reference.
|
||||||
|
const Value* operator->() const;///< Dereferences into a Value reference.
|
||||||
|
operator bool() const;///< True if not done iterating.
|
||||||
|
ConstIter & operator++();///<Go to next iteration.
|
||||||
|
const std::string & key() const;///<Return the name of the current indice.
|
||||||
|
unsigned int num() const;///<Return the number of the current indice.
|
||||||
|
private:
|
||||||
|
ValueType myType;
|
||||||
|
const Value * r;
|
||||||
|
unsigned int i;
|
||||||
|
std::deque<Value*>::const_iterator aIt;
|
||||||
|
std::map<std::string, Value*>::const_iterator oIt;
|
||||||
|
};
|
||||||
|
#define jsonForEach(val, i) for(JSON::Iter i(val); i; ++i)
|
||||||
|
#define jsonForEachConst(val, i) for(JSON::ConstIter i(val); i; ++i)
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
std::string encodeVector(T begin, T end) {
|
std::string encodeVector(T begin, T end) {
|
||||||
std::string result;
|
std::string result;
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include "shared_memory.h"
|
#include "shared_memory.h"
|
||||||
#include "stream.h"
|
#include "stream.h"
|
||||||
#include "procs.h"
|
#include "procs.h"
|
||||||
|
#include "timing.h"
|
||||||
|
|
||||||
namespace IPC {
|
namespace IPC {
|
||||||
|
|
||||||
|
@ -205,6 +206,18 @@ namespace IPC {
|
||||||
WARN_MSG("Consistency error caught on semaphore %s", myName.c_str());
|
WARN_MSG("Consistency error caught on semaphore %s", myName.c_str());
|
||||||
result = 0;
|
result = 0;
|
||||||
}
|
}
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
/// \todo (roxlu) test tryWaitOneSecond, shared_memory.cpp
|
||||||
|
long long unsigned int now = Util::getMicros();
|
||||||
|
long long unsigned int timeout = now + 1e6;
|
||||||
|
while (now < timeout) {
|
||||||
|
if (0 == sem_trywait(mySem)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
usleep(100e3);
|
||||||
|
now = Util::getMicros();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
#else
|
#else
|
||||||
struct timespec wt;
|
struct timespec wt;
|
||||||
wt.tv_sec = 1;
|
wt.tv_sec = 1;
|
||||||
|
|
|
@ -228,10 +228,10 @@ int main(int argc, char ** argv){
|
||||||
std::getline(std::cin, in_string);
|
std::getline(std::cin, in_string);
|
||||||
if (yna(in_string) == 'y'){
|
if (yna(in_string) == 'y'){
|
||||||
//create protocols
|
//create protocols
|
||||||
for (JSON::ObjIter it = Controller::capabilities["connectors"].ObjBegin(); it != Controller::capabilities["connectors"].ObjEnd(); it++){
|
jsonForEach(Controller::capabilities["connectors"], it) {
|
||||||
if ( !it->second.isMember("required")){
|
if (!it->isMember("required")){
|
||||||
JSON::Value newProtocol;
|
JSON::Value newProtocol;
|
||||||
newProtocol["connector"] = it->first;
|
newProtocol["connector"] = it.key();
|
||||||
Controller::Storage["config"]["protocols"].append(newProtocol);
|
Controller::Storage["config"]["protocols"].append(newProtocol);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -282,8 +282,8 @@ int main(int argc, char ** argv){
|
||||||
std::cerr << "Error writing config " << Controller::conf.getString("configFile") << std::endl;
|
std::cerr << "Error writing config " << Controller::conf.getString("configFile") << std::endl;
|
||||||
tthread::lock_guard<tthread::mutex> guard(Controller::logMutex);
|
tthread::lock_guard<tthread::mutex> guard(Controller::logMutex);
|
||||||
Controller::Storage.removeMember("log");
|
Controller::Storage.removeMember("log");
|
||||||
for (JSON::ObjIter it = Controller::Storage["streams"].ObjBegin(); it != Controller::Storage["streams"].ObjEnd(); it++){
|
jsonForEach(Controller::Storage["streams"], it) {
|
||||||
it->second.removeMember("meta");
|
it->removeMember("meta");
|
||||||
}
|
}
|
||||||
std::cerr << "**Config**" << std::endl;
|
std::cerr << "**Config**" << std::endl;
|
||||||
std::cerr << Controller::Storage.toString() << std::endl;
|
std::cerr << Controller::Storage.toString() << std::endl;
|
||||||
|
|
|
@ -32,27 +32,20 @@ namespace Controller {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void builPipedPart(JSON::Value & p, char * argarr[], int & argnum, JSON::Value & argset){
|
static inline void builPipedPart(JSON::Value & p, char * argarr[], int & argnum, const JSON::Value & argset){
|
||||||
for (JSON::ObjIter it = argset.ObjBegin(); it != argset.ObjEnd(); ++it){
|
jsonForEachConst(argset, it) {
|
||||||
if (it->second.isMember("option")){
|
if (it->isMember("option")){
|
||||||
if (p.isMember(it->first)){
|
if (p.isMember(it.key())){
|
||||||
if (it->second.isMember("type")){
|
p[it.key()] = p[it.key()].asString();
|
||||||
if (it->second["type"].asStringRef() == "str" && !p[it->first].isString()){
|
if (p[it.key()].asStringRef().size() > 0){
|
||||||
p[it->first] = p[it->first].asString();
|
argarr[argnum++] = (char*)((*it)["option"].asStringRef().c_str());
|
||||||
}
|
argarr[argnum++] = (char*)(p[it.key()].asStringRef().c_str());
|
||||||
if ((it->second["type"].asStringRef() == "uint" || it->second["type"].asStringRef() == "int") && !p[it->first].isInt()){
|
|
||||||
p[it->first] = p[it->first].asString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (p[it->first].asStringRef().size() > 0){
|
|
||||||
argarr[argnum++] = (char*)(it->second["option"].c_str());
|
|
||||||
argarr[argnum++] = (char*)(p[it->first].c_str());
|
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
if (it->first == "debug"){
|
if (it.key() == "debug"){
|
||||||
static std::string debugLvlStr;
|
static std::string debugLvlStr;
|
||||||
debugLvlStr = JSON::Value((long long)Util::Config::printDebugLevel).asString();
|
debugLvlStr = JSON::Value((long long)Util::Config::printDebugLevel).asString();
|
||||||
argarr[argnum++] = (char*)(it->second["option"].c_str());
|
argarr[argnum++] = (char*)((*it)["option"].asStringRef().c_str());
|
||||||
argarr[argnum++] = (char*)debugLvlStr.c_str();
|
argarr[argnum++] = (char*)debugLvlStr.c_str();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -60,8 +53,7 @@ namespace Controller {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void buildPipedArguments(const std::string & proto, char * argarr[], JSON::Value & capabilities){
|
static inline void buildPipedArguments(JSON::Value & p, char * argarr[], const JSON::Value & capabilities){
|
||||||
JSON::Value p = JSON::fromString(proto);
|
|
||||||
int argnum = 0;
|
int argnum = 0;
|
||||||
static std::string tmparg;
|
static std::string tmparg;
|
||||||
tmparg = Util::getMyPath() + std::string("MistOut") + p["connector"].asStringRef();
|
tmparg = Util::getMyPath() + std::string("MistOut") + p["connector"].asStringRef();
|
||||||
|
@ -73,7 +65,7 @@ namespace Controller {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
argarr[argnum++] = (char*)tmparg.c_str();
|
argarr[argnum++] = (char*)tmparg.c_str();
|
||||||
JSON::Value & pipedCapa = capabilities["connectors"][p["connector"].asStringRef()];
|
const JSON::Value & pipedCapa = capabilities["connectors"][p["connector"].asStringRef()];
|
||||||
if (pipedCapa.isMember("required")){builPipedPart(p, argarr, argnum, pipedCapa["required"]);}
|
if (pipedCapa.isMember("required")){builPipedPart(p, argarr, argnum, pipedCapa["required"]);}
|
||||||
if (pipedCapa.isMember("optional")){builPipedPart(p, argarr, argnum, pipedCapa["optional"]);}
|
if (pipedCapa.isMember("optional")){builPipedPart(p, argarr, argnum, pipedCapa["optional"]);}
|
||||||
}
|
}
|
||||||
|
@ -82,7 +74,7 @@ namespace Controller {
|
||||||
///\param p An object containing all protocols.
|
///\param p An object containing all protocols.
|
||||||
///\param capabilities An object containing the detected capabilities.
|
///\param capabilities An object containing the detected capabilities.
|
||||||
///\returns True if any action was taken
|
///\returns True if any action was taken
|
||||||
bool CheckProtocols(JSON::Value & p, JSON::Value & capabilities){
|
bool CheckProtocols(JSON::Value & p, const JSON::Value & capabilities){
|
||||||
std::set<std::string> runningConns;
|
std::set<std::string> runningConns;
|
||||||
|
|
||||||
// used for building args
|
// used for building args
|
||||||
|
@ -93,10 +85,8 @@ namespace Controller {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
std::string tmp;
|
std::string tmp;
|
||||||
long long counter = 0;
|
|
||||||
|
|
||||||
for (JSON::ArrIter ait = p.ArrBegin(); ait != p.ArrEnd(); ait++){
|
jsonForEach(p, ait) {
|
||||||
counter = ait - p.ArrBegin();
|
|
||||||
std::string prevOnline = (*ait)["online"].asString();
|
std::string prevOnline = (*ait)["online"].asString();
|
||||||
const std::string & connName = (*ait)["connector"].asStringRef();
|
const std::string & connName = (*ait)["connector"].asStringRef();
|
||||||
//do not further parse if there's no connector name
|
//do not further parse if there's no connector name
|
||||||
|
@ -113,7 +103,7 @@ namespace Controller {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
//list connectors that go through HTTP as 'enabled' without actually running them.
|
//list connectors that go through HTTP as 'enabled' without actually running them.
|
||||||
JSON::Value & connCapa = capabilities["connectors"][connName];
|
const JSON::Value & connCapa = capabilities["connectors"][connName];
|
||||||
if (connCapa.isMember("socket") || (connCapa.isMember("deps") && connCapa["deps"].asStringRef() == "HTTP")){
|
if (connCapa.isMember("socket") || (connCapa.isMember("deps") && connCapa["deps"].asStringRef() == "HTTP")){
|
||||||
( *ait)["online"] = "Enabled";
|
( *ait)["online"] = "Enabled";
|
||||||
continue;
|
continue;
|
||||||
|
@ -121,12 +111,12 @@ namespace Controller {
|
||||||
//check required parameters, skip if anything is missing
|
//check required parameters, skip if anything is missing
|
||||||
if (connCapa.isMember("required")){
|
if (connCapa.isMember("required")){
|
||||||
bool gotAll = true;
|
bool gotAll = true;
|
||||||
for (JSON::ObjIter it = connCapa["required"].ObjBegin(); it != connCapa["required"].ObjEnd(); ++it){
|
jsonForEachConst(connCapa["required"], it) {
|
||||||
if ( !(*ait).isMember(it->first) || (*ait)[it->first].asStringRef().size() < 1){
|
if ( !(*ait).isMember(it.key()) || (*ait)[it.key()].asStringRef().size() < 1){
|
||||||
gotAll = false;
|
gotAll = false;
|
||||||
( *ait)["online"] = "Invalid configuration";
|
( *ait)["online"] = "Invalid configuration";
|
||||||
if (( *ait)["online"].asString() != prevOnline){
|
if (( *ait)["online"].asString() != prevOnline){
|
||||||
Log("WARN", connName + " connector is missing required parameter " + it->first + "! Ignoring connector.");
|
Log("WARN", connName + " connector is missing required parameter " + it.key() + "! Ignoring connector.");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -169,7 +159,8 @@ namespace Controller {
|
||||||
// clear out old args
|
// clear out old args
|
||||||
for (i=0; i<15; i++){argarr[i] = 0;}
|
for (i=0; i<15; i++){argarr[i] = 0;}
|
||||||
// get args for this connector
|
// get args for this connector
|
||||||
buildPipedArguments(*runningConns.begin(), (char **)&argarr, capabilities);
|
JSON::Value p = JSON::fromString(*runningConns.begin());
|
||||||
|
buildPipedArguments(p, (char **)&argarr, capabilities);
|
||||||
// start piped w/ generated args
|
// start piped w/ generated args
|
||||||
currentConnectors[*runningConns.begin()] = Util::Procs::StartPiped(argarr, &zero, &out, &err);
|
currentConnectors[*runningConns.begin()] = Util::Procs::StartPiped(argarr, &zero, &out, &err);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,6 @@ namespace Controller {
|
||||||
void UpdateProtocol(std::string protocol);
|
void UpdateProtocol(std::string protocol);
|
||||||
|
|
||||||
/// Checks current protocol configuration, updates state of enabled connectors if neccesary.
|
/// Checks current protocol configuration, updates state of enabled connectors if neccesary.
|
||||||
bool CheckProtocols(JSON::Value & p, JSON::Value & capabilities);
|
bool CheckProtocols(JSON::Value & p, const JSON::Value & capabilities);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -485,7 +485,7 @@ void Controller::fillClients(JSON::Value & req, JSON::Value & rep){
|
||||||
unsigned int fields = 0;
|
unsigned int fields = 0;
|
||||||
//next, figure out the fields wanted
|
//next, figure out the fields wanted
|
||||||
if (req.isMember("fields") && req["fields"].size()){
|
if (req.isMember("fields") && req["fields"].size()){
|
||||||
for (JSON::ArrIter it = req["fields"].ArrBegin(); it != req["fields"].ArrEnd(); it++){
|
jsonForEach(req["fields"], it) {
|
||||||
if ((*it).asStringRef() == "host"){fields |= STAT_CLI_HOST;}
|
if ((*it).asStringRef() == "host"){fields |= STAT_CLI_HOST;}
|
||||||
if ((*it).asStringRef() == "stream"){fields |= STAT_CLI_STREAM;}
|
if ((*it).asStringRef() == "stream"){fields |= STAT_CLI_STREAM;}
|
||||||
if ((*it).asStringRef() == "protocol"){fields |= STAT_CLI_PROTO;}
|
if ((*it).asStringRef() == "protocol"){fields |= STAT_CLI_PROTO;}
|
||||||
|
@ -502,14 +502,14 @@ void Controller::fillClients(JSON::Value & req, JSON::Value & rep){
|
||||||
//figure out what streams are wanted
|
//figure out what streams are wanted
|
||||||
std::set<std::string> streams;
|
std::set<std::string> streams;
|
||||||
if (req.isMember("streams") && req["streams"].size()){
|
if (req.isMember("streams") && req["streams"].size()){
|
||||||
for (JSON::ArrIter it = req["streams"].ArrBegin(); it != req["streams"].ArrEnd(); it++){
|
jsonForEach(req["streams"], it) {
|
||||||
streams.insert((*it).asStringRef());
|
streams.insert((*it).asStringRef());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//figure out what protocols are wanted
|
//figure out what protocols are wanted
|
||||||
std::set<std::string> protos;
|
std::set<std::string> protos;
|
||||||
if (req.isMember("protocols") && req["protocols"].size()){
|
if (req.isMember("protocols") && req["protocols"].size()){
|
||||||
for (JSON::ArrIter it = req["protocols"].ArrBegin(); it != req["protocols"].ArrEnd(); it++){
|
jsonForEach(req["protocols"], it) {
|
||||||
protos.insert((*it).asStringRef());
|
protos.insert((*it).asStringRef());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -638,7 +638,7 @@ void Controller::fillTotals(JSON::Value & req, JSON::Value & rep){
|
||||||
unsigned int fields = 0;
|
unsigned int fields = 0;
|
||||||
//next, figure out the fields wanted
|
//next, figure out the fields wanted
|
||||||
if (req.isMember("fields") && req["fields"].size()){
|
if (req.isMember("fields") && req["fields"].size()){
|
||||||
for (JSON::ArrIter it = req["fields"].ArrBegin(); it != req["fields"].ArrEnd(); it++){
|
jsonForEach(req["fields"], it) {
|
||||||
if ((*it).asStringRef() == "clients"){fields |= STAT_TOT_CLIENTS;}
|
if ((*it).asStringRef() == "clients"){fields |= STAT_TOT_CLIENTS;}
|
||||||
if ((*it).asStringRef() == "downbps"){fields |= STAT_TOT_BPS_DOWN;}
|
if ((*it).asStringRef() == "downbps"){fields |= STAT_TOT_BPS_DOWN;}
|
||||||
if ((*it).asStringRef() == "upbps"){fields |= STAT_TOT_BPS_UP;}
|
if ((*it).asStringRef() == "upbps"){fields |= STAT_TOT_BPS_UP;}
|
||||||
|
@ -649,14 +649,14 @@ void Controller::fillTotals(JSON::Value & req, JSON::Value & rep){
|
||||||
//figure out what streams are wanted
|
//figure out what streams are wanted
|
||||||
std::set<std::string> streams;
|
std::set<std::string> streams;
|
||||||
if (req.isMember("streams") && req["streams"].size()){
|
if (req.isMember("streams") && req["streams"].size()){
|
||||||
for (JSON::ArrIter it = req["streams"].ArrBegin(); it != req["streams"].ArrEnd(); it++){
|
jsonForEach(req["streams"], it) {
|
||||||
streams.insert((*it).asStringRef());
|
streams.insert((*it).asStringRef());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//figure out what protocols are wanted
|
//figure out what protocols are wanted
|
||||||
std::set<std::string> protos;
|
std::set<std::string> protos;
|
||||||
if (req.isMember("protocols") && req["protocols"].size()){
|
if (req.isMember("protocols") && req["protocols"].size()){
|
||||||
for (JSON::ArrIter it = req["protocols"].ArrBegin(); it != req["protocols"].ArrEnd(); it++){
|
jsonForEach(req["protocols"], it) {
|
||||||
protos.insert((*it).asStringRef());
|
protos.insert((*it).asStringRef());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,25 +94,25 @@ namespace Controller {
|
||||||
///\returns True if the server status changed
|
///\returns True if the server status changed
|
||||||
bool CheckAllStreams(JSON::Value & data){
|
bool CheckAllStreams(JSON::Value & data){
|
||||||
long long int currTime = Util::epoch();
|
long long int currTime = Util::epoch();
|
||||||
for (JSON::ObjIter jit = data.ObjBegin(); jit != data.ObjEnd(); jit++){
|
jsonForEach(data, jit) {
|
||||||
checkStream(jit->first, jit->second);
|
checkStream(jit.key(), (*jit));
|
||||||
if (!jit->second.isMember("name")){
|
if (!jit->isMember("name")){
|
||||||
jit->second["name"] = jit->first;
|
(*jit)["name"] = jit.key();
|
||||||
}
|
}
|
||||||
if (!hasViewers(jit->first)){
|
if (!hasViewers(jit.key())){
|
||||||
if (jit->second.isMember("source") && jit->second["source"].asString().substr(0, 1) == "/" && jit->second.isMember("error")
|
if (jit->isMember("source") && (*jit)["source"].asString().substr(0, 1) == "/" && jit->isMember("error")
|
||||||
&& jit->second["error"].asString().substr(0,15) != "Stream offline:"){
|
&& (*jit)["error"].asString().substr(0,15) != "Stream offline:"){
|
||||||
jit->second["online"] = 2;
|
(*jit)["online"] = 2;
|
||||||
}else{
|
}else{
|
||||||
if (jit->second.isMember("error") && jit->second["error"].asString() == "Available"){
|
if (jit->isMember("error") && (*jit)["error"].asString() == "Available"){
|
||||||
jit->second.removeMember("error");
|
jit->removeMember("error");
|
||||||
}
|
}
|
||||||
jit->second["online"] = 0;
|
(*jit)["online"] = 0;
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
// assume all is fine
|
// assume all is fine
|
||||||
jit->second.removeMember("error");
|
jit->removeMember("error");
|
||||||
jit->second["online"] = 1;
|
(*jit)["online"] = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,17 +128,17 @@ namespace Controller {
|
||||||
|
|
||||||
void AddStreams(JSON::Value & in, JSON::Value & out){
|
void AddStreams(JSON::Value & in, JSON::Value & out){
|
||||||
//check for new streams and updates
|
//check for new streams and updates
|
||||||
for (JSON::ObjIter jit = in.ObjBegin(); jit != in.ObjEnd(); jit++){
|
jsonForEach(in, jit) {
|
||||||
if (out.isMember(jit->first)){
|
if (out.isMember(jit.key())){
|
||||||
if ( !streamsEqual(jit->second, out[jit->first])){
|
if ( !streamsEqual((*jit), out[jit.key()])){
|
||||||
out[jit->first] = jit->second;
|
out[jit.key()] = (*jit);
|
||||||
out[jit->first]["name"] = jit->first;
|
out[jit.key()]["name"] = jit.key();
|
||||||
Log("STRM", std::string("Updated stream ") + jit->first);
|
Log("STRM", std::string("Updated stream ") + jit.key());
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
out[jit->first] = jit->second;
|
out[jit.key()] = (*jit);
|
||||||
out[jit->first]["name"] = jit->first;
|
out[jit.key()]["name"] = (*jit);
|
||||||
Log("STRM", std::string("New stream ") + jit->first);
|
Log("STRM", std::string("New stream ") + jit.key());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -198,10 +198,10 @@ namespace Controller {
|
||||||
|
|
||||||
//check for deleted streams
|
//check for deleted streams
|
||||||
std::set<std::string> toDelete;
|
std::set<std::string> toDelete;
|
||||||
for (JSON::ObjIter jit = out.ObjBegin(); jit != out.ObjEnd(); jit++){
|
jsonForEach(out, jit) {
|
||||||
if ( !in.isMember(jit->first)){
|
if ( !in.isMember(jit.key())){
|
||||||
toDelete.insert(jit->first);
|
toDelete.insert(jit.key());
|
||||||
Log("STRM", std::string("Deleted stream ") + jit->first);
|
Log("STRM", std::string("Deleted stream ") + jit.key());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//actually delete the streams
|
//actually delete the streams
|
||||||
|
@ -212,15 +212,15 @@ namespace Controller {
|
||||||
}
|
}
|
||||||
|
|
||||||
//update old-style configurations to new-style
|
//update old-style configurations to new-style
|
||||||
for (JSON::ObjIter jit = in.ObjBegin(); jit != in.ObjEnd(); jit++){
|
jsonForEach(in, jit) {
|
||||||
if (jit->second.isMember("channel")){
|
if (jit->isMember("channel")){
|
||||||
if ( !jit->second.isMember("source")){
|
if ( !jit->isMember("source")){
|
||||||
jit->second["source"] = jit->second["channel"]["URL"];
|
(*jit)["source"] = (*jit)["channel"]["URL"];
|
||||||
}
|
}
|
||||||
jit->second.removeMember("channel");
|
jit->removeMember("channel");
|
||||||
}
|
}
|
||||||
if (jit->second.isMember("preset")){
|
if (jit->isMember("preset")){
|
||||||
jit->second.removeMember("preset");
|
jit->removeMember("preset");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -158,14 +158,14 @@ namespace Mist {
|
||||||
unsigned int bestSoFar = 0;
|
unsigned int bestSoFar = 0;
|
||||||
unsigned int bestSoFarCount = 0;
|
unsigned int bestSoFarCount = 0;
|
||||||
unsigned int index = 0;
|
unsigned int index = 0;
|
||||||
for (JSON::ArrIter it = capa["codecs"].ArrBegin(); it != capa["codecs"].ArrEnd(); it++){
|
jsonForEach(capa["codecs"], it) {
|
||||||
unsigned int genCounter = 0;
|
unsigned int genCounter = 0;
|
||||||
unsigned int selCounter = 0;
|
unsigned int selCounter = 0;
|
||||||
if ((*it).size() > 0){
|
if ((*it).size() > 0){
|
||||||
for (JSON::ArrIter itb = (*it).ArrBegin(); itb != (*it).ArrEnd(); itb++){
|
jsonForEach((*it), itb) {
|
||||||
if ((*itb).size() > 0){
|
if ((*itb).size() > 0){
|
||||||
bool found = false;
|
bool found = false;
|
||||||
for (JSON::ArrIter itc = (*itb).ArrBegin(); itc != (*itb).ArrEnd() && !found; itc++){
|
jsonForEach(*itb, itc) {
|
||||||
for (std::set<unsigned long>::iterator itd = selectedTracks.begin(); itd != selectedTracks.end(); itd++){
|
for (std::set<unsigned long>::iterator itd = selectedTracks.begin(); itd != selectedTracks.end(); itd++){
|
||||||
if (myMeta.tracks[*itd].codec == (*itc).asStringRef()){
|
if (myMeta.tracks[*itd].codec == (*itc).asStringRef()){
|
||||||
selCounter++;
|
selCounter++;
|
||||||
|
@ -201,10 +201,13 @@ namespace Mist {
|
||||||
DEBUG_MSG(DLVL_MEDIUM, "Trying to fill: %s", capa["codecs"][bestSoFar].toString().c_str());
|
DEBUG_MSG(DLVL_MEDIUM, "Trying to fill: %s", capa["codecs"][bestSoFar].toString().c_str());
|
||||||
//try to fill as many codecs simultaneously as possible
|
//try to fill as many codecs simultaneously as possible
|
||||||
if (capa["codecs"][bestSoFar].size() > 0){
|
if (capa["codecs"][bestSoFar].size() > 0){
|
||||||
for (JSON::ArrIter itb = capa["codecs"][bestSoFar].ArrBegin(); itb != capa["codecs"][bestSoFar].ArrEnd(); itb++){
|
jsonForEach(capa["codecs"][bestSoFar], itb) {
|
||||||
if ((*itb).size() && myMeta.tracks.size()){
|
if ((*itb).size() && myMeta.tracks.size()){
|
||||||
bool found = false;
|
bool found = false;
|
||||||
for (JSON::ArrIter itc = (*itb).ArrBegin(); itc != (*itb).ArrEnd() && !found; itc++){
|
jsonForEach((*itb), itc) {
|
||||||
|
if (found) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
for (std::set<unsigned long>::iterator itd = selectedTracks.begin(); itd != selectedTracks.end(); itd++){
|
for (std::set<unsigned long>::iterator itd = selectedTracks.begin(); itd != selectedTracks.end(); itd++){
|
||||||
if (myMeta.tracks[*itd].codec == (*itc).asStringRef()){
|
if (myMeta.tracks[*itd].codec == (*itc).asStringRef()){
|
||||||
found = true;
|
found = true;
|
||||||
|
|
|
@ -13,14 +13,14 @@ namespace Mist {
|
||||||
JSON::Value & vidCapa = capa["codecs"][0u][0u];
|
JSON::Value & vidCapa = capa["codecs"][0u][0u];
|
||||||
JSON::Value & audCapa = capa["codecs"][0u][1u];
|
JSON::Value & audCapa = capa["codecs"][0u][1u];
|
||||||
for (std::map<unsigned int,DTSC::Track>::iterator it = myMeta.tracks.begin(); it != myMeta.tracks.end(); it++){
|
for (std::map<unsigned int,DTSC::Track>::iterator it = myMeta.tracks.begin(); it != myMeta.tracks.end(); it++){
|
||||||
for (JSON::ArrIter itb = vidCapa.ArrBegin(); itb != vidCapa.ArrEnd(); itb++){
|
jsonForEach(vidCapa, itb) {
|
||||||
if (it->second.codec == (*itb).asStringRef()){
|
if (it->second.codec == (*itb).asStringRef()){
|
||||||
videoTracks.insert(it->first);
|
videoTracks.insert(it->first);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!audioTrack){
|
if (!audioTrack){
|
||||||
for (JSON::ArrIter itb = audCapa.ArrBegin(); itb != audCapa.ArrEnd(); itb++){
|
jsonForEach(audCapa, itb) {
|
||||||
if (it->second.codec == (*itb).asStringRef()){
|
if (it->second.codec == (*itb).asStringRef()){
|
||||||
audioTrack = it->first;
|
audioTrack = it->first;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -75,7 +75,7 @@ namespace Mist {
|
||||||
//if there is a matcher, try to match
|
//if there is a matcher, try to match
|
||||||
if (capa.isMember("url_match")){
|
if (capa.isMember("url_match")){
|
||||||
if (capa["url_match"].isArray()){
|
if (capa["url_match"].isArray()){
|
||||||
for (JSON::ArrIter it = capa["url_match"].ArrBegin(); it != capa["url_match"].ArrEnd(); ++it){
|
jsonForEach(capa["url_match"], it) {
|
||||||
match |= isMatch(url, it->asStringRef(), streamname);
|
match |= isMatch(url, it->asStringRef(), streamname);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -86,7 +86,7 @@ namespace Mist {
|
||||||
//if there is a prefix, try to match
|
//if there is a prefix, try to match
|
||||||
if (capa.isMember("url_prefix")){
|
if (capa.isMember("url_prefix")){
|
||||||
if (capa["url_prefix"].isArray()){
|
if (capa["url_prefix"].isArray()){
|
||||||
for (JSON::ArrIter it = capa["url_prefix"].ArrBegin(); it != capa["url_prefix"].ArrEnd(); ++it){
|
jsonForEach(capa["url_prefix"], it) {
|
||||||
match |= isPrefix(url, it->asStringRef(), streamname);
|
match |= isPrefix(url, it->asStringRef(), streamname);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -228,19 +228,19 @@ namespace Mist {
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void builPipedPart(JSON::Value & p, char * argarr[], int & argnum, JSON::Value & argset){
|
static inline void builPipedPart(JSON::Value & p, char * argarr[], int & argnum, JSON::Value & argset){
|
||||||
for (JSON::ObjIter it = argset.ObjBegin(); it != argset.ObjEnd(); ++it){
|
jsonForEach(argset, it) {
|
||||||
if (it->second.isMember("option") && p.isMember(it->first)){
|
if (it->isMember("option") && p.isMember(it.key())){
|
||||||
if (it->second.isMember("type")){
|
if (it->isMember("type")){
|
||||||
if (it->second["type"].asStringRef() == "str" && !p[it->first].isString()){
|
if ((*it)["type"].asStringRef() == "str" && !p[it.key()].isString()){
|
||||||
p[it->first] = p[it->first].asString();
|
p[it.key()] = p[it.key()].asString();
|
||||||
}
|
}
|
||||||
if ((it->second["type"].asStringRef() == "uint" || it->second["type"].asStringRef() == "int") && !p[it->first].isInt()){
|
if (((*it)["type"].asStringRef() == "uint" || (*it)["type"].asStringRef() == "int") && !p[it.key()].isInt()){
|
||||||
p[it->first] = JSON::Value(p[it->first].asInt()).asString();
|
p[it.key()] = JSON::Value(p[it.key()].asInt()).asString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (p[it->first].asStringRef().size() > 0){
|
if (p[it.key()].asStringRef().size() > 0){
|
||||||
argarr[argnum++] = (char*)(it->second["option"].c_str());
|
argarr[argnum++] = (char*)((*it)["option"].c_str());
|
||||||
argarr[argnum++] = (char*)(p[it->first].c_str());
|
argarr[argnum++] = (char*)(p[it.key()].c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -102,15 +102,15 @@ namespace Mist {
|
||||||
unsigned int most_simul = 0;
|
unsigned int most_simul = 0;
|
||||||
unsigned int total_matches = 0;
|
unsigned int total_matches = 0;
|
||||||
if (conncapa.isMember("codecs") && conncapa["codecs"].size() > 0){
|
if (conncapa.isMember("codecs") && conncapa["codecs"].size() > 0){
|
||||||
for (JSON::ArrIter it = conncapa["codecs"].ArrBegin(); it != conncapa["codecs"].ArrEnd(); it++){
|
jsonForEach(conncapa["codecs"], it) {
|
||||||
unsigned int simul = 0;
|
unsigned int simul = 0;
|
||||||
if ((*it).size() > 0){
|
if ((*it).size() > 0){
|
||||||
for (JSON::ArrIter itb = (*it).ArrBegin(); itb != (*it).ArrEnd(); itb++){
|
jsonForEach((*it), itb) {
|
||||||
unsigned int matches = 0;
|
unsigned int matches = 0;
|
||||||
if ((*itb).size() > 0){
|
if ((*itb).size() > 0){
|
||||||
for (JSON::ArrIter itc = (*itb).ArrBegin(); itc != (*itb).ArrEnd(); itc++){
|
jsonForEach((*itb), itc) {
|
||||||
for (JSON::ObjIter trit = strmMeta["tracks"].ObjBegin(); trit != strmMeta["tracks"].ObjEnd(); trit++){
|
jsonForEach(strmMeta["tracks"], trit) {
|
||||||
if (trit->second["codec"].asStringRef() == (*itc).asStringRef()){
|
if ((*trit)["codec"].asStringRef() == (*itc).asStringRef()){
|
||||||
matches++;
|
matches++;
|
||||||
total_matches++;
|
total_matches++;
|
||||||
}
|
}
|
||||||
|
@ -135,7 +135,7 @@ namespace Mist {
|
||||||
}else{
|
}else{
|
||||||
relurl = "/";
|
relurl = "/";
|
||||||
}
|
}
|
||||||
for (JSON::ArrIter it = conncapa["methods"].ArrBegin(); it != conncapa["methods"].ArrEnd(); it++){
|
jsonForEach(conncapa["methods"], it) {
|
||||||
if (!strmMeta.isMember("live") || !it->isMember("nolive")){
|
if (!strmMeta.isMember("live") || !it->isMember("nolive")){
|
||||||
addSource(relurl, sources, host, port, *it, most_simul, total_matches);
|
addSource(relurl, sources, host, port, *it, most_simul, total_matches);
|
||||||
}
|
}
|
||||||
|
@ -307,10 +307,10 @@ namespace Mist {
|
||||||
|
|
||||||
// show ALL the meta datas!
|
// show ALL the meta datas!
|
||||||
json_resp["meta"] = strm.asJSON();
|
json_resp["meta"] = strm.asJSON();
|
||||||
for (JSON::ObjIter it = json_resp["meta"]["tracks"].ObjBegin(); it != json_resp["meta"]["tracks"].ObjEnd(); ++it){
|
jsonForEach(json_resp["meta"]["tracks"], it) {
|
||||||
it->second.removeMember("fragments");
|
it->removeMember("fragments");
|
||||||
it->second.removeMember("keys");
|
it->removeMember("keys");
|
||||||
it->second.removeMember("parts");
|
it->removeMember("parts");
|
||||||
}
|
}
|
||||||
|
|
||||||
//create a set for storing source information
|
//create a set for storing source information
|
||||||
|
@ -386,5 +386,4 @@ namespace Mist {
|
||||||
return;
|
return;
|
||||||
} //embed code generator
|
} //embed code generator
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue