feat: Add stdin support for both encode and decode in VC2022 C version
- Added stdin support for XML encoding: V2GDecoder.exe -encode (reads XML from stdin) - Added stdin support for hex decoding: V2GDecoder.exe -decode (reads hex string from stdin) - Implemented hexStringToBinary() function for hex string to binary conversion - Enhanced main() argument parsing to support stdin mode with filename "-" - Updated help messages to show new pipe support options - Cross-validated with original C program - 100% identical results for both encoding and decoding - Enables pipeline usage: echo hex | V2GDecoder.exe -decode and type file.xml | V2GDecoder.exe -encode 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -829,6 +829,53 @@ void dump_iso1_document_to_file(const struct iso1EXIDocument* doc, const char* f
|
||||
printf("✓ Structure dump saved to %s\n", filename);
|
||||
}
|
||||
|
||||
// Helper function to convert hex string to binary
|
||||
int hexStringToBinary(const char* hex_string, uint8_t* buffer, size_t buffer_size, size_t* bytes_written) {
|
||||
size_t hex_len = strlen(hex_string);
|
||||
|
||||
// Remove any whitespace and newlines
|
||||
char* cleaned_hex = malloc(hex_len + 1);
|
||||
if (!cleaned_hex) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_t clean_pos = 0;
|
||||
for (size_t i = 0; i < hex_len; i++) {
|
||||
char c = hex_string[i];
|
||||
if (isxdigit(c)) {
|
||||
cleaned_hex[clean_pos++] = toupper(c);
|
||||
}
|
||||
}
|
||||
cleaned_hex[clean_pos] = '\0';
|
||||
|
||||
// Check if hex string length is even
|
||||
if (clean_pos % 2 != 0) {
|
||||
free(cleaned_hex);
|
||||
return -1; // Invalid hex string length
|
||||
}
|
||||
|
||||
size_t binary_len = clean_pos / 2;
|
||||
if (binary_len > buffer_size) {
|
||||
free(cleaned_hex);
|
||||
return -2; // Buffer too small
|
||||
}
|
||||
|
||||
// Convert hex pairs to bytes
|
||||
for (size_t i = 0; i < binary_len; i++) {
|
||||
char hex_byte[3] = {cleaned_hex[i*2], cleaned_hex[i*2+1], '\0'};
|
||||
unsigned int byte_val;
|
||||
if (sscanf(hex_byte, "%X", &byte_val) != 1) {
|
||||
free(cleaned_hex);
|
||||
return -3; // Invalid hex character
|
||||
}
|
||||
buffer[i] = (uint8_t)byte_val;
|
||||
}
|
||||
|
||||
*bytes_written = binary_len;
|
||||
free(cleaned_hex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Helper function to read EXI file
|
||||
int readEXIFile(char* file, uint8_t* buffer, size_t buffer_size, size_t *bytes_read) {
|
||||
FILE *fp = fopen(file, "rb");
|
||||
@@ -1099,7 +1146,17 @@ int main(int argc, char *argv[]) {
|
||||
char *filename = NULL;
|
||||
|
||||
if (argc == 2) {
|
||||
if (strcmp(argv[1], "-encode") == 0) {
|
||||
// Special case: -encode without filename reads from stdin
|
||||
encode_mode = 1;
|
||||
filename = "-"; // Use "-" to indicate stdin
|
||||
} else if (strcmp(argv[1], "-decode") == 0) {
|
||||
// Special case: -decode without filename reads from stdin
|
||||
xml_mode = 1;
|
||||
filename = "-"; // Use "-" to indicate stdin
|
||||
} else {
|
||||
filename = argv[1];
|
||||
}
|
||||
} else if (argc == 3 && strcmp(argv[1], "-decode") == 0) {
|
||||
xml_mode = 1;
|
||||
filename = argv[2];
|
||||
@@ -1108,9 +1165,13 @@ int main(int argc, char *argv[]) {
|
||||
filename = argv[2];
|
||||
} else {
|
||||
printf("Usage: %s [-decode|-encode] input_file\\n", argv[0]);
|
||||
printf(" %s -encode (read XML from stdin)\\n", argv[0]);
|
||||
printf(" %s -decode (read hex string from stdin)\\n", argv[0]);
|
||||
printf("Enhanced EXI viewer with XML conversion capabilities\\n");
|
||||
printf(" -decode Convert EXI to Wireshark-style XML format\\n");
|
||||
printf(" -decode Read hex string from stdin (echo hex | %s -decode)\\n", argv[0]);
|
||||
printf(" -encode Convert XML to EXI format\\n");
|
||||
printf(" -encode Read XML from stdin (type file.xml | %s -encode)\\n", argv[0]);
|
||||
printf(" (default) Analyze EXI with detailed output\\n");
|
||||
return -1;
|
||||
}
|
||||
@@ -1131,8 +1192,40 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
// Handle encode mode (XML to EXI)
|
||||
if (encode_mode) {
|
||||
FILE* xml_file;
|
||||
char* xml_content;
|
||||
long xml_size;
|
||||
|
||||
// Check if reading from stdin or file
|
||||
if (strcmp(filename, "-") == 0) {
|
||||
// Read from stdin
|
||||
xml_file = stdin;
|
||||
|
||||
// Read all content from stdin
|
||||
size_t capacity = 4096;
|
||||
xml_content = malloc(capacity);
|
||||
if (!xml_content) {
|
||||
printf("Error allocating memory for XML content\\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
xml_size = 0;
|
||||
int ch;
|
||||
while ((ch = fgetc(stdin)) != EOF) {
|
||||
if (xml_size >= capacity - 1) {
|
||||
capacity *= 2;
|
||||
xml_content = realloc(xml_content, capacity);
|
||||
if (!xml_content) {
|
||||
printf("Error reallocating memory for XML content\\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
xml_content[xml_size++] = ch;
|
||||
}
|
||||
xml_content[xml_size] = '\0';
|
||||
} else {
|
||||
// Read XML file
|
||||
FILE* xml_file = fopen(filename, "r");
|
||||
xml_file = fopen(filename, "r");
|
||||
if (!xml_file) {
|
||||
printf("Error opening XML file: %s\\n", filename);
|
||||
return -1;
|
||||
@@ -1140,10 +1233,10 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
// Read entire XML content
|
||||
fseek(xml_file, 0, SEEK_END);
|
||||
long xml_size = ftell(xml_file);
|
||||
xml_size = ftell(xml_file);
|
||||
fseek(xml_file, 0, SEEK_SET);
|
||||
|
||||
char* xml_content = malloc(xml_size + 1);
|
||||
xml_content = malloc(xml_size + 1);
|
||||
if (!xml_content) {
|
||||
printf("Error allocating memory for XML content\\n");
|
||||
fclose(xml_file);
|
||||
@@ -1153,6 +1246,7 @@ int main(int argc, char *argv[]) {
|
||||
fread(xml_content, 1, xml_size, xml_file);
|
||||
xml_content[xml_size] = '\0';
|
||||
fclose(xml_file);
|
||||
}
|
||||
|
||||
// Parse XML to ISO1 document structure
|
||||
if (parse_xml_to_iso1(xml_content, &iso1Doc) != 0) {
|
||||
@@ -1221,12 +1315,38 @@ int main(int argc, char *argv[]) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Read EXI file for decode/analysis mode
|
||||
// Read EXI data for decode/analysis mode
|
||||
if (strcmp(filename, "-") == 0 && xml_mode) {
|
||||
// Read hex string from stdin for decode mode
|
||||
char hex_input[BUFFER_SIZE * 2 + 1]; // Hex string can be up to 2x binary size
|
||||
size_t hex_len = 0;
|
||||
|
||||
// Read hex string from stdin
|
||||
int ch;
|
||||
while ((ch = fgetc(stdin)) != EOF && hex_len < sizeof(hex_input) - 1) {
|
||||
hex_input[hex_len++] = ch;
|
||||
}
|
||||
hex_input[hex_len] = '\0';
|
||||
|
||||
// Convert hex string to binary
|
||||
errn = hexStringToBinary(hex_input, buffer, BUFFER_SIZE, &pos);
|
||||
if (errn != 0) {
|
||||
printf("Error converting hex string to binary (error: %d)\\n", errn);
|
||||
printf("Make sure input is a valid hex string like: 8098021050908C0C0C0E0C50E001993206002040C40C203030C014000603DA98B3E60C0008\\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!xml_mode) {
|
||||
printf("Hex string from stdin (%zu bytes converted to %zu binary bytes)\\n", hex_len, pos);
|
||||
}
|
||||
} else {
|
||||
// Read from file
|
||||
errn = readEXIFile(filename, buffer, BUFFER_SIZE, &pos);
|
||||
if (errn != 0) {
|
||||
printf("Error reading file: %s\\n", filename);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!xml_mode) {
|
||||
printf("File: %s (%zu bytes)\\n", filename, pos);
|
||||
|
||||
Reference in New Issue
Block a user