/*********************************************************************** * block factory - make blocks from JSON object **********************************************************************/ static Pothos::Proxy makeBlock( const Pothos::Proxy ®istry, const Pothos::Proxy &evaluator, const Poco::JSON::Object::Ptr &blockObj) { const auto id = blockObj->getValue<std::string>("id"); if (not blockObj->has("path")) throw Pothos::DataFormatException( "Pothos::Topology::make()", "blocks["+id+"] missing 'path' field"); const auto path = blockObj->getValue<std::string>("path"); //load up the constructor args Poco::JSON::Array::Ptr argsArray; if (blockObj->isArray("args")) argsArray = blockObj->getArray("args"); const auto ctorArgs = evalArgsArray(evaluator, argsArray); //create the block auto block = registry.getHandle()->call(path, ctorArgs.data(), ctorArgs.size()); //make the calls Poco::JSON::Array::Ptr callsArray; if (blockObj->isArray("calls")) callsArray = blockObj->getArray("calls"); if (callsArray) for (size_t i = 0; i < callsArray->size(); i++) { const auto callArray = callsArray->getArray(i); auto name = callArray->getElement<std::string>(0); const auto callArgs = evalArgsArray(evaluator, callArray, 1/*offset*/); block.getHandle()->call(name, callArgs.data(), callArgs.size()); } return block; }
void ProxyBlockEval::eval(const std::string &id, const Poco::JSON::Object::Ptr &blockDesc) { auto env = Pothos::ProxyEnvironment::make("managed"); auto registry = env->findProxy("Pothos/BlockRegistry"); auto path = blockDesc->getValue<std::string>("path"); //load up the constructor args std::vector<Pothos::Proxy> ctorArgs; if (blockDesc->isArray("args")) for (auto arg : *blockDesc->getArray("args")) { const auto obj = this->lookupOrEvalAsType(arg); ctorArgs.push_back(env->convertObjectToProxy(obj)); } //create the block try { _proxyBlock = registry.getHandle()->call(path, ctorArgs.data(), ctorArgs.size()); } catch (const Pothos::Exception &ex) { throw Pothos::Exception("ProxyBlockEval factory("+path+")", ex); } _proxyBlock.callVoid("setName", id); //make the calls if (blockDesc->isArray("calls")) for (auto call : *blockDesc->getArray("calls")) { this->handleCall(call.extract<Poco::JSON::Object::Ptr>()); } }
void BlockEval::eval(const std::string &id, const Poco::JSON::Object::Ptr &blockDesc) { auto env = Pothos::ProxyEnvironment::make("managed"); auto registry = env->findProxy("Pothos/BlockRegistry"); auto path = blockDesc->getValue<std::string>("path"); //load up the constructor args std::vector<Pothos::Proxy> ctorArgs; for (auto arg : *blockDesc->getArray("args")) { const auto propKey = arg.extract<std::string>(); const auto obj = _properties[propKey]; ctorArgs.push_back(env->convertObjectToProxy(obj)); } //create the block try { _proxyBlock = registry.getHandle()->call(path, ctorArgs.data(), ctorArgs.size()); } catch (const Pothos::Exception &ex) { throw Pothos::Exception("BlockEval factory("+path+")", ex); } _proxyBlock.callVoid("setName", id); //inspect before making any calls -- calls may fails _portDesc = this->inspectPorts(); //make the calls for (auto call : *blockDesc->getArray("calls")) { const auto callObj = call.extract<Poco::JSON::Object::Ptr>(); const auto callName = callObj->get("name").extract<std::string>(); std::vector<Pothos::Proxy> callArgs; for (auto arg : *callObj->getArray("args")) { const auto propKey = arg.extract<std::string>(); const auto obj = _properties[propKey]; callArgs.push_back(env->convertObjectToProxy(obj)); } try { _proxyBlock.getHandle()->call(callName, callArgs.data(), callArgs.size()); } catch (const Pothos::Exception &ex) { throw Pothos::Exception("BlockEval call("+callName+")", ex); } } //inspect after making calls -- ports may have changed _portDesc = this->inspectPorts(); }
void updateTasksList() { printf("updateTasksList()\n"); tasksNum = task_manager->getTasksNumber(); if(tasksNum > 0) { Poco::JSON::Object::Ptr pObj = new Poco::JSON::Object; task_manager->getTasks(pObj); Poco::DynamicStruct ds = *pObj; printf("ds:%s\n", ds.toString().c_str()); if(pObj->has("tasks")) printf("pObj has tasks\n"); if(pObj->isArray("tasks")) printf("pObj is array tasks\n"); Poco::JSON::Array::Ptr pArray = pObj->getArray("tasks"); printf("tasksNum:%d, array size:%d\n", tasksNum, pArray->size()); for(int i = 0; i < tasksNum; i++) { memset(pTask[i], 0, sizeof(TaskInfo)); Poco::Dynamic::Var var = pArray->get(i); Poco::DynamicStruct dss = var.extract<Poco::DynamicStruct>(); pTask[i]->id = (Poco::Int64)dss["id"].extract<Poco::Int64>(); pTask[i]->option = dss["option"].extract<int>(); pTask[i]->hour = dss["hour"].extract<int>(); pTask[i]->minute = dss["minute"].extract<int>(); pTask[i]->weekday = dss["weekday"].extract<int>(); } } }
QString BlockPropertiesPanel::getParamDocString(const Poco::JSON::Object::Ptr ¶mDesc) { assert(paramDesc); QString output; output += QString("<h3>%1</h3>").arg(QString::fromStdString(paramDesc->getValue<std::string>("name"))); if (paramDesc->isArray("desc")) for (const auto &lineObj : *paramDesc->getArray("desc")) { const auto line = lineObj.extract<std::string>(); if (line.empty()) output += "<p /><p>"; else output += QString::fromStdString(line)+"\n"; } else output += QString("<p>%1</p>").arg(tr("Undocumented")); return output; }
bool BlockTreeWidget::blockDescMatchesFilter(const Poco::JSON::Object::Ptr &blockDesc) { if (_filter.isEmpty()) return true; const auto path = blockDesc->get("path").extract<std::string>(); const auto name = blockDesc->get("name").extract<std::string>(); //construct a candidate string from path, name, categories, and keywords. std::string candidate = path+name; if (blockDesc->isArray("categories")) for (auto categoryObj : *blockDesc->getArray("categories")) { candidate += categoryObj.extract<std::string>(); } if(blockDesc->isArray("keywords")) { const auto keywords = blockDesc->getArray("keywords"); for(auto keyword : *keywords) candidate += keyword.extract<std::string>(); } //reject if filter string not found in candidate candidate = Poco::toLower(candidate); const auto searchToken = Poco::toLower(_filter.toStdString()); return (candidate.find(searchToken) != std::string::npos); }
void AffinityZoneEditor::loadFromConfig(const Poco::JSON::Object::Ptr &config) { if (config->has("color")) { auto color = QString::fromStdString(config->getValue<std::string>("color")); _colorPicker->blockSignals(true); _colorPicker->setCurrentColor(QColor(color)); _colorPicker->blockSignals(false); } if (config->has("hostUri")) { auto uri = QString::fromStdString(config->getValue<std::string>("hostUri")); this->selectThisUri(uri); } if (config->has("processName")) { auto name = QString::fromStdString(config->getValue<std::string>("processName")); _processNameEdit->setText(name); } if (config->has("numThreads")) { _numThreadsSpin->setValue(config->getValue<int>("numThreads")); } if (config->has("priority")) { _prioritySpin->setValue(int(config->getValue<double>("priority")*100)); } if (config->has("affinityMode") and config->has("affinityMask")) { auto mode = config->getValue<std::string>("affinityMode"); auto mask = config->getArray("affinityMask"); std::vector<size_t> selection; for (size_t i = 0; i < mask->size(); i++) selection.push_back(mask->getElement<int>(i)); _cpuSelection->setup(mode, selection); } if (config->has("yieldMode")) { auto mode = QString::fromStdString(config->getValue<std::string>("yieldMode")); for (int i = 0; i < _yieldModeBox->count(); i++) { if (_yieldModeBox->itemData(i).toString() == mode) _yieldModeBox->setCurrentIndex(i); } } }
void ProxyBlockEval::handleCall(const Poco::JSON::Object::Ptr &callObj) { auto env = Pothos::ProxyEnvironment::make("managed"); const auto callName = callObj->get("name").extract<std::string>(); std::vector<Pothos::Proxy> callArgs; for (auto arg : *callObj->getArray("args")) { const auto obj = this->lookupOrEvalAsType(arg); callArgs.push_back(env->convertObjectToProxy(obj)); } try { _proxyBlock.getHandle()->call(callName, callArgs.data(), callArgs.size()); } catch (const Pothos::Exception &ex) { throw Pothos::Exception("ProxyBlockEval call("+callName+")", ex); } }
static Poco::JSON::Array::Ptr getConnectedPortInfos( const Poco::JSON::Object::Ptr &topObj, const std::string &blockId, const bool enbFilter, const bool isInput) { const auto connsArray = topObj->getArray("connections"); const auto blocksObj = topObj->getObject("blocks"); const auto blockObj = blocksObj->getObject(blockId); //grab the raw ports info Poco::JSON::Array::Ptr portsInfo(new Poco::JSON::Array()); if (isInput and blockObj->has("inputs")) portsInfo = blockObj->getArray("inputs"); if (not isInput and blockObj->has("outputs")) portsInfo = blockObj->getArray("outputs"); //no filtering? return ASAP if (not enbFilter) return portsInfo; Poco::JSON::Array::Ptr filteredPortsInfo(new Poco::JSON::Array()); for (size_t i = 0; i < portsInfo->size(); i++) { const auto portInfo = portsInfo->getObject(i); for (size_t c_i = 0; c_i < connsArray->size(); c_i++) { const auto conn = connsArray->getObject(c_i); if ( (not isInput and blockId == conn->getValue<std::string>("srcId") and portInfo->getValue<std::string>("name") == conn->getValue<std::string>("srcName")) or (isInput and blockId == conn->getValue<std::string>("dstId") and portInfo->getValue<std::string>("name") == conn->getValue<std::string>("dstName")) ) { filteredPortsInfo->add(portInfo); break; } } } return filteredPortsInfo; }
static bool flattenDump(Poco::JSON::Object::Ptr &topObj) { assert(topObj); bool hierFound = false; //create new blocks object that flattens any hierarchy to 1 depth //if this block is a hierarchy -- bring its blocks to the top level const auto blocksObj = topObj->getObject("blocks"); assert(blocksObj); Poco::JSON::Object::Ptr flatBlocksObj(new Poco::JSON::Object()); std::vector<std::string> blockUids; blocksObj->getNames(blockUids); for (const auto &uid : blockUids) { const auto blockObj = blocksObj->getObject(uid); assert(blockObj); if (blockIsHier(blockObj)) { hierFound = true; const auto subBlocksObj = blockObj->getObject("blocks"); assert(subBlocksObj); const auto thisName = blockObj->getValue<std::string>("name"); std::vector<std::string> subBlockUids; subBlocksObj->getNames(subBlockUids); for (const auto &subUid : subBlockUids) { auto subBlockObj = subBlocksObj->getObject(subUid); assert(subBlockObj); const auto subName = subBlockObj->getValue<std::string>("name"); subBlockObj->set("name", thisName+"/"+subName); //heritage name flatBlocksObj->set(subUid, subBlockObj); } } else flatBlocksObj->set(uid, blockObj); } //create new connections array folding out depth 1 hierarchies const auto connsArray = topObj->getArray("connections"); assert(connsArray); Poco::JSON::Array::Ptr flatConnsArray(new Poco::JSON::Array()); for (size_t c_i = 0; c_i < connsArray->size(); c_i++) { const auto connObj = connsArray->getObject(c_i); assert(connObj); for (const auto & resolvedSrc : resolvePorts(topObj, connObj->getValue<std::string>("srcId"), connObj->getValue<std::string>("srcName"), true)) { for (const auto & resolvedDst : resolvePorts(topObj, connObj->getValue<std::string>("dstId"), connObj->getValue<std::string>("dstName"), false)) { Poco::JSON::Object::Ptr flatConnObj(new Poco::JSON::Object()); flatConnsArray->add(flatConnObj); flatConnObj->set("srcId", resolvedSrc.first); flatConnObj->set("srcName", resolvedSrc.second); flatConnObj->set("dstId", resolvedDst.first); flatConnObj->set("dstName", resolvedDst.second); } } } //resolve pass-through connections and totally internal connections for (const auto &uid : blockUids) { const auto blockObj = blocksObj->getObject(uid); assert(blockObj); if (not blockIsHier(blockObj)) continue; const auto subConnsArray = blockObj->getArray("connections"); for (size_t c_i = 0; c_i < subConnsArray->size(); c_i++) { const auto subConnObj = subConnsArray->getObject(c_i); assert(subConnObj); const bool srcIsThis = subConnObj->getValue<std::string>("srcId") == uid; const bool dstIsThis = subConnObj->getValue<std::string>("dstId") == uid; //totally internal connection if (not srcIsThis and not dstIsThis) flatConnsArray->add(subConnObj); //otherwise not a pass-through if (not srcIsThis or not dstIsThis) continue; //find sources where the destination is this pass-through for (size_t c_s = 0; c_s < connsArray->size(); c_s++) { const auto connObj_s = connsArray->getObject(c_s); assert(connObj_s); if (connObj_s->getValue<std::string>("dstId") != uid) continue; if (connObj_s->getValue<std::string>("dstName") != subConnObj->getValue<std::string>("srcName")) continue; //find sources where the destination is this pass-through for (size_t c_d = 0; c_d < connsArray->size(); c_d++) { const auto connObj_d = connsArray->getObject(c_d); assert(connObj_d); if (connObj_d->getValue<std::string>("srcId") != uid) continue; if (connObj_d->getValue<std::string>("srcName") != subConnObj->getValue<std::string>("dstName")) continue; Poco::JSON::Object::Ptr flatConnObj(new Poco::JSON::Object()); flatConnsArray->add(flatConnObj); flatConnObj->set("srcId", connObj_s->get("srcId")); flatConnObj->set("srcName", connObj_s->get("srcName")); flatConnObj->set("dstId", connObj_d->get("dstId")); flatConnObj->set("dstName", connObj_d->get("dstName")); } } } } //set new flat data into the top object topObj = new Poco::JSON::Object(); topObj->set("blocks", flatBlocksObj); topObj->set("connections", flatConnsArray); return hierFound; }
/*********************************************************************** * Parse a single documentation block for markup **********************************************************************/ static Poco::JSON::Object::Ptr parseCommentBlockForMarkup(const CodeBlock &commentBlock) { Poco::JSON::Object::Ptr topObj(new Poco::JSON::Object()); Poco::JSON::Array calls; Poco::JSON::Array keywords; Poco::JSON::Array::Ptr aliases(new Poco::JSON::Array()); Poco::JSON::Array categories; Poco::JSON::Array params; Poco::JSON::Array::Ptr topDocs(new Poco::JSON::Array()); Poco::JSON::Object::Ptr currentParam; std::string state; std::string indent; std::string instruction; std::string payload; //search for the markup begin tag and record the indent for (const auto &codeLine : commentBlock) { std::string line = codeLine.text; Poco::RegularExpression::MatchVec matches; if (not state.empty()) { if (line.size() >= indent.size() and line.substr(0, indent.size()) != indent) { if (codeLine.lineNo == commentBlock.back().lineNo) line = ""; else throw Pothos::SyntaxException("Inconsistent indentation", codeLine.toString()); } if (line.size() >= indent.size()) line = line.substr(indent.size()); else line = ""; Poco::RegularExpression("^\\|(\\w+)\\s+(.*)$").match(line, 0, matches); if (not matches.empty()) { assert(matches.size() == 3); instruction = line.substr(matches[1].offset, matches[1].length); payload = line.substr(matches[2].offset, matches[2].length); } } if (state.empty()) { Poco::RegularExpression("^(.*)\\|PothosDoc\\s+(.*)$").match(line, 0, matches); if (matches.empty()) continue; assert(matches.size() == 3); indent = line.substr(matches[1].offset, matches[1].length); topObj->set("name", Poco::trim(line.substr(matches[2].offset, matches[2].length))); state = "DOC"; } else if (matches.empty() and state == "DOC") { topDocs->add(line); } else if (matches.empty() and state == "PARAM") { auto array = currentParam->getArray("desc"); array->add(line); currentParam->set("desc", stripDocArray(array)); } else if (instruction == "category" and state == "DOC") { categories.add(Poco::trim(payload)); } else if (instruction == "keywords" and state == "DOC") { for (const auto &keyword : Poco::StringTokenizer( payload, " \t", Poco::StringTokenizer::TOK_TRIM | Poco::StringTokenizer::TOK_IGNORE_EMPTY)) { keywords.add(Poco::trim(keyword)); } } else if (instruction == "alias" and state == "DOC") { const std::string alias(Poco::trim(payload)); try {Pothos::PluginPath(alias);} catch (const Pothos::PluginPathError &) { throw Pothos::SyntaxException("Invalid alias path", codeLine.toString()); } aliases->add(alias); } else if (instruction == "param" and (state == "DOC" or state == "PARAM")) { payload = bracketEscapeEncode(payload); Poco::RegularExpression::MatchVec fields; Poco::RegularExpression("^\\s*(\\w+)(\\s*\\[(.*)\\]\\s*)?(.*)$").match(payload, 0, fields); if (fields.empty()) throw Pothos::SyntaxException( "Expected |param key[name] description", codeLine.toString()); assert(fields.size() == 5); const std::string key = bracketEscapeDecode(Poco::trim(payload.substr(fields[1].offset, fields[1].length))); std::string name = titleCase(key); if (fields[3].length != 0) name = bracketEscapeDecode(Poco::trim(payload.substr(fields[3].offset, fields[3].length))); const std::string desc = bracketEscapeDecode(Poco::trim(payload.substr(fields[4].offset, fields[4].length))); currentParam = Poco::JSON::Object::Ptr(new Poco::JSON::Object()); params.add(currentParam); currentParam->set("key", key); currentParam->set("name", name); Poco::JSON::Array::Ptr descArr(new Poco::JSON::Array()); descArr->add(desc); currentParam->set("desc", descArr); state = "PARAM"; } else if (instruction == "default" and state == "PARAM") { if (currentParam->has("default")) throw Pothos::SyntaxException( "Multiple occurrence of |default for param", codeLine.toString()); currentParam->set("default", payload); } else if (instruction == "units" and state == "PARAM") { if (currentParam->has("units")) throw Pothos::SyntaxException( "Multiple occurrence of |units for param", codeLine.toString()); currentParam->set("units", payload); } else if (instruction == "widget" and state == "PARAM") { if (currentParam->has("widgetType")) throw Pothos::SyntaxException( "Multiple occurrence of |widget for param", codeLine.toString()); Poco::RegularExpression::MatchVec fields; Poco::RegularExpression("^\\s*(\\w+)\\s*\\((.*)\\)$").match(payload, 0, fields); if (fields.empty()) throw Pothos::SyntaxException( "Expected |widget SpinBox(args...)", codeLine.toString()); assert(fields.size() == 3); const std::string widgetType = Poco::trim(payload.substr(fields[1].offset, fields[1].length)); const std::string argsStr = Poco::trim(payload.substr(fields[2].offset, fields[2].length)); currentParam->set("widgetType", widgetType); loadArgs(codeLine, *currentParam, argsStr, "widgetArgs", "widgetKwargs"); } else if (instruction == "tab" and state == "PARAM") { if (currentParam->has("tab")) throw Pothos::SyntaxException( "Multiple occurrence of |tab for param", codeLine.toString()); currentParam->set("tab", payload); } else if (instruction == "preview" and state == "PARAM") { if (currentParam->has("preview")) throw Pothos::SyntaxException( "Multiple occurrence of preview for param", codeLine.toString()); Poco::RegularExpression::MatchVec fields; Poco::RegularExpression("^\\s*(\\w+)(\\s*\\((.*)\\))?$").match(payload, 0, fields); if (fields.empty()) throw Pothos::SyntaxException( "Expected |preview previewType(args...)", codeLine.toString()); assert(fields.size() == 2 or fields.size() == 4); const std::string previewType = Poco::trim(payload.substr(fields[1].offset, fields[1].length)); if (previewType != "disable" and previewType != "enable" and previewType != "valid" and previewType != "invalid" and previewType != "when" ) throw Pothos::SyntaxException( "Only supports enable/disable/valid/invalid/when as value for preview option of param", codeLine.toString()); currentParam->set("preview", previewType); if (fields.size() == 4) { const std::string argsStr = Poco::trim(payload.substr(fields[3].offset, fields[3].length)); loadArgs(codeLine, *currentParam, argsStr, "previewArgs", "previewKwargs"); } } else if (instruction == "option" and state == "PARAM") { payload = bracketEscapeEncode(payload); Poco::RegularExpression::MatchVec fields; Poco::RegularExpression("^(\\s*\\[(.*)\\]\\s*)?(.*)$").match(payload, 0, fields); if (fields.empty()) throw Pothos::SyntaxException( "Expected |option [name] value", codeLine.toString()); assert(fields.size() == 4); const std::string value = bracketEscapeDecode(Poco::trim(payload.substr(fields[3].offset, fields[3].length))); std::string name = titleCase(value); if (fields[2].length != 0) name = bracketEscapeDecode(Poco::trim(payload.substr(fields[2].offset, fields[2].length))); Poco::JSON::Object option; option.set("value", value); option.set("name", name); if (not currentParam->has("options")) currentParam->set( "options", Poco::JSON::Array::Ptr(new Poco::JSON::Array())); currentParam->getArray("options")->add(option); } else if (instruction == "factory" and (state == "DOC" or state == "PARAM")) { Poco::RegularExpression::MatchVec fields; Poco::RegularExpression("^\\s*(/.*)\\s*\\((.*)\\)$").match(payload, 0, fields); if (fields.empty()) throw Pothos::SyntaxException( "Expected |factory /registry/path(args...)", codeLine.toString()); assert(fields.size() == 3); const std::string path = Poco::trim(payload.substr(fields[1].offset, fields[1].length)); const std::string argsStr = Poco::trim(payload.substr(fields[2].offset, fields[2].length)); //add the path try {Pothos::PluginPath(path);} catch (const Pothos::PluginPathError &) { throw Pothos::SyntaxException("Invalid factory path", codeLine.toString()); } if (topObj->has("path")) throw Pothos::SyntaxException( "Multiple occurrence of |factory", codeLine.toString()); topObj->set("path", path); //split and extract args loadArgs(codeLine, *topObj, argsStr); state = "DOC"; } else if ((instruction == "setter" or instruction == "initializer") and (state == "DOC" or state == "PARAM")) { Poco::RegularExpression::MatchVec fields; Poco::RegularExpression("^\\s*(\\w+)\\s*\\((.*)\\)$").match(payload, 0, fields); if (fields.empty()) throw Pothos::SyntaxException( "Expected |"+instruction+" setFooBar(args...)", codeLine.toString()); assert(fields.size() == 3); const std::string callName = Poco::trim(payload.substr(fields[1].offset, fields[1].length)); const std::string argsStr = Poco::trim(payload.substr(fields[2].offset, fields[2].length)); //add to calls Poco::JSON::Object call; call.set("type", instruction); call.set("name", callName); loadArgs(codeLine, call, argsStr); calls.add(call); state = "DOC"; } else if (instruction == "mode" and (state == "DOC" or state == "PARAM")) { if (topObj->has("mode")) throw Pothos::SyntaxException( "Multiple occurrence of |mode", codeLine.toString()); topObj->set("mode", payload); } } //empty state means this was a regular comment block, return null if (state.empty()) return Poco::JSON::Object::Ptr(); topDocs = stripDocArray(topDocs); if (topDocs->size() > 0) topObj->set("docs", topDocs); if (categories.size() > 0) topObj->set("categories", categories); if (keywords.size() > 0) topObj->set("keywords", keywords); if (aliases->size() > 0) topObj->set("aliases", aliases); if (params.size() > 0) topObj->set("params", params); if (calls.size() > 0) topObj->set("calls", calls); //sanity check for required stuff if (not topObj->has("path")) { throw Pothos::SyntaxException("missing |factory declaration"); } return topObj; }