Mercurial > hg > piper-cpp
comparison vamp-server/convert.cpp @ 116:d15cb1151d76
Add JSON support directly to the server. Had hoped to avoid this (using Capnp as canonical in the server and then converting externally as necessary) but it's just too useful for debugging purposes when bundled with client app
author | Chris Cannam <c.cannam@qmul.ac.uk> |
---|---|
date | Thu, 27 Oct 2016 11:39:41 +0100 |
parents | 427c4c725085 |
children | ff3fd8d1b2dc |
comparison
equal
deleted
inserted
replaced
115:5a716f08e4be | 116:d15cb1151d76 |
---|---|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ | |
1 | 2 |
2 #include "vamp-json/VampJson.h" | 3 #include "vamp-json/VampJson.h" |
3 #include "vamp-capnp/VampnProto.h" | 4 #include "vamp-capnp/VampnProto.h" |
4 #include "vamp-support/RequestOrResponse.h" | 5 #include "vamp-support/RequestOrResponse.h" |
5 #include "vamp-support/PreservingPluginHandleMapper.h" | 6 #include "vamp-support/PreservingPluginHandleMapper.h" |
16 | 17 |
17 void usage() | 18 void usage() |
18 { | 19 { |
19 string myname = "piper-convert"; | 20 string myname = "piper-convert"; |
20 cerr << "\n" << myname << | 21 cerr << "\n" << myname << |
21 ": Validate and convert Piper request and response messages\n\n" | 22 ": Validate and convert Piper request and response messages\n\n" |
22 " Usage: " << myname << " [-i <informat>] [-o <outformat>] request\n" | 23 " Usage: " << myname << " [-i <informat>] [-o <outformat>] request\n" |
23 " " << myname << " [-i <informat>] [-o <outformat>] response\n\n" | 24 " " << myname << " [-i <informat>] [-o <outformat>] response\n\n" |
24 " where\n" | 25 " where\n" |
25 " <informat>: the format to read from stdin\n" | 26 " <informat>: the format to read from stdin\n" |
26 " (\"json\" or \"capnp\", default is \"json\")\n" | 27 " (\"json\" or \"capnp\", default is \"json\")\n" |
27 " <outformat>: the format to convert to and write to stdout\n" | 28 " <outformat>: the format to convert to and write to stdout\n" |
28 " (\"json\", \"json-b64\" or \"capnp\", default is \"json\")\n" | 29 " (\"json\", \"json-b64\" or \"capnp\", default is \"json\")\n" |
29 " request|response: whether messages are Vamp request or response type\n\n" | 30 " request|response: whether messages are Vamp request or response type\n\n" |
30 "If <informat> and <outformat> differ, convert from <informat> to <outformat>.\n" | 31 "If <informat> and <outformat> differ, convert from <informat> to <outformat>.\n" |
31 "If <informat> and <outformat> are the same, just check validity of incoming\n" | 32 "If <informat> and <outformat> are the same, just check validity of incoming\n" |
32 "messages and pass them to output.\n\n" | 33 "messages and pass them to output.\n\n" |
33 "Specifying \"json-b64\" as output format forces base64 encoding for process and\n" | 34 "Specifying \"json-b64\" as output format forces base64 encoding for process and\n" |
34 "feature blocks, unlike the \"json\" output format which uses text encoding.\n" | 35 "feature blocks, unlike the \"json\" output format which uses text encoding.\n" |
35 "The \"json\" input format accepts either.\n\n"; | 36 "The \"json\" input format accepts either.\n\n"; |
36 | 37 |
37 exit(2); | 38 exit(2); |
38 } | 39 } |
39 | 40 |
40 Json | 41 Json |
41 convertRequestJson(string input, string &err) | 42 convertRequestJson(string input, string &err) |
42 { | 43 { |
43 Json j = Json::parse(input, err); | 44 Json j = Json::parse(input, err); |
44 if (err != "") { | 45 if (err != "") { |
45 err = "invalid json: " + err; | 46 err = "invalid json: " + err; |
46 return {}; | 47 return {}; |
47 } | 48 } |
48 if (!j.is_object()) { | 49 if (!j.is_object()) { |
49 err = "object expected at top level"; | 50 err = "object expected at top level"; |
50 } else if (!j["method"].is_string()) { | 51 } else if (!j["method"].is_string()) { |
51 err = "string expected for method field"; | 52 err = "string expected for method field"; |
52 } else if (!j["params"].is_null() && !j["params"].is_object()) { | 53 } else if (!j["params"].is_null() && !j["params"].is_object()) { |
53 err = "object expected for params field"; | 54 err = "object expected for params field"; |
54 } | 55 } |
55 return j; | 56 return j; |
56 } | 57 } |
57 | 58 |
58 Json | 59 Json |
59 convertResponseJson(string input, string &err) | 60 convertResponseJson(string input, string &err) |
60 { | 61 { |
61 Json j = Json::parse(input, err); | 62 Json j = Json::parse(input, err); |
62 if (err != "") { | 63 if (err != "") { |
63 err = "invalid json: " + err; | 64 err = "invalid json: " + err; |
64 return {}; | 65 return {}; |
65 } | 66 } |
66 if (!j.is_object()) { | 67 if (!j.is_object()) { |
67 err = "object expected at top level"; | 68 err = "object expected at top level"; |
68 } else { | 69 } else { |
69 if (!j["result"].is_object()) { | 70 if (!j["result"].is_object()) { |
70 if (!j["error"].is_object()) { | 71 if (!j["error"].is_object()) { |
71 err = "expected either result or error object"; | 72 err = "expected either result or error object"; |
72 } | 73 } |
152 RequestOrResponse rr; | 153 RequestOrResponse rr; |
153 rr.direction = RequestOrResponse::Request; | 154 rr.direction = RequestOrResponse::Request; |
154 | 155 |
155 string input; | 156 string input; |
156 if (!getline(cin, input)) { | 157 if (!getline(cin, input)) { |
157 // the EOF case, not actually an error | 158 // the EOF case, not actually an error |
158 rr.type = RRType::NotValid; | 159 rr.type = RRType::NotValid; |
159 return rr; | 160 return rr; |
160 } | 161 } |
161 | 162 |
162 Json j = convertRequestJson(input, err); | 163 Json j = convertRequestJson(input, err); |
163 if (err != "") return {}; | 164 if (err != "") return {}; |
164 | 165 |
171 VampJson::BufferSerialisation::Array; | 172 VampJson::BufferSerialisation::Array; |
172 | 173 |
173 switch (rr.type) { | 174 switch (rr.type) { |
174 | 175 |
175 case RRType::List: | 176 case RRType::List: |
176 VampJson::toRpcRequest_List(j, err); // type check only | 177 VampJson::toRpcRequest_List(j, err); // type check only |
177 break; | 178 break; |
178 case RRType::Load: | 179 case RRType::Load: |
179 rr.loadRequest = VampJson::toRpcRequest_Load(j, err); | 180 rr.loadRequest = VampJson::toRpcRequest_Load(j, err); |
180 break; | 181 break; |
181 case RRType::Configure: | 182 case RRType::Configure: |
182 rr.configurationRequest = VampJson::toRpcRequest_Configure(j, mapper, err); | 183 rr.configurationRequest = VampJson::toRpcRequest_Configure(j, mapper, err); |
183 break; | 184 break; |
184 case RRType::Process: | 185 case RRType::Process: |
185 rr.processRequest = VampJson::toRpcRequest_Process(j, mapper, serialisation, err); | 186 rr.processRequest = VampJson::toRpcRequest_Process(j, mapper, serialisation, err); |
186 break; | 187 break; |
187 case RRType::Finish: | 188 case RRType::Finish: |
188 rr.finishRequest = VampJson::toRpcRequest_Finish(j, mapper, err); | 189 rr.finishRequest = VampJson::toRpcRequest_Finish(j, mapper, err); |
189 break; | 190 break; |
190 case RRType::NotValid: | 191 case RRType::NotValid: |
191 break; | 192 break; |
192 } | 193 } |
193 | 194 |
194 return rr; | 195 return rr; |
195 } | 196 } |
196 | 197 |
207 Json id = writeJsonId(rr.id); | 208 Json id = writeJsonId(rr.id); |
208 | 209 |
209 switch (rr.type) { | 210 switch (rr.type) { |
210 | 211 |
211 case RRType::List: | 212 case RRType::List: |
212 j = VampJson::fromRpcRequest_List(id); | 213 j = VampJson::fromRpcRequest_List(id); |
213 break; | 214 break; |
214 case RRType::Load: | 215 case RRType::Load: |
215 j = VampJson::fromRpcRequest_Load(rr.loadRequest, id); | 216 j = VampJson::fromRpcRequest_Load(rr.loadRequest, id); |
216 break; | 217 break; |
217 case RRType::Configure: | 218 case RRType::Configure: |
218 j = VampJson::fromRpcRequest_Configure(rr.configurationRequest, mapper, id); | 219 j = VampJson::fromRpcRequest_Configure(rr.configurationRequest, mapper, id); |
219 break; | 220 break; |
220 case RRType::Process: | 221 case RRType::Process: |
221 j = VampJson::fromRpcRequest_Process | 222 j = VampJson::fromRpcRequest_Process |
222 (rr.processRequest, mapper, serialisation, id); | 223 (rr.processRequest, mapper, serialisation, id); |
223 break; | 224 break; |
224 case RRType::Finish: | 225 case RRType::Finish: |
225 j = VampJson::fromRpcRequest_Finish(rr.finishRequest, mapper, id); | 226 j = VampJson::fromRpcRequest_Finish(rr.finishRequest, mapper, id); |
226 break; | 227 break; |
227 case RRType::NotValid: | 228 case RRType::NotValid: |
228 break; | 229 break; |
229 } | 230 } |
230 | 231 |
231 cout << j.dump() << endl; | 232 cout << j.dump() << endl; |
232 } | 233 } |
233 | 234 |
237 RequestOrResponse rr; | 238 RequestOrResponse rr; |
238 rr.direction = RequestOrResponse::Response; | 239 rr.direction = RequestOrResponse::Response; |
239 | 240 |
240 string input; | 241 string input; |
241 if (!getline(cin, input)) { | 242 if (!getline(cin, input)) { |
242 // the EOF case, not actually an error | 243 // the EOF case, not actually an error |
243 rr.type = RRType::NotValid; | 244 rr.type = RRType::NotValid; |
244 return rr; | 245 return rr; |
245 } | 246 } |
246 | 247 |
247 Json j = convertResponseJson(input, err); | 248 Json j = convertResponseJson(input, err); |
248 if (err != "") return {}; | 249 if (err != "") return {}; |
249 | 250 |
259 rr.errorText = j["errorText"].string_value(); | 260 rr.errorText = j["errorText"].string_value(); |
260 | 261 |
261 switch (rr.type) { | 262 switch (rr.type) { |
262 | 263 |
263 case RRType::List: | 264 case RRType::List: |
264 rr.listResponse = VampJson::toRpcResponse_List(j, err); | 265 rr.listResponse = VampJson::toRpcResponse_List(j, err); |
265 break; | 266 break; |
266 case RRType::Load: | 267 case RRType::Load: |
267 rr.loadResponse = VampJson::toRpcResponse_Load(j, mapper, err); | 268 rr.loadResponse = VampJson::toRpcResponse_Load(j, mapper, err); |
268 break; | 269 break; |
269 case RRType::Configure: | 270 case RRType::Configure: |
270 rr.configurationResponse = VampJson::toRpcResponse_Configure(j, mapper, err); | 271 rr.configurationResponse = VampJson::toRpcResponse_Configure(j, mapper, err); |
271 break; | 272 break; |
272 case RRType::Process: | 273 case RRType::Process: |
273 rr.processResponse = VampJson::toRpcResponse_Process(j, mapper, serialisation, err); | 274 rr.processResponse = VampJson::toRpcResponse_Process(j, mapper, serialisation, err); |
274 break; | 275 break; |
275 case RRType::Finish: | 276 case RRType::Finish: |
276 rr.finishResponse = VampJson::toRpcResponse_Finish(j, mapper, serialisation, err); | 277 rr.finishResponse = VampJson::toRpcResponse_Finish(j, mapper, serialisation, err); |
277 break; | 278 break; |
278 case RRType::NotValid: | 279 case RRType::NotValid: |
279 break; | 280 break; |
280 } | 281 } |
281 | 282 |
282 return rr; | 283 return rr; |
283 } | 284 } |
284 | 285 |
294 | 295 |
295 Json id = writeJsonId(rr.id); | 296 Json id = writeJsonId(rr.id); |
296 | 297 |
297 if (!rr.success) { | 298 if (!rr.success) { |
298 | 299 |
299 j = VampJson::fromError(rr.errorText, rr.type, id); | 300 j = VampJson::fromError(rr.errorText, rr.type, id); |
300 | 301 |
301 } else { | 302 } else { |
302 | 303 |
303 switch (rr.type) { | 304 switch (rr.type) { |
304 | 305 |
305 case RRType::List: | 306 case RRType::List: |
306 j = VampJson::fromRpcResponse_List(rr.listResponse, id); | 307 j = VampJson::fromRpcResponse_List(rr.listResponse, id); |
307 break; | 308 break; |
308 case RRType::Load: | 309 case RRType::Load: |
309 j = VampJson::fromRpcResponse_Load(rr.loadResponse, mapper, id); | 310 j = VampJson::fromRpcResponse_Load(rr.loadResponse, mapper, id); |
310 break; | 311 break; |
311 case RRType::Configure: | 312 case RRType::Configure: |
312 j = VampJson::fromRpcResponse_Configure(rr.configurationResponse, | 313 j = VampJson::fromRpcResponse_Configure(rr.configurationResponse, |
313 mapper, id); | 314 mapper, id); |
314 break; | 315 break; |
315 case RRType::Process: | 316 case RRType::Process: |
316 j = VampJson::fromRpcResponse_Process | 317 j = VampJson::fromRpcResponse_Process |
317 (rr.processResponse, mapper, serialisation, id); | 318 (rr.processResponse, mapper, serialisation, id); |
318 break; | 319 break; |
319 case RRType::Finish: | 320 case RRType::Finish: |
320 j = VampJson::fromRpcResponse_Finish | 321 j = VampJson::fromRpcResponse_Finish |
321 (rr.finishResponse, mapper, serialisation, id); | 322 (rr.finishResponse, mapper, serialisation, id); |
322 break; | 323 break; |
323 case RRType::NotValid: | 324 case RRType::NotValid: |
324 break; | 325 break; |
325 } | 326 } |
326 } | 327 } |
327 | 328 |
328 cout << j.dump() << endl; | 329 cout << j.dump() << endl; |
329 } | 330 } |
330 | 331 |
341 rr.id = readCapnpId(reader); | 342 rr.id = readCapnpId(reader); |
342 | 343 |
343 switch (rr.type) { | 344 switch (rr.type) { |
344 | 345 |
345 case RRType::List: | 346 case RRType::List: |
346 VampnProto::readRpcRequest_List(reader); // type check only | 347 VampnProto::readRpcRequest_List(reader); // type check only |
347 break; | 348 break; |
348 case RRType::Load: | 349 case RRType::Load: |
349 VampnProto::readRpcRequest_Load(rr.loadRequest, reader); | 350 VampnProto::readRpcRequest_Load(rr.loadRequest, reader); |
350 break; | 351 break; |
351 case RRType::Configure: | 352 case RRType::Configure: |
352 VampnProto::readRpcRequest_Configure(rr.configurationRequest, | 353 VampnProto::readRpcRequest_Configure(rr.configurationRequest, |
353 reader, mapper); | 354 reader, mapper); |
354 break; | 355 break; |
355 case RRType::Process: | 356 case RRType::Process: |
356 VampnProto::readRpcRequest_Process(rr.processRequest, reader, mapper); | 357 VampnProto::readRpcRequest_Process(rr.processRequest, reader, mapper); |
357 break; | 358 break; |
358 case RRType::Finish: | 359 case RRType::Finish: |
359 VampnProto::readRpcRequest_Finish(rr.finishRequest, reader, mapper); | 360 VampnProto::readRpcRequest_Finish(rr.finishRequest, reader, mapper); |
360 break; | 361 break; |
361 case RRType::NotValid: | 362 case RRType::NotValid: |
362 break; | 363 break; |
363 } | 364 } |
364 | 365 |
365 return rr; | 366 return rr; |
366 } | 367 } |
367 | 368 |
374 buildCapnpId(builder, rr.id); | 375 buildCapnpId(builder, rr.id); |
375 | 376 |
376 switch (rr.type) { | 377 switch (rr.type) { |
377 | 378 |
378 case RRType::List: | 379 case RRType::List: |
379 VampnProto::buildRpcRequest_List(builder); | 380 VampnProto::buildRpcRequest_List(builder); |
380 break; | 381 break; |
381 case RRType::Load: | 382 case RRType::Load: |
382 VampnProto::buildRpcRequest_Load(builder, rr.loadRequest); | 383 VampnProto::buildRpcRequest_Load(builder, rr.loadRequest); |
383 break; | 384 break; |
384 case RRType::Configure: | 385 case RRType::Configure: |
385 VampnProto::buildRpcRequest_Configure(builder, | 386 VampnProto::buildRpcRequest_Configure(builder, |
386 rr.configurationRequest, mapper); | 387 rr.configurationRequest, mapper); |
387 break; | 388 break; |
388 case RRType::Process: | 389 case RRType::Process: |
389 VampnProto::buildRpcRequest_Process(builder, rr.processRequest, mapper); | 390 VampnProto::buildRpcRequest_Process(builder, rr.processRequest, mapper); |
390 break; | 391 break; |
391 case RRType::Finish: | 392 case RRType::Finish: |
392 VampnProto::buildRpcRequest_Finish(builder, rr.finishRequest, mapper); | 393 VampnProto::buildRpcRequest_Finish(builder, rr.finishRequest, mapper); |
393 break; | 394 break; |
394 case RRType::NotValid: | 395 case RRType::NotValid: |
395 break; | 396 break; |
396 } | 397 } |
397 | 398 |
398 writeMessageToFd(1, message); | 399 writeMessageToFd(1, message); |
399 } | 400 } |
400 | 401 |
414 int errorCode = 0; | 415 int errorCode = 0; |
415 | 416 |
416 switch (rr.type) { | 417 switch (rr.type) { |
417 | 418 |
418 case RRType::List: | 419 case RRType::List: |
419 VampnProto::readRpcResponse_List(rr.listResponse, reader); | 420 VampnProto::readRpcResponse_List(rr.listResponse, reader); |
420 break; | 421 break; |
421 case RRType::Load: | 422 case RRType::Load: |
422 VampnProto::readRpcResponse_Load(rr.loadResponse, reader, mapper); | 423 VampnProto::readRpcResponse_Load(rr.loadResponse, reader, mapper); |
423 break; | 424 break; |
424 case RRType::Configure: | 425 case RRType::Configure: |
425 VampnProto::readRpcResponse_Configure(rr.configurationResponse, | 426 VampnProto::readRpcResponse_Configure(rr.configurationResponse, |
426 reader, mapper); | 427 reader, mapper); |
427 break; | 428 break; |
428 case RRType::Process: | 429 case RRType::Process: |
429 VampnProto::readRpcResponse_Process(rr.processResponse, reader, mapper); | 430 VampnProto::readRpcResponse_Process(rr.processResponse, reader, mapper); |
430 break; | 431 break; |
431 case RRType::Finish: | 432 case RRType::Finish: |
432 VampnProto::readRpcResponse_Finish(rr.finishResponse, reader, mapper); | 433 VampnProto::readRpcResponse_Finish(rr.finishResponse, reader, mapper); |
433 break; | 434 break; |
434 case RRType::NotValid: | 435 case RRType::NotValid: |
435 // error | 436 // error |
436 rr.success = false; | 437 rr.success = false; |
437 VampnProto::readRpcResponse_Error(errorCode, rr.errorText, reader); | 438 VampnProto::readRpcResponse_Error(errorCode, rr.errorText, reader); |
438 break; | 439 break; |
439 } | 440 } |
440 | 441 |
441 return rr; | 442 return rr; |
442 } | 443 } |
443 | 444 |
449 | 450 |
450 buildCapnpId(builder, rr.id); | 451 buildCapnpId(builder, rr.id); |
451 | 452 |
452 if (!rr.success) { | 453 if (!rr.success) { |
453 | 454 |
454 VampnProto::buildRpcResponse_Error(builder, rr.errorText, rr.type); | 455 VampnProto::buildRpcResponse_Error(builder, rr.errorText, rr.type); |
455 | 456 |
456 } else { | 457 } else { |
457 | 458 |
458 switch (rr.type) { | 459 switch (rr.type) { |
459 | 460 |
460 case RRType::List: | 461 case RRType::List: |
461 VampnProto::buildRpcResponse_List(builder, rr.listResponse); | 462 VampnProto::buildRpcResponse_List(builder, rr.listResponse); |
462 break; | 463 break; |
463 case RRType::Load: | 464 case RRType::Load: |
464 VampnProto::buildRpcResponse_Load(builder, rr.loadResponse, mapper); | 465 VampnProto::buildRpcResponse_Load(builder, rr.loadResponse, mapper); |
465 break; | 466 break; |
466 case RRType::Configure: | 467 case RRType::Configure: |
467 VampnProto::buildRpcResponse_Configure(builder, rr.configurationResponse, mapper); | 468 VampnProto::buildRpcResponse_Configure(builder, rr.configurationResponse, mapper); |
468 break; | 469 break; |
469 case RRType::Process: | 470 case RRType::Process: |
470 VampnProto::buildRpcResponse_Process(builder, rr.processResponse, mapper); | 471 VampnProto::buildRpcResponse_Process(builder, rr.processResponse, mapper); |
471 break; | 472 break; |
472 case RRType::Finish: | 473 case RRType::Finish: |
473 VampnProto::buildRpcResponse_Finish(builder, rr.finishResponse, mapper); | 474 VampnProto::buildRpcResponse_Finish(builder, rr.finishResponse, mapper); |
474 break; | 475 break; |
475 case RRType::NotValid: | 476 case RRType::NotValid: |
476 break; | 477 break; |
477 } | 478 } |
478 } | 479 } |
479 | 480 |
480 writeMessageToFd(1, message); | 481 writeMessageToFd(1, message); |
481 } | 482 } |
482 | 483 |
483 RequestOrResponse | 484 RequestOrResponse |
484 readInputJson(RequestOrResponse::Direction direction, string &err) | 485 readInputJson(RequestOrResponse::Direction direction, string &err) |
485 { | 486 { |
486 if (direction == RequestOrResponse::Request) { | 487 if (direction == RequestOrResponse::Request) { |
487 return readRequestJson(err); | 488 return readRequestJson(err); |
488 } else { | 489 } else { |
489 return readResponseJson(err); | 490 return readResponseJson(err); |
490 } | 491 } |
491 } | 492 } |
492 | 493 |
493 RequestOrResponse | 494 RequestOrResponse |
494 readInputCapnp(RequestOrResponse::Direction direction) | 495 readInputCapnp(RequestOrResponse::Direction direction) |
495 { | 496 { |
496 static kj::FdInputStream stream(0); // stdin | 497 static kj::FdInputStream stream(0); // stdin |
497 static kj::BufferedInputStreamWrapper buffered(stream); | 498 static kj::BufferedInputStreamWrapper buffered(stream); |
498 | 499 |
499 if (buffered.tryGetReadBuffer() == nullptr) { | 500 if (buffered.tryGetReadBuffer() == nullptr) { |
500 return {}; | 501 return {}; |
501 } | 502 } |
502 | 503 |
503 if (direction == RequestOrResponse::Request) { | 504 if (direction == RequestOrResponse::Request) { |
504 return readRequestCapnp(buffered); | 505 return readRequestCapnp(buffered); |
505 } else { | 506 } else { |
506 return readResponseCapnp(buffered); | 507 return readResponseCapnp(buffered); |
507 } | 508 } |
508 } | 509 } |
509 | 510 |
510 RequestOrResponse | 511 RequestOrResponse |
511 readInput(string format, RequestOrResponse::Direction direction) | 512 readInput(string format, RequestOrResponse::Direction direction) |
512 { | 513 { |
513 if (format == "json") { | 514 if (format == "json") { |
514 string err; | 515 string err; |
515 auto result = readInputJson(direction, err); | 516 auto result = readInputJson(direction, err); |
516 if (err != "") throw runtime_error(err); | 517 if (err != "") throw runtime_error(err); |
517 else return result; | 518 else return result; |
518 } else if (format == "capnp") { | 519 } else if (format == "capnp") { |
519 return readInputCapnp(direction); | 520 return readInputCapnp(direction); |
520 } else { | 521 } else { |
521 throw runtime_error("unknown input format \"" + format + "\""); | 522 throw runtime_error("unknown input format \"" + format + "\""); |
522 } | 523 } |
523 } | 524 } |
524 | 525 |
525 void | 526 void |
526 writeOutput(string format, RequestOrResponse &rr) | 527 writeOutput(string format, RequestOrResponse &rr) |
527 { | 528 { |
528 if (format == "json") { | 529 if (format == "json") { |
529 if (rr.direction == RequestOrResponse::Request) { | 530 if (rr.direction == RequestOrResponse::Request) { |
530 writeRequestJson(rr, false); | 531 writeRequestJson(rr, false); |
531 } else { | 532 } else { |
532 writeResponseJson(rr, false); | 533 writeResponseJson(rr, false); |
533 } | 534 } |
534 } else if (format == "json-b64") { | 535 } else if (format == "json-b64") { |
535 if (rr.direction == RequestOrResponse::Request) { | 536 if (rr.direction == RequestOrResponse::Request) { |
536 writeRequestJson(rr, true); | 537 writeRequestJson(rr, true); |
537 } else { | 538 } else { |
538 writeResponseJson(rr, true); | 539 writeResponseJson(rr, true); |
539 } | 540 } |
540 } else if (format == "capnp") { | 541 } else if (format == "capnp") { |
541 if (rr.direction == RequestOrResponse::Request) { | 542 if (rr.direction == RequestOrResponse::Request) { |
542 writeRequestCapnp(rr); | 543 writeRequestCapnp(rr); |
543 } else { | 544 } else { |
544 writeResponseCapnp(rr); | 545 writeResponseCapnp(rr); |
545 } | 546 } |
546 } else { | 547 } else { |
547 throw runtime_error("unknown output format \"" + format + "\""); | 548 throw runtime_error("unknown output format \"" + format + "\""); |
548 } | 549 } |
549 } | 550 } |
550 | 551 |
551 int main(int argc, char **argv) | 552 int main(int argc, char **argv) |
552 { | 553 { |
553 if (argc < 2) { | 554 if (argc < 2) { |
554 usage(); | 555 usage(); |
555 } | 556 } |
556 | 557 |
557 string informat = "json", outformat = "json"; | 558 string informat = "json", outformat = "json"; |
558 RequestOrResponse::Direction direction = RequestOrResponse::Request; | 559 RequestOrResponse::Direction direction = RequestOrResponse::Request; |
559 bool haveDirection = false; | 560 bool haveDirection = false; |
560 | 561 |
561 for (int i = 1; i < argc; ++i) { | 562 for (int i = 1; i < argc; ++i) { |
562 | 563 |
563 string arg = argv[i]; | 564 string arg = argv[i]; |
564 bool final = (i + 1 == argc); | 565 bool final = (i + 1 == argc); |
565 | 566 |
566 if (arg == "-i") { | 567 if (arg == "-i") { |
567 if (final) usage(); | 568 if (final) usage(); |
568 else informat = argv[++i]; | 569 else informat = argv[++i]; |
569 | 570 |
570 } else if (arg == "-o") { | 571 } else if (arg == "-o") { |
571 if (final) usage(); | 572 if (final) usage(); |
572 else outformat = argv[++i]; | 573 else outformat = argv[++i]; |
573 | 574 |
574 } else if (arg == "request") { | 575 } else if (arg == "request") { |
575 direction = RequestOrResponse::Request; | 576 direction = RequestOrResponse::Request; |
576 haveDirection = true; | 577 haveDirection = true; |
577 | 578 |
578 } else if (arg == "response") { | 579 } else if (arg == "response") { |
579 direction = RequestOrResponse::Response; | 580 direction = RequestOrResponse::Response; |
580 haveDirection = true; | 581 haveDirection = true; |
581 | 582 |
582 } else { | 583 } else { |
583 usage(); | 584 usage(); |
584 } | 585 } |
585 } | 586 } |
586 | 587 |
587 if (informat == "" || outformat == "" || !haveDirection) { | 588 if (informat == "" || outformat == "" || !haveDirection) { |
588 usage(); | 589 usage(); |
589 } | 590 } |
590 | 591 |
591 while (true) { | 592 while (true) { |
592 | 593 |
593 try { | 594 try { |
594 | 595 |
595 RequestOrResponse rr = readInput(informat, direction); | 596 RequestOrResponse rr = readInput(informat, direction); |
596 | 597 |
597 // NotValid without an exception indicates EOF: | 598 // NotValid without an exception indicates EOF: |
598 if (rr.type == RRType::NotValid) break; | 599 if (rr.type == RRType::NotValid) break; |
599 | 600 |
600 writeOutput(outformat, rr); | 601 writeOutput(outformat, rr); |
601 | 602 |
602 } catch (std::exception &e) { | 603 } catch (std::exception &e) { |
603 | 604 |
604 cerr << "Error: " << e.what() << endl; | 605 cerr << "Error: " << e.what() << endl; |
605 exit(1); | 606 exit(1); |
606 } | 607 } |
607 } | 608 } |
608 | 609 |
609 exit(0); | 610 exit(0); |
610 } | 611 } |
611 | 612 |