Skip to content

Commit d53a460

Browse files
authored
Escape special chars (#9)
1 parent 06d9e71 commit d53a460

4 files changed

Lines changed: 111 additions & 21 deletions

File tree

cpp2rust/converter/converter.cpp

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1552,26 +1552,27 @@ bool Converter::VisitCharacterLiteral(clang::CharacterLiteral *expr) {
15521552
}
15531553

15541554
std::string Converter::GetEscapedCharLiteral(char character) const {
1555-
std::string esc;
1556-
esc = character;
15571555
switch (character) {
15581556
case '"':
1559-
esc = "\\\"";
1560-
break;
1557+
return "\\\"";
1558+
case '\'':
1559+
return "\\'";
1560+
case '\\':
1561+
return "\\\\";
15611562
case '\n':
1562-
esc = "\\n";
1563-
break;
1563+
return "\\n";
15641564
case '\r':
1565-
esc = "\\r";
1566-
break;
1565+
return "\\r";
15671566
case '\t':
1568-
esc = "\\t";
1569-
break;
1567+
return "\\t";
15701568
case '\0':
1571-
esc = "\\0";
1572-
break;
1569+
return "\\0";
1570+
}
1571+
auto uc = static_cast<unsigned char>(character);
1572+
if (uc < 0x20 || uc == 0x7F) {
1573+
return std::format("\\x{:02x}", uc);
15731574
}
1574-
return esc;
1575+
return std::string(1, character);
15751576
}
15761577

15771578
std::string Converter::GetEscapedUTF8CharLiteral(clang::Expr *expr) const {
@@ -1590,14 +1591,17 @@ std::string Converter::GetEscapedStringLiteral(clang::Expr *expr,
15901591
bool add_null_char) const {
15911592
auto str_expr = clang::dyn_cast<clang::StringLiteral>(expr->IgnoreCasts());
15921593
assert(str_expr);
1593-
std::string string = str_expr->getString().str();
1594-
// escape quotes
1595-
size_t pos = 0;
1596-
while ((pos = string.find_first_of("\"\n\r\t\0", pos)) != std::string::npos) {
1597-
string.replace(pos, 1, GetEscapedCharLiteral(string[pos]));
1598-
pos += 2;
1599-
}
1600-
return '"' + std::move(string) + (add_null_char ? "\\0\"" : "\"");
1594+
auto raw = str_expr->getString();
1595+
std::string out;
1596+
out.push_back('"');
1597+
for (unsigned char c : raw) {
1598+
out += GetEscapedCharLiteral(static_cast<char>(c));
1599+
}
1600+
if (add_null_char) {
1601+
out += "\\0";
1602+
}
1603+
out.push_back('"');
1604+
return out;
16011605
}
16021606

16031607
bool Converter::VisitStringLiteral(clang::StringLiteral *expr) {
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
extern crate libcc2rs;
2+
use libcc2rs::*;
3+
use std::cell::RefCell;
4+
use std::collections::BTreeMap;
5+
use std::io::prelude::*;
6+
use std::io::Seek;
7+
use std::io::{Read, Write};
8+
use std::os::fd::AsFd;
9+
use std::rc::{Rc, Weak};
10+
pub fn main() {
11+
std::process::exit(main_0());
12+
}
13+
fn main_0() -> i32 {
14+
let special: Value<Ptr<u8>> = Rc::new(RefCell::new(Ptr::from_string_literal(
15+
"\x07\x08\t\n\x0b\x0c\r !\"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~",
16+
)));
17+
thread_local!(
18+
static expected: Value<Box<[u8]>> = Rc::new(RefCell::new(Box::new([
19+
7_u8, 8_u8, 9_u8, 10_u8, 11_u8, 12_u8, 13_u8, 32_u8, 33_u8, 34_u8, 35_u8, 36_u8, 37_u8,
20+
38_u8, 39_u8, 40_u8, 41_u8, 42_u8, 43_u8, 44_u8, 45_u8, 46_u8, 47_u8, 58_u8, 59_u8,
21+
60_u8, 61_u8, 62_u8, 63_u8, 64_u8, 91_u8, 92_u8, 93_u8, 94_u8, 95_u8, 96_u8, 123_u8,
22+
124_u8, 125_u8, 126_u8,
23+
])));
24+
);
25+
let i: Value<i32> = Rc::new(RefCell::new(0));
26+
'loop_: while ((*i.borrow())
27+
< ((((::std::mem::size_of::<[u8; 40]>() as u64 as u64)
28+
.wrapping_div(::std::mem::size_of::<u8>() as u64 as u64)) as u64) as i32))
29+
{
30+
assert!({
31+
let _lhs = (((*special.borrow()).offset((*i.borrow()) as isize).read()) as i32);
32+
_lhs == ((*expected.with(Value::clone).borrow())[(*i.borrow()) as usize] as i32)
33+
});
34+
(*i.borrow_mut()).postfix_inc();
35+
}
36+
return 0;
37+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
extern crate libc;
2+
use libc::*;
3+
extern crate libcc2rs;
4+
use libcc2rs::*;
5+
use std::collections::BTreeMap;
6+
use std::io::Seek;
7+
use std::io::{Read, Write};
8+
use std::os::fd::{AsFd, FromRawFd, IntoRawFd};
9+
use std::rc::Rc;
10+
pub fn main() {
11+
unsafe {
12+
std::process::exit(main_0() as i32);
13+
}
14+
}
15+
unsafe fn main_0() -> i32 {
16+
let mut special: *const u8 =
17+
b"\x07\x08\t\n\x0b\x0c\r !\"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~\0".as_ptr();
18+
static expected: [u8; 40] = [
19+
7_u8, 8_u8, 9_u8, 10_u8, 11_u8, 12_u8, 13_u8, 32_u8, 33_u8, 34_u8, 35_u8, 36_u8, 37_u8,
20+
38_u8, 39_u8, 40_u8, 41_u8, 42_u8, 43_u8, 44_u8, 45_u8, 46_u8, 47_u8, 58_u8, 59_u8, 60_u8,
21+
61_u8, 62_u8, 63_u8, 64_u8, 91_u8, 92_u8, 93_u8, 94_u8, 95_u8, 96_u8, 123_u8, 124_u8,
22+
125_u8, 126_u8,
23+
];;
24+
let mut i: i32 = 0;
25+
'loop_: while ((i)
26+
< ((((::std::mem::size_of::<[u8; 40]>() as u64 as u64)
27+
.wrapping_div(::std::mem::size_of::<u8>() as u64 as u64)) as u64) as i32))
28+
{
29+
assert!((((*special.offset((i) as isize)) as i32) == (expected[(i) as usize] as i32)));
30+
i.postfix_inc();
31+
}
32+
return 0;
33+
}

tests/unit/string_escape.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#include <assert.h>
2+
#include <string.h>
3+
4+
int main() {
5+
const char *special = "\a\b\t\n\v\f\r !\"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~";
6+
static const char expected[] = {
7+
7, 8, 9, 10, 11, 12, 13, 32, 33, 34, 35, 36, 37, 38,
8+
39, 40, 41, 42, 43, 44, 45, 46, 47, 58, 59, 60, 61, 62,
9+
63, 64, 91, 92, 93, 94, 95, 96, 123, 124, 125, 126,
10+
};
11+
for (int i = 0; i < (int)(sizeof(expected) / sizeof(expected[0])); i++) {
12+
assert(special[i] == expected[i]);
13+
}
14+
15+
return 0;
16+
}

0 commit comments

Comments
 (0)