From 683eb5aa53d7e62576bbeda9257aaa3deb04bcda Mon Sep 17 00:00:00 2001 From: Henri Sivonen Date: Fri, 27 Jan 2017 09:42:56 +0200 Subject: [PATCH] Optimize Big5 astral encode. --- generate-encoding-data.py | 19 +++++++++++++++++ src/big5.rs | 44 ++++++++++++++++++++++----------------- src/data.rs | 19 +++++++++++++++++ src/lib.rs | 5 +++++ 4 files changed, 68 insertions(+), 19 deletions(-) diff --git a/generate-encoding-data.py b/generate-encoding-data.py index b13dee5..7369818 100644 --- a/generate-encoding-data.py +++ b/generate-encoding-data.py @@ -1185,6 +1185,25 @@ pub fn big5_low_bits(rebased_pointer: usize) -> u16 { } } +#[inline(always)] +pub fn big5_astral_encode(low_bits: u16) -> Option { + match low_bits { + 0x00CC => Some(11205 - 942), + 0x008A => Some(11207 - 942), + 0x7607 => Some(11213 - 942), + _ => { + let mut i = 18997 - 942; + while i < BIG5_LOW_BITS.len() { + if BIG5_LOW_BITS[i] == low_bits && big5_is_astral(i) { + return Some(i); + } + i += 1; + } + None + } + } +} + #[inline(always)] pub fn big5_find_pointer(low_bits: u16, is_astral: bool) -> usize { if !is_astral { diff --git a/src/big5.rs b/src/big5.rs index a22cc0c..256f2c9 100644 --- a/src/big5.rs +++ b/src/big5.rs @@ -194,26 +194,31 @@ impl Big5Encoder { handle.write_two(lead as u8, trail as u8) }, { - if astral as u32 & 0xFF0000 != 0x20000 { - // Only Plane 2 is potentially mappable of the astral planes. - return (EncoderResult::Unmappable(astral), - source.consumed(), - handle.written()); - } - let pointer = big5_find_pointer(astral as u16, true); - if pointer == 0 { - return (EncoderResult::Unmappable(astral), - source.consumed(), - handle.written()); - } - let lead = pointer / 157 + 0x81; - let remainder = pointer % 157; - let trail = if remainder < 0x3F { - remainder + 0x40 + if in_inclusive_range32(astral as u32, + 0x2008A, + 0x2F8A6) { + if let Some(rebased_pointer) = + big5_astral_encode(astral as u16) { + // big5_astral_encode returns rebased pointer, + // so adding 0x87 instead of 0x81. + let lead = rebased_pointer / 157 + 0x87; + let remainder = rebased_pointer % 157; + let trail = if remainder < 0x3F { + remainder + 0x40 + } else { + remainder + 0x62 + }; + handle.write_two(lead as u8, trail as u8) + } else { + return (EncoderResult::Unmappable(astral), + source.consumed(), + handle.written()); + } } else { - remainder + 0x62 - }; - handle.write_two(lead as u8, trail as u8) + return (EncoderResult::Unmappable(astral), + source.consumed(), + handle.written()); + } }, bmp, astral, @@ -321,6 +326,7 @@ mod tests { // duplicate low bits encode_big5("\u{203B5}", b"\xFD\x6A"); + encode_big5("\u{25605}", b"\xFE\x46"); // prefer last encode_big5("\u{2550}", b"\xF9\xF9"); diff --git a/src/data.rs b/src/data.rs index 6fb5ce8..ae0ff39 100644 --- a/src/data.rs +++ b/src/data.rs @@ -18606,6 +18606,25 @@ pub fn big5_low_bits(rebased_pointer: usize) -> u16 { } } +#[inline(always)] +pub fn big5_astral_encode(low_bits: u16) -> Option { + match low_bits { + 0x00CC => Some(11205 - 942), + 0x008A => Some(11207 - 942), + 0x7607 => Some(11213 - 942), + _ => { + let mut i = 18997 - 942; + while i < BIG5_LOW_BITS.len() { + if BIG5_LOW_BITS[i] == low_bits && big5_is_astral(i) { + return Some(i); + } + i += 1; + } + None + } + } +} + #[inline(always)] pub fn big5_find_pointer(low_bits: u16, is_astral: bool) -> usize { if !is_astral { diff --git a/src/lib.rs b/src/lib.rs index 3d09e10..f2aa838 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3646,6 +3646,11 @@ fn in_inclusive_range16(i: u16, start: u16, end: u16) -> bool { i.wrapping_sub(start) <= (end - start) } +#[inline(always)] +fn in_inclusive_range32(i: u32, start: u32, end: u32) -> bool { + i.wrapping_sub(start) <= (end - start) +} + #[inline(always)] fn in_inclusive_range(i: usize, start: usize, end: usize) -> bool { i.wrapping_sub(start) <= (end - start)