Skip to main content

relibc/header/langinfo/
mod.rs

1//! `langinfo.h` implementation.
2//!
3//! See <https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/langinfo.h.html>.
4
5// TODO : involve loading locale data. Currently, the implementation only supports the "C" locale.
6
7use crate::{header::bits_locale_t::locale_t, platform::types::size_t};
8use core::ffi::c_char;
9
10// TODO move `nl_item` to nl_types.h (not yet present in relibc) or bits header
11/// See <https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/langinfo.h.html>.
12///
13/// POSIX type for items used with `nl_langinfo`
14/// In practice, this is an index into the string table.
15pub type nl_item = size_t;
16
17// Static string table for langinfo constants
18/// cbindgen:ignore
19static STRING_TABLE: [&[u8]; 81] = [
20    b"UTF-8\0",                // CODESET
21    b"%a %b %e %H:%M:%S %Y\0", // D_T_FMT
22    b"%m/%d/%y\0",             // D_FMT
23    b"%H:%M:%S\0",             // T_FMT
24    b"%I:%M:%S %p\0",          // T_FMT_AMPM
25    b"AM\0",                   // AM_STR
26    b"PM\0",                   // PM_STR
27    b"Sunday\0",               // DAY_1
28    b"Monday\0",               // DAY_2
29    b"Tuesday\0",              // DAY_3
30    b"Wednesday\0",            // DAY_4
31    b"Thursday\0",             // DAY_5
32    b"Friday\0",               // DAY_6
33    b"Saturday\0",             // DAY_7
34    b"Sun\0",                  // ABDAY_1
35    b"Mon\0",                  // ABDAY_2
36    b"Tue\0",                  // ABDAY_3
37    b"Wed\0",                  // ABDAY_4
38    b"Thu\0",                  // ABDAY_5
39    b"Fri\0",                  // ABDAY_6
40    b"Sat\0",                  // ABDAY_7
41    b"January\0",              // MON_1
42    b"February\0",             // MON_2
43    b"March\0",                // MON_3
44    b"April\0",                // MON_4
45    b"May\0",                  // MON_5
46    b"June\0",                 // MON_6
47    b"July\0",                 // MON_7
48    b"August\0",               // MON_8
49    b"September\0",            // MON_9
50    b"October\0",              // MON_10
51    b"November\0",             // MON_11
52    b"December\0",             // MON_12
53    b"Jan\0",                  // ABMON_1
54    b"Feb\0",                  // ABMON_2
55    b"Mar\0",                  // ABMON_3
56    b"Apr\0",                  // ABMON_4
57    b"May\0",                  // ABMON_5
58    b"Jun\0",                  // ABMON_6
59    b"Jul\0",                  // ABMON_7
60    b"Aug\0",                  // ABMON_8
61    b"Sep\0",                  // ABMON_9
62    b"Oct\0",                  // ABMON_10
63    b"Nov\0",                  // ABMON_11
64    b"Dec\0",                  // ABMON_12
65    b"\0",                     // ERA
66    b"\0",                     // ERA_D_FMT
67    b"\0",                     // ERA_D_T_FMT
68    b"\0",                     // ERA_T_FMT
69    b"\0",                     // ALT_DIGITS
70    b".\0",                    // RADIXCHAR
71    b"\0",                     // THOUSEP
72    b"^[yY]\0",                // YESEXPR
73    b"^[nN]\0",                // NOEXPR
74    b"yes\0",                  // YESSTR
75    b"no\0",                   // NOSTR
76    b".\0",                    // CRNCYSTR
77    // Some languages have alternative names for
78    // months. For the "C" locale, we just use one.
79    b"January\0",   // ALTMON_1
80    b"February\0",  // ALTMON_2
81    b"March\0",     // ALTMON_3
82    b"April\0",     // ALTMON_4
83    b"May\0",       // ALTMON_5
84    b"June\0",      // ALTMON_6
85    b"July\0",      // ALTMON_7
86    b"August\0",    // ALTMON_8
87    b"September\0", // ALTMON_9
88    b"October\0",   // ALTMON_10
89    b"November\0",  // ALTMON_11
90    b"December\0",  // ALTMON_12
91    b"Jan\0",       // ABALTMON_1
92    b"Feb\0",       // ABALTMON_2
93    b"Mar\0",       // ABALTMON_3
94    b"Apr\0",       // ABALTMON_4
95    b"May\0",       // ABALTMON_5
96    b"Jun\0",       // ABALTMON_6
97    b"Jul\0",       // ABALTMON_7
98    b"Aug\0",       // ABALTMON_8
99    b"Sep\0",       // ABALTMON_9
100    b"Oct\0",       // ABALTMON_10
101    b"Nov\0",       // ABALTMON_11
102    b"Dec\0",       // ABALTMON_12
103];
104
105// Item constants
106pub const CODESET: nl_item = 0;
107pub const D_T_FMT: nl_item = 1;
108pub const D_FMT: nl_item = 2;
109pub const T_FMT: nl_item = 3;
110pub const T_FMT_AMPM: nl_item = 4;
111pub const AM_STR: nl_item = 5;
112pub const PM_STR: nl_item = 6;
113
114pub const DAY_1: nl_item = 7;
115pub const DAY_2: nl_item = 8;
116pub const DAY_3: nl_item = 9;
117pub const DAY_4: nl_item = 10;
118pub const DAY_5: nl_item = 11;
119pub const DAY_6: nl_item = 12;
120pub const DAY_7: nl_item = 13;
121
122pub const ABDAY_1: nl_item = 14;
123pub const ABDAY_2: nl_item = 15;
124pub const ABDAY_3: nl_item = 16;
125pub const ABDAY_4: nl_item = 17;
126pub const ABDAY_5: nl_item = 18;
127pub const ABDAY_6: nl_item = 19;
128pub const ABDAY_7: nl_item = 20;
129
130pub const MON_1: nl_item = 21;
131pub const MON_2: nl_item = 22;
132pub const MON_3: nl_item = 23;
133pub const MON_4: nl_item = 24;
134pub const MON_5: nl_item = 25;
135pub const MON_6: nl_item = 26;
136pub const MON_7: nl_item = 27;
137pub const MON_8: nl_item = 28;
138pub const MON_9: nl_item = 29;
139pub const MON_10: nl_item = 30;
140pub const MON_11: nl_item = 31;
141pub const MON_12: nl_item = 32;
142
143pub const ABMON_1: nl_item = 33;
144pub const ABMON_2: nl_item = 34;
145pub const ABMON_3: nl_item = 35;
146pub const ABMON_4: nl_item = 36;
147pub const ABMON_5: nl_item = 37;
148pub const ABMON_6: nl_item = 38;
149pub const ABMON_7: nl_item = 39;
150pub const ABMON_8: nl_item = 40;
151pub const ABMON_9: nl_item = 41;
152pub const ABMON_10: nl_item = 42;
153pub const ABMON_11: nl_item = 43;
154pub const ABMON_12: nl_item = 44;
155
156pub const ERA: nl_item = 45;
157pub const ERA_D_FMT: nl_item = 46;
158pub const ERA_D_T_FMT: nl_item = 47;
159pub const ERA_T_FMT: nl_item = 48;
160pub const ALT_DIGITS: nl_item = 49;
161pub const RADIXCHAR: nl_item = 50;
162pub const THOUSEP: nl_item = 51;
163pub const YESEXPR: nl_item = 52;
164pub const NOEXPR: nl_item = 53;
165pub const YESSTR: nl_item = 54; // Legacy
166pub const NOSTR: nl_item = 55; // Legacy
167pub const CRNCYSTR: nl_item = 56;
168
169pub const ALTMON_1: nl_item = 57;
170pub const ALTMON_2: nl_item = 58;
171pub const ALTMON_3: nl_item = 59;
172pub const ALTMON_4: nl_item = 60;
173pub const ALTMON_5: nl_item = 61;
174pub const ALTMON_6: nl_item = 62;
175pub const ALTMON_7: nl_item = 63;
176pub const ALTMON_8: nl_item = 64;
177pub const ALTMON_9: nl_item = 65;
178pub const ALTMON_10: nl_item = 66;
179pub const ALTMON_11: nl_item = 67;
180pub const ALTMON_12: nl_item = 68;
181
182pub const ABALTMON_1: nl_item = 69;
183pub const ABALTMON_2: nl_item = 70;
184pub const ABALTMON_3: nl_item = 71;
185pub const ABALTMON_4: nl_item = 72;
186pub const ABALTMON_5: nl_item = 73;
187pub const ABALTMON_6: nl_item = 74;
188pub const ABALTMON_7: nl_item = 75;
189pub const ABALTMON_8: nl_item = 76;
190pub const ABALTMON_9: nl_item = 77;
191pub const ABALTMON_10: nl_item = 78;
192pub const ABALTMON_11: nl_item = 79;
193pub const ABALTMON_12: nl_item = 80;
194
195/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/nl_langinfo.html>.
196///
197/// Get a string from the langinfo table
198///
199/// # Safety
200/// - Caller must ensure `item` is a valid `nl_item` index.
201/// - Returns a pointer to a null-terminated string, or an empty string if the item is invalid.
202/// - Compatibility requires mutable pointer to be returned, but it should not be mutated!
203#[unsafe(no_mangle)]
204pub unsafe extern "C" fn nl_langinfo(item: nl_item) -> *mut c_char {
205    // Validate the item and perform the lookup
206    let ptr = if item < STRING_TABLE.len() {
207        STRING_TABLE[item].as_ptr().cast::<c_char>()
208    } else {
209        // Return a pointer to an empty string if the item is invalid
210        c"".as_ptr().cast::<c_char>()
211    };
212    // Mutable pointer is required (unsafe!)
213    ptr.cast_mut()
214}
215
216/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/nl_langinfo_l.html>.
217///
218/// Get a string from the langinfo table
219///
220/// # Safety
221/// - Caller must ensure `item` is a valid `nl_item` index.
222/// - Returns a pointer to a null-terminated string, or an empty string if the item is invalid.
223/// - Compatibility requires mutable pointer to be returned, but it should not be mutated!
224#[unsafe(no_mangle)]
225pub unsafe extern "C" fn nl_langinfo_l(item: nl_item, _loc: locale_t) -> *mut c_char {
226    unsafe { nl_langinfo(item) }
227}