Made JSON library non-recursive.

Co-authored with Diederick.
This commit is contained in:
Thulinma 2015-10-06 13:21:14 +02:00
parent 7905bb2bda
commit 16d38459b6
14 changed files with 503 additions and 328 deletions

View file

@ -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;
} }
} }

View file

@ -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")) {

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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);
} }

View file

@ -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);
} }

View file

@ -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());
} }
} }

View file

@ -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");
} }
} }

View file

@ -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;

View file

@ -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;

View file

@ -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());
} }
} }
} }

View file

@ -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
} }
} }