|
3 | 3 | // This program is made available under an ISC-style license. See the |
4 | 4 | // accompanying file LICENSE for details. |
5 | 5 |
|
| 6 | +/// Annotates input buffer string with logging information. |
| 7 | +/// Returns result as a ffi::CStr for use with native cubeb logging functions. |
| 8 | +pub fn cubeb_log_internal_buf_fmt<'a>( |
| 9 | + buf: &'a mut [u8; 1024], |
| 10 | + file: &str, |
| 11 | + line: u32, |
| 12 | + msg: &str, |
| 13 | +) -> &'a std::ffi::CStr { |
| 14 | + use std::io::Write; |
| 15 | + let filename = std::path::Path::new(file) |
| 16 | + .file_name() |
| 17 | + .unwrap() |
| 18 | + .to_str() |
| 19 | + .unwrap(); |
| 20 | + // 2 for ':', 1 for ' ', 1 for '\n', and 1 for converting `line!()` to number of digits |
| 21 | + let len = filename.len() + ((line as f32).log10().trunc() as usize) + msg.len() + 5; |
| 22 | + debug_assert!(len < buf.len(), "log will be truncated"); |
| 23 | + let _ = writeln!(&mut buf[..], "{}:{}: {}", filename, line, msg); |
| 24 | + let last = std::cmp::min(len, buf.len() - 1); |
| 25 | + buf[last] = 0; |
| 26 | + let cstr = unsafe { std::ffi::CStr::from_bytes_with_nul_unchecked(&buf[..=last]) }; |
| 27 | + cstr |
| 28 | +} |
| 29 | + |
6 | 30 | #[macro_export] |
7 | 31 | macro_rules! cubeb_log_internal { |
8 | | - ($level: expr, $msg: expr) => { |
9 | | - #[allow(unused_unsafe)] |
10 | | - unsafe { |
11 | | - if $level <= $crate::ffi::g_cubeb_log_level.into() { |
12 | | - cubeb_log_internal!(__INTERNAL__ $msg); |
13 | | - } |
14 | | - } |
| 32 | + ($log_callback: expr, $level: expr, $fmt: expr, $($arg: expr),+) => { |
| 33 | + cubeb_log_internal!($log_callback, $level, format!($fmt, $($arg),*)); |
15 | 34 | }; |
16 | | - ($level: expr, $fmt: expr, $($arg: expr),+) => { |
| 35 | + ($log_callback: expr, $level: expr, $msg: expr) => { |
17 | 36 | #[allow(unused_unsafe)] |
18 | 37 | unsafe { |
19 | 38 | if $level <= $crate::ffi::g_cubeb_log_level.into() { |
20 | | - cubeb_log_internal!(__INTERNAL__ format!($fmt, $($arg),*)); |
| 39 | + if let Some(log_callback) = $log_callback { |
| 40 | + let mut buf = [0u8; 1024]; |
| 41 | + log_callback( |
| 42 | + $crate::log::cubeb_log_internal_buf_fmt(&mut buf, file!(), line!(), &$msg) |
| 43 | + .as_ptr(), |
| 44 | + ); |
| 45 | + } |
21 | 46 | } |
22 | 47 | } |
23 | 48 | }; |
24 | | - (__INTERNAL__ $msg: expr) => { |
25 | | - if let Some(log_callback) = $crate::ffi::g_cubeb_log_callback { |
26 | | - use std::io::Write; |
| 49 | +} |
27 | 50 |
|
28 | | - let mut buf = [0 as u8; 1024]; |
29 | | - let filename = std::path::Path::new(file!()) |
30 | | - .file_name() |
31 | | - .unwrap() |
32 | | - .to_str() |
33 | | - .unwrap(); |
34 | | - // 2 for ':', 1 for ' ', 1 for '\n', and 1 for converting `line!()` to number of digits |
35 | | - let len = filename.len() + ((line!() as f32).log10().trunc() as usize) + $msg.len() + 5; |
36 | | - debug_assert!(len < buf.len(), "log will be truncated"); |
37 | | - let _ = write!(&mut buf[..], "{}:{}: {}\n", filename, line!(), $msg); |
38 | | - let last = std::cmp::min(len, buf.len() - 1); |
39 | | - buf[last] = 0; |
40 | | - let cstr = unsafe { std::ffi::CStr::from_bytes_with_nul_unchecked(&buf[..=last]) }; |
41 | | - log_callback(cstr.as_ptr()); |
42 | | - } |
43 | | - } |
| 51 | +#[macro_export] |
| 52 | +macro_rules! cubeb_log { |
| 53 | + ($($arg: expr),+) => (cubeb_log_internal!($crate::ffi::g_cubeb_log_callback, $crate::LogLevel::Normal, $($arg),+)); |
44 | 54 | } |
45 | 55 |
|
46 | 56 | #[macro_export] |
47 | 57 | macro_rules! cubeb_logv { |
48 | | - ($msg: expr) => (cubeb_log_internal!($crate::LogLevel::Verbose, $msg)); |
49 | | - ($fmt: expr, $($arg: expr),+) => (cubeb_log_internal!($crate::LogLevel::Verbose, $fmt, $($arg),*)); |
| 58 | + ($($arg: expr),+) => (cubeb_log_internal!($crate::ffi::g_cubeb_log_callback, $crate::LogLevel::Verbose, $($arg),+)); |
50 | 59 | } |
51 | 60 |
|
52 | 61 | #[macro_export] |
53 | | -macro_rules! cubeb_log { |
54 | | - ($msg: expr) => (cubeb_log_internal!($crate::LogLevel::Normal, $msg)); |
55 | | - ($fmt: expr, $($arg: expr),+) => (cubeb_log_internal!($crate::LogLevel::Normal, $fmt, $($arg),*)); |
| 62 | +macro_rules! cubeb_alog { |
| 63 | + ($($arg: expr),+) => (cubeb_log_internal!($crate::ffi::cubeb_async_log.into(), $crate::LogLevel::Normal, $($arg),+)); |
| 64 | +} |
| 65 | + |
| 66 | +#[macro_export] |
| 67 | +macro_rules! cubeb_alogv { |
| 68 | + ($($arg: expr),+) => (cubeb_log_internal!($crate::ffi::cubeb_async_log.into(), $crate::LogLevel::Verbose, $($arg),+)); |
56 | 69 | } |
57 | 70 |
|
58 | 71 | #[cfg(test)] |
59 | 72 | mod tests { |
60 | 73 | #[test] |
61 | | - fn test_normal_logging() { |
62 | | - cubeb_log!("This is log at normal level"); |
| 74 | + fn test_normal_logging_sync() { |
| 75 | + cubeb_log!("This is synchronous log output at normal level"); |
63 | 76 | cubeb_log!("{} Formatted log", 1); |
64 | 77 | cubeb_log!("{} Formatted {} log {}", 1, 2, 3); |
65 | 78 | } |
66 | 79 |
|
67 | 80 | #[test] |
68 | | - fn test_verbose_logging() { |
69 | | - cubeb_logv!("This is a log at verbose level"); |
| 81 | + fn test_verbose_logging_sync() { |
| 82 | + cubeb_logv!("This is synchronous log output at verbose level"); |
70 | 83 | cubeb_logv!("{} Formatted log", 1); |
71 | 84 | cubeb_logv!("{} Formatted {} log {}", 1, 2, 3); |
72 | 85 | } |
| 86 | + |
| 87 | + #[test] |
| 88 | + fn test_normal_logging_async() { |
| 89 | + cubeb_alog!("This is asynchronous log output at normal level"); |
| 90 | + cubeb_alog!("{} Formatted log", 1); |
| 91 | + cubeb_alog!("{} Formatted {} log {}", 1, 2, 3); |
| 92 | + } |
| 93 | + |
| 94 | + #[test] |
| 95 | + fn test_verbose_logging_async() { |
| 96 | + cubeb_alogv!("This is asynchronous log output at verbose level"); |
| 97 | + cubeb_alogv!("{} Formatted log", 1); |
| 98 | + cubeb_alogv!("{} Formatted {} log {}", 1, 2, 3); |
| 99 | + } |
73 | 100 | } |
0 commit comments