1 //! Slow, simple lexical integer-to-string conversion routine. 2 3 use crate::util::*; 4 5 // Naive itoa algorithm. 6 macro_rules! naive_algorithm { 7 ($value:ident, $radix:ident, $buffer:ident, $index:ident) => ({ 8 while $value >= $radix { 9 let r = ($value % $radix).as_usize(); 10 $value /= $radix; 11 12 // This is always safe, since r must be [0, radix). 13 $index -= 1; 14 unchecked_index_mut!($buffer[$index] = digit_to_char(r)); 15 } 16 17 // Decode last digit. 18 let r = ($value % $radix).as_usize(); 19 // This is always safe, since r must be [0, radix). 20 $index -= 1; 21 unchecked_index_mut!($buffer[$index] = digit_to_char(r)); 22 }); 23 } 24 25 // Naive implementation for radix-N numbers. 26 // Precondition: `value` must be non-negative and mutable. 27 perftools_inline!{ 28 fn naive<T>(mut value: T, radix: u32, buffer: &mut [u8]) 29 -> usize 30 where T: UnsignedInteger 31 { 32 // Decode all but last digit, 1 at a time. 33 let mut index = buffer.len(); 34 let radix: T = as_cast(radix); 35 naive_algorithm!(value, radix, buffer, index); 36 index 37 }} 38 39 pub(crate) trait Naive { 40 // Export integer to string. naive(self, radix: u32, buffer: &mut [u8]) -> usize41 fn naive(self, radix: u32, buffer: &mut [u8]) -> usize; 42 } 43 44 // Implement naive for type. 45 macro_rules! naive_impl { 46 ($($t:ty)*) => ($( 47 impl Naive for $t { 48 perftools_inline_always!{ 49 fn naive(self, radix: u32, buffer: &mut [u8]) -> usize { 50 naive(self, radix, buffer) 51 }} 52 } 53 )*); 54 } 55 56 naive_impl! { u8 u16 u32 u64 usize } 57 58 // Naive implementation for 128-bit radix-N numbers. 59 // Precondition: `value` must be non-negative and mutable. 60 perftools_inline!{ 61 fn naive_u128(value: u128, radix: u32, buffer: &mut [u8]) 62 -> usize 63 { 64 // Decode all but last digit, 1 at a time. 65 let (divisor, digits_per_iter, d_cltz) = u128_divisor(radix); 66 let radix: u64 = as_cast(radix); 67 68 // To deal with internal 0 values or values with internal 0 digits set, 69 // we store the starting index, and if not all digits are written, 70 // we just skip down `digits` digits for the next value. 71 let mut index = buffer.len(); 72 let mut start_index = index; 73 let (value, mut low) = u128_divrem(value, divisor, d_cltz); 74 naive_algorithm!(low, radix, buffer, index); 75 if value != 0 { 76 start_index -= digits_per_iter; 77 index = index.min(start_index); 78 let (value, mut mid) = u128_divrem(value, divisor, d_cltz); 79 naive_algorithm!(mid, radix, buffer, index); 80 81 if value != 0 { 82 start_index -= digits_per_iter; 83 index = index.min(start_index); 84 let mut high = value as u64; 85 naive_algorithm!(high, radix, buffer, index); 86 } 87 } 88 index 89 }} 90 91 impl Naive for u128 { 92 perftools_inline_always!{ 93 fn naive(self, radix: u32, buffer: &mut [u8]) -> usize { 94 naive_u128(self, radix, buffer) 95 }} 96 } 97