diff --git a/lib/config.cpp b/lib/config.cpp index d4808da0..1dcbec36 100644 --- a/lib/config.cpp +++ b/lib/config.cpp @@ -84,11 +84,11 @@ void Util::Config::addOption(std::string optname, JSON::Value option) { vals[optname].removeMember("default"); } long_count = 0; - for (JSON::ObjIter it = vals.ObjBegin(); it != vals.ObjEnd(); it++) { - if (it->second.isMember("long")) { + jsonForEach(vals, it) { + if (it->isMember("long")) { long_count++; } - if (it->second.isMember("long_off")) { + if (it->isMember("long_off")) { long_count++; } } @@ -98,33 +98,33 @@ void Util::Config::addOption(std::string optname, JSON::Value option) { void Util::Config::printHelp(std::ostream & output) { unsigned int longest = 0; std::map args; - for (JSON::ObjIter it = vals.ObjBegin(); it != vals.ObjEnd(); it++) { + jsonForEach(vals, it) { unsigned int current = 0; - if (it->second.isMember("long")) { - current += it->second["long"].asString().size() + 4; + if (it->isMember("long")) { + current += (*it)["long"].asString().size() + 4; } - if (it->second.isMember("short")) { - current += it->second["short"].asString().size() + 3; + if (it->isMember("short")) { + current += (*it)["short"].asString().size() + 3; } if (current > longest) { longest = current; } current = 0; - if (it->second.isMember("long_off")) { - current += it->second["long_off"].asString().size() + 4; + if (it->isMember("long_off")) { + current += (*it)["long_off"].asString().size() + 4; } - if (it->second.isMember("short_off")) { - current += it->second["short_off"].asString().size() + 3; + if (it->isMember("short_off")) { + current += (*it)["short_off"].asString().size() + 3; } if (current > longest) { longest = current; } - if (it->second.isMember("arg_num")) { - current = it->first.size() + 3; + if (it->isMember("arg_num")) { + current = it.key().size() + 3; if (current > longest) { longest = current; } - args[it->second["arg_num"].asInt()] = it->first; + args[(*it)["arg_num"].asInt()] = it.key(); } } output << "Usage: " << getString("cmd") << " [options]"; @@ -136,54 +136,54 @@ void Util::Config::printHelp(std::ostream & output) { } } output << std::endl << std::endl; - for (JSON::ObjIter it = vals.ObjBegin(); it != vals.ObjEnd(); it++) { + jsonForEach(vals, it) { std::string f; - if (it->second.isMember("long") || it->second.isMember("short")) { - if (it->second.isMember("long") && it->second.isMember("short")) { - f = "--" + it->second["long"].asString() + ", -" + it->second["short"].asString(); + if (it->isMember("long") || it->isMember("short")) { + if (it->isMember("long") && it->isMember("short")) { + f = "--" + (*it)["long"].asString() + ", -" + (*it)["short"].asString(); } else { - if (it->second.isMember("long")) { - f = "--" + it->second["long"].asString(); + if (it->isMember("long")) { + f = "--" + (*it)["long"].asString(); } - if (it->second.isMember("short")) { - f = "-" + it->second["short"].asString(); + if (it->isMember("short")) { + f = "-" + (*it)["short"].asString(); } } while (f.size() < longest) { f.append(" "); } - if (it->second.isMember("arg")) { - output << f << "(" << it->second["arg"].asString() << ") " << it->second["help"].asString() << std::endl; + if (it->isMember("arg")) { + output << f << "(" << (*it)["arg"].asString() << ") " << (*it)["help"].asString() << std::endl; } 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->second.isMember("long_off") && it->second.isMember("short_off")) { - f = "--" + it->second["long_off"].asString() + ", -" + it->second["short_off"].asString(); + if (it->isMember("long_off") || it->isMember("short_off")) { + if (it->isMember("long_off") && it->isMember("short_off")) { + f = "--" + (*it)["long_off"].asString() + ", -" + (*it)["short_off"].asString(); } else { - if (it->second.isMember("long_off")) { - f = "--" + it->second["long_off"].asString(); + if (it->isMember("long_off")) { + f = "--" + (*it)["long_off"].asString(); } - if (it->second.isMember("short_off")) { - f = "-" + it->second["short_off"].asString(); + if (it->isMember("short_off")) { + f = "-" + (*it)["short_off"].asString(); } } while (f.size() < longest) { f.append(" "); } - if (it->second.isMember("arg")) { - output << f << "(" << it->second["arg"].asString() << ") " << it->second["help"].asString() << std::endl; + if (it->isMember("arg")) { + output << f << "(" << (*it)["arg"].asString() << ") " << (*it)["help"].asString() << std::endl; } else { - output << f << it->second["help"].asString() << std::endl; + output << f << (*it)["help"].asString() << std::endl; } } - if (it->second.isMember("arg_num")) { - f = it->first; + if (it->isMember("arg_num")) { + f = it.key(); while (f.size() < longest) { 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 arg_count = 0; if (vals.size()) { - for (JSON::ObjIter it = vals.ObjBegin(); it != vals.ObjEnd(); it++) { - if (it->second.isMember("short")) { - shortopts += it->second["short"].asString(); - if (it->second.isMember("arg")) { + jsonForEach(vals, it) { + if (it->isMember("short")) { + shortopts += (*it)["short"].asString(); + if (it->isMember("arg")) { shortopts += ":"; } } - if (it->second.isMember("short_off")) { - shortopts += it->second["short_off"].asString(); - if (it->second.isMember("arg")) { + if (it->isMember("short_off")) { + shortopts += (*it)["short_off"].asString(); + if (it->isMember("arg")) { shortopts += ":"; } } - if (it->second.isMember("long")) { - longOpts[long_i].name = it->second["long"].asString().c_str(); - longOpts[long_i].val = it->second["short"].asString()[0]; - if (it->second.isMember("arg")) { + if (it->isMember("long")) { + longOpts[long_i].name = (*it)["long"].asStringRef().c_str(); + longOpts[long_i].val = (*it)["short"].asString()[0]; + if (it->isMember("arg")) { longOpts[long_i].has_arg = 1; } long_i++; } - if (it->second.isMember("long_off")) { - longOpts[long_i].name = it->second["long_off"].asString().c_str(); - longOpts[long_i].val = it->second["short_off"].asString()[0]; - if (it->second.isMember("arg")) { + if (it->isMember("long_off")) { + longOpts[long_i].name = (*it)["long_off"].asStringRef().c_str(); + longOpts[long_i].val = (*it)["short_off"].asString()[0]; + if (it->isMember("arg")) { longOpts[long_i].has_arg = 1; } long_i++; } - if (it->second.isMember("arg_num") && !(it->second.isMember("value") && it->second["value"].size())) { - if (it->second["arg_num"].asInt() > arg_count) { - arg_count = it->second["arg_num"].asInt(); + if (it->isMember("arg_num") && !(it->isMember("value") && (*it)["value"].size())) { + if ((*it)["arg_num"].asInt() > arg_count) { + arg_count = (*it)["arg_num"].asInt(); } } } } + while ((opt = getopt_long(argc, argv, shortopts.c_str(), longOpts, 0)) != -1) { switch (opt) { case 'h': @@ -267,17 +268,17 @@ bool Util::Config::parseArgs(int & argc, char ** & argv) { exit(1); break; default: - for (JSON::ObjIter it = vals.ObjBegin(); it != vals.ObjEnd(); it++) { - if (it->second.isMember("short") && it->second["short"].asString()[0] == opt) { - if (it->second.isMember("arg")) { - it->second["value"].append((std::string)optarg); + jsonForEach(vals, it) { + if (it->isMember("short") && (*it)["short"].asString()[0] == opt) { + if (it->isMember("arg")) { + (*it)["value"].append((std::string)optarg); } else { - it->second["value"].append((long long int)1); + (*it)["value"].append((long long int)1); } break; } - if (it->second.isMember("short_off") && it->second["short_off"].asString()[0] == opt) { - it->second["value"].append((long long int)0); + if (it->isMember("short_off") && (*it)["short_off"].asString()[0] == opt) { + (*it)["value"].append((long long int)0); } } break; @@ -286,9 +287,9 @@ bool Util::Config::parseArgs(int & argc, char ** & argv) { free(longOpts); //free the long options array long_i = 1; //re-use long_i as an argument counter while (optind < argc) { //parse all remaining options, ignoring anything unexpected. - for (JSON::ObjIter it = vals.ObjBegin(); it != vals.ObjEnd(); it++) { - if (it->second.isMember("arg_num") && it->second["arg_num"].asInt() == long_i) { - it->second["value"].append((std::string)argv[optind]); + jsonForEach(vals, it) { + if (it->isMember("arg_num") && (*it)["arg_num"].asInt() == long_i) { + (*it)["value"].append((std::string)argv[optind]); break; } } diff --git a/lib/dtscmeta.cpp b/lib/dtscmeta.cpp index 705effeb..b353c483 100644 --- a/lib/dtscmeta.cpp +++ b/lib/dtscmeta.cpp @@ -1325,9 +1325,10 @@ namespace DTSC { if (meta.isMember("buffer_window")) { bufferWindow = meta["buffer_window"].asInt(); } - for (JSON::ObjIter it = meta["tracks"].ObjBegin(); it != meta["tracks"].ObjEnd(); it++) { - if (it->second["trackid"].asInt()) { - tracks[it->second["trackid"].asInt()] = Track(it->second); + //for (JSON::ObjIter it = meta["tracks"].ObjBegin(); it != meta["tracks"].ObjEnd(); it++) { + jsonForEach(meta["tracks"], it) { + if ((*it)["trackid"].asInt()) { + tracks[(*it)["trackid"].asInt()] = Track((*it)); } } if (meta.isMember("moreheader")) { diff --git a/lib/json.cpp b/lib/json.cpp index 40a4be14..5df51f2a 100644 --- a/lib/json.cpp +++ b/lib/json.cpp @@ -9,6 +9,140 @@ #include //for memcpy #include //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) { if (c >= '0' && c <= '9') return c - '0'; if (c >= 'a' && c <= 'f') return c - 'a' + 10; @@ -142,6 +276,16 @@ JSON::Value::Value() { 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 JSON::Value::Value(std::istream & fromstream) { null(); @@ -271,6 +415,16 @@ JSON::Value::Value(long long int 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. bool JSON::Value::operator==(const JSON::Value & rhs) const { if (myType != rhs.myType) return false; @@ -285,11 +439,11 @@ bool JSON::Value::operator==(const JSON::Value & rhs) const { } if (myType == OBJECT) { if (objVal.size() != rhs.objVal.size()) return false; - for (std::map::const_iterator it = objVal.begin(); it != objVal.end(); ++it) { + for (std::map::const_iterator it = objVal.begin(); it != objVal.end(); ++it) { if (!rhs.isMember(it->first)) { return false; } - if (it->second != rhs.objVal.find(it->first)->second) { + if (*(it->second) != rhs.objVal.find(it->first)->second) { return false; } } @@ -298,8 +452,8 @@ bool JSON::Value::operator==(const JSON::Value & rhs) const { if (myType == ARRAY) { if (arrVal.size() != rhs.arrVal.size()) return false; int i = 0; - for (std::deque::const_iterator it = arrVal.begin(); it != arrVal.end(); ++it) { - if (*it != rhs.arrVal[i]) { + for (std::deque::const_iterator it = arrVal.begin(); it != arrVal.end(); ++it) { + if (**it != *(rhs.arrVal[i])) { return false; } i++; @@ -314,6 +468,38 @@ bool JSON::Value::operator!=(const JSON::Value & rhs) const { 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. JSON::Value & JSON::Value::operator=(const bool & rhs) { null(); @@ -445,7 +631,12 @@ JSON::Value & JSON::Value::operator[](const std::string i) { null(); 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. @@ -455,7 +646,12 @@ JSON::Value & JSON::Value::operator[](const char * i) { null(); 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. @@ -466,27 +662,27 @@ JSON::Value & JSON::Value::operator[](unsigned int i) { myType = ARRAY; } 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. /// Fails horribly if that values does not exist. 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. /// Fails horribly if that values does not exist. 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. /// Fails horribly if that values does not exist. 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. @@ -517,12 +713,12 @@ std::string JSON::Value::toPacked() const { if (isObject()) { r += 0xE0; if (objVal.size() > 0) { - for (JSON::ObjConstIter it = objVal.begin(); it != objVal.end(); it++) { - if (it->first.size() > 0) { - r += it->first.size() / 256; - r += it->first.size() % 256; - r += it->first; - r += it->second.toPacked(); + jsonForEachConst(*this, i){ + if (i.key().size() > 0) { + r += i.key().size() / 256; + r += i.key().size() % 256; + r += i.key(); + r += i->toPacked(); } } } @@ -532,8 +728,8 @@ std::string JSON::Value::toPacked() const { } if (isArray()) { r += 0x0A; - for (JSON::ArrConstIter it = arrVal.begin(); it != arrVal.end(); it++) { - r += it->toPacked(); + jsonForEachConst(*this, i){ + r += i->toPacked(); } r += (char)0x0; r += (char)0x0; @@ -563,13 +759,13 @@ void JSON::Value::sendTo(Socket::Connection & socket) const { } if (isObject()) { if (isMember("trackid") && isMember("time")) { - unsigned int trackid = objVal.find("trackid")->second.asInt(); - long long time = objVal.find("time")->second.asInt(); + unsigned int trackid = objVal.find("trackid")->second->asInt(); + long long time = objVal.find("time")->second->asInt(); unsigned int size = 16; if (objVal.size() > 0) { - for (JSON::ObjConstIter it = objVal.begin(); it != objVal.end(); it++) { - if (it->first.size() > 0 && it->first != "trackid" && it->first != "time" && it->first != "datatype") { - size += 2 + it->first.size() + it->second.packedSize(); + jsonForEachConst(*this, i){ + if (i.key().size() > 0 && i.key() != "trackid" && i.key() != "time" && i.key() != "datatype") { + 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("\340", 1); if (objVal.size() > 0) { - for (JSON::ObjConstIter it = objVal.begin(); it != objVal.end(); it++) { - if (it->first.size() > 0 && it->first != "trackid" && it->first != "time" && it->first != "datatype") { + jsonForEachConst(*this, i){ + if (i.key().size() > 0 && i.key() != "trackid" && i.key() != "time" && i.key() != "datatype") { char sizebuffer[2] = {0, 0}; - sizebuffer[0] = (it->first.size() >> 8) & 0xFF; - sizebuffer[1] = it->first.size() & 0xFF; + sizebuffer[0] = (i.key().size() >> 8) & 0xFF; + sizebuffer[1] = i.key().size() & 0xFF; socket.SendNow(sizebuffer, 2); - socket.SendNow(it->first); - it->second.sendTo(socket); + socket.SendNow(i.key()); + i->sendTo(socket); } } } @@ -605,14 +801,14 @@ void JSON::Value::sendTo(Socket::Connection & socket) const { } socket.SendNow("\340", 1); if (objVal.size() > 0) { - for (JSON::ObjConstIter it = objVal.begin(); it != objVal.end(); it++) { - if (it->first.size() > 0) { + jsonForEachConst(*this, i){ + if (i.key().size() > 0) { char sizebuffer[2] = {0, 0}; - sizebuffer[0] = (it->first.size() >> 8) & 0xFF; - sizebuffer[1] = it->first.size() & 0xFF; + sizebuffer[0] = (i.key().size() >> 8) & 0xFF; + sizebuffer[1] = i.key().size() & 0xFF; socket.SendNow(sizebuffer, 2); - socket.SendNow(it->first); - it->second.sendTo(socket); + socket.SendNow(i.key()); + i->sendTo(socket); } } } @@ -621,8 +817,8 @@ void JSON::Value::sendTo(Socket::Connection & socket) const { } if (isArray()) { socket.SendNow("\012", 1); - for (JSON::ArrConstIter it = arrVal.begin(); it != arrVal.end(); it++) { - it->sendTo(socket); + jsonForEachConst(*this, i){ + i->sendTo(socket); } socket.SendNow("\000\000\356", 3); return; @@ -640,9 +836,9 @@ unsigned int JSON::Value::packedSize() const { if (isObject()) { unsigned int ret = 4; if (objVal.size() > 0) { - for (JSON::ObjConstIter it = objVal.begin(); it != objVal.end(); it++) { - if (it->first.size() > 0) { - ret += 2 + it->first.size() + it->second.packedSize(); + jsonForEachConst(*this, i){ + if (i.key().size() > 0) { + ret += 2 + i.key().size() + i->packedSize(); } } } @@ -650,8 +846,8 @@ unsigned int JSON::Value::packedSize() const { } if (isArray()) { unsigned int ret = 4; - for (JSON::ArrConstIter it = arrVal.begin(); it != arrVal.end(); it++) { - ret += it->packedSize(); + jsonForEachConst(*this, i){ + ret += i->packedSize(); } return ret; } @@ -669,20 +865,20 @@ void JSON::Value::netPrepare() { std::string packed = toPacked(); //insert proper header for this type of data int packID = -1; - long long unsigned int time = objVal["time"].asInt(); + long long unsigned int time = (*this)["time"].asInt(); std::string dataType; if (isMember("datatype") || isMember("trackid")) { - dataType = objVal["datatype"].asString(); + dataType = (*this)["datatype"].asString(); if (isMember("trackid")) { - packID = objVal["trackid"].asInt(); + packID = (*this)["trackid"].asInt(); } else { - if (objVal["datatype"].asString() == "video") { + if ((*this)["datatype"].asString() == "video") { packID = 1; } - if (objVal["datatype"].asString() == "audio") { + if ((*this)["datatype"].asString() == "audio") { packID = 2; } - if (objVal["datatype"].asString() == "meta") { + if ((*this)["datatype"].asString() == "meta") { packID = 3; } //endmark and the likes... @@ -696,9 +892,9 @@ void JSON::Value::netPrepare() { } removeMember("trackid"); packed = toPacked(); - objVal["time"] = (long long int)time; - objVal["datatype"] = dataType; - objVal["trackid"] = packID; + (*this)["time"] = (long long int)time; + (*this)["datatype"] = dataType; + (*this)["trackid"] = packID; strVal.resize(packed.size() + 20); memcpy((void *)strVal.c_str(), "DTP2", 4); } else { @@ -771,9 +967,9 @@ std::string JSON::Value::toString() const { case ARRAY: { std::string tmp = "["; if (arrVal.size() > 0) { - for (ArrConstIter it = ArrBegin(); it != ArrEnd(); it++) { - tmp += it->toString(); - if (it + 1 != ArrEnd()) { + jsonForEachConst(*this, i){ + tmp += i->toString(); + if (i.num()+1 != arrVal.size()) { tmp += ","; } } @@ -785,12 +981,10 @@ std::string JSON::Value::toString() const { case OBJECT: { std::string tmp2 = "{"; if (objVal.size() > 0) { - ObjConstIter it3 = ObjEnd(); - --it3; - for (ObjConstIter it2 = ObjBegin(); it2 != ObjEnd(); it2++) { - tmp2 += string_escape(it2->first) + ":"; - tmp2 += it2->second.toString(); - if (it2 != it3) { + jsonForEachConst(*this, i){ + tmp2 += string_escape(i.key()) + ":"; + tmp2 += i->toString(); + if (i.num()+1 != objVal.size()) { tmp2 += ","; } } @@ -828,9 +1022,9 @@ std::string JSON::Value::toPrettyString(int indentation) const { case ARRAY: { if (arrVal.size() > 0) { std::string tmp = "[\n" + std::string(indentation + 2, ' '); - for (ArrConstIter it = ArrBegin(); it != ArrEnd(); it++) { - tmp += it->toPrettyString(indentation + 2); - if (it + 1 != ArrEnd()) { + jsonForEachConst(*this, i){ + tmp += i->toPrettyString(indentation + 2); + if (i.num() + 1 != arrVal.size()) { tmp += ", "; } } @@ -848,12 +1042,10 @@ std::string JSON::Value::toPrettyString(int indentation) const { shortMode = true; } std::string tmp2 = "{" + std::string((shortMode ? "" : "\n")); - ObjConstIter it3 = ObjEnd(); - --it3; - for (ObjConstIter it2 = ObjBegin(); it2 != ObjEnd(); it2++) { - tmp2 += (shortMode ? std::string("") : std::string(indentation + 2, ' ')) + string_escape(it2->first) + ":"; - tmp2 += it2->second.toPrettyString(indentation + 2); - if (it2 != it3) { + jsonForEachConst(*this, i){ + tmp2 += (shortMode ? std::string("") : std::string(indentation + 2, ' ')) + string_escape(i.key()) + ":"; + tmp2 += i->toPrettyString(indentation + 2); + if (i.num() + 1 != objVal.size()) { tmp2 += "," + std::string((shortMode ? " " : "\n")); } } @@ -878,7 +1070,7 @@ void JSON::Value::append(const JSON::Value & rhs) { null(); 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. @@ -888,7 +1080,7 @@ void JSON::Value::prepend(const JSON::Value & rhs) { null(); myType = ARRAY; } - arrVal.push_front(rhs); + arrVal.push_front(new JSON::Value(rhs)); } /// For array and object JSON::Value objects, reduces them @@ -898,24 +1090,23 @@ void JSON::Value::prepend(const JSON::Value & rhs) { /// do anything if the size is already lower or equal to the /// given size. void JSON::Value::shrink(unsigned int size) { - if (myType == ARRAY) { - while (arrVal.size() > size) { - arrVal.pop_front(); - } - return; + while (arrVal.size() > size) { + delete arrVal.front(); + arrVal.pop_front(); } - if (myType == OBJECT) { - while (objVal.size() > size) { - objVal.erase(objVal.begin()); - } - return; + while (objVal.size() > size) { + delete objVal.begin()->second; + objVal.erase(objVal.begin()); } } /// For object JSON::Value objects, removes the member with /// the given name, if it exists. Has no effect otherwise. void JSON::Value::removeMember(const std::string & name) { - objVal.erase(name); + if (objVal.count(name)){ + delete objVal[name]; + objVal.erase(name); + } } /// For object JSON::Value objects, returns true if the @@ -954,61 +1145,11 @@ bool JSON::Value::isNull() const { 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. unsigned int JSON::Value::size() const { 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. JSON::Value JSON::fromString(std::string json) { std::istringstream is(json); @@ -1101,8 +1242,9 @@ void JSON::fromDTMI(const unsigned char * data, unsigned int len, unsigned int & case 0x0A: { //array ++i; while (data[i] + data[i + 1] != 0 && i < len) { //while not encountering 0x0000 (we assume 0x0000EE) - ret.append(JSON::Value()); - fromDTMI(data, len, i, *--ret.ArrEnd()); //add content, recursively parsed, updating i + JSON::Value tval; + fromDTMI(data, len, i, tval); //add content, recursively parsed, updating i + ret.append(tval); } i += 3; //skip 0x0000EE return; diff --git a/lib/json.h b/lib/json.h index 6fe3c239..958ee5d6 100644 --- a/lib/json.h +++ b/lib/json.h @@ -21,27 +21,24 @@ namespace JSON { EMPTY, BOOL, INTEGER, STRING, ARRAY, OBJECT }; - class Value; - //forward declaration for below typedef - - typedef std::map::iterator ObjIter; - typedef std::deque::iterator ArrIter; - typedef std::map::const_iterator ObjConstIter; - typedef std::deque::const_iterator ArrConstIter; /// A JSON::Value is either a string or an integer, but may also be an object, array or null. class Value { + friend class Iter; + friend class ConstIter; private: ValueType myType; long long int intVal; std::string strVal; - std::deque arrVal; - std::map objVal; + std::deque arrVal; + std::map objVal; public: //friends friend class DTSC::Stream; //for access to strVal - //constructors + //constructors/destructors Value(); + ~Value(); + Value(const Value & rhs); Value(std::istream & fromstream); Value(const std::string & val); Value(const char * val); @@ -51,6 +48,7 @@ namespace JSON { bool operator==(const Value & rhs) const; bool operator!=(const Value & rhs) const; //assignment operators + Value & operator=(const Value & rhs); Value & operator=(const std::string & rhs); Value & operator=(const char * rhs); Value & operator=(const long long int & rhs); @@ -92,14 +90,6 @@ namespace JSON { bool isObject() const; bool isArray() 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; void null(); }; @@ -115,6 +105,41 @@ namespace JSON { void fromDTMI(std::string & data, Value & ret); void fromDTMI(const unsigned char * data, unsigned int len, unsigned int & i, Value & ret); + class Iter { + public: + Iter(Value & root);///() const;///< Dereferences into a Value reference. + operator bool() const;///< True if not done iterating. + Iter & operator++();///::iterator aIt; + std::map::iterator oIt; + }; + class ConstIter { + public: + ConstIter(const Value & root);///() const;///< Dereferences into a Value reference. + operator bool() const;///< True if not done iterating. + ConstIter & operator++();///::const_iterator aIt; + std::map::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 std::string encodeVector(T begin, T end) { std::string result; diff --git a/lib/shared_memory.cpp b/lib/shared_memory.cpp index c6186ede..70bdfae9 100644 --- a/lib/shared_memory.cpp +++ b/lib/shared_memory.cpp @@ -13,6 +13,7 @@ #include "stream.h" #include "procs.h" #include "bitfields.h" +#include "timing.h" namespace IPC { @@ -206,6 +207,18 @@ namespace IPC { WARN_MSG("Consistency error caught on semaphore %s", myName.c_str()); 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 struct timespec wt; wt.tv_sec = 1; diff --git a/lsp/mist.js b/lsp/mist.js index de5fb329..a30f944f 100644 --- a/lsp/mist.js +++ b/lsp/mist.js @@ -3510,9 +3510,6 @@ var UI = { } $main.append(UI.buildUI([{ - type: 'help', - help: '' - },{ label: 'Trigger on', pointer: { main: saveas, @@ -3539,7 +3536,21 @@ var UI = { ['CONN_CLOSE', 'CONN_CLOSE: right after a connection has been closed'], ['CONN_PLAY', 'CONN_PLAY: right before a stream playback of a connection'] ], - LTSonly: true + LTSonly: true, + 'function': function(){ + var v = $(this).getval(); + switch (v) { + case 'SYSTEM_START': + case 'SYSTEM_STOP': + case 'SYSTEM_CONFIG': + case 'OUTPUT_START': + case 'OUTPUT_STOP': + $('[name=appliesto]').setval([]).closest('.UIelement').hide(); + break; + default: + $('[name=appliesto]').closest('.UIelement').show(); + } + } },{ label: 'Applies to', pointer: { @@ -3616,6 +3627,7 @@ var UI = { } ] }])); + $('[name=triggeron]').trigger('change'); break; case 'Logs': @@ -4534,7 +4546,7 @@ $.fn.setval = function(val){ } break; case 'checklist': - var $inputs = $(this).find('.checklist input[type=checkbox]'); + var $inputs = $(this).find('.checklist input[type=checkbox]').prop('checked',false); for (i in val) { $inputs.filter('[name="'+val[i]+'"]').prop('checked',true); } diff --git a/src/controller/controller.cpp b/src/controller/controller.cpp index 3fb60d5d..1e5e2062 100644 --- a/src/controller/controller.cpp +++ b/src/controller/controller.cpp @@ -251,10 +251,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); } } @@ -319,8 +319,8 @@ int main(int argc, char ** argv){ //write config tthread::lock_guard 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"); } if ( !Controller::WriteFile(Controller::conf.getString("configFile"), Controller::Storage.toString())){ std::cerr << "Error writing config " << Controller::conf.getString("configFile") << std::endl; diff --git a/src/controller/controller_connectors.cpp b/src/controller/controller_connectors.cpp index 4351b78e..1354dfc7 100644 --- a/src/controller/controller_connectors.cpp +++ b/src/controller/controller_connectors.cpp @@ -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 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); } diff --git a/src/controller/controller_connectors.h b/src/controller/controller_connectors.h index 7e8b4c18..97e53267 100644 --- a/src/controller/controller_connectors.h +++ b/src/controller/controller_connectors.h @@ -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); } diff --git a/src/controller/controller_statistics.cpp b/src/controller/controller_statistics.cpp index ddb19cc9..072f569a 100644 --- a/src/controller/controller_statistics.cpp +++ b/src/controller/controller_statistics.cpp @@ -509,7 +509,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;} @@ -526,14 +526,14 @@ void Controller::fillClients(JSON::Value & req, JSON::Value & rep){ //figure out what streams are wanted std::set 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 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()); } } @@ -692,7 +692,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;} @@ -703,14 +703,14 @@ void Controller::fillTotals(JSON::Value & req, JSON::Value & rep){ //figure out what streams are wanted std::set 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 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()); } } diff --git a/src/controller/controller_streams.cpp b/src/controller/controller_streams.cpp index 319a905b..8684042d 100644 --- a/src/controller/controller_streams.cpp +++ b/src/controller/controller_streams.cpp @@ -122,26 +122,26 @@ 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; } checkServerLimits(); /*LTS*/ }else{ // assume all is fine - jit->second.removeMember("error"); - jit->second["online"] = 1; + jit->removeMember("error"); + (*jit)["online"] = 1; } } @@ -157,17 +157,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()); } } } @@ -227,9 +227,10 @@ namespace Controller { //check for deleted streams std::set toDelete; - for (JSON::ObjIter jit = out.ObjBegin(); jit != out.ObjEnd(); jit++){ - if ( !in.isMember(jit->first)){ - toDelete.insert(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 @@ -240,15 +241,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"); } } diff --git a/src/input/input_flv.cpp b/src/input/input_flv.cpp index 82e0697a..b6163aa7 100644 --- a/src/input/input_flv.cpp +++ b/src/input/input_flv.cpp @@ -6,7 +6,6 @@ #include #include #include -#include #include #include "input_flv.h" @@ -66,7 +65,6 @@ namespace Mist { } //Create header file from FLV data fseek(inFile, 13, SEEK_SET); - FLV::Tag tmpTag; AMF::Object amf_storage; long long int lastBytePos = 13; while (!feof(inFile) && !FLV::Parse_Error){ @@ -90,7 +88,6 @@ namespace Mist { void inputFLV::getNext(bool smart) { long long int lastBytePos = ftell(inFile); - FLV::Tag tmpTag; while (!feof(inFile) && !FLV::Parse_Error){ if (tmpTag.FileLoader(inFile)){ if ( !selectedTracks.count(tmpTag.getTrackID())){ diff --git a/src/input/input_flv.h b/src/input/input_flv.h index 6a8d5af9..66b85861 100644 --- a/src/input/input_flv.h +++ b/src/input/input_flv.h @@ -1,5 +1,6 @@ #include "input.h" #include +#include namespace Mist { class inputFLV : public Input { @@ -12,7 +13,7 @@ namespace Mist { void getNext(bool smart = true); void seek(int seekTime); void trackSelect(std::string trackSpec); - + FLV::Tag tmpTag; FILE * inFile; }; } diff --git a/src/io.cpp b/src/io.cpp index d2864615..ec35814d 100644 --- a/src/io.cpp +++ b/src/io.cpp @@ -266,12 +266,13 @@ namespace Mist { INFO_MSG("Trying to buffer a packet on track %lu~>%lu, but no page is initialized", tid, mapTid); return; } + IPC::sharedPage & myPage = curPage[tid]; + DTSCPageData & pageData = pagesByTrack[tid][curPageNum[tid]]; //Save the current write position - size_t curOffset = pagesByTrack[tid][curPageNum[tid]].curOffset; - DONTEVEN_MSG("Buffering packet on page %lu for track %lu~>%lu: %d bytes @ %lu: %s", curPageNum[tid], tid, mapTid, pack.getDataLen(), curOffset); + size_t curOffset = pageData.curOffset; //Do nothing when there is not enough free space on the page to add the packet. - if (pagesByTrack[tid][curPageNum[tid]].dataSize - curOffset < pack.getDataLen()) { - FAIL_MSG("Trying to buffer a packet on page %lu for track %lu~>%lu, but we have a size mismatch. The packet is %d bytes long, so won't fit at offset %lu on a page of %llu bytes!", curPageNum[tid], tid, mapTid, pack.getDataLen(), curOffset, pagesByTrack[tid][curPageNum[tid]].dataSize); + if (pageData.dataSize - curOffset < pack.getDataLen()) { + FAIL_MSG("Trying to buffer a packet on page %lu for track %lu~>%lu, but we have a size mismatch. The packet is %d bytes long, so won't fit at offset %lu on a page of %llu bytes!", curPageNum[tid], tid, mapTid, pack.getDataLen(), curOffset, pageData.dataSize); return; } @@ -289,18 +290,18 @@ namespace Mist { //First memcpy only the payload to the destination //Leaves the 20 bytes inbetween empty to ensure the data is not accidentally read before it is complete - memcpy(curPage[tid].mapped + curOffset + 20, pack.getData() + 20, pack.getDataLen() - 20); + memcpy(myPage.mapped + curOffset + 20, pack.getData() + 20, pack.getDataLen() - 20); if (encrypt){ //write ivec field + new object end at (currOffset + pack.getDataLen() - 3); int ivecOffset = curOffset + pack.getDataLen() - 3; - memcpy(curPage[tid].mapped+ivecOffset, "\000\004ivec\002\000\000\000\010", 11); - memcpy(curPage[tid].mapped+ivecOffset+11, iVec, 8); + memcpy(myPage.mapped+ivecOffset, "\000\004ivec\002\000\000\000\010", 11); + memcpy(myPage.mapped+ivecOffset+11, iVec, 8); //finish container with 0x0000EE - memcpy(curPage[tid].mapped+ivecOffset+19, "\000\000\356", 3); + memcpy(myPage.mapped+ivecOffset+19, "\000\000\356", 3); } //Copy the remaing values in reverse order: //8 byte timestamp - memcpy(curPage[tid].mapped + curOffset + 12, pack.getData() + 12, 8); + memcpy(myPage.mapped + curOffset + 12, pack.getData() + 12, 8); //The mapped track id ((int *)(curPage[tid].mapped + curOffset + 8))[0] = htonl(mapTid); int size = Bit::btohl(pack.getData() + 4); @@ -316,12 +317,12 @@ namespace Mist { if (myMeta.live){ //Update the metadata - DTSC::Packet updatePack(curPage[tid].mapped + curOffset, size + 8, true); + DTSC::Packet updatePack(myPage.mapped + curOffset, size + 8, true); myMeta.update(updatePack); } //End of brain melt - pagesByTrack[tid][curPageNum[tid]].curOffset += size + 8; + pageData.curOffset += size + 8; } ///Wraps up the buffering of a shared memory data page diff --git a/src/output/output.cpp b/src/output/output.cpp index 29192081..b00fcac5 100644 --- a/src/output/output.cpp +++ b/src/output/output.cpp @@ -169,14 +169,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::iterator itd = selectedTracks.begin(); itd != selectedTracks.end(); itd++){ if (myMeta.tracks[*itd].codec == (*itc).asStringRef()){ selCounter++; @@ -212,10 +212,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::iterator itd = selectedTracks.begin(); itd != selectedTracks.end(); itd++){ if (myMeta.tracks[*itd].codec == (*itc).asStringRef()){ found = true; diff --git a/src/output/output_hds.cpp b/src/output/output_hds.cpp index beec2895..b35ef718 100644 --- a/src/output/output_hds.cpp +++ b/src/output/output_hds.cpp @@ -13,14 +13,14 @@ namespace Mist { JSON::Value & vidCapa = capa["codecs"][0u][0u]; JSON::Value & audCapa = capa["codecs"][0u][1u]; for (std::map::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; diff --git a/src/output/output_http.cpp b/src/output/output_http.cpp index 4d72c11c..7dbe18a5 100644 --- a/src/output/output_http.cpp +++ b/src/output/output_http.cpp @@ -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()); } } } diff --git a/src/output/output_http_internal.cpp b/src/output/output_http_internal.cpp index 03ecfd13..15eb36a3 100644 --- a/src/output/output_http_internal.cpp +++ b/src/output/output_http_internal.cpp @@ -110,15 +110,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++; } @@ -143,7 +143,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); } @@ -327,11 +327,11 @@ 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"); - it->second.removeMember("ivecs");/*LTS*/ + jsonForEach(json_resp["meta"]["tracks"], it) { + it->removeMember("fragments"); + it->removeMember("keys"); + it->removeMember("parts"); + it->removeMember("ivecs");/*LTS*/ } //create a set for storing source information @@ -407,5 +407,4 @@ namespace Mist { return; } //embed code generator } - }