jabyengine/src/Tools/cpp_out/src/lib.rs

102 lines
3.2 KiB
Rust

use tool_helper::{Input, Output};
use std::io::Read;
pub use tool_helper::Error;
pub enum LineFeed {
Unix,
Windows
}
pub enum FileType {
CHeader,
CSource,
CPPHeader,
CPPSource,
}
pub struct Configuration {
pub file_name: String,
pub data_name: String,
pub line_feed: LineFeed,
pub file_type: FileType,
}
struct FileDeclarations<'a> {
include: &'a str,
var_type: &'a str,
}
const UNIX_LINEFEED: &'static str = "\n";
const WINDOWS_LINEFEED: &'static str = "\r\n";
const C_DECLARATIONS: FileDeclarations = FileDeclarations{include: "", var_type: "char"};
const CPP_DECLARATIONS: FileDeclarations = FileDeclarations{include: "#include <stdint.h>", var_type: "uint8_t"};
fn output_bytes(input: Input, output: &mut Output, line_feed: &str) -> Result<(), std::io::Error> {
let mut byte_line_count = 1;
let mut bytes = input.bytes();
if let Some(byte) = bytes.next() {
write!(output, "\t{:#04X}", byte?)?;
for byte in bytes {
write!(output, ", {:#04X}", byte?)?;
byte_line_count += 1;
if byte_line_count >= 16 {
write!(output, "{}\t", line_feed)?;
byte_line_count = 0;
}
}
}
Ok(())
}
fn write_header_file(input: Input, output: &mut Output, file_name: String, declarations: &FileDeclarations, data_name: String, line_feed: &str) -> Result<(), std::io::Error> {
let file_name = file_name.to_uppercase().replace('.', "_");
write!(output, "#ifndef __{}__{}", file_name, line_feed)?;
write!(output, "#define __{}__{}", file_name, line_feed)?;
write!(output, "{}{}{}", declarations.include, line_feed, line_feed)?;
write!(output, "static const {} {}[] = {{{}", declarations.var_type, data_name, line_feed)?;
output_bytes(input, output, line_feed)?;
write!(output, "{}}};{}", line_feed, line_feed)?;
write!(output, "#endif // !__{}__{}", file_name, line_feed)
}
fn write_source_file(input: Input, output: &mut Output, declarations: &FileDeclarations, data_name: String, line_feed: &str) -> Result<(), std::io::Error> {
write!(output, "{}{}{}", declarations.include, line_feed, line_feed)?;
write!(output, "const {} {}[] = {{{}", declarations.var_type, data_name, line_feed)?;
output_bytes(input, output, line_feed)?;
write!(output, "{}}};", line_feed)
}
pub fn convert(cfg: Configuration, input: Input, mut output: Output) -> Result<(), Error> {
let line_feed = {
match cfg.line_feed {
LineFeed::Windows => WINDOWS_LINEFEED,
LineFeed::Unix => UNIX_LINEFEED
}
};
let (declarations, is_source_file) = {
match cfg.file_type {
FileType::CHeader => (&C_DECLARATIONS, false),
FileType::CSource => (&C_DECLARATIONS, true),
FileType::CPPHeader => (&CPP_DECLARATIONS, false),
FileType::CPPSource => (&CPP_DECLARATIONS, true),
}
};
if is_source_file {
Error::try_or_new(write_source_file(input, &mut output, declarations, cfg.data_name, line_feed), None)
}
else {
Error::try_or_new(write_header_file(input, &mut output, cfg.file_name, declarations, cfg.data_name, line_feed), None)
}
}