[glib] [MacOS] Fallback to CFStringGetCSTring if CFStringGetCStringPtr fails.



commit c60226e0a1cae40a96ed0bf95ca7d5a508548f58
Author: John Ralls <jralls ceridwen us>
Date:   Fri Oct 13 13:45:01 2017 -0700

    [MacOS] Fallback to CFStringGetCSTring if CFStringGetCStringPtr fails.

 gio/gosxappinfo.c     |   34 ++++++++++++++++++++++++++++++++--
 gio/gosxcontenttype.c |   34 ++++++++++++++++++++++++++++++++--
 2 files changed, 64 insertions(+), 4 deletions(-)
---
diff --git a/gio/gosxappinfo.c b/gio/gosxappinfo.c
index b24b6ff..7c2b402 100644
--- a/gio/gosxappinfo.c
+++ b/gio/gosxappinfo.c
@@ -175,14 +175,44 @@ static gchar *
 create_cstr_from_cfstring (CFStringRef str)
 {
   const gchar *cstr;
+  CFIndex length = CFStringGetLength (str);
+  char *buffer = NULL;
 
   if (str == NULL)
     return NULL;
 
   cstr = CFStringGetCStringPtr (str, kCFStringEncodingUTF8);
+  /* CFStringGetCStringPtr returns "NULL if the internal storage of
+   * theString does not allow [a pointer] to be returned efficiently".
+   * (Apple's docs don't say what that means). In that case we must
+   * use CFStringGetCString as a fallback.
+   */
+  if (cstr != NULL)
+    {
+        CFRelease (str);
+        return g_strdup (cstr);
+    }
+  
+  buffer = g_malloc0 (length + 1);
+  /* Start off with a buffer size sufficient for the most likely case
+   * that the CFString is ASCII so the UTF8 representation will be 1
+   * byte per code point. Keep trying up to 4 bytes per code point,
+   * the max allowed by RFC3629.
+   */
+  for (int i = 1; i <= 4; ++i)
+    {
+      if (CFStringGetCString (str, buffer, length, kCFStringEncodingUTF8))
+      {
+        CFRelease (str);
+        return buffer;
+      }
+      length += length;
+      buffer = g_realloc (buffer, length + 1);
+    }
+  
+  g_free (buffer);
   CFRelease (str);
-
-  return g_strdup (cstr);
+  return NULL;
 }
 
 static char *
diff --git a/gio/gosxcontenttype.c b/gio/gosxcontenttype.c
index 485f5bf..c046d9e 100644
--- a/gio/gosxcontenttype.c
+++ b/gio/gosxcontenttype.c
@@ -53,14 +53,44 @@ static gchar *
 create_cstr_from_cfstring (CFStringRef str)
 {
   const gchar *cstr;
+  CFIndex length = CFStringGetLength (str);
+  char *buffer = NULL;
 
   if (str == NULL)
     return NULL;
 
   cstr = CFStringGetCStringPtr (str, kCFStringEncodingUTF8);
+  /* CFStringGetCStringPtr returns "NULL if the internal storage of
+   * theString does not allow [a pointer] to be returned efficiently".
+   * (Apple's docs don't say what that means). In that case we must
+   * use CFStringGetCString as a fallback.
+   */
+  if (cstr != NULL)
+    {
+        CFRelease (str);
+        return g_strdup (cstr);
+    }
+  
+  buffer = g_malloc0 (length + 1);
+  /* Start off with a buffer size sufficient for the most likely case
+   * that the CFString is ASCII so the UTF8 representation will be 1
+   * byte per code point. Keep trying up to 4 bytes per code point,
+   * the max allowed by RFC3629.
+   */
+  for (int i = 1; i <= 4; ++i)
+    {
+      if (CFStringGetCString (str, buffer, length, kCFStringEncodingUTF8))
+        {
+          CFRelease (str);
+          return buffer;
+        }
+      length += length;
+      buffer = g_realloc (buffer, length + 1);
+    }
+  
+  g_free (buffer);
   CFRelease (str);
-
-  return g_strdup (cstr);
+  return NULL;
 }
 
 /*< internal >


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