#ifndef __serialization_translator_H__ #define __serialization_translator_H__ #include "binaryserialization/BinarySerializationContext.h" #include "binaryserialization/BinarySerializationShared.h" #include "jsonserialization/JSONSerializationContext.h" #include "jsonserialization/JSONSerializationShared.h" #include "serialization/DeserializationContext.h" #include "serialization/DeserializationTypeDetector.h" #include "serialization/SerializationContext.h" #include "utilities/IOUtilities.h" #include "utilities/printfFormats.h" #include #include #include #include static void printUsage(void) { fprintf(stderr, "Usage: serialization_translator [--format ] [-o ] \n" " JSON format options: [--json-format ]\n" " Binary format options: [--binary-endian ]\n"); } enum outputFormat { FORMAT_BINARY, FORMAT_JSON }; static int serialization_translator_main(int argc, const char ** argv, void * (* deserializeCallback)(DeserializationContext * context), void (* serializeCallback)(void * object, SerializationContext * context)) { DeserializationTypeDetector * typeDetector = DeserializationTypeDetector_create(); DeserializationTypeDetector_registerDetectionCallback(typeDetector, JSONSerialization_typeDetector); DeserializationTypeDetector_registerDetectionCallback(typeDetector, BinarySerialization_typeDetector); const char * inputPath = NULL, * outputPath = NULL; enum outputFormat format = FORMAT_JSON; enum JSONEmitterFormat jsonFormat = JSONEmitterFormat_multiLine; bool bigEndian = false; for (int argIndex = 1; argIndex < argc; argIndex++) { if (!strcmp(argv[argIndex], "--help")) { printUsage(); return EXIT_SUCCESS; } if (!strcmp(argv[argIndex], "--format")) { if (argIndex >= argc - 1) { fprintf(stderr, "Error: --format specified at the end of argv\n"); printUsage(); return EXIT_FAILURE; } ++argIndex; if (!strcmp(argv[argIndex], "binary")) { format = FORMAT_BINARY; } else if (!strcmp(argv[argIndex], "json")) { format = FORMAT_JSON; } else { fprintf(stderr, "Error: Couldn't understand format \"%s\"\n", argv[argIndex]); printUsage(); return EXIT_FAILURE; } } else if (!strcmp(argv[argIndex], "-o")) { if (argIndex >= argc - 1) { fprintf(stderr, "Error: -o specified at the end of argv\n"); printUsage(); return EXIT_FAILURE; } outputPath = argv[++argIndex]; } else if (!strcmp(argv[argIndex], "--json-format")) { if (argIndex >= argc - 1) { fprintf(stderr, "Error: --json-format specified at the end of argv\n"); printUsage(); return EXIT_FAILURE; } ++argIndex; if (!strcmp(argv[argIndex], "compact")) { jsonFormat = JSONEmitterFormat_compact; } else if (!strcmp(argv[argIndex], "singleLine")) { jsonFormat = JSONEmitterFormat_singleLine; } else if (!strcmp(argv[argIndex], "multiLine")) { jsonFormat = JSONEmitterFormat_multiLine; } else { fprintf(stderr, "Error: Couldn't understand JSON format \"%s\"\n", argv[argIndex]); printUsage(); return EXIT_FAILURE; } } else if (!strcmp(argv[argIndex], "--binary-endian")) { if (argIndex >= argc - 1) { fprintf(stderr, "Error: --binary-endian specified at the end of argv\n"); printUsage(); return EXIT_FAILURE; } ++argIndex; if (!strcmp(argv[argIndex], "big")) { bigEndian = true; } else if (!strcmp(argv[argIndex], "little")) { bigEndian = false; } else { fprintf(stderr, "Error: Couldn't understand binary endianness \"%s\"\n", argv[argIndex]); printUsage(); return EXIT_FAILURE; } } else { if (inputPath != NULL) { fprintf(stderr, "Couldn't understand argument \"%s\" (already took \"%s\" as input file path)\n", argv[argIndex], inputPath); printUsage(); return EXIT_FAILURE; } inputPath = argv[argIndex]; } } DeserializationContext * deserializationContext = NULL; if (inputPath == NULL || !strcmp(inputPath, "-")) { size_t inputSize; void * input = readStdinSimple(&inputSize); deserializationContext = DeserializationTypeDetector_createDeserializationContextWithData(typeDetector, input, inputSize); free(input); } else { deserializationContext = DeserializationTypeDetector_createDeserializationContextWithFile(typeDetector, inputPath); } if (deserializationContext == NULL) { fprintf(stderr, "Couldn't create deserialization context for \"%s\"\n", inputPath); } void * object = deserializeCallback(deserializationContext); if (object == NULL) { fprintf(stderr, "Failed to deserialize file \"%s\"\n", inputPath); return EXIT_FAILURE; } call_virtual(dispose, deserializationContext); SerializationContext * serializationContext = NULL; switch (format) { case FORMAT_BINARY: serializationContext = (SerializationContext *) BinarySerializationContext_create(bigEndian); break; case FORMAT_JSON: serializationContext = (SerializationContext *) JSONSerializationContext_create(); break; } serializeCallback(object, serializationContext); void * outputData = NULL; size_t outputLength = 0; switch (format) { case FORMAT_BINARY: outputData = BinarySerializationContext_writeToBytes((BinarySerializationContext *) serializationContext, &outputLength); break; case FORMAT_JSON: outputData = JSONSerializationContext_writeToString((JSONSerializationContext *) serializationContext, jsonFormat, &outputLength, NULL); break; } if (outputData == NULL) { fprintf(stderr, "Error: Couldn't write to \"%s\" (errno = %d)\n", outputPath, errno); return EXIT_FAILURE; } if (outputPath == NULL) { switch (format) { case FORMAT_BINARY: outputPath = "a.bin"; break; case FORMAT_JSON: outputPath = "a.json"; break; } } if (!strcmp(outputPath, "-")) { size_t result = write(STDOUT_FILENO, outputData, outputLength); if (result < outputLength) { fprintf(stderr, "Warning: Only " SIZE_T_FORMAT " bytes out of " SIZE_T_FORMAT" could be written\n", result, outputLength); } } else { writeFileSimple(outputPath, outputData, outputLength); } call_virtual(dispose, serializationContext); return EXIT_SUCCESS; } #endif