]> git.eshelyaron.com Git - emacs.git/commitdiff
Optimize creation of multibyte menu items on Android
authorPo Lu <luangruo@yahoo.com>
Fri, 4 Aug 2023 06:29:55 +0000 (14:29 +0800)
committerPo Lu <luangruo@yahoo.com>
Fri, 4 Aug 2023 06:29:55 +0000 (14:29 +0800)
* src/androidvfs.c (android_verify_jni_string): Move to
android.c.
* src/android.c (android_verify_jni_string): New function.
(android_build_string): Forgo encoding menu text if TEXT is a
multibyte string that's also a valid JNI string.
* src/android.h: Update prototypes.

src/android.c
src/android.h
src/androidvfs.c

index c30d7b58979c66493c9a950c20d5c25b075e30d4..bd19107f53a1cf5f1df00e9901cdccd3d08d7664 100644 (file)
@@ -5480,6 +5480,69 @@ android_check_string (Lisp_Object text)
   return true;
 }
 
+/* Verify that the specified NULL-terminated STRING is a valid JNI
+   ``UTF-8'' string.  Return 0 if so, 1 otherwise.
+
+   Do not perform GC, enabling NAME to be a direct reference to string
+   data.
+
+   The native coding system used by the JVM to store strings derives
+   from UTF-8, but deviates from it in two aspects in an attempt to
+   better represent the UCS-16 based Java String format, and to let
+   strings contain NULL characters while remaining valid C strings:
+   NULL bytes are encoded as two-byte sequences, and Unicode surrogate
+   pairs encoded as two-byte sequences are prefered to four-byte
+   sequences when encoding characters above the BMP.  */
+
+int
+android_verify_jni_string (const char *name)
+{
+  const unsigned char *chars;
+
+  chars = (unsigned char *) name;
+  while (*chars)
+    {
+      /* Switch on the high 4 bits.  */
+
+      switch (*chars++ >> 4)
+       {
+       case 0 ... 7:
+         /* The 8th bit is clean, so this is a regular C
+            character.  */
+         break;
+
+       case 8 ... 0xb:
+         /* Invalid starting byte! */
+         return 1;
+
+       case 0xf:
+         /* The start of a four byte sequence.  These aren't allowed
+            in Java.  */
+         return 1;
+
+       case 0xe:
+         /* The start of a three byte sequence.  Verify that its
+            continued.  */
+
+         if ((*chars++ & 0xc0) != 0x80)
+           return 1;
+
+         FALLTHROUGH;
+
+       case 0xc ... 0xd:
+         /* The start of a two byte sequence.  Verify that the
+            next byte exists and has its high bit set.  */
+
+         if ((*chars++ & 0xc0) != 0x80)
+           return 1;
+
+         break;
+       }
+    }
+
+  return 0;
+}
+
 /* Given a Lisp string TEXT, return a local reference to an equivalent
    Java string.  */
 
@@ -5492,12 +5555,18 @@ android_build_string (Lisp_Object text)
   jchar *characters;
   USE_SAFE_ALLOCA;
 
-  /* Directly encode TEXT if it contains no multibyte
-     characters.  This is okay because the Java extended UTF
-     format is compatible with ASCII.  */
-
-  if (SBYTES (text) == SCHARS (text)
-      && android_check_string (text))
+  /* Directly encode TEXT if it contains no non-ASCII characters, or
+     is multibyte and a valid Modified UTF-8 string.  This is okay
+     because the Java extended UTF format is compatible with
+     ASCII.  */
+
+  if ((SBYTES (text) == SCHARS (text)
+       && android_check_string (text))
+      /* If TEXT is a multibyte string, then it's using Emacs's
+        internal UTF-8 coding system, a significant subset of which
+        is compatible with JNI.  */
+      || (STRING_MULTIBYTE (text)
+         && !android_verify_jni_string (SSDATA (text))))
     {
       string = (*android_java_env)->NewStringUTF (android_java_env,
                                                  SSDATA (text));
index cecdfab002f0654ae42014579839a4e0eb42bdd6..a052d3a3b21d38bf457854212aac971311cf4c7d 100644 (file)
@@ -105,6 +105,7 @@ extern bool android_detect_mouse (void);
 extern void android_set_dont_focus_on_map (android_window, bool);
 extern void android_set_dont_accept_focus (android_window, bool);
 
+extern int android_verify_jni_string (const char *);
 extern jstring android_build_string (Lisp_Object);
 extern jstring android_build_jstring (const char *);
 extern void android_exception_check (void);
index 2b467bc444f3fb1db693ca9557d7ce9ef0252b88..0d99116c75c119e4ca13a89fb2c945de51f3100d 100644 (file)
@@ -3299,9 +3299,6 @@ static struct android_saf_root_vdir *all_saf_root_vdirs;
 static struct android_vnode *android_saf_tree_from_name (char *, const char *,
                                                         const char *);
 
-/* Forward declaration.  */
-static int android_verify_jni_string (const char *);
-
 /* Ascertain and return whether or not AUTHORITY designates a content
    provider offering at least one directory tree accessible to
    Emacs.  */
@@ -4437,66 +4434,6 @@ static struct android_vops saf_new_vfs_ops;
 /* Chain of all open SAF directory streams.  */
 static struct android_saf_tree_vdir *all_saf_tree_vdirs;
 
-/* Verify that the specified NULL-terminated STRING is a valid JNI
-   ``UTF-8'' string.  Return 0 if so, 1 otherwise.
-
-   The native coding system used by the JVM to store strings derives
-   from UTF-8, but deviates from it in two aspects in an attempt to
-   better represent the UCS-16 based Java String format, and to let
-   strings contain NULL characters while remaining valid C strings:
-   NULL bytes are encoded as two-byte sequences, and Unicode surrogate
-   pairs encoded as two-byte sequences are prefered to four-byte
-   sequences when encoding characters above the BMP.  */
-
-static int
-android_verify_jni_string (const char *name)
-{
-  const unsigned char *chars;
-
-  chars = (unsigned char *) name;
-  while (*chars)
-    {
-      /* Switch on the high 4 bits.  */
-
-      switch (*chars++ >> 4)
-       {
-       case 0 ... 7:
-         /* The 8th bit is clean, so this is a regular C
-            character.  */
-         break;
-
-       case 8 ... 0xb:
-         /* Invalid starting byte! */
-         return 1;
-
-       case 0xf:
-         /* The start of a four byte sequence.  These aren't allowed
-            in Java.  */
-         return 1;
-
-       case 0xe:
-         /* The start of a three byte sequence.  Verify that its
-            continued.  */
-
-         if ((*chars++ & 0xc0) != 0x80)
-           return 1;
-
-         FALLTHROUGH;
-
-       case 0xc ... 0xd:
-         /* The start of a two byte sequence.  Verify that the
-            next byte exists and has its high bit set.  */
-
-         if ((*chars++ & 0xc0) != 0x80)
-           return 1;
-
-         break;
-       }
-    }
-
-  return 0;
-}
-
 /* Find the document ID of the file within TREE_URI designated by
    NAME.