+7
src/c_str.rs
+7
src/c_str.rs
···
35
35
fn c2r(c: Self::C) -> Self::Char;
36
36
37
37
fn chars_from_bytes(b: &[u8]) -> Option<&[Self::Char]>;
38
+
fn chars_to_bytes(c: &[Self::Char]) -> Option<&[u8]>;
38
39
39
40
unsafe fn strlen(s: *const Self::C) -> usize;
40
41
unsafe fn strchr(s: *const Self::C, c: Self::C) -> *const Self::C;
···
64
65
}
65
66
fn chars_from_bytes(b: &[u8]) -> Option<&[Self::Char]> {
66
67
Some(b)
68
+
}
69
+
fn chars_to_bytes(c: &[Self::Char]) -> Option<&[u8]> {
70
+
Some(c)
67
71
}
68
72
}
69
73
impl Kind for Wide {
···
93
97
c as _
94
98
}
95
99
fn chars_from_bytes(b: &[u8]) -> Option<&[Self::Char]> {
100
+
None
101
+
}
102
+
fn chars_to_bytes(c: &[Self::Char]) -> Option<&[u8]> {
96
103
None
97
104
}
98
105
}
+48
-32
src/header/stdio/printf.rs
+48
-32
src/header/stdio/printf.rs
···
322
322
}
323
323
}
324
324
325
-
fn fmt_int<I>(fmt: u8, i: I) -> String
325
+
fn fmt_int<I, T: c_str::Kind>(fmt: char, i: I) -> String
326
326
where
327
327
I: fmt::Display + fmt::Octal + fmt::LowerHex + fmt::UpperHex + fmt::Binary,
328
328
{
329
329
match fmt {
330
-
b'o' => format!("{:o}", i),
331
-
b'u' => i.to_string(),
332
-
b'x' => format!("{:x}", i),
333
-
b'X' => format!("{:X}", i),
334
-
b'b' | b'B' => format!("{:b}", i),
330
+
'o' => format!("{:o}", i),
331
+
'u' => i.to_string(),
332
+
'x' => format!("{:x}", i),
333
+
'X' => format!("{:X}", i),
334
+
'b' | 'B' if T::IS_THIN_NOT_WIDE => format!("{:b}", i),
335
335
_ => panic!(
336
336
"fmt_int should never be called with the fmt {:?}",
337
337
fmt as char,
···
384
384
385
385
fn fmt_float_exp<W: Write>(
386
386
w: &mut W,
387
-
exp_fmt: u8,
387
+
exp_fmt: char,
388
388
trim: bool,
389
389
precision: usize,
390
390
float: c_double,
···
412
412
};
413
413
pad(w, !left, b'0', len..pad_zero)?;
414
414
w.write_all(bytes)?;
415
-
write!(w, "{}{:+03}", exp_fmt as char, exp)?;
415
+
write!(w, "{}{:+03}", exp_fmt, exp)?;
416
416
pad(w, left, b' ', len..pad_space)?;
417
417
418
418
Ok(())
···
622
622
}
623
623
}
624
624
625
-
unsafe fn inner_printf<W: Write>(w: W, format: CStr, mut ap: VaList) -> io::Result<c_int> {
625
+
pub(crate) unsafe fn inner_printf<T: c_str::Kind>(
626
+
w: impl Write,
627
+
format: NulStr<T>,
628
+
mut ap: VaList,
629
+
) -> io::Result<c_int> {
626
630
let w = &mut platform::CountingWriter::new(w);
627
631
628
632
let iterator = PrintfIter { format };
···
669
673
for section in iterator {
670
674
let arg = match section {
671
675
Ok(PrintfFmt::Plain(text)) => {
672
-
w.write_all(text)?;
676
+
if T::IS_THIN_NOT_WIDE {
677
+
let bytes = T::chars_to_bytes(text).expect("is thin");
678
+
w.write_all(bytes)?;
679
+
} else {
680
+
// TODO: wcsrtombs wrapper
681
+
for c in text.iter().filter_map(|u| char::from_u32((*u).into())) {
682
+
write!(w, "{}", c);
683
+
}
684
+
}
673
685
continue;
674
686
}
675
687
Ok(PrintfFmt::Arg(arg)) => arg,
···
694
706
signed_space as usize
695
707
};
696
708
let intkind = arg.intkind;
697
-
let fmt = arg.fmt as u8;
709
+
let fmt = arg.fmt;
698
710
let fmtkind = arg.fmtkind;
699
711
let fmtcase = match fmt {
700
-
b'x' | b'b' | b'f' | b'e' | b'g' => Some(FmtCase::Lower),
701
-
b'X' | b'B' | b'F' | b'E' | b'G' => Some(FmtCase::Upper),
712
+
'b' if T::IS_THIN_NOT_WIDE => Some(FmtCase::Lower),
713
+
'B' if T::IS_THIN_NOT_WIDE => Some(FmtCase::Upper),
714
+
'x' | 'f' | 'e' | 'g' => Some(FmtCase::Lower),
715
+
'X' | 'F' | 'E' | 'G' => Some(FmtCase::Upper),
702
716
_ => None,
703
717
};
704
718
···
764
778
}
765
779
FmtKind::Unsigned => {
766
780
let string = match varargs.get(index, &mut ap, Some((arg.fmtkind, arg.intkind))) {
767
-
VaArg::c_char(i) => fmt_int(fmt, i as c_uchar),
781
+
VaArg::c_char(i) => fmt_int::<_, T>(fmt, i as c_uchar),
768
782
VaArg::c_double(i) => panic!("this should not be possible"),
769
-
VaArg::c_int(i) => fmt_int(fmt, i as c_uint),
770
-
VaArg::c_long(i) => fmt_int(fmt, i as c_ulong),
771
-
VaArg::c_longlong(i) => fmt_int(fmt, i as c_ulonglong),
772
-
VaArg::c_short(i) => fmt_int(fmt, i as c_ushort),
773
-
VaArg::intmax_t(i) => fmt_int(fmt, i as uintmax_t),
774
-
VaArg::pointer(i) => fmt_int(fmt, i as usize),
775
-
VaArg::ptrdiff_t(i) => fmt_int(fmt, i as size_t),
776
-
VaArg::ssize_t(i) => fmt_int(fmt, i as size_t),
783
+
VaArg::c_int(i) => fmt_int::<_, T>(fmt, i as c_uint),
784
+
VaArg::c_long(i) => fmt_int::<_, T>(fmt, i as c_ulong),
785
+
VaArg::c_longlong(i) => fmt_int::<_, T>(fmt, i as c_ulonglong),
786
+
VaArg::c_short(i) => fmt_int::<_, T>(fmt, i as c_ushort),
787
+
VaArg::intmax_t(i) => fmt_int::<_, T>(fmt, i as uintmax_t),
788
+
VaArg::pointer(i) => fmt_int::<_, T>(fmt, i as usize),
789
+
VaArg::ptrdiff_t(i) => fmt_int::<_, T>(fmt, i as size_t),
790
+
VaArg::ssize_t(i) => fmt_int::<_, T>(fmt, i as size_t),
777
791
VaArg::wint_t(_) => unreachable!("this should not be possible"),
778
792
};
779
793
let zero = precision == Some(0) && string == "0";
···
791
805
len.max(precision.unwrap_or(0))
792
806
+ if alternate && string != "0" {
793
807
match fmt {
794
-
b'o' if no_precision => 1,
795
-
b'x' | b'X' | b'b' | b'B' => 2,
808
+
'o' if no_precision => 1,
809
+
'x' | 'X' => 2,
810
+
'b' | 'B' if T::IS_THIN_NOT_WIDE => 2,
796
811
_ => 0,
797
812
}
798
813
} else {
···
804
819
805
820
if alternate && string != "0" {
806
821
match fmt {
807
-
b'o' if no_precision => w.write_all(b"0")?,
808
-
b'x' => w.write_all(b"0x")?,
809
-
b'X' => w.write_all(b"0X")?,
810
-
b'b' => w.write_all(b"0b")?,
811
-
b'B' => w.write_all(b"0B")?,
822
+
'o' if no_precision => w.write_all(b"0")?,
823
+
'x' => w.write_all(b"0x")?,
824
+
'X' => w.write_all(b"0X")?,
825
+
'b' if T::IS_THIN_NOT_WIDE => w.write_all(b"0b")?,
826
+
'B' if T::IS_THIN_NOT_WIDE => w.write_all(b"0B")?,
812
827
_ => (),
813
828
}
814
829
}
···
856
871
};
857
872
if float.is_finite() {
858
873
let (log, exp) = float_exp(float);
859
-
let exp_fmt = b'E' | (fmt & 32);
874
+
// TODO: .is_uppercase()?
875
+
let exp_fmt = if fmt as u32 & 32 == 32 { 'e' } else { 'E' };
860
876
let precision = precision.unwrap_or(6);
861
877
let use_exp_format = exp < -4 || exp >= precision as isize;
862
878
···
1263
1279
/// # Safety
1264
1280
/// Behavior is undefined if any of the following conditions are violated:
1265
1281
/// - `ap` must follow the safety contract of variable arguments of C.
1266
-
pub unsafe fn printf<W: Write>(w: W, format: CStr, ap: VaList) -> c_int {
1267
-
inner_printf(w, format, ap).unwrap_or(-1)
1282
+
pub unsafe fn printf(w: impl Write, format: CStr, ap: VaList) -> c_int {
1283
+
inner_printf::<c_str::Thin>(w, format, ap).unwrap_or(-1)
1268
1284
}
+6
-568
src/header/wchar/wprintf.rs
+6
-568
src/header/wchar/wprintf.rs
···
1
1
// TODO: reuse more code with the thin printf impl
2
2
use crate::{
3
3
c_str::{self, WStr},
4
-
header::stdio::printf::{FmtKind, IntKind, Number, PrintfFmt, PrintfIter, VaArg, VaListCache},
5
-
io::{self, Write},
6
-
};
7
-
use alloc::{
8
-
collections::BTreeMap,
9
-
string::{String, ToString},
10
-
vec::Vec,
11
-
};
12
-
use core::{char, cmp, f64, ffi::VaList, fmt, num::FpCategory, ops::Range, slice};
13
-
14
-
use crate::{
15
-
header::errno::EILSEQ,
16
-
platform::{self, types::*},
4
+
header::stdio::printf::inner_printf,
5
+
io::Write,
17
6
};
18
-
19
-
// ___ _ _ _ _
20
-
// |_ _|_ __ ___ _ __ | | ___ _ __ ___ ___ _ __ | |_ __ _| |_(_) ___ _ __ _
21
-
// | || '_ ` _ \| '_ \| |/ _ \ '_ ` _ \ / _ \ '_ \| __/ _` | __| |/ _ \| '_ \(_)
22
-
// | || | | | | | |_) | | __/ | | | | | __/ | | | || (_| | |_| | (_) | | | |_
23
-
// |___|_| |_| |_| .__/|_|\___|_| |_| |_|\___|_| |_|\__\__,_|\__|_|\___/|_| |_(_)
24
-
// |_|
25
-
26
-
enum FmtCase {
27
-
Lower,
28
-
Upper,
29
-
}
30
-
31
-
// The spelled-out "infinity"/"INFINITY" is also permitted by the standard
32
-
static INF_STR_LOWER: &str = "inf";
33
-
static INF_STR_UPPER: &str = "INF";
34
-
35
-
static NAN_STR_LOWER: &str = "nan";
36
-
static NAN_STR_UPPER: &str = "NAN";
37
-
38
-
fn fmt_int<I>(fmt: u32, i: I) -> String
39
-
where
40
-
I: fmt::Display + fmt::Octal + fmt::LowerHex + fmt::UpperHex,
41
-
{
42
-
match char::from_u32(fmt).unwrap_or('\0') {
43
-
'o' => format!("{:o}", i),
44
-
'u' => i.to_string(),
45
-
'x' => format!("{:x}", i),
46
-
'X' => format!("{:X}", i),
47
-
_ => panic!(
48
-
"fmt_int should never be called with the fmt {:?}",
49
-
char::from_u32(fmt)
50
-
),
51
-
}
52
-
}
53
-
54
-
fn pad<W: Write>(
55
-
w: &mut W,
56
-
current_side: bool,
57
-
pad_char: u32,
58
-
range: Range<usize>,
59
-
) -> io::Result<()> {
60
-
if current_side {
61
-
for _ in range {
62
-
if let Some(c) = char::from_u32(pad_char) {
63
-
write!(w, "{}", c)?;
64
-
}
65
-
}
66
-
}
67
-
Ok(())
68
-
}
69
-
70
-
fn abs(float: c_double) -> c_double {
71
-
// Don't ask me whe float.abs() seems absent...
72
-
if float.is_sign_negative() {
73
-
-float
74
-
} else {
75
-
float
76
-
}
77
-
}
78
-
79
-
fn float_string(float: c_double, precision: usize, trim: bool) -> String {
80
-
let mut string = format!("{:.p$}", float, p = precision);
81
-
if trim && string.contains('.') {
82
-
let truncate = {
83
-
let slice = string.trim_end_matches('0');
84
-
let mut truncate = slice.len();
85
-
if slice.ends_with('.') {
86
-
truncate -= 1;
87
-
}
88
-
truncate
89
-
};
90
-
string.truncate(truncate);
91
-
}
92
-
string
93
-
}
94
-
95
-
fn float_exp(mut float: c_double) -> (c_double, isize) {
96
-
let mut exp: isize = 0;
97
-
while abs(float) >= 10.0 {
98
-
float /= 10.0;
99
-
exp += 1;
100
-
}
101
-
while f64::EPSILON < abs(float) && abs(float) < 1.0 {
102
-
float *= 10.0;
103
-
exp -= 1;
104
-
}
105
-
(float, exp)
106
-
}
107
-
108
-
fn fmt_float_exp<W: Write>(
109
-
w: &mut W,
110
-
exp_fmt: u32,
111
-
trim: bool,
112
-
precision: usize,
113
-
float: c_double,
114
-
exp: isize,
115
-
left: bool,
116
-
pad_space: usize,
117
-
pad_zero: usize,
118
-
) -> io::Result<()> {
119
-
let mut exp2 = exp;
120
-
let mut exp_len = 1;
121
-
while exp2 >= 10 {
122
-
exp2 /= 10;
123
-
exp_len += 1;
124
-
}
125
-
126
-
let string = float_string(float, precision, trim);
127
-
let len = string.len() + 2 + 2.max(exp_len);
128
-
129
-
pad(w, !left, ' ' as u32, len..pad_space)?;
130
-
let bytes = if string.starts_with('-') {
131
-
w.write_all(&[b'-'])?;
132
-
&string.as_bytes()[1..]
133
-
} else {
134
-
string.as_bytes()
135
-
};
136
-
pad(w, !left, '0' as u32, len..pad_zero)?;
137
-
w.write_all(bytes)?;
138
-
if let Some(c) = char::from_u32(exp_fmt) {
139
-
write!(w, "{}{:+03}", c, exp)?;
140
-
}
141
-
pad(w, left, ' ' as u32, len..pad_space)?;
142
-
143
-
Ok(())
144
-
}
145
-
146
-
fn fmt_float_normal<W: Write>(
147
-
w: &mut W,
148
-
trim: bool,
149
-
precision: usize,
150
-
float: c_double,
151
-
left: bool,
152
-
pad_space: usize,
153
-
pad_zero: usize,
154
-
) -> io::Result<usize> {
155
-
let string = float_string(float, precision, trim);
156
-
157
-
pad(w, !left, ' ' as u32, string.len()..pad_space)?;
158
-
let bytes = if string.starts_with('-') {
159
-
w.write_all(&[b'-'])?;
160
-
&string.as_bytes()[1..]
161
-
} else {
162
-
string.as_bytes()
163
-
};
164
-
pad(w, true, '0' as u32, string.len()..pad_zero)?;
165
-
w.write_all(bytes)?;
166
-
pad(w, left, ' ' as u32, string.len()..pad_space)?;
167
-
168
-
Ok(string.len())
169
-
}
170
-
171
-
/// Write ±infinity or ±NaN representation for any floating-point style
172
-
fn fmt_float_nonfinite<W: Write>(w: &mut W, float: c_double, case: FmtCase) -> io::Result<()> {
173
-
if float.is_sign_negative() {
174
-
w.write_all(&[b'-'])?;
175
-
}
176
-
177
-
let nonfinite_str = match float.classify() {
178
-
FpCategory::Infinite => match case {
179
-
FmtCase::Lower => INF_STR_LOWER,
180
-
FmtCase::Upper => INF_STR_UPPER,
181
-
},
182
-
FpCategory::Nan => match case {
183
-
FmtCase::Lower => NAN_STR_LOWER,
184
-
FmtCase::Upper => NAN_STR_UPPER,
185
-
},
186
-
_ => {
187
-
// This function should only be called with infinite or NaN value.
188
-
panic!("this should not be possible")
189
-
}
190
-
};
191
-
192
-
w.write_all(nonfinite_str.as_bytes())?;
193
-
194
-
Ok(())
195
-
}
196
-
197
-
unsafe fn inner_wprintf<W: Write>(w: W, format: WStr, mut ap: VaList) -> io::Result<c_int> {
198
-
let w = &mut platform::CountingWriter::new(w);
199
-
200
-
let iterator = PrintfIter::<c_str::Wide> { format };
201
-
202
-
// Pre-fetch vararg types
203
-
let mut varargs = VaListCache::default();
204
-
let mut positional = BTreeMap::new();
205
-
// ^ NOTE: This depends on the sorted order, do not change to HashMap or whatever
206
-
207
-
for section in iterator {
208
-
let arg = match section {
209
-
Ok(PrintfFmt::Plain(text)) => continue,
210
-
Ok(PrintfFmt::Arg(arg)) => arg,
211
-
Err(()) => return Ok(-1),
212
-
};
213
-
if arg.fmtkind == FmtKind::Percent {
214
-
continue;
215
-
}
216
-
for num in &[arg.min_width, arg.precision.unwrap_or(Number::Static(0))] {
217
-
match num {
218
-
Number::Next => varargs.args.push(VaArg::c_int(ap.arg::<c_int>())),
219
-
Number::Index(i) => {
220
-
positional.insert(i - 1, (FmtKind::Signed, IntKind::Int));
221
-
}
222
-
Number::Static(_) => (),
223
-
}
224
-
}
225
-
match arg.index {
226
-
Some(i) => {
227
-
positional.insert(i - 1, (arg.fmtkind, arg.intkind));
228
-
}
229
-
None => varargs
230
-
.args
231
-
.push(VaArg::arg_from(arg.fmtkind, arg.intkind, &mut ap)),
232
-
}
233
-
}
234
-
235
-
// Make sure, in order, the positional arguments exist with the specified type
236
-
for (i, arg) in positional {
237
-
varargs.get(i, &mut ap, Some(arg));
238
-
}
239
-
240
-
// Main loop
241
-
for section in iterator {
242
-
let arg = match section {
243
-
Ok(PrintfFmt::Plain(text)) => {
244
-
for &wc in text.iter() {
245
-
if let Some(c) = char::from_u32(wc) {
246
-
write!(w, "{}", c)?;
247
-
}
248
-
}
249
-
continue;
250
-
}
251
-
Ok(PrintfFmt::Arg(arg)) => arg,
252
-
Err(()) => return Ok(-1),
253
-
};
254
-
let alternate = arg.alternate;
255
-
let zero = arg.zero;
256
-
let mut left = arg.left;
257
-
let sign_reserve = arg.sign_reserve;
258
-
let sign_always = arg.sign_always;
259
-
let min_width = arg.min_width.resolve(&mut varargs, &mut ap);
260
-
let precision = arg.precision.map(|n| n.resolve(&mut varargs, &mut ap));
261
-
let pad_zero = if zero { min_width } else { 0 };
262
-
let signed_space = match pad_zero {
263
-
0 => min_width as isize,
264
-
_ => 0,
265
-
};
266
-
let pad_space = if signed_space < 0 {
267
-
left = true;
268
-
-signed_space as usize
269
-
} else {
270
-
signed_space as usize
271
-
};
272
-
let intkind = arg.intkind;
273
-
let fmt_char = arg.fmt;
274
-
let fmt = fmt_char as u32;
275
-
let fmtkind = arg.fmtkind;
276
-
let fmtcase = match fmt_char {
277
-
'x' | 'f' | 'e' | 'g' => Some(FmtCase::Lower),
278
-
'X' | 'F' | 'E' | 'G' => Some(FmtCase::Upper),
279
-
_ => None,
280
-
};
281
-
282
-
let index = arg.index.map(|i| i - 1).unwrap_or_else(|| {
283
-
if fmtkind == FmtKind::Percent {
284
-
0
285
-
} else {
286
-
let i = varargs.i;
287
-
varargs.i += 1;
288
-
i
289
-
}
290
-
});
291
-
292
-
match fmtkind {
293
-
FmtKind::Percent => w.write_all(&[b'%'])?,
294
-
FmtKind::Signed => {
295
-
let string = match varargs.get(index, &mut ap, Some((arg.fmtkind, arg.intkind))) {
296
-
VaArg::c_char(i) => i.to_string(),
297
-
VaArg::c_double(i) => panic!("this should not be possible"),
298
-
VaArg::c_int(i) => i.to_string(),
299
-
VaArg::c_long(i) => i.to_string(),
300
-
VaArg::c_longlong(i) => i.to_string(),
301
-
VaArg::c_short(i) => i.to_string(),
302
-
VaArg::intmax_t(i) => i.to_string(),
303
-
VaArg::pointer(i) => (i as usize).to_string(),
304
-
VaArg::ptrdiff_t(i) => i.to_string(),
305
-
VaArg::ssize_t(i) => i.to_string(),
306
-
VaArg::wint_t(_) => unreachable!("this should not be possible"),
307
-
};
308
-
let positive = !string.starts_with('-');
309
-
let zero = precision == Some(0) && string == "0";
310
-
311
-
let mut len = string.len();
312
-
let mut final_len = string.len().max(precision.unwrap_or(0));
313
-
if positive && (sign_reserve || sign_always) {
314
-
final_len += 1;
315
-
}
316
-
if zero {
317
-
len = 0;
318
-
final_len = 0;
319
-
}
320
-
321
-
pad(w, !left, ' ' as u32, final_len..pad_space)?;
322
-
323
-
let bytes = if positive {
324
-
if sign_reserve {
325
-
w.write_all(&[b' '])?;
326
-
} else if sign_always {
327
-
w.write_all(&[b'+'])?;
328
-
}
329
-
string.as_bytes()
330
-
} else {
331
-
w.write_all(&[b'-'])?;
332
-
&string.as_bytes()[1..]
333
-
};
334
-
pad(w, true, '0' as u32, len..precision.unwrap_or(pad_zero))?;
335
-
336
-
if !zero {
337
-
w.write_all(bytes)?;
338
-
}
339
-
340
-
pad(w, left, ' ' as u32, final_len..pad_space)?;
341
-
}
342
-
FmtKind::Unsigned => {
343
-
let string = match varargs.get(index, &mut ap, Some((arg.fmtkind, arg.intkind))) {
344
-
VaArg::c_char(i) => fmt_int(fmt, i as c_uchar),
345
-
VaArg::c_double(i) => panic!("this should not be possible"),
346
-
VaArg::c_int(i) => fmt_int(fmt, i as c_uint),
347
-
VaArg::c_long(i) => fmt_int(fmt, i as c_ulong),
348
-
VaArg::c_longlong(i) => fmt_int(fmt, i as c_ulonglong),
349
-
VaArg::c_short(i) => fmt_int(fmt, i as c_ushort),
350
-
VaArg::intmax_t(i) => fmt_int(fmt, i as uintmax_t),
351
-
VaArg::pointer(i) => fmt_int(fmt, i as usize),
352
-
VaArg::ptrdiff_t(i) => fmt_int(fmt, i as size_t),
353
-
VaArg::ssize_t(i) => fmt_int(fmt, i as size_t),
354
-
VaArg::wint_t(_) => unreachable!("this should not be possible"),
355
-
};
356
-
let zero = precision == Some(0) && string == "0";
357
-
358
-
// If this int is padded out to be larger than it is, don't
359
-
// add an extra zero if octal.
360
-
let no_precision = precision.map(|pad| pad < string.len()).unwrap_or(true);
361
-
362
-
let len;
363
-
let final_len = if zero {
364
-
len = 0;
365
-
0
366
-
} else {
367
-
len = string.len();
368
-
len.max(precision.unwrap_or(0))
369
-
+ if alternate && string != "0" {
370
-
match char::from_u32(fmt).unwrap_or('\0') {
371
-
'o' if no_precision => 1,
372
-
'x' | 'X' => 2,
373
-
_ => 0,
374
-
}
375
-
} else {
376
-
0
377
-
}
378
-
};
379
-
380
-
pad(w, !left, ' ' as u32, final_len..pad_space)?;
381
-
382
-
if alternate && string != "0" {
383
-
match char::from_u32(fmt).unwrap_or('\0') {
384
-
'o' if no_precision => w.write_all(&[b'0'])?,
385
-
'x' => w.write_all(&[b'0', b'x'])?,
386
-
'X' => w.write_all(&[b'0', b'X'])?,
387
-
_ => (),
388
-
}
389
-
}
390
-
pad(w, true, '0' as u32, len..precision.unwrap_or(pad_zero))?;
391
-
392
-
if !zero {
393
-
w.write_all(string.as_bytes())?;
394
-
}
395
-
396
-
pad(w, left, ' ' as u32, final_len..pad_space)?;
397
-
}
398
-
FmtKind::Scientific => {
399
-
let float = match varargs.get(index, &mut ap, Some((arg.fmtkind, arg.intkind))) {
400
-
VaArg::c_double(i) => i,
401
-
_ => panic!("this should not be possible"),
402
-
};
403
-
if float.is_finite() {
404
-
let (float, exp) = float_exp(float);
405
-
let precision = precision.unwrap_or(6);
7
+
use core::ffi::VaList;
406
8
407
-
fmt_float_exp(
408
-
w, fmt, false, precision, float, exp, left, pad_space, pad_zero,
409
-
)?;
410
-
} else {
411
-
fmt_float_nonfinite(w, float, fmtcase.unwrap())?;
412
-
}
413
-
}
414
-
FmtKind::Decimal => {
415
-
let float = match varargs.get(index, &mut ap, Some((arg.fmtkind, arg.intkind))) {
416
-
VaArg::c_double(i) => i,
417
-
_ => panic!("this should not be possible"),
418
-
};
419
-
if float.is_finite() {
420
-
let precision = precision.unwrap_or(6);
9
+
use crate::platform::{self, types::*};
421
10
422
-
fmt_float_normal(w, false, precision, float, left, pad_space, pad_zero)?;
423
-
} else {
424
-
fmt_float_nonfinite(w, float, fmtcase.unwrap())?;
425
-
}
426
-
}
427
-
FmtKind::AnyNotation => {
428
-
let float = match varargs.get(index, &mut ap, Some((arg.fmtkind, arg.intkind))) {
429
-
VaArg::c_double(i) => i,
430
-
_ => panic!("this should not be possible"),
431
-
};
432
-
if float.is_finite() {
433
-
let (log, exp) = float_exp(float);
434
-
let exp_fmt = ('E' as u32) | (fmt & 32);
435
-
let precision = precision.unwrap_or(6);
436
-
let use_exp_format = exp < -4 || exp >= precision as isize;
437
-
438
-
if use_exp_format {
439
-
// Length of integral part will always be 1 here,
440
-
// because that's how x/floor(log10(x)) works
441
-
let precision = precision.saturating_sub(1);
442
-
fmt_float_exp(
443
-
w, exp_fmt, true, precision, log, exp, left, pad_space, pad_zero,
444
-
)?;
445
-
} else {
446
-
// Length of integral part will be the exponent of
447
-
// the unused logarithm, unless the exponent is
448
-
// negative which in case the integral part must
449
-
// of course be 0, 1 in length
450
-
let len = 1 + cmp::max(0, exp) as usize;
451
-
let precision = precision.saturating_sub(len);
452
-
fmt_float_normal(w, true, precision, float, left, pad_space, pad_zero)?;
453
-
}
454
-
} else {
455
-
fmt_float_nonfinite(w, float, fmtcase.unwrap())?;
456
-
}
457
-
}
458
-
FmtKind::String => {
459
-
let ptr = match varargs.get(index, &mut ap, Some((arg.fmtkind, arg.intkind))) {
460
-
VaArg::pointer(p) => p,
461
-
_ => panic!("this should not be possible"),
462
-
} as *const c_char;
463
-
464
-
if ptr.is_null() {
465
-
w.write_all(b"(null)")?;
466
-
} else {
467
-
let max = precision.unwrap_or(::core::usize::MAX);
468
-
469
-
if intkind == IntKind::Long || intkind == IntKind::LongLong {
470
-
// Handle wchar_t
471
-
let mut ptr = ptr as *const wchar_t;
472
-
let mut string = String::new();
473
-
474
-
while *ptr != 0 {
475
-
let c = match char::from_u32(*ptr as _) {
476
-
Some(c) => c,
477
-
None => {
478
-
platform::ERRNO.set(EILSEQ);
479
-
return Err(io::last_os_error());
480
-
}
481
-
};
482
-
if string.len() + c.len_utf8() >= max {
483
-
break;
484
-
}
485
-
string.push(c);
486
-
ptr = ptr.add(1);
487
-
}
488
-
489
-
pad(w, !left, ' ' as u32, string.len()..pad_space)?;
490
-
w.write_all(string.as_bytes())?;
491
-
pad(w, left, ' ' as u32, string.len()..pad_space)?;
492
-
} else {
493
-
let mut len = 0;
494
-
while *ptr.add(len) != 0 && len < max {
495
-
len += 1;
496
-
}
497
-
498
-
pad(w, !left, ' ' as u32, len..pad_space)?;
499
-
w.write_all(slice::from_raw_parts(ptr as *const u8, len))?;
500
-
pad(w, left, ' ' as u32, len..pad_space)?;
501
-
}
502
-
}
503
-
}
504
-
FmtKind::Char => match varargs.get(index, &mut ap, Some((arg.fmtkind, arg.intkind))) {
505
-
VaArg::c_char(c) => {
506
-
pad(w, !left, ' ' as u32, 1..pad_space)?;
507
-
w.write_all(&[c as u8])?;
508
-
pad(w, left, ' ' as u32, 1..pad_space)?;
509
-
}
510
-
VaArg::wint_t(c) => {
511
-
let c = match char::from_u32(c as _) {
512
-
Some(c) => c,
513
-
None => {
514
-
platform::ERRNO.set(EILSEQ);
515
-
return Err(io::last_os_error());
516
-
}
517
-
};
518
-
let mut buf = [0; 4];
519
-
520
-
pad(w, !left, ' ' as u32, 1..pad_space)?;
521
-
w.write_all(c.encode_utf8(&mut buf).as_bytes())?;
522
-
pad(w, left, ' ' as u32, 1..pad_space)?;
523
-
}
524
-
_ => unreachable!("this should not be possible"),
525
-
},
526
-
FmtKind::Pointer => {
527
-
let ptr = match varargs.get(index, &mut ap, Some((arg.fmtkind, arg.intkind))) {
528
-
VaArg::pointer(p) => p,
529
-
_ => panic!("this should not be possible"),
530
-
};
531
-
532
-
let mut len = 1;
533
-
if ptr.is_null() {
534
-
len = "(nil)".len();
535
-
} else {
536
-
let mut ptr = ptr as usize;
537
-
while ptr >= 10 {
538
-
ptr /= 10;
539
-
len += 1;
540
-
}
541
-
}
542
-
543
-
pad(w, !left, ' ' as u32, len..pad_space)?;
544
-
if ptr.is_null() {
545
-
write!(w, "(nil)")?;
546
-
} else {
547
-
write!(w, "0x{:x}", ptr as usize)?;
548
-
}
549
-
pad(w, left, ' ' as u32, len..pad_space)?;
550
-
}
551
-
FmtKind::GetWritten => {
552
-
let ptr = match varargs.get(index, &mut ap, Some((arg.fmtkind, arg.intkind))) {
553
-
VaArg::pointer(p) => p,
554
-
_ => panic!("this should not be possible"),
555
-
};
556
-
557
-
match intkind {
558
-
IntKind::Byte => *(ptr as *mut c_char) = w.written as c_char,
559
-
IntKind::Short => *(ptr as *mut c_short) = w.written as c_short,
560
-
IntKind::Int => *(ptr as *mut c_int) = w.written as c_int,
561
-
IntKind::Long => *(ptr as *mut c_long) = w.written as c_long,
562
-
IntKind::LongLong => *(ptr as *mut c_longlong) = w.written as c_longlong,
563
-
IntKind::IntMax => *(ptr as *mut intmax_t) = w.written as intmax_t,
564
-
IntKind::PtrDiff => *(ptr as *mut ptrdiff_t) = w.written as ptrdiff_t,
565
-
IntKind::Size => *(ptr as *mut size_t) = w.written as size_t,
566
-
}
567
-
}
568
-
}
569
-
}
570
-
Ok(w.written as c_int)
571
-
}
572
-
573
-
pub unsafe fn wprintf<W: Write>(w: W, format: WStr, ap: VaList) -> c_int {
574
-
inner_wprintf(w, format, ap).unwrap_or(-1)
11
+
pub unsafe fn wprintf(w: impl Write, format: WStr, ap: VaList) -> c_int {
12
+
inner_printf::<c_str::Wide>(w, format, ap).unwrap_or(-1)
575
13
}