mirror of
https://github.com/scp-fs2open/fs2open.github.com.git
synced 2026-11-08 07:28:22 -10:00
* fix some usages of std::transform * change parse_string_flag_list to use a reference * add a variant of parse_string_flag_list that can use a SCP_set, and make a templated version of flag_def_list
294 lines
7.6 KiB
C++
294 lines
7.6 KiB
C++
/**
|
|
* Originally written by z64555
|
|
* Adapted to use stdlib by m!m
|
|
*/
|
|
|
|
// ToDo: Review wxWidgets API to file input and output
|
|
// Correct the code so that the program will properly output text to a target .h file
|
|
// Correct the code so that the program will properly read bytes in and output as hexidecimal string values.
|
|
|
|
#include <cstring>
|
|
#include <string>
|
|
#include <fstream>
|
|
#include <iostream>
|
|
#include <algorithm>
|
|
#include <iomanip>
|
|
|
|
bool casecmp(const char* strA, const char* strB) {
|
|
size_t lenA = strlen(strA);
|
|
|
|
if (lenA != strlen(strB)) {
|
|
return false;
|
|
}
|
|
|
|
for (size_t i = 0; i < lenA; i++) {
|
|
if (toupper(static_cast<unsigned char>(strA[i])) != toupper(static_cast<unsigned char>(strB[i]))) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
// Input: Filename of file to convert
|
|
// Function output: standard status codes
|
|
// Side-effect output: converted file
|
|
enum embedpng_errors {
|
|
error_none = 0,
|
|
error_cantopenfile,
|
|
error_cantoutputfile,
|
|
error_invalidargs,
|
|
error_ioerror,
|
|
};
|
|
|
|
static const size_t INPUT_BUFFER_SIZE = 1024;
|
|
|
|
typedef unsigned char ubyte;
|
|
|
|
void write_byte(std::ostream& stream, ubyte byte, size_t i) {
|
|
auto flags = stream.flags();
|
|
stream << "0x" << std::hex << std::setw(2) << std::setfill('0') << std::uppercase << int(byte);
|
|
stream.flags(flags);
|
|
|
|
if ((i % 16) == 0) {
|
|
// End of 16-byte row
|
|
stream << "," << std::endl;
|
|
stream << "\t";
|
|
}
|
|
else {
|
|
// Somewhere within a column
|
|
stream << ", ";
|
|
}
|
|
}
|
|
|
|
void do_binary_content(std::ifstream& file_in, std::ofstream& file_out,
|
|
const std::string& field_name, size_t input_size, bool wxWidgets_image) {
|
|
file_out << "#ifdef __cplusplus" << std::endl;
|
|
file_out << "\t#include <cstddef>" << std::endl;
|
|
file_out << "\tusing std::size_t;" << std::endl;
|
|
file_out << "#else" << std::endl;
|
|
file_out << "\t#include <stddef.h>" << std::endl;
|
|
file_out << "#endif" << std::endl;
|
|
if (wxWidgets_image) {
|
|
file_out << "#include <wx/mstream.h>" << std::endl;
|
|
file_out << "#include <wx/image.h>" << std::endl;
|
|
file_out << "#include <wx/bitmap.h>" << std::endl;
|
|
file_out << std::endl;
|
|
}
|
|
|
|
file_out << "unsigned char " << field_name << "[] = " << std::endl;
|
|
file_out << "{" << std::endl;
|
|
file_out << "\t";
|
|
|
|
ubyte buffer[INPUT_BUFFER_SIZE];
|
|
|
|
size_t i = 0;
|
|
while (i < input_size) {
|
|
size_t current_size = std::min(input_size - i, INPUT_BUFFER_SIZE);
|
|
file_in.read((char*) buffer, current_size);
|
|
|
|
for (size_t j = 0; j < current_size; j++) {
|
|
i++;
|
|
write_byte(file_out, buffer[j], i);
|
|
}
|
|
}
|
|
|
|
file_out << std::endl;
|
|
|
|
file_out << "};" << std::endl;
|
|
file_out << "size_t " << field_name << "_size = sizeof(" << field_name << ");" << std::endl;
|
|
|
|
|
|
if (wxWidgets_image) {
|
|
file_out << std::endl;
|
|
|
|
file_out << "wxBitmap& " << field_name << "_to_wx_bitmap()" << std::endl;
|
|
file_out << "{" << std::endl;
|
|
file_out << "\tstatic wxMemoryInputStream memIStream( " << field_name << ", sizeof( " << field_name << " ) );"
|
|
<< std::endl;
|
|
file_out << "\tstatic wxImage image( memIStream );" << std::endl;
|
|
file_out << "\tstatic wxBitmap bmp( image );" << std::endl;
|
|
file_out << "\treturn bmp;" << std::endl;
|
|
file_out << "};" << std::endl;
|
|
}
|
|
}
|
|
|
|
void do_text_content(std::ifstream& file_in, std::ofstream& file_out,
|
|
const std::string& field_name, size_t input_size) {
|
|
const char* escapeCharacters = "\\\"\n\r";
|
|
|
|
std::string file_content;
|
|
file_content.reserve(input_size);
|
|
|
|
file_content.assign((std::istreambuf_iterator<char>(file_in)),
|
|
std::istreambuf_iterator<char>());
|
|
|
|
file_out << "const char *" << field_name << " = " << std::endl;
|
|
file_out << "\"";
|
|
|
|
size_t pos = 0;
|
|
const char* str = file_content.c_str();
|
|
|
|
while (pos < file_content.length()) {
|
|
const char* found_ptr = strpbrk(str + pos, escapeCharacters);
|
|
|
|
if (found_ptr == nullptr) {
|
|
file_out.write(str + pos, file_content.length() - pos);
|
|
break;
|
|
}
|
|
|
|
size_t found_pos = (size_t) (found_ptr - str);
|
|
|
|
size_t delta = found_pos - pos;
|
|
|
|
if (delta != 0) {
|
|
file_out.write(str + pos, delta);
|
|
}
|
|
|
|
switch (str[found_pos]) {
|
|
case '\\':
|
|
file_out << "\\\\";
|
|
break;
|
|
case '\n':
|
|
file_out << "\\n\"" << std::endl << "\"";
|
|
break;
|
|
case '"':
|
|
file_out << "\\\"";
|
|
break;
|
|
case '\r':
|
|
// Discard this character, possibly breaks on mac but whatever...
|
|
break;
|
|
default:
|
|
std::cout << "ERROR: Invalid character encountered!" << std::endl;
|
|
}
|
|
|
|
pos = found_pos + 1;
|
|
}
|
|
|
|
file_out << "\";" << std::endl;
|
|
}
|
|
|
|
void write_header(std::ostream& out, const std::string& fieldName, bool text_content, bool wxWidgets_image) {
|
|
std::string headerDefine(fieldName);
|
|
|
|
std::transform(fieldName.begin(), fieldName.end(), std::back_inserter(headerDefine),
|
|
[](char c) { return static_cast<char>(::toupper(static_cast<unsigned char>(c))); });
|
|
|
|
headerDefine = "SCP_" + headerDefine + "_H";
|
|
|
|
out << "#ifndef " << headerDefine << std::endl;
|
|
out << "#define " << headerDefine << std::endl;
|
|
out << "#pragma once" << std::endl;
|
|
out << "#ifdef __cplusplus" << std::endl;
|
|
out << "\t#include <cstddef>" << std::endl;
|
|
out << "\tusing std::size_t;" << std::endl;
|
|
out << "#else" << std::endl;
|
|
out << "\t#include <stddef.h>" << std::endl;
|
|
out << "#endif" << std::endl;
|
|
if (wxWidgets_image) {
|
|
out << "#include <wx/bitmap.h>" << std::endl;
|
|
}
|
|
|
|
out << std::endl;
|
|
|
|
if (text_content) {
|
|
out << "extern const char* " << fieldName << ";" << std::endl;
|
|
}
|
|
else {
|
|
out << "extern unsigned char " << fieldName << "[];" << std::endl;
|
|
out << "extern size_t " << fieldName << "_size;" << std::endl;
|
|
}
|
|
out << std::endl;
|
|
if (wxWidgets_image) {
|
|
out << "wxBitmap& " << fieldName << "_to_wx_bitmap();" << std::endl;
|
|
}
|
|
out << "#endif" << std::endl;
|
|
}
|
|
|
|
int main(int argc, char* argv[]) {
|
|
if (argc < 4 || argc > 6) {
|
|
std::cout << "Usage: embedfile [-wx] [-text] <inout> <output> <fieldname>" << std::endl;
|
|
|
|
return error_invalidargs;
|
|
}
|
|
|
|
bool wxWidgets_image = false;
|
|
bool text_content = false;
|
|
|
|
int argc_offset = 1;
|
|
|
|
if (casecmp(argv[argc_offset], "-wx")) {
|
|
wxWidgets_image = true;
|
|
|
|
argc_offset++;
|
|
}
|
|
|
|
if (casecmp(argv[argc_offset], "-text")) {
|
|
text_content = true;
|
|
|
|
argc_offset++;
|
|
}
|
|
|
|
std::string input_file(argv[argc_offset]);
|
|
std::string output_basename(argv[argc_offset + 1]);
|
|
std::string field_name(argv[argc_offset + 2]);
|
|
|
|
std::ios::openmode mode = std::ios::in;
|
|
if (!text_content) {
|
|
mode |= std::ios::binary;
|
|
}
|
|
|
|
std::ifstream file_in(input_file.c_str(), mode);
|
|
if (file_in.bad()) {
|
|
std::cout << "ERROR: Error opening input file: " << input_file << std::endl;
|
|
return error_cantopenfile;
|
|
}
|
|
|
|
// Get the size of the input stream
|
|
size_t input_size;
|
|
file_in.seekg(0, std::ios::end);
|
|
|
|
if ((int) file_in.tellg() != -1) {
|
|
input_size = (size_t) file_in.tellg();
|
|
}
|
|
else {
|
|
std::cout << "ERROR: Failed to get size of input file: " << input_file << std::endl;
|
|
file_in.close();
|
|
return error_ioerror;
|
|
}
|
|
|
|
file_in.seekg(0, std::ios::beg);
|
|
|
|
// Generates two files, one header and one source file
|
|
std::string headerName = output_basename + ".h";
|
|
std::string sourceName = output_basename + ".cpp";
|
|
|
|
std::ofstream source_out(sourceName.c_str());
|
|
if (source_out.bad()) {
|
|
std::cout << "ERROR: Error opening output file: " << sourceName << std::endl;
|
|
return error_cantoutputfile;
|
|
}
|
|
|
|
std::ofstream header_out(headerName.c_str());
|
|
if (header_out.bad()) {
|
|
std::cout << "ERROR: Error opening output file: " << headerName << std::endl;
|
|
return error_cantoutputfile;
|
|
}
|
|
|
|
if (text_content) {
|
|
do_text_content(file_in, source_out, field_name, input_size);
|
|
}
|
|
else {
|
|
do_binary_content(file_in, source_out, field_name, input_size, wxWidgets_image);
|
|
}
|
|
|
|
write_header(header_out, field_name, text_content, wxWidgets_image);
|
|
|
|
file_in.close();
|
|
|
|
source_out.close();
|
|
header_out.close();
|
|
|
|
return error_none;
|
|
}
|