Enhance monetary formatting implementation and improve comments for clarity
This commit is contained in:
+16
-13
@@ -1,8 +1,7 @@
|
||||
|
||||
/// monetary.h implementation for Redox, following the POSIX standard.
|
||||
/// Following https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/monetary.h.html
|
||||
///
|
||||
/// We should provide a strfmon() implementation that formats a monetary value.
|
||||
/// We should provide a strfmon() implementation that formats a monetary value,
|
||||
/// according to the current locale (TODO).
|
||||
use alloc::string::{String, ToString};
|
||||
use core::{ffi::CStr, ptr, slice, str};
|
||||
@@ -62,7 +61,7 @@ struct FormatFlags {
|
||||
}
|
||||
|
||||
/// Use our own floating point implementation
|
||||
/// TODO : use num-traits crate
|
||||
/// TODO : maybe we can use num-traits crate
|
||||
#[inline]
|
||||
fn my_fabs(x: f64) -> f64 {
|
||||
if x < 0.0 {
|
||||
@@ -105,32 +104,36 @@ fn my_pow10(n: usize) -> f64 {
|
||||
result
|
||||
}
|
||||
|
||||
/// TODO : improve grouping implementation
|
||||
/// Formats a monetary value according to the current locale.
|
||||
fn apply_grouping(int_str: &str, monetary: &LocaleMonetaryInfo) -> String {
|
||||
let mut grouped = String::with_capacity(int_str.len() * 2);
|
||||
let mut count = 0;
|
||||
let mut group_idx = 0;
|
||||
let current_grouping = &monetary.mon_grouping;
|
||||
let separator = monetary.mon_thousands_sep;
|
||||
|
||||
// The grouping array can have up to 4 elements, but the last element is always 0
|
||||
for c in int_str.chars().rev() {
|
||||
if count > 0 && count % monetary.mon_grouping[group_idx] == 0 {
|
||||
grouped.push_str(monetary.mon_thousands_sep);
|
||||
// Move to next grouping size if available
|
||||
if group_idx + 1 < monetary.mon_grouping.len() {
|
||||
group_idx += 1;
|
||||
for c in int_str.chars() {
|
||||
if count > 0 {
|
||||
let current_group = current_grouping[group_idx.min(current_grouping.len() - 1)];
|
||||
if current_group > 0 && count % current_group == 0 {
|
||||
grouped.push_str(separator);
|
||||
if group_idx + 1 < current_grouping.len() {
|
||||
group_idx += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
grouped.push(c);
|
||||
count += 1;
|
||||
}
|
||||
// Reverse the string to get the correct order
|
||||
grouped.chars().rev().collect()
|
||||
|
||||
grouped
|
||||
}
|
||||
|
||||
/// Safe handling of large monetary values. Returns None if the value is too large to format
|
||||
fn format_value_parts(value: f64, frac_digits: usize) -> Option<(String, i64)> {
|
||||
let abs_value = my_fabs(value);
|
||||
if abs_value > (i64::MAX as f64) {
|
||||
// Check if the value is too large to format
|
||||
return None;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,9 +12,10 @@ use core::{ffi::CStr, ptr, slice, str};
|
||||
an optional left precision, an optional right precision, and a conversion specifier.
|
||||
The conversion specifier can be either 'i' or 'n'. The 'i' specifier formats the monetary value according to the
|
||||
locale-specific rules, while the 'n' specifier formats the monetary value according to the international rules.
|
||||
|
||||
|
||||
The function returns the number of characters written to the buffer, excluding the null terminator, or -1 if an error occurred.
|
||||
|
||||
TODO : better handling error : always return -1 if an error occurred
|
||||
*/
|
||||
pub unsafe extern "C" fn strfmon(
|
||||
s: *mut i8, // char *
|
||||
@@ -208,7 +209,7 @@ fn format_monetary(
|
||||
// Reverse the string to get the correct order
|
||||
let mut result = String::with_capacity(grouped.len() + 20);
|
||||
|
||||
// Add the sign
|
||||
// Add the sign position
|
||||
let sign_posn = if is_negative {
|
||||
monetary.n_sign_posn
|
||||
} else {
|
||||
@@ -226,7 +227,7 @@ fn format_monetary(
|
||||
""
|
||||
};
|
||||
|
||||
// Add the sign
|
||||
// Add the sign at the beginning
|
||||
if sign_posn == 0 {
|
||||
result.push('(');
|
||||
} else if sign_posn == 1 {
|
||||
@@ -273,6 +274,7 @@ fn format_monetary(
|
||||
}
|
||||
|
||||
if !cs_precedes {
|
||||
// Add the currency symbol after the value
|
||||
if sep_by_space {
|
||||
result.push(' ');
|
||||
}
|
||||
@@ -284,6 +286,7 @@ fn format_monetary(
|
||||
}
|
||||
|
||||
if let Some(width) = flags.field_width {
|
||||
// Check if the field width is specified
|
||||
if result.len() < width {
|
||||
let padding = " ".repeat(width - result.len());
|
||||
if flags.left_justify {
|
||||
|
||||
Reference in New Issue
Block a user