annotate utilities/vampipe-convert.cpp @ 31:b376ab0ce003

Begin server
author Chris Cannam <c.cannam@qmul.ac.uk>
date Tue, 24 May 2016 16:30:01 +0100
parents eb679afcd1bb
children 2d97883d20df
rev   line source
c@23 1
c@23 2 #include "VampJson.h"
c@23 3 #include "VampnProto.h"
c@23 4
c@31 5 #include "bits/RequestOrResponse.h"
c@31 6
c@23 7 #include <iostream>
c@23 8 #include <sstream>
c@23 9 #include <stdexcept>
c@23 10
c@23 11 using namespace std;
c@23 12 using namespace json11;
c@23 13 using namespace vampipe;
c@23 14
c@23 15 void usage()
c@23 16 {
c@23 17 string myname = "vampipe-convert";
c@23 18 cerr << "\n" << myname <<
c@24 19 ": Validate and convert Vamp request and response messages\n\n"
c@24 20 " Usage: " << myname << " [-i <informat>] [-o <outformat>] request\n"
c@24 21 " " << myname << " [-i <informat>] [-o <outformat>] response\n\n"
c@24 22 " where\n"
c@24 23 " <informat>: the format to read from stdin\n"
c@24 24 " (\"json\" or \"capnp\", default is \"json\")\n"
c@24 25 " <outformat>: the format to convert to and write to stdout\n"
c@24 26 " (\"json\" or \"capnp\", default is \"json\")\n"
c@24 27 " request|response: whether to expect Vamp request or response messages\n\n"
c@24 28 "If <informat> and <outformat> differ, convert from <informat> to <outformat>.\n"
c@24 29 "If <informat> and <outformat> are the same, just check validity of incoming\n"
c@24 30 "messages and pass them to output.\n\n";
c@24 31
c@23 32 exit(2);
c@23 33 }
c@23 34
c@24 35 Json
c@24 36 convertRequestJson(string input)
c@24 37 {
c@24 38 string err;
c@24 39 Json j = Json::parse(input, err);
c@24 40 if (err != "") {
c@24 41 throw VampJson::Failure("invalid json: " + err);
c@24 42 }
c@24 43 if (!j.is_object()) {
c@24 44 throw VampJson::Failure("object expected at top level");
c@24 45 }
c@24 46 if (!j["type"].is_string()) {
c@24 47 throw VampJson::Failure("string expected for type field");
c@24 48 }
c@24 49 if (!j["content"].is_object()) {
c@24 50 throw VampJson::Failure("object expected for content field");
c@24 51 }
c@24 52 return j;
c@24 53 }
c@24 54
c@24 55 Json
c@24 56 convertResponseJson(string input)
c@24 57 {
c@24 58 string err;
c@24 59 Json j = Json::parse(input, err);
c@24 60 if (err != "") {
c@24 61 throw VampJson::Failure("invalid json: " + err);
c@24 62 }
c@24 63 if (!j.is_object()) {
c@24 64 throw VampJson::Failure("object expected at top level");
c@24 65 }
c@24 66 if (!j["success"].is_bool()) {
c@24 67 throw VampJson::Failure("bool expected for success field");
c@24 68 }
c@24 69 if (!j["content"].is_object()) {
c@24 70 throw VampJson::Failure("object expected for content field");
c@24 71 }
c@24 72 return j;
c@24 73 }
c@24 74
c@30 75 //!!! Lots of potential for refactoring the conversion classes based
c@30 76 //!!! on the common matter in the following eight functions...
c@30 77
c@23 78 RequestOrResponse
c@24 79 readRequestJson()
c@23 80 {
c@23 81 RequestOrResponse rr;
c@24 82 rr.direction = RequestOrResponse::Request;
c@24 83
c@24 84 string input;
c@24 85 if (!getline(cin, input)) {
c@25 86 rr.type = RRType::NotValid;
c@24 87 return rr;
c@24 88 }
c@24 89
c@24 90 Json j = convertRequestJson(input);
c@27 91
c@25 92 rr.type = VampJson::getRequestResponseType(j);
c@24 93
c@27 94 switch (rr.type) {
c@27 95
c@27 96 case RRType::List:
c@27 97 VampJson::toVampRequest_List(j); // type check only
c@27 98 break;
c@27 99 case RRType::Load:
c@24 100 rr.loadRequest = VampJson::toVampRequest_Load(j);
c@27 101 break;
c@27 102 case RRType::Configure:
c@27 103 rr.configurationRequest =
c@27 104 VampJson::toVampRequest_Configure(j, rr.mapper);
c@27 105 break;
c@27 106 case RRType::Process:
c@24 107 rr.processRequest = VampJson::toVampRequest_Process(j, rr.mapper);
c@27 108 break;
c@27 109 case RRType::Finish:
c@24 110 rr.finishPlugin = VampJson::toVampRequest_Finish(j, rr.mapper);
c@27 111 break;
c@27 112 case RRType::NotValid:
c@27 113 break;
c@24 114 }
c@24 115
c@24 116 return rr;
c@24 117 }
c@24 118
c@24 119 void
c@24 120 writeRequestJson(RequestOrResponse &rr)
c@24 121 {
c@24 122 Json j;
c@24 123
c@27 124 switch (rr.type) {
c@27 125
c@27 126 case RRType::List:
c@24 127 j = VampJson::fromVampRequest_List();
c@27 128 break;
c@27 129 case RRType::Load:
c@24 130 j = VampJson::fromVampRequest_Load(rr.loadRequest);
c@27 131 break;
c@27 132 case RRType::Configure:
c@27 133 j = VampJson::fromVampRequest_Configure(rr.configurationRequest,
c@27 134 rr.mapper);
c@27 135 break;
c@27 136 case RRType::Process:
c@24 137 j = VampJson::fromVampRequest_Process(rr.processRequest, rr.mapper);
c@27 138 break;
c@27 139 case RRType::Finish:
c@24 140 j = VampJson::fromVampRequest_Finish(rr.finishPlugin, rr.mapper);
c@27 141 break;
c@27 142 case RRType::NotValid:
c@27 143 break;
c@24 144 }
c@24 145
c@24 146 cout << j.dump() << endl;
c@24 147 }
c@24 148
c@24 149 RequestOrResponse
c@24 150 readResponseJson()
c@24 151 {
c@24 152 RequestOrResponse rr;
c@24 153 rr.direction = RequestOrResponse::Response;
c@24 154
c@23 155 string input;
c@23 156 if (!getline(cin, input)) {
c@25 157 rr.type = RRType::NotValid;
c@23 158 return rr;
c@23 159 }
c@23 160
c@24 161 Json j = convertResponseJson(input);
c@27 162
c@25 163 rr.type = VampJson::getRequestResponseType(j);
c@23 164
c@27 165 switch (rr.type) {
c@27 166
c@27 167 case RRType::List:
c@24 168 rr.listResponse = VampJson::toVampResponse_List(j);
c@27 169 break;
c@27 170 case RRType::Load:
c@24 171 rr.loadResponse = VampJson::toVampResponse_Load(j, rr.mapper);
c@27 172 break;
c@27 173 case RRType::Configure:
c@24 174 rr.configurationResponse = VampJson::toVampResponse_Configure(j);
c@27 175 break;
c@27 176 case RRType::Process:
c@24 177 rr.processResponse = VampJson::toVampResponse_Process(j);
c@27 178 break;
c@27 179 case RRType::Finish:
c@24 180 rr.finishResponse = VampJson::toVampResponse_Finish(j);
c@27 181 break;
c@27 182 case RRType::NotValid:
c@27 183 break;
c@23 184 }
c@23 185
c@23 186 return rr;
c@23 187 }
c@23 188
c@24 189 void
c@24 190 writeResponseJson(RequestOrResponse &rr)
c@24 191 {
c@24 192 Json j;
c@24 193
c@27 194 switch (rr.type) {
c@27 195
c@27 196 case RRType::List:
c@24 197 j = VampJson::fromVampResponse_List("", rr.listResponse);
c@27 198 break;
c@27 199 case RRType::Load:
c@24 200 j = VampJson::fromVampResponse_Load(rr.loadResponse, rr.mapper);
c@27 201 break;
c@27 202 case RRType::Configure:
c@27 203 j = VampJson::fromVampResponse_Configure(rr.configurationResponse);
c@27 204 break;
c@27 205 case RRType::Process:
c@27 206 j = VampJson::fromVampResponse_Process(rr.processResponse);
c@27 207 break;
c@27 208 case RRType::Finish:
c@27 209 j = VampJson::fromVampResponse_Finish(rr.finishResponse);
c@27 210 break;
c@27 211 case RRType::NotValid:
c@27 212 break;
c@24 213 }
c@24 214
c@27 215 cout << j.dump() << endl;
c@27 216 }
c@25 217
c@27 218 RequestOrResponse
c@27 219 readRequestCapnp()
c@27 220 {
c@27 221 RequestOrResponse rr;
c@27 222 rr.direction = RequestOrResponse::Request;
c@27 223
c@27 224 ::capnp::PackedFdMessageReader message(0); // stdin
c@27 225 VampRequest::Reader reader = message.getRoot<VampRequest>();
c@27 226
c@27 227 rr.type = VampnProto::getRequestResponseType(reader);
c@27 228
c@27 229 switch (rr.type) {
c@27 230
c@27 231 case RRType::List:
c@27 232 VampnProto::readVampRequest_List(reader); // type check only
c@27 233 break;
c@27 234 case RRType::Load:
c@27 235 VampnProto::readVampRequest_Load(rr.loadRequest, reader);
c@27 236 break;
c@27 237 case RRType::Configure:
c@27 238 VampnProto::readVampRequest_Configure(rr.configurationRequest, reader,
c@27 239 rr.mapper);
c@27 240 break;
c@27 241 case RRType::Process:
c@27 242 VampnProto::readVampRequest_Process(rr.processRequest, reader,
c@27 243 rr.mapper);
c@27 244 break;
c@27 245 case RRType::Finish:
c@27 246 VampnProto::readVampRequest_Finish(rr.finishPlugin, reader,
c@27 247 rr.mapper);
c@27 248 break;
c@27 249 case RRType::NotValid:
c@27 250 break;
c@27 251 }
c@27 252
c@27 253 return rr;
c@27 254 }
c@27 255
c@29 256 void
c@29 257 writeRequestCapnp(RequestOrResponse &rr)
c@29 258 {
c@29 259 ::capnp::MallocMessageBuilder message;
c@29 260 VampRequest::Builder builder = message.initRoot<VampRequest>();
c@29 261
c@29 262 switch (rr.type) {
c@29 263
c@29 264 case RRType::List:
c@29 265 VampnProto::buildVampRequest_List(builder);
c@29 266 break;
c@29 267 case RRType::Load:
c@29 268 VampnProto::buildVampRequest_Load(builder, rr.loadRequest);
c@29 269 break;
c@29 270 case RRType::Configure:
c@29 271 VampnProto::buildVampRequest_Configure(builder,
c@29 272 rr.configurationRequest,
c@29 273 rr.mapper);
c@29 274 break;
c@29 275 case RRType::Process:
c@29 276 VampnProto::buildVampRequest_Process(builder,
c@29 277 rr.processRequest,
c@29 278 rr.mapper);
c@29 279 break;
c@29 280 case RRType::Finish:
c@29 281 VampnProto::buildVampRequest_Finish(builder,
c@29 282 rr.finishPlugin,
c@29 283 rr.mapper);
c@29 284 break;
c@29 285 case RRType::NotValid:
c@29 286 break;
c@29 287 }
c@29 288
c@29 289 writePackedMessageToFd(1, message);
c@29 290 }
c@29 291
c@27 292 RequestOrResponse
c@27 293 readResponseCapnp()
c@27 294 {
c@27 295 RequestOrResponse rr;
c@27 296 rr.direction = RequestOrResponse::Response;
c@27 297
c@27 298 ::capnp::PackedFdMessageReader message(0); // stdin
c@27 299 VampResponse::Reader reader = message.getRoot<VampResponse>();
c@27 300
c@27 301 rr.type = VampnProto::getRequestResponseType(reader);
c@27 302
c@27 303 switch (rr.type) {
c@27 304
c@27 305 case RRType::List:
c@27 306 VampnProto::readVampResponse_List(rr.listResponse, reader);
c@27 307 break;
c@27 308 case RRType::Load:
c@27 309 VampnProto::readVampResponse_Load(rr.loadResponse, reader, rr.mapper);
c@27 310 break;
c@27 311 case RRType::Configure:
c@27 312 VampnProto::readVampResponse_Configure(rr.configurationResponse,
c@27 313 reader);
c@27 314 break;
c@27 315 case RRType::Process:
c@27 316 VampnProto::readVampResponse_Process(rr.processResponse, reader);
c@27 317 break;
c@27 318 case RRType::Finish:
c@27 319 VampnProto::readVampResponse_Finish(rr.finishResponse, reader);
c@27 320 break;
c@27 321 case RRType::NotValid:
c@27 322 break;
c@27 323 }
c@27 324
c@27 325 return rr;
c@24 326 }
c@24 327
c@29 328 void
c@29 329 writeResponseCapnp(RequestOrResponse &rr)
c@29 330 {
c@29 331 ::capnp::MallocMessageBuilder message;
c@29 332 VampResponse::Builder builder = message.initRoot<VampResponse>();
c@29 333
c@29 334 switch (rr.type) {
c@29 335
c@29 336 case RRType::List:
c@29 337 VampnProto::buildVampResponse_List(builder, "", rr.listResponse);
c@29 338 break;
c@29 339 case RRType::Load:
c@29 340 VampnProto::buildVampResponse_Load(builder, rr.loadResponse, rr.mapper);
c@29 341 break;
c@29 342 case RRType::Configure:
c@29 343 VampnProto::buildVampResponse_Configure(builder, rr.configurationResponse);
c@29 344 break;
c@29 345 case RRType::Process:
c@29 346 VampnProto::buildVampResponse_Process(builder, rr.processResponse);
c@29 347 break;
c@29 348 case RRType::Finish:
c@29 349 VampnProto::buildVampResponse_Finish(builder, rr.finishResponse);
c@29 350 break;
c@29 351 case RRType::NotValid:
c@29 352 break;
c@29 353 }
c@29 354
c@29 355 writePackedMessageToFd(1, message);
c@29 356 }
c@29 357
c@23 358 RequestOrResponse
c@24 359 readInput(string format, RequestOrResponse::Direction direction)
c@23 360 {
c@23 361 if (format == "json") {
c@24 362 if (direction == RequestOrResponse::Request) {
c@24 363 return readRequestJson();
c@24 364 } else {
c@24 365 return readResponseJson();
c@24 366 }
c@27 367 } else if (format == "capnp") {
c@27 368 if (direction == RequestOrResponse::Request) {
c@27 369 return readRequestCapnp();
c@27 370 } else {
c@27 371 return readResponseCapnp();
c@27 372 }
c@23 373 } else {
c@27 374 throw runtime_error("unknown input format \"" + format + "\"");
c@23 375 }
c@23 376 }
c@23 377
c@23 378 void
c@24 379 writeOutput(string format, RequestOrResponse &rr)
c@23 380 {
c@24 381 if (format == "json") {
c@24 382 if (rr.direction == RequestOrResponse::Request) {
c@24 383 writeRequestJson(rr);
c@24 384 } else {
c@24 385 writeResponseJson(rr);
c@24 386 }
c@29 387 } else if (format == "capnp") {
c@29 388 if (rr.direction == RequestOrResponse::Request) {
c@29 389 writeRequestCapnp(rr);
c@29 390 } else {
c@29 391 writeResponseCapnp(rr);
c@29 392 }
c@24 393 } else {
c@27 394 throw runtime_error("unknown output format \"" + format + "\"");
c@24 395 }
c@23 396 }
c@23 397
c@23 398 int main(int argc, char **argv)
c@23 399 {
c@24 400 if (argc < 2) {
c@23 401 usage();
c@23 402 }
c@23 403
c@24 404 string informat = "json", outformat = "json";
c@27 405 RequestOrResponse::Direction direction = RequestOrResponse::Request;
c@24 406 bool haveDirection = false;
c@23 407
c@24 408 for (int i = 1; i < argc; ++i) {
c@23 409
c@23 410 string arg = argv[i];
c@24 411 bool final = (i + 1 == argc);
c@23 412
c@23 413 if (arg == "-i") {
c@27 414 if (final) usage();
c@23 415 else informat = argv[++i];
c@23 416
c@23 417 } else if (arg == "-o") {
c@27 418 if (final) usage();
c@23 419 else outformat = argv[++i];
c@23 420
c@24 421 } else if (arg == "request") {
c@24 422 direction = RequestOrResponse::Request;
c@24 423 haveDirection = true;
c@24 424
c@24 425 } else if (arg == "response") {
c@24 426 direction = RequestOrResponse::Response;
c@24 427 haveDirection = true;
c@24 428
c@23 429 } else {
c@23 430 usage();
c@23 431 }
c@23 432 }
c@23 433
c@24 434 if (informat == "" || outformat == "" || !haveDirection) {
c@23 435 usage();
c@23 436 }
c@23 437
c@23 438 while (true) {
c@23 439
c@23 440 try {
c@23 441
c@24 442 RequestOrResponse rr = readInput(informat, direction);
c@29 443
c@29 444 // NotValid without an exception indicates EOF:
c@25 445 if (rr.type == RRType::NotValid) break;
c@29 446
c@23 447 writeOutput(outformat, rr);
c@23 448
c@23 449 } catch (std::exception &e) {
c@23 450 cerr << "Error: " << e.what() << endl;
c@23 451 exit(1);
c@23 452 }
c@23 453 }
c@23 454
c@23 455 exit(0);
c@23 456 }
c@23 457
c@23 458