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

@ -228,10 +228,10 @@ int main(int argc, char ** argv){
std::getline(std::cin, in_string);
if (yna(in_string) == 'y'){
//create protocols
for (JSON::ObjIter it = Controller::capabilities["connectors"].ObjBegin(); it != Controller::capabilities["connectors"].ObjEnd(); it++){
if ( !it->second.isMember("required")){
jsonForEach(Controller::capabilities["connectors"], it) {
if (!it->isMember("required")){
JSON::Value newProtocol;
newProtocol["connector"] = it->first;
newProtocol["connector"] = it.key();
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;
tthread::lock_guard<tthread::mutex> guard(Controller::logMutex);
Controller::Storage.removeMember("log");
for (JSON::ObjIter it = Controller::Storage["streams"].ObjBegin(); it != Controller::Storage["streams"].ObjEnd(); it++){
it->second.removeMember("meta");
jsonForEach(Controller::Storage["streams"], it) {
it->removeMember("meta");
}
std::cerr << "**Config**" << 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){
for (JSON::ObjIter it = argset.ObjBegin(); it != argset.ObjEnd(); ++it){
if (it->second.isMember("option")){
if (p.isMember(it->first)){
if (it->second.isMember("type")){
if (it->second["type"].asStringRef() == "str" && !p[it->first].isString()){
p[it->first] = p[it->first].asString();
}
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());
static inline void builPipedPart(JSON::Value & p, char * argarr[], int & argnum, const JSON::Value & argset){
jsonForEachConst(argset, it) {
if (it->isMember("option")){
if (p.isMember(it.key())){
p[it.key()] = p[it.key()].asString();
if (p[it.key()].asStringRef().size() > 0){
argarr[argnum++] = (char*)((*it)["option"].asStringRef().c_str());
argarr[argnum++] = (char*)(p[it.key()].asStringRef().c_str());
}
}else{
if (it->first == "debug"){
if (it.key() == "debug"){
static std::string debugLvlStr;
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();
}
}
@ -60,8 +53,7 @@ namespace Controller {
}
}
static inline void buildPipedArguments(const std::string & proto, char * argarr[], JSON::Value & capabilities){
JSON::Value p = JSON::fromString(proto);
static inline void buildPipedArguments(JSON::Value & p, char * argarr[], const JSON::Value & capabilities){
int argnum = 0;
static std::string tmparg;
tmparg = Util::getMyPath() + std::string("MistOut") + p["connector"].asStringRef();
@ -73,7 +65,7 @@ namespace Controller {
return;
}
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("optional")){builPipedPart(p, argarr, argnum, pipedCapa["optional"]);}
}
@ -82,7 +74,7 @@ namespace Controller {
///\param p An object containing all protocols.
///\param capabilities An object containing the detected capabilities.
///\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;
// used for building args
@ -93,11 +85,9 @@ namespace Controller {
int i;
std::string tmp;
long long counter = 0;
for (JSON::ArrIter ait = p.ArrBegin(); ait != p.ArrEnd(); ait++){
counter = ait - p.ArrBegin();
std::string prevOnline = ( *ait)["online"].asString();
jsonForEach(p, ait) {
std::string prevOnline = (*ait)["online"].asString();
const std::string & connName = (*ait)["connector"].asStringRef();
//do not further parse if there's no connector name
if ( !(*ait).isMember("connector") || connName == ""){
@ -113,7 +103,7 @@ namespace Controller {
continue;
}
//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")){
( *ait)["online"] = "Enabled";
continue;
@ -121,12 +111,12 @@ namespace Controller {
//check required parameters, skip if anything is missing
if (connCapa.isMember("required")){
bool gotAll = true;
for (JSON::ObjIter it = connCapa["required"].ObjBegin(); it != connCapa["required"].ObjEnd(); ++it){
if ( !(*ait).isMember(it->first) || (*ait)[it->first].asStringRef().size() < 1){
jsonForEachConst(connCapa["required"], it) {
if ( !(*ait).isMember(it.key()) || (*ait)[it.key()].asStringRef().size() < 1){
gotAll = false;
( *ait)["online"] = "Invalid configuration";
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;
}
@ -169,7 +159,8 @@ namespace Controller {
// clear out old args
for (i=0; i<15; i++){argarr[i] = 0;}
// 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
currentConnectors[*runningConns.begin()] = Util::Procs::StartPiped(argarr, &zero, &out, &err);
}

View file

@ -6,6 +6,6 @@ namespace Controller {
void UpdateProtocol(std::string protocol);
/// 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;
//next, figure out the fields wanted
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() == "stream"){fields |= STAT_CLI_STREAM;}
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
std::set<std::string> streams;
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());
}
}
//figure out what protocols are wanted
std::set<std::string> protos;
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());
}
}
@ -638,7 +638,7 @@ void Controller::fillTotals(JSON::Value & req, JSON::Value & rep){
unsigned int fields = 0;
//next, figure out the fields wanted
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() == "downbps"){fields |= STAT_TOT_BPS_DOWN;}
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
std::set<std::string> streams;
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());
}
}
//figure out what protocols are wanted
std::set<std::string> protos;
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());
}
}

View file

@ -94,25 +94,25 @@ namespace Controller {
///\returns True if the server status changed
bool CheckAllStreams(JSON::Value & data){
long long int currTime = Util::epoch();
for (JSON::ObjIter jit = data.ObjBegin(); jit != data.ObjEnd(); jit++){
checkStream(jit->first, jit->second);
if (!jit->second.isMember("name")){
jit->second["name"] = jit->first;
jsonForEach(data, jit) {
checkStream(jit.key(), (*jit));
if (!jit->isMember("name")){
(*jit)["name"] = jit.key();
}
if (!hasViewers(jit->first)){
if (jit->second.isMember("source") && jit->second["source"].asString().substr(0, 1) == "/" && jit->second.isMember("error")
&& jit->second["error"].asString().substr(0,15) != "Stream offline:"){
jit->second["online"] = 2;
if (!hasViewers(jit.key())){
if (jit->isMember("source") && (*jit)["source"].asString().substr(0, 1) == "/" && jit->isMember("error")
&& (*jit)["error"].asString().substr(0,15) != "Stream offline:"){
(*jit)["online"] = 2;
}else{
if (jit->second.isMember("error") && jit->second["error"].asString() == "Available"){
jit->second.removeMember("error");
if (jit->isMember("error") && (*jit)["error"].asString() == "Available"){
jit->removeMember("error");
}
jit->second["online"] = 0;
(*jit)["online"] = 0;
}
}else{
// assume all is fine
jit->second.removeMember("error");
jit->second["online"] = 1;
jit->removeMember("error");
(*jit)["online"] = 1;
}
}
@ -128,17 +128,17 @@ namespace Controller {
void AddStreams(JSON::Value & in, JSON::Value & out){
//check for new streams and updates
for (JSON::ObjIter jit = in.ObjBegin(); jit != in.ObjEnd(); jit++){
if (out.isMember(jit->first)){
if ( !streamsEqual(jit->second, out[jit->first])){
out[jit->first] = jit->second;
out[jit->first]["name"] = jit->first;
Log("STRM", std::string("Updated stream ") + jit->first);
jsonForEach(in, jit) {
if (out.isMember(jit.key())){
if ( !streamsEqual((*jit), out[jit.key()])){
out[jit.key()] = (*jit);
out[jit.key()]["name"] = jit.key();
Log("STRM", std::string("Updated stream ") + jit.key());
}
}else{
out[jit->first] = jit->second;
out[jit->first]["name"] = jit->first;
Log("STRM", std::string("New stream ") + jit->first);
out[jit.key()] = (*jit);
out[jit.key()]["name"] = (*jit);
Log("STRM", std::string("New stream ") + jit.key());
}
}
}
@ -198,10 +198,10 @@ namespace Controller {
//check for deleted streams
std::set<std::string> toDelete;
for (JSON::ObjIter jit = out.ObjBegin(); jit != out.ObjEnd(); jit++){
if ( !in.isMember(jit->first)){
toDelete.insert(jit->first);
Log("STRM", std::string("Deleted stream ") + jit->first);
jsonForEach(out, jit) {
if ( !in.isMember(jit.key())){
toDelete.insert(jit.key());
Log("STRM", std::string("Deleted stream ") + jit.key());
}
}
//actually delete the streams
@ -212,15 +212,15 @@ namespace Controller {
}
//update old-style configurations to new-style
for (JSON::ObjIter jit = in.ObjBegin(); jit != in.ObjEnd(); jit++){
if (jit->second.isMember("channel")){
if ( !jit->second.isMember("source")){
jit->second["source"] = jit->second["channel"]["URL"];
jsonForEach(in, jit) {
if (jit->isMember("channel")){
if ( !jit->isMember("source")){
(*jit)["source"] = (*jit)["channel"]["URL"];
}
jit->second.removeMember("channel");
jit->removeMember("channel");
}
if (jit->second.isMember("preset")){
jit->second.removeMember("preset");
if (jit->isMember("preset")){
jit->removeMember("preset");
}
}

View file

@ -158,14 +158,14 @@ namespace Mist {
unsigned int bestSoFar = 0;
unsigned int bestSoFarCount = 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 selCounter = 0;
if ((*it).size() > 0){
for (JSON::ArrIter itb = (*it).ArrBegin(); itb != (*it).ArrEnd(); itb++){
jsonForEach((*it), itb) {
if ((*itb).size() > 0){
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++){
if (myMeta.tracks[*itd].codec == (*itc).asStringRef()){
selCounter++;
@ -201,10 +201,13 @@ namespace Mist {
DEBUG_MSG(DLVL_MEDIUM, "Trying to fill: %s", capa["codecs"][bestSoFar].toString().c_str());
//try to fill as many codecs simultaneously as possible
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()){
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++){
if (myMeta.tracks[*itd].codec == (*itc).asStringRef()){
found = true;

View file

@ -13,14 +13,14 @@ namespace Mist {
JSON::Value & vidCapa = capa["codecs"][0u][0u];
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 (JSON::ArrIter itb = vidCapa.ArrBegin(); itb != vidCapa.ArrEnd(); itb++){
jsonForEach(vidCapa, itb) {
if (it->second.codec == (*itb).asStringRef()){
videoTracks.insert(it->first);
break;
}
}
if (!audioTrack){
for (JSON::ArrIter itb = audCapa.ArrBegin(); itb != audCapa.ArrEnd(); itb++){
jsonForEach(audCapa, itb) {
if (it->second.codec == (*itb).asStringRef()){
audioTrack = it->first;
break;

View file

@ -75,7 +75,7 @@ namespace Mist {
//if there is a matcher, try to match
if (capa.isMember("url_match")){
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);
}
}
@ -86,7 +86,7 @@ namespace Mist {
//if there is a prefix, try to match
if (capa.isMember("url_prefix")){
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);
}
}
@ -228,19 +228,19 @@ namespace Mist {
}
static inline void builPipedPart(JSON::Value & p, char * argarr[], int & argnum, JSON::Value & argset){
for (JSON::ObjIter it = argset.ObjBegin(); it != argset.ObjEnd(); ++it){
if (it->second.isMember("option") && p.isMember(it->first)){
if (it->second.isMember("type")){
if (it->second["type"].asStringRef() == "str" && !p[it->first].isString()){
p[it->first] = p[it->first].asString();
jsonForEach(argset, it) {
if (it->isMember("option") && p.isMember(it.key())){
if (it->isMember("type")){
if ((*it)["type"].asStringRef() == "str" && !p[it.key()].isString()){
p[it.key()] = p[it.key()].asString();
}
if ((it->second["type"].asStringRef() == "uint" || it->second["type"].asStringRef() == "int") && !p[it->first].isInt()){
p[it->first] = JSON::Value(p[it->first].asInt()).asString();
if (((*it)["type"].asStringRef() == "uint" || (*it)["type"].asStringRef() == "int") && !p[it.key()].isInt()){
p[it.key()] = JSON::Value(p[it.key()].asInt()).asString();
}
}
if (p[it->first].asStringRef().size() > 0){
argarr[argnum++] = (char*)(it->second["option"].c_str());
argarr[argnum++] = (char*)(p[it->first].c_str());
if (p[it.key()].asStringRef().size() > 0){
argarr[argnum++] = (char*)((*it)["option"].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 total_matches = 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;
if ((*it).size() > 0){
for (JSON::ArrIter itb = (*it).ArrBegin(); itb != (*it).ArrEnd(); itb++){
jsonForEach((*it), itb) {
unsigned int matches = 0;
if ((*itb).size() > 0){
for (JSON::ArrIter itc = (*itb).ArrBegin(); itc != (*itb).ArrEnd(); itc++){
for (JSON::ObjIter trit = strmMeta["tracks"].ObjBegin(); trit != strmMeta["tracks"].ObjEnd(); trit++){
if (trit->second["codec"].asStringRef() == (*itc).asStringRef()){
jsonForEach((*itb), itc) {
jsonForEach(strmMeta["tracks"], trit) {
if ((*trit)["codec"].asStringRef() == (*itc).asStringRef()){
matches++;
total_matches++;
}
@ -135,7 +135,7 @@ namespace Mist {
}else{
relurl = "/";
}
for (JSON::ArrIter it = conncapa["methods"].ArrBegin(); it != conncapa["methods"].ArrEnd(); it++){
jsonForEach(conncapa["methods"], it) {
if (!strmMeta.isMember("live") || !it->isMember("nolive")){
addSource(relurl, sources, host, port, *it, most_simul, total_matches);
}
@ -307,10 +307,10 @@ namespace Mist {
// show ALL the meta datas!
json_resp["meta"] = strm.asJSON();
for (JSON::ObjIter it = json_resp["meta"]["tracks"].ObjBegin(); it != json_resp["meta"]["tracks"].ObjEnd(); ++it){
it->second.removeMember("fragments");
it->second.removeMember("keys");
it->second.removeMember("parts");
jsonForEach(json_resp["meta"]["tracks"], it) {
it->removeMember("fragments");
it->removeMember("keys");
it->removeMember("parts");
}
//create a set for storing source information
@ -386,5 +386,4 @@ namespace Mist {
return;
} //embed code generator
}
}