mirror of
https://github.com/openharmony/third_party_rust_encoding_rs.git
synced 2026-07-21 02:05:23 -04:00
Upgrade rustfmt.
This commit is contained in:
+398
-361
@@ -21,8 +21,16 @@
|
||||
// on Raspberry Pi 3 measurements. The UTF-16 and UTF-8 ALU cases take
|
||||
// different approaches based on benchmarking on Raspberry Pi 3.
|
||||
|
||||
#[cfg(all(feature = "simd-accel",
|
||||
any(target_feature = "sse2", all(target_endian = "little", target_arch = "aarch64"), all(target_endian = "little", target_feature = "neon"))))]
|
||||
#[cfg(
|
||||
all(
|
||||
feature = "simd-accel",
|
||||
any(
|
||||
target_feature = "sse2",
|
||||
all(target_endian = "little", target_arch = "aarch64"),
|
||||
all(target_endian = "little", target_feature = "neon")
|
||||
)
|
||||
)
|
||||
)]
|
||||
use simd_funcs::*;
|
||||
|
||||
// `as` truncates, so works on 32-bit, too.
|
||||
@@ -35,22 +43,25 @@ pub const BASIC_LATIN_MASK: usize = 0xFF80FF80_FF80FF80u64 as usize;
|
||||
|
||||
#[allow(unused_macros)]
|
||||
macro_rules! ascii_naive {
|
||||
($name:ident,
|
||||
$src_unit:ty,
|
||||
$dst_unit:ty) => (
|
||||
#[inline(always)]
|
||||
pub unsafe fn $name(src: *const $src_unit, dst: *mut $dst_unit, len: usize) -> Option<($src_unit, usize)> {
|
||||
// Yes, manually omitting the bound check here matters
|
||||
// a lot for perf.
|
||||
for i in 0..len {
|
||||
let code_unit = *(src.offset(i as isize));
|
||||
if code_unit > 127 {
|
||||
return Some((code_unit, i));
|
||||
($name:ident, $src_unit:ty, $dst_unit:ty) => {
|
||||
#[inline(always)]
|
||||
pub unsafe fn $name(
|
||||
src: *const $src_unit,
|
||||
dst: *mut $dst_unit,
|
||||
len: usize,
|
||||
) -> Option<($src_unit, usize)> {
|
||||
// Yes, manually omitting the bound check here matters
|
||||
// a lot for perf.
|
||||
for i in 0..len {
|
||||
let code_unit = *(src.offset(i as isize));
|
||||
if code_unit > 127 {
|
||||
return Some((code_unit, i));
|
||||
}
|
||||
*(dst.offset(i as isize)) = code_unit as $dst_unit;
|
||||
}
|
||||
*(dst.offset(i as isize)) = code_unit as $dst_unit;
|
||||
return None;
|
||||
}
|
||||
return None;
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
#[allow(unused_macros)]
|
||||
@@ -223,364 +234,397 @@ macro_rules! basic_latin_alu {
|
||||
|
||||
#[allow(unused_macros)]
|
||||
macro_rules! latin1_alu {
|
||||
($name:ident,
|
||||
$src_unit:ty,
|
||||
$dst_unit:ty,
|
||||
$stride_fn:ident) => (
|
||||
#[cfg_attr(feature = "cargo-clippy", allow(never_loop))]
|
||||
#[inline(always)]
|
||||
pub unsafe fn $name(src: *const $src_unit, dst: *mut $dst_unit, len: usize) {
|
||||
let mut offset = 0usize;
|
||||
// This loop is only broken out of as a `goto` forward
|
||||
loop {
|
||||
let mut until_alignment = {
|
||||
if ::std::mem::size_of::<$src_unit>() < ::std::mem::size_of::<$dst_unit>() {
|
||||
// unpack
|
||||
let src_until_alignment = (ALU_ALIGNMENT - ((src as usize) & ALU_ALIGNMENT_MASK)) & ALU_ALIGNMENT_MASK;
|
||||
if (dst.offset(src_until_alignment as isize) as usize) & ALU_ALIGNMENT_MASK != 0 {
|
||||
break;
|
||||
($name:ident, $src_unit:ty, $dst_unit:ty, $stride_fn:ident) => {
|
||||
#[cfg_attr(feature = "cargo-clippy", allow(never_loop))]
|
||||
#[inline(always)]
|
||||
pub unsafe fn $name(src: *const $src_unit, dst: *mut $dst_unit, len: usize) {
|
||||
let mut offset = 0usize;
|
||||
// This loop is only broken out of as a `goto` forward
|
||||
loop {
|
||||
let mut until_alignment = {
|
||||
if ::std::mem::size_of::<$src_unit>() < ::std::mem::size_of::<$dst_unit>() {
|
||||
// unpack
|
||||
let src_until_alignment = (ALU_ALIGNMENT
|
||||
- ((src as usize) & ALU_ALIGNMENT_MASK))
|
||||
& ALU_ALIGNMENT_MASK;
|
||||
if (dst.offset(src_until_alignment as isize) as usize) & ALU_ALIGNMENT_MASK
|
||||
!= 0
|
||||
{
|
||||
break;
|
||||
}
|
||||
src_until_alignment
|
||||
} else {
|
||||
// pack
|
||||
let dst_until_alignment = (ALU_ALIGNMENT
|
||||
- ((dst as usize) & ALU_ALIGNMENT_MASK))
|
||||
& ALU_ALIGNMENT_MASK;
|
||||
if (src.offset(dst_until_alignment as isize) as usize) & ALU_ALIGNMENT_MASK
|
||||
!= 0
|
||||
{
|
||||
break;
|
||||
}
|
||||
dst_until_alignment
|
||||
}
|
||||
};
|
||||
if until_alignment + ALU_STRIDE_SIZE <= len {
|
||||
while until_alignment != 0 {
|
||||
let code_unit = *(src.offset(offset as isize));
|
||||
*(dst.offset(offset as isize)) = code_unit as $dst_unit;
|
||||
offset += 1;
|
||||
until_alignment -= 1;
|
||||
}
|
||||
let len_minus_stride = len - ALU_STRIDE_SIZE;
|
||||
loop {
|
||||
$stride_fn(
|
||||
src.offset(offset as isize) as *const usize,
|
||||
dst.offset(offset as isize) as *mut usize,
|
||||
);
|
||||
offset += ALU_STRIDE_SIZE;
|
||||
if offset > len_minus_stride {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
while offset < len {
|
||||
let code_unit = *(src.offset(offset as isize));
|
||||
*(dst.offset(offset as isize)) = code_unit as $dst_unit;
|
||||
offset += 1;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[allow(unused_macros)]
|
||||
macro_rules! ascii_simd_check_align {
|
||||
(
|
||||
$name:ident,
|
||||
$src_unit:ty,
|
||||
$dst_unit:ty,
|
||||
$stride_both_aligned:ident,
|
||||
$stride_src_aligned:ident,
|
||||
$stride_dst_aligned:ident,
|
||||
$stride_neither_aligned:ident
|
||||
) => {
|
||||
#[inline(always)]
|
||||
pub unsafe fn $name(
|
||||
src: *const $src_unit,
|
||||
dst: *mut $dst_unit,
|
||||
len: usize,
|
||||
) -> Option<($src_unit, usize)> {
|
||||
let mut offset = 0usize;
|
||||
if SIMD_STRIDE_SIZE <= len {
|
||||
let len_minus_stride = len - SIMD_STRIDE_SIZE;
|
||||
// XXX Should we first process one stride unconditinoally as unaligned to
|
||||
// avoid the cost of the branchiness below if the first stride fails anyway?
|
||||
// XXX Should we just use unaligned SSE2 access unconditionally? It seems that
|
||||
// on Haswell, it would make sense to just use unaligned and not bother
|
||||
// checking. Need to benchmark older architectures before deciding.
|
||||
let dst_masked = (dst as usize) & SIMD_ALIGNMENT_MASK;
|
||||
if ((src as usize) & SIMD_ALIGNMENT_MASK) == 0 {
|
||||
if dst_masked == 0 {
|
||||
loop {
|
||||
if !$stride_both_aligned(
|
||||
src.offset(offset as isize),
|
||||
dst.offset(offset as isize),
|
||||
) {
|
||||
break;
|
||||
}
|
||||
offset += SIMD_STRIDE_SIZE;
|
||||
if offset > len_minus_stride {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
loop {
|
||||
if !$stride_src_aligned(
|
||||
src.offset(offset as isize),
|
||||
dst.offset(offset as isize),
|
||||
) {
|
||||
break;
|
||||
}
|
||||
offset += SIMD_STRIDE_SIZE;
|
||||
if offset > len_minus_stride {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
src_until_alignment
|
||||
} else {
|
||||
// pack
|
||||
let dst_until_alignment = (ALU_ALIGNMENT - ((dst as usize) & ALU_ALIGNMENT_MASK)) & ALU_ALIGNMENT_MASK;
|
||||
if (src.offset(dst_until_alignment as isize) as usize) & ALU_ALIGNMENT_MASK != 0 {
|
||||
if dst_masked == 0 {
|
||||
loop {
|
||||
if !$stride_dst_aligned(
|
||||
src.offset(offset as isize),
|
||||
dst.offset(offset as isize),
|
||||
) {
|
||||
break;
|
||||
}
|
||||
offset += SIMD_STRIDE_SIZE;
|
||||
if offset > len_minus_stride {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
loop {
|
||||
if !$stride_neither_aligned(
|
||||
src.offset(offset as isize),
|
||||
dst.offset(offset as isize),
|
||||
) {
|
||||
break;
|
||||
}
|
||||
offset += SIMD_STRIDE_SIZE;
|
||||
if offset > len_minus_stride {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
while offset < len {
|
||||
let code_unit = *(src.offset(offset as isize));
|
||||
if code_unit > 127 {
|
||||
return Some((code_unit, offset));
|
||||
}
|
||||
*(dst.offset(offset as isize)) = code_unit as $dst_unit;
|
||||
offset += 1;
|
||||
}
|
||||
None
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[allow(unused_macros)]
|
||||
macro_rules! latin1_simd_check_align {
|
||||
(
|
||||
$name:ident,
|
||||
$src_unit:ty,
|
||||
$dst_unit:ty,
|
||||
$stride_both_aligned:ident,
|
||||
$stride_src_aligned:ident,
|
||||
$stride_dst_aligned:ident,
|
||||
$stride_neither_aligned:ident
|
||||
) => {
|
||||
#[inline(always)]
|
||||
pub unsafe fn $name(src: *const $src_unit, dst: *mut $dst_unit, len: usize) {
|
||||
let mut offset = 0usize;
|
||||
if SIMD_STRIDE_SIZE <= len {
|
||||
let len_minus_stride = len - SIMD_STRIDE_SIZE;
|
||||
// XXX Should we first process one stride unconditinoally as unaligned to
|
||||
// avoid the cost of the branchiness below if the first stride fails anyway?
|
||||
// XXX Should we just use unaligned SSE2 access unconditionally? It seems that
|
||||
// on Haswell, it would make sense to just use unaligned and not bother
|
||||
// checking. Need to benchmark older architectures before deciding.
|
||||
let dst_masked = (dst as usize) & SIMD_ALIGNMENT_MASK;
|
||||
if ((src as usize) & SIMD_ALIGNMENT_MASK) == 0 {
|
||||
if dst_masked == 0 {
|
||||
loop {
|
||||
$stride_both_aligned(
|
||||
src.offset(offset as isize),
|
||||
dst.offset(offset as isize),
|
||||
);
|
||||
offset += SIMD_STRIDE_SIZE;
|
||||
if offset > len_minus_stride {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
loop {
|
||||
$stride_src_aligned(
|
||||
src.offset(offset as isize),
|
||||
dst.offset(offset as isize),
|
||||
);
|
||||
offset += SIMD_STRIDE_SIZE;
|
||||
if offset > len_minus_stride {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if dst_masked == 0 {
|
||||
loop {
|
||||
$stride_dst_aligned(
|
||||
src.offset(offset as isize),
|
||||
dst.offset(offset as isize),
|
||||
);
|
||||
offset += SIMD_STRIDE_SIZE;
|
||||
if offset > len_minus_stride {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
loop {
|
||||
$stride_neither_aligned(
|
||||
src.offset(offset as isize),
|
||||
dst.offset(offset as isize),
|
||||
);
|
||||
offset += SIMD_STRIDE_SIZE;
|
||||
if offset > len_minus_stride {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
while offset < len {
|
||||
let code_unit = *(src.offset(offset as isize));
|
||||
// On x86_64, this loop autovectorizes but in the pack
|
||||
// case there are instructions whose purpose is to make sure
|
||||
// each u16 in the vector is truncated before packing. However,
|
||||
// since we don't care about saturating behavior of SSE2 packing
|
||||
// when the input isn't Latin1, those instructions are useless.
|
||||
// Unfortunately, using the `assume` intrinsic to lie to the
|
||||
// optimizer doesn't make LLVM omit the trunctation that we
|
||||
// don't need. Possibly this loop could be manually optimized
|
||||
// to do the sort of thing that LLVM does but without the
|
||||
// ANDing the read vectors of u16 with a constant that discards
|
||||
// the high half of each u16. As far as I can tell, the
|
||||
// optimization assumes that doing a SIMD read past the end of
|
||||
// the array is OK.
|
||||
*(dst.offset(offset as isize)) = code_unit as $dst_unit;
|
||||
offset += 1;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[allow(unused_macros)]
|
||||
macro_rules! ascii_simd_unalign {
|
||||
($name:ident, $src_unit:ty, $dst_unit:ty, $stride_neither_aligned:ident) => {
|
||||
#[inline(always)]
|
||||
pub unsafe fn $name(
|
||||
src: *const $src_unit,
|
||||
dst: *mut $dst_unit,
|
||||
len: usize,
|
||||
) -> Option<($src_unit, usize)> {
|
||||
let mut offset = 0usize;
|
||||
if SIMD_STRIDE_SIZE <= len {
|
||||
let len_minus_stride = len - SIMD_STRIDE_SIZE;
|
||||
loop {
|
||||
if !$stride_neither_aligned(
|
||||
src.offset(offset as isize),
|
||||
dst.offset(offset as isize),
|
||||
) {
|
||||
break;
|
||||
}
|
||||
dst_until_alignment
|
||||
}
|
||||
};
|
||||
if until_alignment + ALU_STRIDE_SIZE <= len {
|
||||
while until_alignment != 0 {
|
||||
let code_unit = *(src.offset(offset as isize));
|
||||
*(dst.offset(offset as isize)) = code_unit as $dst_unit;
|
||||
offset += 1;
|
||||
until_alignment -= 1;
|
||||
}
|
||||
let len_minus_stride = len - ALU_STRIDE_SIZE;
|
||||
loop {
|
||||
$stride_fn(src.offset(offset as isize) as *const usize,
|
||||
dst.offset(offset as isize) as *mut usize);
|
||||
offset += ALU_STRIDE_SIZE;
|
||||
offset += SIMD_STRIDE_SIZE;
|
||||
if offset > len_minus_stride {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
while offset < len {
|
||||
let code_unit = *(src.offset(offset as isize));
|
||||
*(dst.offset(offset as isize)) = code_unit as $dst_unit;
|
||||
offset += 1;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[allow(unused_macros)]
|
||||
macro_rules! ascii_simd_check_align {
|
||||
($name:ident,
|
||||
$src_unit:ty,
|
||||
$dst_unit:ty,
|
||||
$stride_both_aligned:ident,
|
||||
$stride_src_aligned:ident,
|
||||
$stride_dst_aligned:ident,
|
||||
$stride_neither_aligned:ident) => (
|
||||
#[inline(always)]
|
||||
pub unsafe fn $name(src: *const $src_unit, dst: *mut $dst_unit, len: usize) -> Option<($src_unit, usize)> {
|
||||
let mut offset = 0usize;
|
||||
if SIMD_STRIDE_SIZE <= len {
|
||||
let len_minus_stride = len - SIMD_STRIDE_SIZE;
|
||||
// XXX Should we first process one stride unconditinoally as unaligned to
|
||||
// avoid the cost of the branchiness below if the first stride fails anyway?
|
||||
// XXX Should we just use unaligned SSE2 access unconditionally? It seems that
|
||||
// on Haswell, it would make sense to just use unaligned and not bother
|
||||
// checking. Need to benchmark older architectures before deciding.
|
||||
let dst_masked = (dst as usize) & SIMD_ALIGNMENT_MASK;
|
||||
if ((src as usize) & SIMD_ALIGNMENT_MASK) == 0 {
|
||||
if dst_masked == 0 {
|
||||
loop {
|
||||
if !$stride_both_aligned(src.offset(offset as isize),
|
||||
dst.offset(offset as isize)) {
|
||||
break;
|
||||
}
|
||||
offset += SIMD_STRIDE_SIZE;
|
||||
if offset > len_minus_stride {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
loop {
|
||||
if !$stride_src_aligned(src.offset(offset as isize),
|
||||
dst.offset(offset as isize)) {
|
||||
break;
|
||||
}
|
||||
offset += SIMD_STRIDE_SIZE;
|
||||
if offset > len_minus_stride {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if dst_masked == 0 {
|
||||
loop {
|
||||
if !$stride_dst_aligned(src.offset(offset as isize),
|
||||
dst.offset(offset as isize)) {
|
||||
break;
|
||||
}
|
||||
offset += SIMD_STRIDE_SIZE;
|
||||
if offset > len_minus_stride {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
loop {
|
||||
if !$stride_neither_aligned(src.offset(offset as isize),
|
||||
dst.offset(offset as isize)) {
|
||||
break;
|
||||
}
|
||||
offset += SIMD_STRIDE_SIZE;
|
||||
if offset > len_minus_stride {
|
||||
break;
|
||||
}
|
||||
}
|
||||
while offset < len {
|
||||
let code_unit = *(src.offset(offset as isize));
|
||||
if code_unit > 127 {
|
||||
return Some((code_unit, offset));
|
||||
}
|
||||
*(dst.offset(offset as isize)) = code_unit as $dst_unit;
|
||||
offset += 1;
|
||||
}
|
||||
None
|
||||
}
|
||||
while offset < len {
|
||||
let code_unit = *(src.offset(offset as isize));
|
||||
if code_unit > 127 {
|
||||
return Some((code_unit, offset));
|
||||
}
|
||||
*(dst.offset(offset as isize)) = code_unit as $dst_unit;
|
||||
offset += 1;
|
||||
}
|
||||
None
|
||||
});
|
||||
}
|
||||
|
||||
#[allow(unused_macros)]
|
||||
macro_rules! latin1_simd_check_align {
|
||||
($name:ident,
|
||||
$src_unit:ty,
|
||||
$dst_unit:ty,
|
||||
$stride_both_aligned:ident,
|
||||
$stride_src_aligned:ident,
|
||||
$stride_dst_aligned:ident,
|
||||
$stride_neither_aligned:ident) => (
|
||||
#[inline(always)]
|
||||
pub unsafe fn $name(src: *const $src_unit, dst: *mut $dst_unit, len: usize) {
|
||||
let mut offset = 0usize;
|
||||
if SIMD_STRIDE_SIZE <= len {
|
||||
let len_minus_stride = len - SIMD_STRIDE_SIZE;
|
||||
// XXX Should we first process one stride unconditinoally as unaligned to
|
||||
// avoid the cost of the branchiness below if the first stride fails anyway?
|
||||
// XXX Should we just use unaligned SSE2 access unconditionally? It seems that
|
||||
// on Haswell, it would make sense to just use unaligned and not bother
|
||||
// checking. Need to benchmark older architectures before deciding.
|
||||
let dst_masked = (dst as usize) & SIMD_ALIGNMENT_MASK;
|
||||
if ((src as usize) & SIMD_ALIGNMENT_MASK) == 0 {
|
||||
if dst_masked == 0 {
|
||||
loop {
|
||||
$stride_both_aligned(src.offset(offset as isize),
|
||||
dst.offset(offset as isize));
|
||||
offset += SIMD_STRIDE_SIZE;
|
||||
if offset > len_minus_stride {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
loop {
|
||||
$stride_src_aligned(src.offset(offset as isize),
|
||||
dst.offset(offset as isize));
|
||||
offset += SIMD_STRIDE_SIZE;
|
||||
if offset > len_minus_stride {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if dst_masked == 0 {
|
||||
loop {
|
||||
$stride_dst_aligned(src.offset(offset as isize),
|
||||
dst.offset(offset as isize));
|
||||
offset += SIMD_STRIDE_SIZE;
|
||||
if offset > len_minus_stride {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
loop {
|
||||
$stride_neither_aligned(src.offset(offset as isize),
|
||||
dst.offset(offset as isize));
|
||||
offset += SIMD_STRIDE_SIZE;
|
||||
if offset > len_minus_stride {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
while offset < len {
|
||||
let code_unit = *(src.offset(offset as isize));
|
||||
// On x86_64, this loop autovectorizes but in the pack
|
||||
// case there are instructions whose purpose is to make sure
|
||||
// each u16 in the vector is truncated before packing. However,
|
||||
// since we don't care about saturating behavior of SSE2 packing
|
||||
// when the input isn't Latin1, those instructions are useless.
|
||||
// Unfortunately, using the `assume` intrinsic to lie to the
|
||||
// optimizer doesn't make LLVM omit the trunctation that we
|
||||
// don't need. Possibly this loop could be manually optimized
|
||||
// to do the sort of thing that LLVM does but without the
|
||||
// ANDing the read vectors of u16 with a constant that discards
|
||||
// the high half of each u16. As far as I can tell, the
|
||||
// optimization assumes that doing a SIMD read past the end of
|
||||
// the array is OK.
|
||||
*(dst.offset(offset as isize)) = code_unit as $dst_unit;
|
||||
offset += 1;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[allow(unused_macros)]
|
||||
macro_rules! ascii_simd_unalign {
|
||||
($name:ident,
|
||||
$src_unit:ty,
|
||||
$dst_unit:ty,
|
||||
$stride_neither_aligned:ident) => (
|
||||
#[inline(always)]
|
||||
pub unsafe fn $name(src: *const $src_unit, dst: *mut $dst_unit, len: usize) -> Option<($src_unit, usize)> {
|
||||
let mut offset = 0usize;
|
||||
if SIMD_STRIDE_SIZE <= len {
|
||||
let len_minus_stride = len - SIMD_STRIDE_SIZE;
|
||||
loop {
|
||||
if !$stride_neither_aligned(src.offset(offset as isize),
|
||||
dst.offset(offset as isize)) {
|
||||
break;
|
||||
}
|
||||
offset += SIMD_STRIDE_SIZE;
|
||||
if offset > len_minus_stride {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
while offset < len {
|
||||
let code_unit = *(src.offset(offset as isize));
|
||||
if code_unit > 127 {
|
||||
return Some((code_unit, offset));
|
||||
}
|
||||
*(dst.offset(offset as isize)) = code_unit as $dst_unit;
|
||||
offset += 1;
|
||||
}
|
||||
None
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
#[allow(unused_macros)]
|
||||
macro_rules! latin1_simd_unalign {
|
||||
($name:ident,
|
||||
$src_unit:ty,
|
||||
$dst_unit:ty,
|
||||
$stride_neither_aligned:ident) => (
|
||||
#[inline(always)]
|
||||
pub unsafe fn $name(src: *const $src_unit, dst: *mut $dst_unit, len: usize) {
|
||||
let mut offset = 0usize;
|
||||
if SIMD_STRIDE_SIZE <= len {
|
||||
let len_minus_stride = len - SIMD_STRIDE_SIZE;
|
||||
loop {
|
||||
$stride_neither_aligned(src.offset(offset as isize),
|
||||
dst.offset(offset as isize));
|
||||
offset += SIMD_STRIDE_SIZE;
|
||||
if offset > len_minus_stride {
|
||||
break;
|
||||
($name:ident, $src_unit:ty, $dst_unit:ty, $stride_neither_aligned:ident) => {
|
||||
#[inline(always)]
|
||||
pub unsafe fn $name(src: *const $src_unit, dst: *mut $dst_unit, len: usize) {
|
||||
let mut offset = 0usize;
|
||||
if SIMD_STRIDE_SIZE <= len {
|
||||
let len_minus_stride = len - SIMD_STRIDE_SIZE;
|
||||
loop {
|
||||
$stride_neither_aligned(
|
||||
src.offset(offset as isize),
|
||||
dst.offset(offset as isize),
|
||||
);
|
||||
offset += SIMD_STRIDE_SIZE;
|
||||
if offset > len_minus_stride {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
while offset < len {
|
||||
let code_unit = *(src.offset(offset as isize));
|
||||
*(dst.offset(offset as isize)) = code_unit as $dst_unit;
|
||||
offset += 1;
|
||||
}
|
||||
}
|
||||
while offset < len {
|
||||
let code_unit = *(src.offset(offset as isize));
|
||||
*(dst.offset(offset as isize)) = code_unit as $dst_unit;
|
||||
offset += 1;
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
#[allow(unused_macros)]
|
||||
macro_rules! ascii_to_ascii_simd_stride {
|
||||
($name:ident,
|
||||
$load:ident,
|
||||
$store:ident) => (
|
||||
#[inline(always)]
|
||||
pub unsafe fn $name(src: *const u8, dst: *mut u8) -> bool {
|
||||
let simd = $load(src);
|
||||
if !simd_is_ascii(simd) {
|
||||
return false;
|
||||
($name:ident, $load:ident, $store:ident) => {
|
||||
#[inline(always)]
|
||||
pub unsafe fn $name(src: *const u8, dst: *mut u8) -> bool {
|
||||
let simd = $load(src);
|
||||
if !simd_is_ascii(simd) {
|
||||
return false;
|
||||
}
|
||||
$store(dst, simd);
|
||||
true
|
||||
}
|
||||
$store(dst, simd);
|
||||
true
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
#[allow(unused_macros)]
|
||||
macro_rules! ascii_to_basic_latin_simd_stride {
|
||||
($name:ident,
|
||||
$load:ident,
|
||||
$store:ident) => (
|
||||
#[inline(always)]
|
||||
pub unsafe fn $name(src: *const u8, dst: *mut u16) -> bool {
|
||||
let simd = $load(src);
|
||||
if !simd_is_ascii(simd) {
|
||||
return false;
|
||||
($name:ident, $load:ident, $store:ident) => {
|
||||
#[inline(always)]
|
||||
pub unsafe fn $name(src: *const u8, dst: *mut u16) -> bool {
|
||||
let simd = $load(src);
|
||||
if !simd_is_ascii(simd) {
|
||||
return false;
|
||||
}
|
||||
let (first, second) = simd_unpack(simd);
|
||||
$store(dst, first);
|
||||
$store(dst.offset(8), second);
|
||||
true
|
||||
}
|
||||
let (first, second) = simd_unpack(simd);
|
||||
$store(dst, first);
|
||||
$store(dst.offset(8), second);
|
||||
true
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
#[allow(unused_macros)]
|
||||
macro_rules! unpack_simd_stride {
|
||||
($name:ident,
|
||||
$load:ident,
|
||||
$store:ident) => (
|
||||
#[inline(always)]
|
||||
pub unsafe fn $name(src: *const u8, dst: *mut u16) {
|
||||
let simd = $load(src);
|
||||
let (first, second) = simd_unpack(simd);
|
||||
$store(dst, first);
|
||||
$store(dst.offset(8), second);
|
||||
});
|
||||
($name:ident, $load:ident, $store:ident) => {
|
||||
#[inline(always)]
|
||||
pub unsafe fn $name(src: *const u8, dst: *mut u16) {
|
||||
let simd = $load(src);
|
||||
let (first, second) = simd_unpack(simd);
|
||||
$store(dst, first);
|
||||
$store(dst.offset(8), second);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[allow(unused_macros)]
|
||||
macro_rules! basic_latin_to_ascii_simd_stride {
|
||||
($name:ident,
|
||||
$load:ident,
|
||||
$store:ident) => (
|
||||
#[inline(always)]
|
||||
pub unsafe fn $name(src: *const u16, dst: *mut u8) -> bool {
|
||||
let first = $load(src);
|
||||
let second = $load(src.offset(8));
|
||||
if simd_is_basic_latin(first | second) {
|
||||
$store(dst, simd_pack(first, second));
|
||||
true
|
||||
} else {
|
||||
false
|
||||
($name:ident, $load:ident, $store:ident) => {
|
||||
#[inline(always)]
|
||||
pub unsafe fn $name(src: *const u16, dst: *mut u8) -> bool {
|
||||
let first = $load(src);
|
||||
let second = $load(src.offset(8));
|
||||
if simd_is_basic_latin(first | second) {
|
||||
$store(dst, simd_pack(first, second));
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
#[allow(unused_macros)]
|
||||
macro_rules! pack_simd_stride {
|
||||
($name:ident,
|
||||
$load:ident,
|
||||
$store:ident) => (
|
||||
#[inline(always)]
|
||||
pub unsafe fn $name(src: *const u16, dst: *mut u8) {
|
||||
let first = $load(src);
|
||||
let second = $load(src.offset(8));
|
||||
$store(dst, simd_pack(first, second));
|
||||
});
|
||||
($name:ident, $load:ident, $store:ident) => {
|
||||
#[inline(always)]
|
||||
pub unsafe fn $name(src: *const u16, dst: *mut u8) {
|
||||
let first = $load(src);
|
||||
let second = $load(src.offset(8));
|
||||
$store(dst, simd_pack(first, second));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
cfg_if! {
|
||||
@@ -1091,7 +1135,6 @@ cfg_if! {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn ascii_valid_up_to(bytes: &[u8]) -> usize {
|
||||
match validate_ascii(bytes) {
|
||||
None => bytes.len(),
|
||||
@@ -1117,38 +1160,32 @@ mod tests {
|
||||
use super::*;
|
||||
|
||||
macro_rules! test_ascii {
|
||||
($test_name:ident,
|
||||
$fn_tested:ident,
|
||||
$src_unit:ty,
|
||||
$dst_unit:ty) => (
|
||||
#[test]
|
||||
fn $test_name() {
|
||||
let mut src: Vec<$src_unit> = Vec::with_capacity(32);
|
||||
let mut dst: Vec<$dst_unit> = Vec::with_capacity(32);
|
||||
for i in 0..32 {
|
||||
src.clear();
|
||||
dst.clear();
|
||||
dst.resize(32, 0);
|
||||
for j in 0..32 {
|
||||
let c = if i == j {
|
||||
0xAA
|
||||
} else {
|
||||
j + 0x40
|
||||
};
|
||||
src.push(c as $src_unit);
|
||||
}
|
||||
match unsafe { $fn_tested(src.as_ptr(), dst.as_mut_ptr(), 32) } {
|
||||
None => unreachable!("Should always find non-ASCII"),
|
||||
Some((non_ascii, num_ascii)) => {
|
||||
assert_eq!(non_ascii, 0xAA);
|
||||
assert_eq!(num_ascii, i);
|
||||
for j in 0..i {
|
||||
assert_eq!(dst[j], (j + 0x40) as $dst_unit);
|
||||
($test_name:ident, $fn_tested:ident, $src_unit:ty, $dst_unit:ty) => {
|
||||
#[test]
|
||||
fn $test_name() {
|
||||
let mut src: Vec<$src_unit> = Vec::with_capacity(32);
|
||||
let mut dst: Vec<$dst_unit> = Vec::with_capacity(32);
|
||||
for i in 0..32 {
|
||||
src.clear();
|
||||
dst.clear();
|
||||
dst.resize(32, 0);
|
||||
for j in 0..32 {
|
||||
let c = if i == j { 0xAA } else { j + 0x40 };
|
||||
src.push(c as $src_unit);
|
||||
}
|
||||
match unsafe { $fn_tested(src.as_ptr(), dst.as_mut_ptr(), 32) } {
|
||||
None => unreachable!("Should always find non-ASCII"),
|
||||
Some((non_ascii, num_ascii)) => {
|
||||
assert_eq!(non_ascii, 0xAA);
|
||||
assert_eq!(num_ascii, i);
|
||||
for j in 0..i {
|
||||
assert_eq!(dst[j], (j + 0x40) as $dst_unit);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
test_ascii!(test_ascii_to_ascii, ascii_to_ascii, u8, u8);
|
||||
|
||||
+3
-3
@@ -7,10 +7,10 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use handles::*;
|
||||
use data::*;
|
||||
use variant::*;
|
||||
use super::*;
|
||||
use data::*;
|
||||
use handles::*;
|
||||
use variant::*;
|
||||
// Rust 1.14.0 requires the following despite the asterisk above.
|
||||
use super::in_inclusive_range32;
|
||||
|
||||
|
||||
+3
-3
@@ -7,10 +7,10 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use handles::*;
|
||||
use data::*;
|
||||
use variant::*;
|
||||
use super::*;
|
||||
use data::*;
|
||||
use handles::*;
|
||||
use variant::*;
|
||||
// Rust 1.14.0 requires the following despite the asterisk above.
|
||||
use super::in_inclusive_range16;
|
||||
|
||||
|
||||
+4
-4
@@ -7,13 +7,13 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use handles::*;
|
||||
use data::*;
|
||||
use variant::*;
|
||||
use super::*;
|
||||
use data::*;
|
||||
use handles::*;
|
||||
use variant::*;
|
||||
// Rust 1.14.0 requires the following despite the asterisk above.
|
||||
use super::in_range16;
|
||||
use super::in_inclusive_range16;
|
||||
use super::in_range16;
|
||||
|
||||
pub struct EucKrDecoder {
|
||||
lead: Option<u8>,
|
||||
|
||||
+3
-3
@@ -7,10 +7,10 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use handles::*;
|
||||
use data::*;
|
||||
use variant::*;
|
||||
use super::*;
|
||||
use data::*;
|
||||
use handles::*;
|
||||
use variant::*;
|
||||
// Rust 1.14.0 requires the following despite the asterisk above.
|
||||
use super::in_inclusive_range16;
|
||||
use super::in_range16;
|
||||
|
||||
+1
-1
@@ -19,8 +19,8 @@
|
||||
use super::DecoderResult;
|
||||
use super::EncoderResult;
|
||||
use ascii::*;
|
||||
use utf_8::utf8_valid_up_to;
|
||||
use utf_8::convert_utf8_to_utf16_up_to_invalid;
|
||||
use utf_8::utf8_valid_up_to;
|
||||
|
||||
pub enum Space<T> {
|
||||
Available(T),
|
||||
|
||||
+3
-3
@@ -7,10 +7,10 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use handles::*;
|
||||
use data::*;
|
||||
use variant::*;
|
||||
use super::*;
|
||||
use data::*;
|
||||
use handles::*;
|
||||
use variant::*;
|
||||
// Rust 1.14.0 requires the following despite the asterisk above.
|
||||
use super::in_inclusive_range16;
|
||||
|
||||
|
||||
+41
-20
@@ -636,14 +636,23 @@
|
||||
//! See the section [_UTF-16LE, UTF-16BE and Unicode Encoding Schemes_](#utf-16le-utf-16be-and-unicode-encoding-schemes)
|
||||
//! for discussion about the UTF-16 family.
|
||||
|
||||
#![cfg_attr(feature = "simd-accel",
|
||||
feature(cfg_target_feature, platform_intrinsics, core_intrinsics))]
|
||||
#![cfg_attr(
|
||||
feature = "simd-accel", feature(cfg_target_feature, platform_intrinsics, core_intrinsics)
|
||||
)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate cfg_if;
|
||||
|
||||
#[cfg(all(feature = "simd-accel",
|
||||
any(target_feature = "sse2", all(target_endian = "little", target_arch = "aarch64"), all(target_endian = "little", target_feature = "neon"))))]
|
||||
#[cfg(
|
||||
all(
|
||||
feature = "simd-accel",
|
||||
any(
|
||||
target_feature = "sse2",
|
||||
all(target_endian = "little", target_arch = "aarch64"),
|
||||
all(target_endian = "little", target_feature = "neon")
|
||||
)
|
||||
)
|
||||
)]
|
||||
extern crate simd;
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
@@ -660,51 +669,63 @@ extern crate serde_json;
|
||||
#[macro_use]
|
||||
mod macros;
|
||||
|
||||
#[cfg(all(feature = "simd-accel",
|
||||
any(target_feature = "sse2", all(target_endian = "little", target_arch = "aarch64"), all(target_endian = "little", target_feature = "neon"))))]
|
||||
#[cfg(
|
||||
all(
|
||||
feature = "simd-accel",
|
||||
any(
|
||||
target_feature = "sse2",
|
||||
all(target_endian = "little", target_arch = "aarch64"),
|
||||
all(target_endian = "little", target_feature = "neon")
|
||||
)
|
||||
)
|
||||
)]
|
||||
mod simd_funcs;
|
||||
|
||||
#[cfg(any(all(feature = "simd-accel", target_feature = "sse2"),
|
||||
all(target_endian = "little", target_arch = "aarch64"),
|
||||
all(target_endian = "little", target_arch = "arm")))]
|
||||
#[cfg(
|
||||
any(
|
||||
all(feature = "simd-accel", target_feature = "sse2"),
|
||||
all(target_endian = "little", target_arch = "aarch64"),
|
||||
all(target_endian = "little", target_arch = "arm")
|
||||
)
|
||||
)]
|
||||
mod utf_8_core;
|
||||
|
||||
#[cfg(test)]
|
||||
mod testing;
|
||||
|
||||
mod single_byte;
|
||||
mod utf_8;
|
||||
mod gb18030;
|
||||
mod big5;
|
||||
mod euc_jp;
|
||||
mod iso_2022_jp;
|
||||
mod shift_jis;
|
||||
mod euc_kr;
|
||||
mod gb18030;
|
||||
mod iso_2022_jp;
|
||||
mod replacement;
|
||||
mod x_user_defined;
|
||||
mod shift_jis;
|
||||
mod single_byte;
|
||||
mod utf_16;
|
||||
mod utf_8;
|
||||
mod x_user_defined;
|
||||
|
||||
mod ascii;
|
||||
mod handles;
|
||||
mod data;
|
||||
mod handles;
|
||||
mod variant;
|
||||
|
||||
pub mod mem;
|
||||
|
||||
use variant::*;
|
||||
use utf_8::utf8_valid_up_to;
|
||||
use ascii::ascii_valid_up_to;
|
||||
use ascii::iso_2022_jp_ascii_valid_up_to;
|
||||
use utf_8::utf8_valid_up_to;
|
||||
use variant::*;
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::cmp::Ordering;
|
||||
use std::hash::Hash;
|
||||
use std::hash::Hasher;
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
#[cfg(feature = "serde")]
|
||||
use serde::de::Visitor;
|
||||
#[cfg(feature = "serde")]
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
|
||||
/// This has to be the max length of an NCR instead of max
|
||||
/// minus one, because we can't rely on getting the minus
|
||||
|
||||
+375
-327
@@ -71,49 +71,55 @@ macro_rules! decoder_function {
|
||||
}
|
||||
|
||||
macro_rules! decoder_functions {
|
||||
($preamble:block,
|
||||
$loop_preable:block,
|
||||
$eof:block,
|
||||
$body:block,
|
||||
$slf:ident,
|
||||
$src_consumed:ident,
|
||||
$dest:ident,
|
||||
$source:ident,
|
||||
$b:ident,
|
||||
$destination_handle:ident,
|
||||
$unread_handle:ident,
|
||||
$destination_check:ident) => (
|
||||
decoder_function!($preamble,
|
||||
$loop_preable,
|
||||
$eof,
|
||||
$body,
|
||||
$slf,
|
||||
$src_consumed,
|
||||
$dest,
|
||||
$source,
|
||||
$b,
|
||||
$destination_handle,
|
||||
$unread_handle,
|
||||
$destination_check,
|
||||
decode_to_utf8_raw,
|
||||
u8,
|
||||
Utf8Destination);
|
||||
decoder_function!($preamble,
|
||||
$loop_preable,
|
||||
$eof,
|
||||
$body,
|
||||
$slf,
|
||||
$src_consumed,
|
||||
$dest,
|
||||
$source,
|
||||
$b,
|
||||
$destination_handle,
|
||||
$unread_handle,
|
||||
$destination_check,
|
||||
decode_to_utf16_raw,
|
||||
u16,
|
||||
Utf16Destination);
|
||||
);
|
||||
(
|
||||
$preamble:block,
|
||||
$loop_preable:block,
|
||||
$eof:block,
|
||||
$body:block,
|
||||
$slf:ident,
|
||||
$src_consumed:ident,
|
||||
$dest:ident,
|
||||
$source:ident,
|
||||
$b:ident,
|
||||
$destination_handle:ident,
|
||||
$unread_handle:ident,
|
||||
$destination_check:ident
|
||||
) => {
|
||||
decoder_function!(
|
||||
$preamble,
|
||||
$loop_preable,
|
||||
$eof,
|
||||
$body,
|
||||
$slf,
|
||||
$src_consumed,
|
||||
$dest,
|
||||
$source,
|
||||
$b,
|
||||
$destination_handle,
|
||||
$unread_handle,
|
||||
$destination_check,
|
||||
decode_to_utf8_raw,
|
||||
u8,
|
||||
Utf8Destination
|
||||
);
|
||||
decoder_function!(
|
||||
$preamble,
|
||||
$loop_preable,
|
||||
$eof,
|
||||
$body,
|
||||
$slf,
|
||||
$src_consumed,
|
||||
$dest,
|
||||
$source,
|
||||
$b,
|
||||
$destination_handle,
|
||||
$unread_handle,
|
||||
$destination_check,
|
||||
decode_to_utf16_raw,
|
||||
u16,
|
||||
Utf16Destination
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! ascii_compatible_two_byte_decoder_function {
|
||||
@@ -278,52 +284,58 @@ macro_rules! ascii_compatible_two_byte_decoder_function {
|
||||
}
|
||||
|
||||
macro_rules! ascii_compatible_two_byte_decoder_functions {
|
||||
($lead:block,
|
||||
$trail:block,
|
||||
$slf:ident,
|
||||
$non_ascii:ident,
|
||||
$byte:ident,
|
||||
$lead_minus_offset:ident,
|
||||
$unread_handle_trail:ident,
|
||||
$source:ident,
|
||||
$handle:ident,
|
||||
$outermost:tt,
|
||||
$copy_ascii:ident,
|
||||
$destination_check:ident,
|
||||
$ascii_punctuation:expr) => (
|
||||
ascii_compatible_two_byte_decoder_function!($lead,
|
||||
$trail,
|
||||
$slf,
|
||||
$non_ascii,
|
||||
$byte,
|
||||
$lead_minus_offset,
|
||||
$unread_handle_trail,
|
||||
$source,
|
||||
$handle,
|
||||
$outermost,
|
||||
$copy_ascii,
|
||||
$destination_check,
|
||||
decode_to_utf8_raw,
|
||||
u8,
|
||||
Utf8Destination,
|
||||
$ascii_punctuation);
|
||||
ascii_compatible_two_byte_decoder_function!($lead,
|
||||
$trail,
|
||||
$slf,
|
||||
$non_ascii,
|
||||
$byte,
|
||||
$lead_minus_offset,
|
||||
$unread_handle_trail,
|
||||
$source,
|
||||
$handle,
|
||||
$outermost,
|
||||
$copy_ascii,
|
||||
$destination_check,
|
||||
decode_to_utf16_raw,
|
||||
u16,
|
||||
Utf16Destination,
|
||||
$ascii_punctuation);
|
||||
);
|
||||
(
|
||||
$lead:block,
|
||||
$trail:block,
|
||||
$slf:ident,
|
||||
$non_ascii:ident,
|
||||
$byte:ident,
|
||||
$lead_minus_offset:ident,
|
||||
$unread_handle_trail:ident,
|
||||
$source:ident,
|
||||
$handle:ident,
|
||||
$outermost:tt,
|
||||
$copy_ascii:ident,
|
||||
$destination_check:ident,
|
||||
$ascii_punctuation:expr
|
||||
) => {
|
||||
ascii_compatible_two_byte_decoder_function!(
|
||||
$lead,
|
||||
$trail,
|
||||
$slf,
|
||||
$non_ascii,
|
||||
$byte,
|
||||
$lead_minus_offset,
|
||||
$unread_handle_trail,
|
||||
$source,
|
||||
$handle,
|
||||
$outermost,
|
||||
$copy_ascii,
|
||||
$destination_check,
|
||||
decode_to_utf8_raw,
|
||||
u8,
|
||||
Utf8Destination,
|
||||
$ascii_punctuation
|
||||
);
|
||||
ascii_compatible_two_byte_decoder_function!(
|
||||
$lead,
|
||||
$trail,
|
||||
$slf,
|
||||
$non_ascii,
|
||||
$byte,
|
||||
$lead_minus_offset,
|
||||
$unread_handle_trail,
|
||||
$source,
|
||||
$handle,
|
||||
$outermost,
|
||||
$copy_ascii,
|
||||
$destination_check,
|
||||
decode_to_utf16_raw,
|
||||
u16,
|
||||
Utf16Destination,
|
||||
$ascii_punctuation
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! gb18030_decoder_function {
|
||||
@@ -583,70 +595,76 @@ macro_rules! gb18030_decoder_function {
|
||||
}
|
||||
|
||||
macro_rules! gb18030_decoder_functions {
|
||||
($first_body:block,
|
||||
$second_body:block,
|
||||
$third_body:block,
|
||||
$fourth_body:block,
|
||||
$slf:ident,
|
||||
$non_ascii:ident,
|
||||
$first_minus_offset:ident,
|
||||
$second:ident,
|
||||
$second_minus_offset:ident,
|
||||
$unread_handle_second:ident,
|
||||
$third:ident,
|
||||
$third_minus_offset:ident,
|
||||
$unread_handle_third:ident,
|
||||
$fourth:ident,
|
||||
$fourth_minus_offset:ident,
|
||||
$unread_handle_fourth:ident,
|
||||
$source:ident,
|
||||
$handle:ident,
|
||||
$outermost:tt) => (
|
||||
gb18030_decoder_function!($first_body,
|
||||
$second_body,
|
||||
$third_body,
|
||||
$fourth_body,
|
||||
$slf,
|
||||
$non_ascii,
|
||||
$first_minus_offset,
|
||||
$second,
|
||||
$second_minus_offset,
|
||||
$unread_handle_second,
|
||||
$third,
|
||||
$third_minus_offset,
|
||||
$unread_handle_third,
|
||||
$fourth,
|
||||
$fourth_minus_offset,
|
||||
$unread_handle_fourth,
|
||||
$source,
|
||||
$handle,
|
||||
$outermost,
|
||||
decode_to_utf8_raw,
|
||||
u8,
|
||||
Utf8Destination);
|
||||
gb18030_decoder_function!($first_body,
|
||||
$second_body,
|
||||
$third_body,
|
||||
$fourth_body,
|
||||
$slf,
|
||||
$non_ascii,
|
||||
$first_minus_offset,
|
||||
$second,
|
||||
$second_minus_offset,
|
||||
$unread_handle_second,
|
||||
$third,
|
||||
$third_minus_offset,
|
||||
$unread_handle_third,
|
||||
$fourth,
|
||||
$fourth_minus_offset,
|
||||
$unread_handle_fourth,
|
||||
$source,
|
||||
$handle,
|
||||
$outermost,
|
||||
decode_to_utf16_raw,
|
||||
u16,
|
||||
Utf16Destination);
|
||||
);
|
||||
(
|
||||
$first_body:block,
|
||||
$second_body:block,
|
||||
$third_body:block,
|
||||
$fourth_body:block,
|
||||
$slf:ident,
|
||||
$non_ascii:ident,
|
||||
$first_minus_offset:ident,
|
||||
$second:ident,
|
||||
$second_minus_offset:ident,
|
||||
$unread_handle_second:ident,
|
||||
$third:ident,
|
||||
$third_minus_offset:ident,
|
||||
$unread_handle_third:ident,
|
||||
$fourth:ident,
|
||||
$fourth_minus_offset:ident,
|
||||
$unread_handle_fourth:ident,
|
||||
$source:ident,
|
||||
$handle:ident,
|
||||
$outermost:tt
|
||||
) => {
|
||||
gb18030_decoder_function!(
|
||||
$first_body,
|
||||
$second_body,
|
||||
$third_body,
|
||||
$fourth_body,
|
||||
$slf,
|
||||
$non_ascii,
|
||||
$first_minus_offset,
|
||||
$second,
|
||||
$second_minus_offset,
|
||||
$unread_handle_second,
|
||||
$third,
|
||||
$third_minus_offset,
|
||||
$unread_handle_third,
|
||||
$fourth,
|
||||
$fourth_minus_offset,
|
||||
$unread_handle_fourth,
|
||||
$source,
|
||||
$handle,
|
||||
$outermost,
|
||||
decode_to_utf8_raw,
|
||||
u8,
|
||||
Utf8Destination
|
||||
);
|
||||
gb18030_decoder_function!(
|
||||
$first_body,
|
||||
$second_body,
|
||||
$third_body,
|
||||
$fourth_body,
|
||||
$slf,
|
||||
$non_ascii,
|
||||
$first_minus_offset,
|
||||
$second,
|
||||
$second_minus_offset,
|
||||
$unread_handle_second,
|
||||
$third,
|
||||
$third_minus_offset,
|
||||
$unread_handle_third,
|
||||
$fourth,
|
||||
$fourth_minus_offset,
|
||||
$unread_handle_fourth,
|
||||
$source,
|
||||
$handle,
|
||||
$outermost,
|
||||
decode_to_utf16_raw,
|
||||
u16,
|
||||
Utf16Destination
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! euc_jp_decoder_function {
|
||||
@@ -880,55 +898,61 @@ macro_rules! euc_jp_decoder_function {
|
||||
}
|
||||
|
||||
macro_rules! euc_jp_decoder_functions {
|
||||
($jis0802_trail_body:block,
|
||||
$jis0812_lead_body:block,
|
||||
$jis0812_trail_body:block,
|
||||
$half_width_katakana_body:block,
|
||||
$slf:ident,
|
||||
$non_ascii:ident,
|
||||
$jis0208_lead_minus_offset:ident,
|
||||
$byte:ident,
|
||||
$unread_handle_trail:ident,
|
||||
$jis0212_lead_minus_offset:ident,
|
||||
$lead:ident,
|
||||
$unread_handle_jis0212:ident,
|
||||
$source:ident,
|
||||
$handle:ident) => (
|
||||
euc_jp_decoder_function!($jis0802_trail_body,
|
||||
$jis0812_lead_body,
|
||||
$jis0812_trail_body,
|
||||
$half_width_katakana_body,
|
||||
$slf,
|
||||
$non_ascii,
|
||||
$jis0208_lead_minus_offset,
|
||||
$byte,
|
||||
$unread_handle_trail,
|
||||
$jis0212_lead_minus_offset,
|
||||
$lead,
|
||||
$unread_handle_jis0212,
|
||||
$source,
|
||||
$handle,
|
||||
decode_to_utf8_raw,
|
||||
u8,
|
||||
Utf8Destination);
|
||||
euc_jp_decoder_function!($jis0802_trail_body,
|
||||
$jis0812_lead_body,
|
||||
$jis0812_trail_body,
|
||||
$half_width_katakana_body,
|
||||
$slf,
|
||||
$non_ascii,
|
||||
$jis0208_lead_minus_offset,
|
||||
$byte,
|
||||
$unread_handle_trail,
|
||||
$jis0212_lead_minus_offset,
|
||||
$lead,
|
||||
$unread_handle_jis0212,
|
||||
$source,
|
||||
$handle,
|
||||
decode_to_utf16_raw,
|
||||
u16,
|
||||
Utf16Destination);
|
||||
(
|
||||
$jis0802_trail_body:block,
|
||||
$jis0812_lead_body:block,
|
||||
$jis0812_trail_body:block,
|
||||
$half_width_katakana_body:block,
|
||||
$slf:ident,
|
||||
$non_ascii:ident,
|
||||
$jis0208_lead_minus_offset:ident,
|
||||
$byte:ident,
|
||||
$unread_handle_trail:ident,
|
||||
$jis0212_lead_minus_offset:ident,
|
||||
$lead:ident,
|
||||
$unread_handle_jis0212:ident,
|
||||
$source:ident,
|
||||
$handle:ident
|
||||
) => {
|
||||
euc_jp_decoder_function!(
|
||||
$jis0802_trail_body,
|
||||
$jis0812_lead_body,
|
||||
$jis0812_trail_body,
|
||||
$half_width_katakana_body,
|
||||
$slf,
|
||||
$non_ascii,
|
||||
$jis0208_lead_minus_offset,
|
||||
$byte,
|
||||
$unread_handle_trail,
|
||||
$jis0212_lead_minus_offset,
|
||||
$lead,
|
||||
$unread_handle_jis0212,
|
||||
$source,
|
||||
$handle,
|
||||
decode_to_utf8_raw,
|
||||
u8,
|
||||
Utf8Destination
|
||||
);
|
||||
euc_jp_decoder_function!(
|
||||
$jis0802_trail_body,
|
||||
$jis0812_lead_body,
|
||||
$jis0812_trail_body,
|
||||
$half_width_katakana_body,
|
||||
$slf,
|
||||
$non_ascii,
|
||||
$jis0208_lead_minus_offset,
|
||||
$byte,
|
||||
$unread_handle_trail,
|
||||
$jis0212_lead_minus_offset,
|
||||
$lead,
|
||||
$unread_handle_jis0212,
|
||||
$source,
|
||||
$handle,
|
||||
decode_to_utf16_raw,
|
||||
u16,
|
||||
Utf16Destination
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! encoder_function {
|
||||
@@ -983,43 +1007,49 @@ macro_rules! encoder_function {
|
||||
}
|
||||
|
||||
macro_rules! encoder_functions {
|
||||
($eof:block,
|
||||
$body:block,
|
||||
$slf:ident,
|
||||
$src_consumed:ident,
|
||||
$source:ident,
|
||||
$dest:ident,
|
||||
$c:ident,
|
||||
$destination_handle:ident,
|
||||
$unread_handle:ident,
|
||||
$destination_check:ident) => (
|
||||
encoder_function!($eof,
|
||||
$body,
|
||||
$slf,
|
||||
$src_consumed,
|
||||
$source,
|
||||
$dest,
|
||||
$c,
|
||||
$destination_handle,
|
||||
$unread_handle,
|
||||
$destination_check,
|
||||
encode_from_utf8_raw,
|
||||
str,
|
||||
Utf8Source);
|
||||
encoder_function!($eof,
|
||||
$body,
|
||||
$slf,
|
||||
$src_consumed,
|
||||
$source,
|
||||
$dest,
|
||||
$c,
|
||||
$destination_handle,
|
||||
$unread_handle,
|
||||
$destination_check,
|
||||
encode_from_utf16_raw,
|
||||
[u16],
|
||||
Utf16Source);
|
||||
);
|
||||
(
|
||||
$eof:block,
|
||||
$body:block,
|
||||
$slf:ident,
|
||||
$src_consumed:ident,
|
||||
$source:ident,
|
||||
$dest:ident,
|
||||
$c:ident,
|
||||
$destination_handle:ident,
|
||||
$unread_handle:ident,
|
||||
$destination_check:ident
|
||||
) => {
|
||||
encoder_function!(
|
||||
$eof,
|
||||
$body,
|
||||
$slf,
|
||||
$src_consumed,
|
||||
$source,
|
||||
$dest,
|
||||
$c,
|
||||
$destination_handle,
|
||||
$unread_handle,
|
||||
$destination_check,
|
||||
encode_from_utf8_raw,
|
||||
str,
|
||||
Utf8Source
|
||||
);
|
||||
encoder_function!(
|
||||
$eof,
|
||||
$body,
|
||||
$slf,
|
||||
$src_consumed,
|
||||
$source,
|
||||
$dest,
|
||||
$c,
|
||||
$destination_handle,
|
||||
$unread_handle,
|
||||
$destination_check,
|
||||
encode_from_utf16_raw,
|
||||
[u16],
|
||||
Utf16Source
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! ascii_compatible_encoder_function {
|
||||
@@ -1133,101 +1163,119 @@ macro_rules! ascii_compatible_encoder_function {
|
||||
}
|
||||
|
||||
macro_rules! ascii_compatible_encoder_functions {
|
||||
($bmp_body:block,
|
||||
$astral_body:block,
|
||||
$bmp:ident,
|
||||
$astral:ident,
|
||||
$slf:ident,
|
||||
$source:ident,
|
||||
$handle:ident,
|
||||
$copy_ascii:ident,
|
||||
$destination_check:ident,
|
||||
$ascii_punctuation:expr) => (
|
||||
ascii_compatible_encoder_function!($bmp_body,
|
||||
$astral_body,
|
||||
$bmp,
|
||||
$astral,
|
||||
$slf,
|
||||
$source,
|
||||
$handle,
|
||||
$copy_ascii,
|
||||
$destination_check,
|
||||
encode_from_utf8_raw,
|
||||
str,
|
||||
Utf8Source,
|
||||
$ascii_punctuation);
|
||||
ascii_compatible_encoder_function!($bmp_body,
|
||||
$astral_body,
|
||||
$bmp,
|
||||
$astral,
|
||||
$slf,
|
||||
$source,
|
||||
$handle,
|
||||
$copy_ascii,
|
||||
$destination_check,
|
||||
encode_from_utf16_raw,
|
||||
[u16],
|
||||
Utf16Source,
|
||||
$ascii_punctuation);
|
||||
);
|
||||
(
|
||||
$bmp_body:block,
|
||||
$astral_body:block,
|
||||
$bmp:ident,
|
||||
$astral:ident,
|
||||
$slf:ident,
|
||||
$source:ident,
|
||||
$handle:ident,
|
||||
$copy_ascii:ident,
|
||||
$destination_check:ident,
|
||||
$ascii_punctuation:expr
|
||||
) => {
|
||||
ascii_compatible_encoder_function!(
|
||||
$bmp_body,
|
||||
$astral_body,
|
||||
$bmp,
|
||||
$astral,
|
||||
$slf,
|
||||
$source,
|
||||
$handle,
|
||||
$copy_ascii,
|
||||
$destination_check,
|
||||
encode_from_utf8_raw,
|
||||
str,
|
||||
Utf8Source,
|
||||
$ascii_punctuation
|
||||
);
|
||||
ascii_compatible_encoder_function!(
|
||||
$bmp_body,
|
||||
$astral_body,
|
||||
$bmp,
|
||||
$astral,
|
||||
$slf,
|
||||
$source,
|
||||
$handle,
|
||||
$copy_ascii,
|
||||
$destination_check,
|
||||
encode_from_utf16_raw,
|
||||
[u16],
|
||||
Utf16Source,
|
||||
$ascii_punctuation
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! ascii_compatible_bmp_encoder_function {
|
||||
($bmp_body:block,
|
||||
$bmp:ident,
|
||||
$slf:ident,
|
||||
$source:ident,
|
||||
$handle:ident,
|
||||
$copy_ascii:ident,
|
||||
$destination_check:ident,
|
||||
$name:ident,
|
||||
$input:ty,
|
||||
$source_struct:ident,
|
||||
$ascii_punctuation:expr) => (
|
||||
ascii_compatible_encoder_function!($bmp_body,
|
||||
{
|
||||
return (EncoderResult::Unmappable(astral),
|
||||
$source.consumed(),
|
||||
$handle.written());
|
||||
},
|
||||
$bmp,
|
||||
astral,
|
||||
$slf,
|
||||
$source,
|
||||
$handle,
|
||||
$copy_ascii,
|
||||
$destination_check,
|
||||
$name,
|
||||
$input,
|
||||
$source_struct,
|
||||
$ascii_punctuation);
|
||||
);
|
||||
(
|
||||
$bmp_body:block,
|
||||
$bmp:ident,
|
||||
$slf:ident,
|
||||
$source:ident,
|
||||
$handle:ident,
|
||||
$copy_ascii:ident,
|
||||
$destination_check:ident,
|
||||
$name:ident,
|
||||
$input:ty,
|
||||
$source_struct:ident,
|
||||
$ascii_punctuation:expr
|
||||
) => {
|
||||
ascii_compatible_encoder_function!(
|
||||
$bmp_body,
|
||||
{
|
||||
return (
|
||||
EncoderResult::Unmappable(astral),
|
||||
$source.consumed(),
|
||||
$handle.written(),
|
||||
);
|
||||
},
|
||||
$bmp,
|
||||
astral,
|
||||
$slf,
|
||||
$source,
|
||||
$handle,
|
||||
$copy_ascii,
|
||||
$destination_check,
|
||||
$name,
|
||||
$input,
|
||||
$source_struct,
|
||||
$ascii_punctuation
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! ascii_compatible_bmp_encoder_functions {
|
||||
($bmp_body:block,
|
||||
$bmp:ident,
|
||||
$slf:ident,
|
||||
$source:ident,
|
||||
$handle:ident,
|
||||
$copy_ascii:ident,
|
||||
$destination_check:ident,
|
||||
$ascii_punctuation:expr) => (
|
||||
ascii_compatible_encoder_functions!($bmp_body,
|
||||
{
|
||||
return (EncoderResult::Unmappable(astral),
|
||||
$source.consumed(),
|
||||
$handle.written());
|
||||
},
|
||||
$bmp,
|
||||
astral,
|
||||
$slf,
|
||||
$source,
|
||||
$handle,
|
||||
$copy_ascii,
|
||||
$destination_check,
|
||||
$ascii_punctuation);
|
||||
);
|
||||
(
|
||||
$bmp_body:block,
|
||||
$bmp:ident,
|
||||
$slf:ident,
|
||||
$source:ident,
|
||||
$handle:ident,
|
||||
$copy_ascii:ident,
|
||||
$destination_check:ident,
|
||||
$ascii_punctuation:expr
|
||||
) => {
|
||||
ascii_compatible_encoder_functions!(
|
||||
$bmp_body,
|
||||
{
|
||||
return (
|
||||
EncoderResult::Unmappable(astral),
|
||||
$source.consumed(),
|
||||
$handle.written(),
|
||||
);
|
||||
},
|
||||
$bmp,
|
||||
astral,
|
||||
$slf,
|
||||
$source,
|
||||
$handle,
|
||||
$copy_ascii,
|
||||
$destination_check,
|
||||
$ascii_punctuation
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! public_decode_function{
|
||||
|
||||
+126
-112
@@ -21,14 +21,14 @@
|
||||
//! in-memory encoding is sometimes used as a storage optimization of text
|
||||
//! when UTF-16 indexing and length semantics are exposed.
|
||||
|
||||
use ascii::*;
|
||||
use super::in_inclusive_range8;
|
||||
use super::in_inclusive_range16;
|
||||
use super::in_range16;
|
||||
use super::in_inclusive_range32;
|
||||
use super::in_inclusive_range8;
|
||||
use super::in_range16;
|
||||
use super::in_range32;
|
||||
use super::DecoderResult;
|
||||
use super::EncoderResult;
|
||||
use ascii::*;
|
||||
use utf_8::*;
|
||||
|
||||
cfg_if!{
|
||||
@@ -65,138 +65,152 @@ const LATIN1_MASK: usize = 0xFF00FF00_FF00FF00u64 as usize;
|
||||
|
||||
#[allow(unused_macros)]
|
||||
macro_rules! by_unit_check_alu {
|
||||
($name:ident,
|
||||
$unit:ty,
|
||||
$bound:expr,
|
||||
$mask:ident) => (
|
||||
#[inline(always)]
|
||||
fn $name(buffer: &[$unit]) -> bool {
|
||||
let mut offset = 0usize;
|
||||
let mut accu = 0usize;
|
||||
let unit_size = ::std::mem::size_of::<$unit>();
|
||||
let len = buffer.len();
|
||||
if len >= ALU_ALIGNMENT / unit_size {
|
||||
// The most common reason to return `false` is for the first code
|
||||
// unit to fail the test, so check that first.
|
||||
if buffer[0] >= $bound {
|
||||
return false;
|
||||
}
|
||||
let src = buffer.as_ptr();
|
||||
let mut until_alignment = ((ALU_ALIGNMENT - ((src as usize) & ALU_ALIGNMENT_MASK)) &
|
||||
ALU_ALIGNMENT_MASK) / unit_size;
|
||||
if until_alignment + ALU_ALIGNMENT / unit_size <= len {
|
||||
if until_alignment != 0 {
|
||||
accu |= buffer[offset] as usize;
|
||||
offset += 1;
|
||||
until_alignment -= 1;
|
||||
while until_alignment != 0 {
|
||||
($name:ident, $unit:ty, $bound:expr, $mask:ident) => {
|
||||
#[inline(always)]
|
||||
fn $name(buffer: &[$unit]) -> bool {
|
||||
let mut offset = 0usize;
|
||||
let mut accu = 0usize;
|
||||
let unit_size = ::std::mem::size_of::<$unit>();
|
||||
let len = buffer.len();
|
||||
if len >= ALU_ALIGNMENT / unit_size {
|
||||
// The most common reason to return `false` is for the first code
|
||||
// unit to fail the test, so check that first.
|
||||
if buffer[0] >= $bound {
|
||||
return false;
|
||||
}
|
||||
let src = buffer.as_ptr();
|
||||
let mut until_alignment = ((ALU_ALIGNMENT - ((src as usize) & ALU_ALIGNMENT_MASK))
|
||||
& ALU_ALIGNMENT_MASK) / unit_size;
|
||||
if until_alignment + ALU_ALIGNMENT / unit_size <= len {
|
||||
if until_alignment != 0 {
|
||||
accu |= buffer[offset] as usize;
|
||||
offset += 1;
|
||||
until_alignment -= 1;
|
||||
}
|
||||
if accu >= $bound {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
let len_minus_stride = len - ALU_ALIGNMENT / unit_size;
|
||||
if offset + (4 * (ALU_ALIGNMENT / unit_size)) <= len {
|
||||
let len_minus_unroll = len - (4 * (ALU_ALIGNMENT / unit_size));
|
||||
loop {
|
||||
let unroll_accu = unsafe { *(src.offset(offset as isize) as *const usize) } |
|
||||
unsafe { *(src.offset((offset + (ALU_ALIGNMENT / unit_size)) as isize) as *const usize) } |
|
||||
unsafe { *(src.offset((offset + (2 * (ALU_ALIGNMENT / unit_size))) as isize) as *const usize) } |
|
||||
unsafe { *(src.offset((offset + (3 * (ALU_ALIGNMENT / unit_size))) as isize) as *const usize) };
|
||||
if unroll_accu & $mask != 0 {
|
||||
while until_alignment != 0 {
|
||||
accu |= buffer[offset] as usize;
|
||||
offset += 1;
|
||||
until_alignment -= 1;
|
||||
}
|
||||
if accu >= $bound {
|
||||
return false;
|
||||
}
|
||||
offset += 4 * (ALU_ALIGNMENT / unit_size);
|
||||
if offset > len_minus_unroll {
|
||||
break;
|
||||
}
|
||||
let len_minus_stride = len - ALU_ALIGNMENT / unit_size;
|
||||
if offset + (4 * (ALU_ALIGNMENT / unit_size)) <= len {
|
||||
let len_minus_unroll = len - (4 * (ALU_ALIGNMENT / unit_size));
|
||||
loop {
|
||||
let unroll_accu = unsafe {
|
||||
*(src.offset(offset as isize) as *const usize)
|
||||
} | unsafe {
|
||||
*(src.offset((offset + (ALU_ALIGNMENT / unit_size)) as isize)
|
||||
as *const usize)
|
||||
} | unsafe {
|
||||
*(src.offset((offset + (2 * (ALU_ALIGNMENT / unit_size))) as isize)
|
||||
as *const usize)
|
||||
} | unsafe {
|
||||
*(src.offset((offset + (3 * (ALU_ALIGNMENT / unit_size))) as isize)
|
||||
as *const usize)
|
||||
};
|
||||
if unroll_accu & $mask != 0 {
|
||||
return false;
|
||||
}
|
||||
offset += 4 * (ALU_ALIGNMENT / unit_size);
|
||||
if offset > len_minus_unroll {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
while offset <= len_minus_stride {
|
||||
accu |= unsafe { *(src.offset(offset as isize) as *const usize) };
|
||||
offset += ALU_ALIGNMENT / unit_size;
|
||||
while offset <= len_minus_stride {
|
||||
accu |= unsafe { *(src.offset(offset as isize) as *const usize) };
|
||||
offset += ALU_ALIGNMENT / unit_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
for &unit in &buffer[offset..] {
|
||||
accu |= unit as usize;
|
||||
}
|
||||
accu & $mask == 0
|
||||
}
|
||||
for &unit in &buffer[offset..] {
|
||||
accu |= unit as usize;
|
||||
}
|
||||
accu & $mask == 0
|
||||
})
|
||||
};
|
||||
}
|
||||
|
||||
#[allow(unused_macros)]
|
||||
macro_rules! by_unit_check_simd {
|
||||
($name:ident,
|
||||
$unit:ty,
|
||||
$splat:expr,
|
||||
$simd_ty:ty,
|
||||
$bound:expr,
|
||||
$func:ident) => (
|
||||
#[inline(always)]
|
||||
fn $name(buffer: &[$unit]) -> bool {
|
||||
let mut offset = 0usize;
|
||||
let mut accu = 0usize;
|
||||
let unit_size = ::std::mem::size_of::<$unit>();
|
||||
let len = buffer.len();
|
||||
if len >= SIMD_STRIDE_SIZE / unit_size {
|
||||
// The most common reason to return `false` is for the first code
|
||||
// unit to fail the test, so check that first.
|
||||
if buffer[0] >= $bound {
|
||||
return false;
|
||||
}
|
||||
let src = buffer.as_ptr();
|
||||
let mut until_alignment = ((SIMD_ALIGNMENT - ((src as usize) & SIMD_ALIGNMENT_MASK)) &
|
||||
SIMD_ALIGNMENT_MASK) / unit_size;
|
||||
if until_alignment + SIMD_STRIDE_SIZE / unit_size <= len {
|
||||
if until_alignment != 0 {
|
||||
accu |= buffer[offset] as usize;
|
||||
offset += 1;
|
||||
until_alignment -= 1;
|
||||
while until_alignment != 0 {
|
||||
($name:ident, $unit:ty, $splat:expr, $simd_ty:ty, $bound:expr, $func:ident) => {
|
||||
#[inline(always)]
|
||||
fn $name(buffer: &[$unit]) -> bool {
|
||||
let mut offset = 0usize;
|
||||
let mut accu = 0usize;
|
||||
let unit_size = ::std::mem::size_of::<$unit>();
|
||||
let len = buffer.len();
|
||||
if len >= SIMD_STRIDE_SIZE / unit_size {
|
||||
// The most common reason to return `false` is for the first code
|
||||
// unit to fail the test, so check that first.
|
||||
if buffer[0] >= $bound {
|
||||
return false;
|
||||
}
|
||||
let src = buffer.as_ptr();
|
||||
let mut until_alignment = ((SIMD_ALIGNMENT - ((src as usize) & SIMD_ALIGNMENT_MASK))
|
||||
& SIMD_ALIGNMENT_MASK) / unit_size;
|
||||
if until_alignment + SIMD_STRIDE_SIZE / unit_size <= len {
|
||||
if until_alignment != 0 {
|
||||
accu |= buffer[offset] as usize;
|
||||
offset += 1;
|
||||
until_alignment -= 1;
|
||||
while until_alignment != 0 {
|
||||
accu |= buffer[offset] as usize;
|
||||
offset += 1;
|
||||
until_alignment -= 1;
|
||||
}
|
||||
if accu >= $bound {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if accu >= $bound {
|
||||
let len_minus_stride = len - SIMD_STRIDE_SIZE / unit_size;
|
||||
if offset + (4 * (SIMD_STRIDE_SIZE / unit_size)) <= len {
|
||||
let len_minus_unroll = len - (4 * (SIMD_STRIDE_SIZE / unit_size));
|
||||
loop {
|
||||
let unroll_accu = unsafe {
|
||||
*(src.offset(offset as isize) as *const $simd_ty)
|
||||
} | unsafe {
|
||||
*(src.offset((offset + (SIMD_STRIDE_SIZE / unit_size)) as isize)
|
||||
as *const $simd_ty)
|
||||
} | unsafe {
|
||||
*(src.offset(
|
||||
(offset + (2 * (SIMD_STRIDE_SIZE / unit_size))) as isize,
|
||||
) as *const $simd_ty)
|
||||
} | unsafe {
|
||||
*(src.offset(
|
||||
(offset + (3 * (SIMD_STRIDE_SIZE / unit_size))) as isize,
|
||||
) as *const $simd_ty)
|
||||
};
|
||||
if !$func(unroll_accu) {
|
||||
return false;
|
||||
}
|
||||
offset += 4 * (SIMD_STRIDE_SIZE / unit_size);
|
||||
if offset > len_minus_unroll {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
let mut simd_accu = $splat;
|
||||
while offset <= len_minus_stride {
|
||||
simd_accu = simd_accu | unsafe {
|
||||
*(src.offset(offset as isize) as *const $simd_ty)
|
||||
};
|
||||
offset += SIMD_STRIDE_SIZE / unit_size;
|
||||
}
|
||||
if !$func(simd_accu) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
let len_minus_stride = len - SIMD_STRIDE_SIZE / unit_size;
|
||||
if offset + (4 * (SIMD_STRIDE_SIZE / unit_size)) <= len {
|
||||
let len_minus_unroll = len - (4 * (SIMD_STRIDE_SIZE / unit_size));
|
||||
loop {
|
||||
let unroll_accu = unsafe { *(src.offset(offset as isize) as *const $simd_ty) } |
|
||||
unsafe { *(src.offset((offset + (SIMD_STRIDE_SIZE / unit_size)) as isize) as *const $simd_ty) } |
|
||||
unsafe { *(src.offset((offset + (2 * (SIMD_STRIDE_SIZE / unit_size))) as isize) as *const $simd_ty) } |
|
||||
unsafe { *(src.offset((offset + (3 * (SIMD_STRIDE_SIZE / unit_size))) as isize) as *const $simd_ty) };
|
||||
if !$func(unroll_accu) {
|
||||
return false;
|
||||
}
|
||||
offset += 4 * (SIMD_STRIDE_SIZE / unit_size);
|
||||
if offset > len_minus_unroll {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
let mut simd_accu = $splat;
|
||||
while offset <= len_minus_stride {
|
||||
simd_accu = simd_accu | unsafe { *(src.offset(offset as isize) as *const $simd_ty) };
|
||||
offset += SIMD_STRIDE_SIZE / unit_size;
|
||||
}
|
||||
if !$func(simd_accu) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for &unit in &buffer[offset..] {
|
||||
accu |= unit as usize;
|
||||
}
|
||||
accu < $bound
|
||||
}
|
||||
for &unit in &buffer[offset..] {
|
||||
accu |= unit as usize;
|
||||
}
|
||||
accu < $bound
|
||||
})
|
||||
};
|
||||
}
|
||||
|
||||
cfg_if!{
|
||||
|
||||
+1
-1
@@ -7,8 +7,8 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use variant::*;
|
||||
use super::*;
|
||||
use variant::*;
|
||||
|
||||
pub struct ReplacementDecoder {
|
||||
emitted: bool,
|
||||
|
||||
+3
-3
@@ -7,10 +7,10 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use handles::*;
|
||||
use data::*;
|
||||
use variant::*;
|
||||
use super::*;
|
||||
use data::*;
|
||||
use handles::*;
|
||||
use variant::*;
|
||||
// Rust 1.14.0 requires the following despite the asterisk above.
|
||||
use super::in_inclusive_range;
|
||||
use super::in_inclusive_range16;
|
||||
|
||||
+3
-3
@@ -7,8 +7,8 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use simd::u8x16;
|
||||
use simd::u16x8;
|
||||
use simd::u8x16;
|
||||
use simd::Simd;
|
||||
|
||||
// TODO: Migrate unaligned access to stdlib code if/when the RFC
|
||||
@@ -222,10 +222,10 @@ cfg_if! {
|
||||
}
|
||||
|
||||
macro_rules! in_range16x8 {
|
||||
($s:ident, $start:expr, $end:expr) => ({
|
||||
($s:ident, $start:expr, $end:expr) => {{
|
||||
// SIMD sub is wrapping
|
||||
($s - u16x8::splat($start)).lt(u16x8::splat($end - $start))
|
||||
})
|
||||
}};
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
|
||||
+2
-2
@@ -7,10 +7,10 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use super::*;
|
||||
use ascii::*;
|
||||
use handles::*;
|
||||
use variant::*;
|
||||
use ascii::*;
|
||||
use super::*;
|
||||
|
||||
pub struct SingleByteDecoder {
|
||||
table: &'static [u16; 128],
|
||||
|
||||
+1
-1
@@ -7,9 +7,9 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use super::*;
|
||||
use handles::*;
|
||||
use variant::*;
|
||||
use super::*;
|
||||
|
||||
pub struct Utf16Decoder {
|
||||
lead_surrogate: u16, // If non-zero and pending_bmp == false, a pending lead surrogate
|
||||
|
||||
+2
-2
@@ -10,11 +10,11 @@
|
||||
#[cfg(feature = "parallel-utf8")]
|
||||
extern crate rayon;
|
||||
|
||||
use handles::*;
|
||||
use variant::*;
|
||||
use super::*;
|
||||
use ascii::ascii_to_basic_latin;
|
||||
use ascii::basic_latin_to_ascii;
|
||||
use handles::*;
|
||||
use variant::*;
|
||||
|
||||
// Keep this cfg_if in sync with whether the utf_8_core module is defined in lib.rs.
|
||||
cfg_if! {
|
||||
|
||||
+269
-27
@@ -76,21 +76,23 @@ pub fn run_utf8_validation(v: &[u8]) -> Result<(), Utf8Error> {
|
||||
};
|
||||
let old_offset = index;
|
||||
macro_rules! err {
|
||||
($error_len: expr) => {
|
||||
($error_len:expr) => {
|
||||
return Err(Utf8Error {
|
||||
valid_up_to: old_offset,
|
||||
})
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! next { () => {{
|
||||
index += 1;
|
||||
// we needed data, but there was none: error!
|
||||
if index >= len {
|
||||
err!(None)
|
||||
}
|
||||
v[index]
|
||||
}}}
|
||||
macro_rules! next {
|
||||
() => {{
|
||||
index += 1;
|
||||
// we needed data, but there was none: error!
|
||||
if index >= len {
|
||||
err!(None)
|
||||
}
|
||||
v[index]
|
||||
}};
|
||||
}
|
||||
|
||||
'inner: loop {
|
||||
let w = UTF8_CHAR_WIDTH[first as usize];
|
||||
@@ -164,22 +166,262 @@ pub fn run_utf8_validation(v: &[u8]) -> Result<(), Utf8Error> {
|
||||
|
||||
// https://tools.ietf.org/html/rfc3629
|
||||
static UTF8_CHAR_WIDTH: [u8; 256] = [
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x1F
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x3F
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x5F
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x7F
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 0x9F
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 0xBF
|
||||
0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
|
||||
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 0xDF
|
||||
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 0xEF
|
||||
4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0, // 0xFF
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1, // 0x1F
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1, // 0x3F
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1, // 0x5F
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1, // 0x7F
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0, // 0x9F
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0, // 0xBF
|
||||
0,
|
||||
0,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2, // 0xDF
|
||||
3,
|
||||
3,
|
||||
3,
|
||||
3,
|
||||
3,
|
||||
3,
|
||||
3,
|
||||
3,
|
||||
3,
|
||||
3,
|
||||
3,
|
||||
3,
|
||||
3,
|
||||
3,
|
||||
3,
|
||||
3, // 0xEF
|
||||
4,
|
||||
4,
|
||||
4,
|
||||
4,
|
||||
4,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0, // 0xFF
|
||||
];
|
||||
|
||||
/// Mask of the value bits of a continuation byte
|
||||
|
||||
+7
-7
@@ -19,18 +19,18 @@
|
||||
//! The purpose of making `Decoder` and `Encoder` `Sized` is to allow stack
|
||||
//! allocation in Rust code, including the convenience methods on `Encoding`.
|
||||
|
||||
use single_byte::*;
|
||||
use utf_8::*;
|
||||
use gb18030::*;
|
||||
use super::*;
|
||||
use big5::*;
|
||||
use euc_jp::*;
|
||||
use iso_2022_jp::*;
|
||||
use shift_jis::*;
|
||||
use euc_kr::*;
|
||||
use gb18030::*;
|
||||
use iso_2022_jp::*;
|
||||
use replacement::*;
|
||||
use x_user_defined::*;
|
||||
use shift_jis::*;
|
||||
use single_byte::*;
|
||||
use utf_16::*;
|
||||
use super::*;
|
||||
use utf_8::*;
|
||||
use x_user_defined::*;
|
||||
|
||||
pub enum VariantDecoder {
|
||||
SingleByte(SingleByteDecoder),
|
||||
|
||||
@@ -7,9 +7,9 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use super::*;
|
||||
use handles::*;
|
||||
use variant::*;
|
||||
use super::*;
|
||||
|
||||
cfg_if!{
|
||||
if #[cfg(feature = "simd-accel")] {
|
||||
|
||||
Reference in New Issue
Block a user