From 8054e10c7b3bd5ba5b57c11407b58e759ba7516c Mon Sep 17 00:00:00 2001 From: Adam Macdonald Date: Sun, 17 Aug 2025 17:52:15 +0100 Subject: [PATCH] 0.2.5: fix signed literals --- Cargo.lock | 2 +- Cargo.toml | 2 +- README.md | 12 +++--- src/cli.rs | 20 ++++++++++ src/generate.rs | 102 +++++++++++++++++++++++++++++++----------------- 5 files changed, 95 insertions(+), 43 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 955dc1b..c2b4b65 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,7 +4,7 @@ version = 4 [[package]] name = "bin2hpp" -version = "0.2.4" +version = "0.2.5" dependencies = [ "thiserror", ] diff --git a/Cargo.toml b/Cargo.toml index 74e658d..8baba5f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "bin2hpp" -version = "0.2.4" +version = "0.2.5" authors = ["Adam Macdonald"] edition = "2024" license = "GPL-3.0-only" diff --git a/README.md b/README.md index d4e8c40..24dcc28 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,9 @@ CLI tool for converting files into header files which one can use to directly em ## Building -1. `cargo build` +`cargo build`, or `cargo [build | run | install] --profile optimised` to build an optimised binary. + +The performance (but potentially not the executable size) can be further optimised by telling the compiler to use a more modern instruction set: `RUSTFLAGS="-C target-cpu=native"`. ## Usage @@ -15,11 +17,11 @@ CLI tool for converting files into header files which one can use to directly em `$ bin2hpp -i my_library.dll -o c_header.h` will generate an `c_header.h` file in your current working directory containing something similar to the following: ```c -// Generated by bin2hpp 0.2.4 +// Generated by bin2hpp 0.2.5 #ifndef C_HEADER_H #define C_HEADER_H #define MY_LIBRARY_DLL_LEN 9728 -const unsigned char MY_LIBRARY_DLL[MY_LIBRARY_DLL_LEN] = {0x4d,0x5a,0x90,0x0,0x3,0x0,0x0, ...}; +const unsigned char MY_LIBRARY_DLL[MY_LIBRARY_DLL_LEN] = {77,90,144,0,3,0,0,0,4, ...}; #else extern const unsigned char MY_LIBRARY_DLL[MY_LIBRARY_DLL_LEN]; #endif @@ -28,13 +30,13 @@ extern const unsigned char MY_LIBRARY_DLL[MY_LIBRARY_DLL_LEN]; Alternatively, in **C++ mode**: `bin2hpp -i my_library.dll -o cpp_header.hpp --cpp --constexpr --stdarray --i8` ```cpp -// Generated by bin2hpp 0.2.4 +// Generated by bin2hpp 0.2.5 #if !defined(CPP_HEADER_HPP) #define CPP_HEADER_HPP #include #include #define MY_LIBRARY_DLL_LEN 9728 -inline constexpr std::array MY_LIBRARY_DLL = {0x4d,0x5a,0x90,0x0,0x3,0x0,0x0, ...}; +inline constexpr std::array MY_LIBRARY_DLL = {77,90,-112,0,3,0,0,0,4, ...}; #endif ``` diff --git a/src/cli.rs b/src/cli.rs index 689c841..c402ab7 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -20,6 +20,26 @@ pub enum ByteType { I8, } +impl ByteType { + pub fn to_c_type(&self) -> &'static str { + match self { + ByteType::UnsignedChar => "unsigned char", + ByteType::Char => "char", + ByteType::U8 => "uint8_t", + ByteType::I8 => "int8_t", + } + } + + pub fn to_cpp_type(&self) -> &'static str { + match self { + ByteType::UnsignedChar => self.to_c_type(), + ByteType::Char => self.to_c_type(), + ByteType::U8 => "std::uint8_t", + ByteType::I8 => "std::int8_t", + } + } +} + #[derive(Debug, PartialEq, Clone, Copy)] pub enum ContainerType { CArray(ByteType), diff --git a/src/generate.rs b/src/generate.rs index a8e6ffc..8fea73b 100644 --- a/src/generate.rs +++ b/src/generate.rs @@ -175,8 +175,8 @@ pub fn with_definition( modifiers, data_type_and_symbol(config), match config.container_type { - ContainerType::CArray(_) => with_array_initialiser(in_data), - ContainerType::StdArray(_) => with_array_initialiser(in_data), + ContainerType::CArray(_) => with_array_initialiser(config, in_data), + ContainerType::StdArray(_) => with_array_initialiser(config, in_data), _ => with_string_initialiser(config, in_data)?, }, config.line_ending @@ -199,12 +199,34 @@ pub fn with_declaration(config: &Config, buf: &mut String) { .unwrap(); } -pub fn with_array_initialiser(in_data: &[u8]) -> String { +pub fn with_array_initialiser(config: &Config, in_data: &[u8]) -> String { let mut out_str: String = String::with_capacity(in_data.len() * 6 + 16); + let signed_literals = match config.container_type { + ContainerType::CArray(byte_type) => match byte_type { + ByteType::Char => true, + ByteType::I8 => true, + _ => false, + }, + ContainerType::StdArray(byte_type) => match byte_type { + ByteType::Char => true, + ByteType::I8 => true, + _ => false, + }, + _ => false, + }; + write!(out_str, "{{").unwrap(); - for b in in_data { - write!(out_str, "{:#x},", b).unwrap(); + + if signed_literals { + for b in in_data { + let b = i8::from_ne_bytes([*b; 1]); + write!(out_str, "{},", b).unwrap(); + } + } else { + for b in in_data { + write!(out_str, "{},", b).unwrap(); + } } let _ = out_str.pop(); write!(out_str, "}}").unwrap(); @@ -249,40 +271,48 @@ pub fn length_symbol(config: &Config) -> String { } pub fn data_type_and_symbol(config: &Config) -> String { - let u8_type = match config.language { - Language::C => "uint8_t", - Language::Cpp => "std::uint8_t", - }; - let i8_type = match config.language { - Language::C => "int8_t", - Language::Cpp => "std::int8_t", - }; + let mut out_str = String::with_capacity(config.symbol_name.len() + 20); let length_sym = length_symbol(config); match config.container_type { - ContainerType::CArray(byte_type) => match byte_type { - ByteType::UnsignedChar => { - format!("unsigned char {}[{}]", config.symbol_name, length_sym) - } - ByteType::Char => format!("char {}[{}]", config.symbol_name, length_sym), - _ => format!("{} {}[{}]", u8_type, config.symbol_name, length_sym), - }, - ContainerType::StdArray(byte_type) => { - format!( - "std::array<{},{}> {}", - match byte_type { - ByteType::UnsignedChar => "unsigned char", - ByteType::Char => "char", - ByteType::U8 => u8_type, - ByteType::I8 => i8_type, - }, - length_sym, - config.symbol_name - ) + ContainerType::CArray(byte_type) => write!( + out_str, + "{} {}[{}]", + if config.language == Language::Cpp { + byte_type.to_cpp_type() + } else { + byte_type.to_c_type() + }, + config.symbol_name, + length_sym + ) + .unwrap(), + ContainerType::StdArray(byte_type) => write!( + out_str, + "std::array<{},{}> {}", + if config.language == Language::Cpp { + byte_type.to_cpp_type() + } else { + byte_type.to_c_type() + }, + length_sym, + config.symbol_name + ) + .unwrap(), + ContainerType::CString => write!( + out_str, + "{} {}[{}]", + ByteType::Char.to_c_type(), + config.symbol_name, + length_sym + ) + .unwrap(), + ContainerType::StdString => write!(out_str, "std::string {}", config.symbol_name).unwrap(), + ContainerType::StdStringView => { + write!(out_str, "std::string_view {}", config.symbol_name).unwrap() } - ContainerType::CString => format!("char {}[{}]", config.symbol_name, length_sym), - ContainerType::StdString => format!("std::string {}", config.symbol_name), - ContainerType::StdStringView => format!("std::string_view {}", config.symbol_name), - } + }; + + out_str }