Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

io: implement Print for i8/u8 + add Writer::char #81

Merged
merged 3 commits into from
Feb 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 25 additions & 1 deletion basm-std/src/platform/io/writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,30 @@ impl<const N: usize> Writer<N> {
let printed = buffer.format(f);
self.bytes(printed.as_bytes());
}
pub fn char(&mut self, c: char) {
self.try_flush(6);
let u = c as u32;
if u < 0x80 {
self.byte_unchecked(u as u8);
} else if u < 0x800 {
self.byte_unchecked(0b11000000 | (u >> 6) as u8);
self.byte_unchecked(0b10000000 | (u & 0x3F) as u8);
} else if u < 0xFFFF {
self.byte_unchecked(0b11100000 | (u >> 12) as u8);
self.byte_unchecked(0b10000000 | ((u >> 6) & 0x3F) as u8);
self.byte_unchecked(0b10000000 | (u & 0x3F) as u8);
} else {
// The Unicode standard dictates that every codepoint
// that is not representable in UTF-16 (including the use of surrogates)
// should be considered invalid. Hence, we put an assert here
// and do not deal with the case of u > 0x10_FFFF.
assert!(u <= 0x10_FFFF);
self.byte_unchecked(0b11110000 | (u >> 18) as u8);
self.byte_unchecked(0b10000000 | ((u >> 12) & 0x3F) as u8);
self.byte_unchecked(0b10000000 | ((u >> 6) & 0x3F) as u8);
self.byte_unchecked(0b10000000 | (u & 0x3F) as u8);
}
}
}

pub trait Print<T> {
Expand Down Expand Up @@ -363,7 +387,7 @@ macro_rules! impl_print{
}
}

impl_print!(i16 u16 i32 u32 i64 u64 f64 i128 u128 isize usize);
impl_print!(i8 u8 i16 u16 i32 u32 i64 u64 f64 i128 u128 isize usize char);

/*
#[cfg(test)]
Expand Down
10 changes: 10 additions & 0 deletions basm-std/src/platform/os/windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ impl WinApi {
pub const STD_OUTPUT_HANDLE: u32 = -11i32 as u32;
pub const STD_ERROR_HANDLE: u32 = -12i32 as u32;
pub const ERROR_IO_PENDING: u32 = 997;
pub const CP_UTF8: u32 = 65001;
#[inline(always)]
pub unsafe fn VirtualAlloc(&self, lpAddress: *mut u8, dwSize: usize, flAllocationType: u32, flProtect: u32) -> *mut u8 {
(self.ptr_VirtualAlloc.unwrap())(lpAddress, dwSize, flAllocationType, flProtect)
Expand Down Expand Up @@ -196,6 +197,15 @@ pub unsafe fn init() {
WINAPI.ptr_GetOverlappedResult = Some(core::mem::transmute(GetProcAddress(kernel32, b"GetOverlappedResult\0".as_ptr())));
WINAPI.ptr_GetLastError = Some(core::mem::transmute(GetProcAddress(kernel32, b"GetLastError\0".as_ptr())));

// On Windows, set console codepage to UTF-8,
// since the default encoding is (historically) MBCS
// which depends on the host platform's language and
// other factors.
let SetConsoleCP: ms_abi!{fn(u32) -> i32} = core::mem::transmute(GetProcAddress(kernel32, b"SetConsoleCP\0".as_ptr()));
SetConsoleCP(WinApi::CP_UTF8); // for stdin
let SetConsoleOutputCP: ms_abi!{fn(u32) -> i32} = core::mem::transmute(GetProcAddress(kernel32, b"SetConsoleOutputCP\0".as_ptr()));
SetConsoleOutputCP(WinApi::CP_UTF8); // for stdout

allocator::install_malloc_impl(
dlmalloc_alloc,
dlmalloc_alloc_zeroed,
Expand Down
2 changes: 1 addition & 1 deletion scripts/build-and-judge.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ def test_equal(x, y):

# Run the binary
with open(indata_path, mode="r", encoding="utf8") as f:
completed_process = subprocess.run(run_cmd, shell=False, stdin=f, capture_output=True, text=True)
completed_process = subprocess.run(run_cmd, shell=False, stdin=f, capture_output=True, text=True, encoding="utf8")
if completed_process.returncode != 0:
raise Exception("Program {0} exited with non-zero code {3} (hex {3:X}) for input {1} and output {2}\n\n{4}"
.format(sol_path, indata_path, outdata_path, completed_process.returncode, completed_process.stderr))
Expand Down
5 changes: 5 additions & 0 deletions tests/ci.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,10 @@
"solution": "./tests/reloc.rs",
"input": "./tests/reloc.in",
"output": "./tests/reloc.out"
},
{
"solution": "./tests/utf8.rs",
"input": "./tests/utf8.in",
"output": "./tests/utf8.out"
}
]
1 change: 1 addition & 0 deletions tests/utf8.in
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3 4
3 changes: 3 additions & 0 deletions tests/utf8.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
7
a
π한
11 changes: 11 additions & 0 deletions tests/utf8.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
use basm::platform::io::{Reader, ReaderTrait, Writer, Print};
pub fn main() {
let mut reader: Reader = Default::default();
let mut writer: Writer = Default::default();
let a = reader.i64();
let b = reader.i64();
writer.println(a + b);
writer.println('a');
writer.char('\u{3C0}');
writer.println('\u{D55C}');
}
Loading