ActionResponse Service::onAction(const std::string& action, const xml::Document& doc) { try { ActionResponse response(action, ServiceType::ConnectionManager); auto request = doc.getFirstChild(); switch (actionFromString(action)) { case Action::GetProtocolInfo: response.addArgument("Source", getVariable(Variable::SourceProtocolInfo).getValue()); response.addArgument("Sink", getVariable(Variable::SinkProtocolInfo).getValue()); break; case Action::PrepareForConnection: { ConnectionInfo connInfo; connInfo.peerConnectionManager = request.getChildNodeValue("PeerConnectionManager"); connInfo.peerConnectionId = std::stoi(request.getChildNodeValue("PeerConnectionID")); connInfo.direction = directionFromString(request.getChildNodeValue("Direction")); ProtocolInfo protoInfo(request.getChildNodeValue("RemoteProtocolInfo"));; m_connectionManager.prepareForConnection(protoInfo, connInfo); response.addArgument("ConnectionID", std::to_string(connInfo.connectionId)); response.addArgument("AVTransportID", std::to_string(connInfo.avTransportId)); response.addArgument("RcsID", std::to_string(connInfo.renderingControlServiceId)); break; } case Action::ConnectionComplete: m_connectionManager.connectionComplete(std::stoi(request.getChildNodeValue("ConnectionID"))); break; case Action::GetCurrentConnectionIDs: response.addArgument("ConnectionIDs", getVariable(Variable::CurrentConnectionIds).getValue()); break; case Action::GetCurrentConnectionInfo: { auto connInfo = m_connectionManager.getCurrentConnectionInfo(std::stoi(request.getChildNodeValue("ConnectionID"))); response.addArgument("RcsID", std::to_string(connInfo.renderingControlServiceId)); response.addArgument("AVTransportID", std::to_string(connInfo.avTransportId)); response.addArgument("ProtocolInfo", connInfo.protocolInfo.toString()); response.addArgument("PeerConnectionManager", connInfo.peerConnectionManager); response.addArgument("PeerConnectionID", std::to_string(connInfo.peerConnectionId)); response.addArgument("Direction", toString(connInfo.direction)); response.addArgument("Status", toString(connInfo.connectionStatus)); break; } default: throw InvalidActionException(); } return response; } catch (std::exception& e) { log::error("Error processing ConnectionManager request: %s", e.what()); throw InvalidActionException(); } }
void APEditHandler::move(Direction direction) { if (direction == Forward) current++; QString joinedActions = history[current]; QStringList actions = joinedActions.split(ActionSeparator); foreach (QString serializedAction, actions) { QStringList tokens = serializedAction.split(InfoSeparator); EditAction action = actionFromString(tokens.first()); QString info = tokens.last(); EPSegment *segment; switch (action) { case Create: // info is just a serialized segment case Remove: { segment = EPSegment::unserialize(info); if ((direction == Forward && action == Create) || (direction == Backward && action == Remove)) profile->addSegment(segment, true); else profile->removeSegmentWithId(segment->id(), true); break; } case Update: { // info has format: id:property=prev-next QStringList idAndChange = info.split(":"); int id = idAndChange.first().toInt(); segment = profile->segmentWithId(id); if (!segment) { qCritical("APEditHandler::move() => no segment found for " "requested id %i", id); } segment->pushSerializedChange(idAndChange.last(), direction); break; } case None: break; } }
Command *CommandParser::parse(const std::vector<std::string> &argv) { command_.clear(); if (argv.begin() == argv.end()) { std::clog << "error: no command specified.\n" "See 'irony-server help' to list available commands\n"; return 0; } const std::string &actionStr = argv[0]; command_.action = actionFromString(actionStr); bool handleUnsaved = false; bool readCompileOptions = false; std::vector<std::function<bool(const std::string &)>> positionalArgs; switch (command_.action) { case Command::SetDebug: positionalArgs.push_back(OptionConverter(&command_.opt)); break; case Command::Parse: positionalArgs.push_back(StringConverter(&command_.file)); handleUnsaved = true; readCompileOptions = true; break; case Command::Complete: positionalArgs.push_back(StringConverter(&command_.file)); positionalArgs.push_back(UnsignedIntConverter(&command_.line)); positionalArgs.push_back(UnsignedIntConverter(&command_.column)); handleUnsaved = true; readCompileOptions = true; break; case Command::GetType: positionalArgs.push_back(UnsignedIntConverter(&command_.line)); positionalArgs.push_back(UnsignedIntConverter(&command_.column)); break; case Command::Diagnostics: case Command::Help: case Command::Exit: // no-arguments commands break; case Command::GetCompileOptions: positionalArgs.push_back(StringConverter(&command_.dir)); positionalArgs.push_back(StringConverter(&command_.file)); break; case Command::Unknown: std::clog << "error: invalid command specified: " << actionStr << "\n"; return 0; } auto argIt = argv.begin() + 1; int argCount = std::distance(argIt, argv.end()); // parse optional arguments come first while (argIt != argv.end()) { // '-' is allowed as a "default" file, this isn't an option but a positional // argument if ((*argIt)[0] != '-' || *argIt == "-") break; const std::string &opt = *argIt; ++argIt; argCount--; if (handleUnsaved) { // TODO: handle multiple unsaved files if (opt == "--num-unsaved=1") { command_.unsavedFiles.resize(1); } } else { std::clog << "error: invalid option for '" << actionStr << "': '" << opt << "' unknown\n"; return 0; } } if (argCount != static_cast<int>(positionalArgs.size())) { std::clog << "error: invalid number of arguments for '" << actionStr << "' (requires " << positionalArgs.size() << " got " << argCount << ")\n"; return 0; } for (auto fn : positionalArgs) { if (!fn(*argIt)) { std::clog << "error: parsing command '" << actionStr << "': invalid argument '" << *argIt << "'\n"; return 0; } ++argIt; } // '-' is used as a special file to inform that the buffer hasn't been saved // on disk and only the buffer content is available. libclang needs a file, so // this is treated as a special value for irony-server to create a temporary // file for this. note taht libclang will gladly accept '-' as a filename but // we don't want to let this happen since irony already reads stdin. if (command_.file == "-") { command_.file = tempFile_.getPath(); } // When a file is provided, the next line contains the compilation options to // pass to libclang. if (readCompileOptions) { std::string compileOptions; std::getline(std::cin, compileOptions); command_.flags = unescapeCommandLine(compileOptions); } // read unsaved files // filename // filesize // <file content...> for (auto &p : command_.unsavedFiles) { std::getline(std::cin, p.first); unsigned length; std::string filesizeStr; std::getline(std::cin, filesizeStr); UnsignedIntConverter uintConverter(&length); if (!uintConverter(filesizeStr)) { std::clog << "error: invalid file size '" << filesizeStr << "'\n"; return 0; } p.second.resize(length); std::cin.read(p.second.data(), p.second.size()); CXUnsavedFile cxUnsavedFile; cxUnsavedFile.Filename = p.first.c_str(); cxUnsavedFile.Contents = p.second.data(); cxUnsavedFile.Length = p.second.size(); command_.cxUnsavedFiles.push_back(cxUnsavedFile); char nl; std::cin.read(&nl, 1); if (nl != '\n') { std::clog << "error: missing newline for unsaved file content\n"; return 0; } } return &command_; }