mirror of
https://github.com/torvalds/linux.git
synced 2024-11-21 19:41:42 +00:00
rust: str: add {make,to}_{upper,lower}case() to CString
Add functions to convert a CString to upper- / lowercase, either in-place or by creating a copy of the original CString. Naming follows the one from the Rust stdlib, where functions starting with 'to' create a copy and functions starting with 'make' perform an in-place conversion. This is required by the Nova project (GSP only Rust successor of Nouveau) to convert stringified enum values (representing different GPU chipsets) to strings in order to generate the corresponding firmware paths. See also [1]. Link: https://rust-for-linux.zulipchat.com/#narrow/stream/288089-General/topic/String.20manipulation.20in.20kernel.20Rust [1] Reviewed-by: Alice Ryhl <aliceryhl@google.com> Signed-off-by: Danilo Krummrich <dakr@redhat.com> Reviewed-by: Benno Lossin <benno.lossin@proton.me> Link: https://lore.kernel.org/r/20240223163726.12397-1-dakr@redhat.com [ Reworded to fix typo and to make the link use the `Link:` tag. ] Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
This commit is contained in:
parent
dbef1811c8
commit
a321f3ad0a
@ -5,7 +5,7 @@
|
||||
use alloc::alloc::AllocError;
|
||||
use alloc::vec::Vec;
|
||||
use core::fmt::{self, Write};
|
||||
use core::ops::{self, Deref, Index};
|
||||
use core::ops::{self, Deref, DerefMut, Index};
|
||||
|
||||
use crate::{
|
||||
bindings,
|
||||
@ -236,6 +236,19 @@ impl CStr {
|
||||
unsafe { core::mem::transmute(bytes) }
|
||||
}
|
||||
|
||||
/// Creates a mutable [`CStr`] from a `[u8]` without performing any
|
||||
/// additional checks.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// `bytes` *must* end with a `NUL` byte, and should only have a single
|
||||
/// `NUL` byte (or the string will be truncated).
|
||||
#[inline]
|
||||
pub unsafe fn from_bytes_with_nul_unchecked_mut(bytes: &mut [u8]) -> &mut CStr {
|
||||
// SAFETY: Properties of `bytes` guaranteed by the safety precondition.
|
||||
unsafe { &mut *(bytes as *mut [u8] as *mut CStr) }
|
||||
}
|
||||
|
||||
/// Returns a C pointer to the string.
|
||||
#[inline]
|
||||
pub const fn as_char_ptr(&self) -> *const core::ffi::c_char {
|
||||
@ -299,6 +312,70 @@ impl CStr {
|
||||
pub fn to_cstring(&self) -> Result<CString, AllocError> {
|
||||
CString::try_from(self)
|
||||
}
|
||||
|
||||
/// Converts this [`CStr`] to its ASCII lower case equivalent in-place.
|
||||
///
|
||||
/// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
|
||||
/// but non-ASCII letters are unchanged.
|
||||
///
|
||||
/// To return a new lowercased value without modifying the existing one, use
|
||||
/// [`to_ascii_lowercase()`].
|
||||
///
|
||||
/// [`to_ascii_lowercase()`]: #method.to_ascii_lowercase
|
||||
pub fn make_ascii_lowercase(&mut self) {
|
||||
// INVARIANT: This doesn't introduce or remove NUL bytes in the C
|
||||
// string.
|
||||
self.0.make_ascii_lowercase();
|
||||
}
|
||||
|
||||
/// Converts this [`CStr`] to its ASCII upper case equivalent in-place.
|
||||
///
|
||||
/// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
|
||||
/// but non-ASCII letters are unchanged.
|
||||
///
|
||||
/// To return a new uppercased value without modifying the existing one, use
|
||||
/// [`to_ascii_uppercase()`].
|
||||
///
|
||||
/// [`to_ascii_uppercase()`]: #method.to_ascii_uppercase
|
||||
pub fn make_ascii_uppercase(&mut self) {
|
||||
// INVARIANT: This doesn't introduce or remove NUL bytes in the C
|
||||
// string.
|
||||
self.0.make_ascii_uppercase();
|
||||
}
|
||||
|
||||
/// Returns a copy of this [`CString`] where each character is mapped to its
|
||||
/// ASCII lower case equivalent.
|
||||
///
|
||||
/// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
|
||||
/// but non-ASCII letters are unchanged.
|
||||
///
|
||||
/// To lowercase the value in-place, use [`make_ascii_lowercase`].
|
||||
///
|
||||
/// [`make_ascii_lowercase`]: str::make_ascii_lowercase
|
||||
pub fn to_ascii_lowercase(&self) -> Result<CString, AllocError> {
|
||||
let mut s = self.to_cstring()?;
|
||||
|
||||
s.make_ascii_lowercase();
|
||||
|
||||
Ok(s)
|
||||
}
|
||||
|
||||
/// Returns a copy of this [`CString`] where each character is mapped to its
|
||||
/// ASCII upper case equivalent.
|
||||
///
|
||||
/// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
|
||||
/// but non-ASCII letters are unchanged.
|
||||
///
|
||||
/// To uppercase the value in-place, use [`make_ascii_uppercase`].
|
||||
///
|
||||
/// [`make_ascii_uppercase`]: str::make_ascii_uppercase
|
||||
pub fn to_ascii_uppercase(&self) -> Result<CString, AllocError> {
|
||||
let mut s = self.to_cstring()?;
|
||||
|
||||
s.make_ascii_uppercase();
|
||||
|
||||
Ok(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for CStr {
|
||||
@ -764,6 +841,14 @@ impl Deref for CString {
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for CString {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
// SAFETY: A `CString` is always NUL-terminated and contains no other
|
||||
// NUL bytes.
|
||||
unsafe { CStr::from_bytes_with_nul_unchecked_mut(self.buf.as_mut_slice()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> TryFrom<&'a CStr> for CString {
|
||||
type Error = AllocError;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user