[librsvg: 1/2] Use CStr for C string conversion instead of `as`




commit d3602edde902381910166b057ee98af9383a2e0f
Author: Michael Howell <michael notriddle com>
Date:   Sat Oct 30 12:16:59 2021 -0700

    Use CStr for C string conversion instead of `as`
    
    This way, we get the type directly converted to `*const c_char`,
    instead of having to go through `*const u8`. This avoids a redundant-cast
    warning on platforms that already use `u8` as `c_char`.
    
    Fixes #808
    
    Part-of: <https://gitlab.gnome.org/GNOME/librsvg/-/merge_requests/624>

 src/c_api/handle.rs   | 20 ++++++++++----------
 src/c_api/messages.rs | 37 +++++++++++++++++++++++++------------
 2 files changed, 35 insertions(+), 22 deletions(-)
---
diff --git a/src/c_api/handle.rs b/src/c_api/handle.rs
index 1d04216d6..73af1c693 100644
--- a/src/c_api/handle.rs
+++ b/src/c_api/handle.rs
@@ -2137,12 +2137,12 @@ mod tests {
     #[test]
     fn path_or_url_unix() {
         unsafe {
-            match PathOrUrl::new(b"/foo/bar\0" as *const u8 as *const _).unwrap() {
+            match PathOrUrl::new(rsvg_c_str!("/foo/bar")).unwrap() {
                 PathOrUrl::Path(_) => (),
                 _ => panic!("unix filename should be a PathOrUrl::Path"),
             }
 
-            match PathOrUrl::new(b"foo/bar\0" as *const u8 as *const _).unwrap() {
+            match PathOrUrl::new(rsvg_c_str!("foo/bar")).unwrap() {
                 PathOrUrl::Path(_) => (),
                 _ => panic!("unix filename should be a PathOrUrl::Path"),
             }
@@ -2152,22 +2152,22 @@ mod tests {
     #[test]
     fn path_or_url_windows() {
         unsafe {
-            match PathOrUrl::new(b"c:/foo/bar\0" as *const u8 as *const _).unwrap() {
+            match PathOrUrl::new(rsvg_c_str!("c:/foo/bar")).unwrap() {
                 PathOrUrl::Path(_) => (),
                 _ => panic!("windows filename should be a PathOrUrl::Path"),
             }
 
-            match PathOrUrl::new(b"C:/foo/bar\0" as *const u8 as *const _).unwrap() {
+            match PathOrUrl::new(rsvg_c_str!("C:/foo/bar")).unwrap() {
                 PathOrUrl::Path(_) => (),
                 _ => panic!("windows filename should be a PathOrUrl::Path"),
             }
 
-            match PathOrUrl::new(b"c:\\foo\\bar\0" as *const u8 as *const _).unwrap() {
+            match PathOrUrl::new(rsvg_c_str!("c:\\foo\\bar")).unwrap() {
                 PathOrUrl::Path(_) => (),
                 _ => panic!("windows filename should be a PathOrUrl::Path"),
             }
 
-            match PathOrUrl::new(b"C:\\foo\\bar\0" as *const u8 as *const _).unwrap() {
+            match PathOrUrl::new(rsvg_c_str!("C:\\foo\\bar")).unwrap() {
                 PathOrUrl::Path(_) => (),
                 _ => panic!("windows filename should be a PathOrUrl::Path"),
             }
@@ -2177,7 +2177,7 @@ mod tests {
     #[test]
     fn path_or_url_unix_url() {
         unsafe {
-            match PathOrUrl::new(b"file:///foo/bar\0" as *const u8 as *const _).unwrap() {
+            match PathOrUrl::new(rsvg_c_str!("file:///foo/bar")).unwrap() {
                 PathOrUrl::Url(_) => (),
                 _ => panic!("file:// unix filename should be a PathOrUrl::Url"),
             }
@@ -2187,12 +2187,12 @@ mod tests {
     #[test]
     fn path_or_url_windows_url() {
         unsafe {
-            match PathOrUrl::new(b"file://c:/foo/bar\0" as *const u8 as *const _).unwrap() {
+            match PathOrUrl::new(rsvg_c_str!("file://c:/foo/bar")).unwrap() {
                 PathOrUrl::Url(_) => (),
                 _ => panic!("file:// windows filename should be a PathOrUrl::Url"),
             }
 
-            match PathOrUrl::new(b"file://C:/foo/bar\0" as *const u8 as *const _).unwrap() {
+            match PathOrUrl::new(rsvg_c_str!("file://C:/foo/bar")).unwrap() {
                 PathOrUrl::Url(_) => (),
                 _ => panic!("file:// windows filename should be a PathOrUrl::Url"),
             }
@@ -2202,7 +2202,7 @@ mod tests {
     #[test]
     fn path_or_url_empty_str() {
         unsafe {
-            assert!(PathOrUrl::new(b"\0" as *const u8 as *const _).is_err());
+            assert!(PathOrUrl::new(rsvg_c_str!("")).is_err());
         }
 
         assert!(PathOrUrl::from_os_str(OsStr::new("")).is_err());
diff --git a/src/c_api/messages.rs b/src/c_api/messages.rs
index 564f506cb..5b227cb80 100644
--- a/src/c_api/messages.rs
+++ b/src/c_api/messages.rs
@@ -33,6 +33,19 @@ use glib::translate::*;
   g_log_structured_array (log_level, fields, n_fields);
  */
 
+/// Helper function for converting string literals to C char pointers.
+#[macro_export]
+macro_rules! rsvg_c_str {
+    ($txt:expr) => {
+        // SAFETY: it's important that the type we pass to `from_bytes_with_nul` is 'static,
+        // so that the storage behind the returned pointer doesn't get freed while it's still
+        // being used. We get that by only allowing string literals.
+        std::ffi::CStr::from_bytes_with_nul(concat!($txt, "\0").as_bytes())
+            .unwrap()
+            .as_ptr()
+    };
+}
+
 /// Helper for `rsvg_g_warning` and `rsvg_g_critical`
 ///
 /// This simulates what in C would be a call to the g_warning() or g_critical()
@@ -43,7 +56,7 @@ use glib::translate::*;
 fn rsvg_g_log(level: glib::ffi::GLogLevelFlags, msg: &str) {
     // stolen from gmessages.c:log_level_to_priority()
     let priority = match level {
-        G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL => b"4\0",
+        G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL => rsvg_c_str!("4"),
         _ => unreachable!("please add another log level priority to rsvg_g_log()"),
     };
 
@@ -55,19 +68,19 @@ fn rsvg_g_log(level: glib::ffi::GLogLevelFlags, msg: &str) {
     // trace.  So, we'll omit them.
     let fields = [
         GLogField {
-            key: b"PRIORITY\0" as *const u8 as *const _,
-            value: priority as *const u8 as *const _,
+            key: rsvg_c_str!("PRIORITY"),
+            value: priority as *const _,
             length: -1,
         },
         GLogField {
-            key: b"MESSAGE\0" as *const u8 as *const _,
+            key: rsvg_c_str!("MESSAGE"),
             value: c_char_msg as *const _,
             length: msg.len() as _,
         },
         // This is the G_LOG_DOMAIN set from the Makefile
         GLogField {
-            key: b"GLIB_DOMAIN\0" as *const u8 as *const _,
-            value: b"librsvg\0" as *const u8 as *const _,
+            key: rsvg_c_str!("GLIB_DOMAIN"),
+            value: rsvg_c_str!("librsvg") as *const _,
             length: -1,
         },
     ];
@@ -114,9 +127,9 @@ macro_rules! rsvg_return_if_fail {
         $(
             if !$condition {
                 glib::ffi::g_return_if_fail_warning(
-                    b"librsvg\0" as *const u8 as *const _,
-                    concat!(stringify!($func_name), "\0").as_ptr() as *const _,
-                    concat!(stringify!($condition), "\0").as_ptr() as *const _,
+                    rsvg_c_str!("librsvg"),
+                    rsvg_c_str!(stringify!($func_name)),
+                    rsvg_c_str!(stringify!($condition)),
                 );
                 return;
             }
@@ -134,9 +147,9 @@ macro_rules! rsvg_return_val_if_fail {
         $(
             if !$condition {
                 glib::ffi::g_return_if_fail_warning(
-                    b"librsvg\0" as *const u8 as *const _,
-                    concat!(stringify!($func_name), "\0").as_ptr() as *const _,
-                    concat!(stringify!($condition), "\0").as_ptr() as *const _,
+                    rsvg_c_str!("librsvg"),
+                    rsvg_c_str!(stringify!($func_name)),
+                    rsvg_c_str!(stringify!($condition)),
                 );
                 return $retval;
             }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]