]> git.eshelyaron.com Git - emacs.git/commitdiff
Allow creating unibyte strings from Emacs modules
authorLars Ingebrigtsen <larsi@gnus.org>
Tue, 13 Oct 2020 04:51:06 +0000 (06:51 +0200)
committerLars Ingebrigtsen <larsi@gnus.org>
Tue, 13 Oct 2020 04:51:06 +0000 (06:51 +0200)
* doc/lispref/internals.texi (Module Values): Document
make_unibyte_string (bug#34873).

* src/emacs-module.c (module_make_unibyte_string): New function.
(initialize_environment): Export it.

* src/module-env-25.h: Define it.

* test/data/emacs-module/mod-test.c (Fmod_test_return_unibyte):
Test it.

* test/src/emacs-module-tests.el (module/unibyte): Test it.

doc/lispref/internals.texi
src/emacs-module.c
src/module-env-25.h
test/data/emacs-module/mod-test.c
test/src/emacs-module-tests.el

index fed9612e3295520194ee940581d383e044f4101b..bb25983aa4b7b457d550cffc7dd35f1e3bf4621b 100644 (file)
@@ -1854,6 +1854,12 @@ raises the @code{overflow-error} error condition if @var{len} is
 negative or exceeds the maximum length of an Emacs string.
 @end deftypefn
 
+@deftypefn Function emacs_value make_unibyte_string (emacs_env *@var{env}, const char *@var{str}, ptrdiff_t @var{len})
+This function is like @code{make_string}, but has no restrictions on
+the values of the bytes in the C string, and can be used to pass
+binary data to Emacs in the form of a unibyte string.
+@end deftypefn
+
 The @acronym{API} does not provide functions to manipulate Lisp data
 structures, for example, create lists with @code{cons} and @code{list}
 (@pxref{Building Lists}), extract list members with @code{car} and
index 3581daad1129f1fdccbfe8b87cf5dd1f250b3a75..ba9de58de54d6f3a0882da6c2bb680ba4c9805b5 100644 (file)
@@ -790,6 +790,18 @@ module_make_string (emacs_env *env, const char *str, ptrdiff_t len)
   return lisp_to_value (env, lstr);
 }
 
+static emacs_value
+module_make_unibyte_string (emacs_env *env, const char *str, ptrdiff_t length)
+{
+  MODULE_FUNCTION_BEGIN (NULL);
+  if (! (0 <= length && length <= STRING_BYTES_BOUND))
+    overflow_error ();
+  Lisp_Object lstr = make_uninit_string (length);
+  memcpy (SDATA (lstr), str, length);
+  SDATA (lstr)[length] = 0;
+  return lisp_to_value (env, lstr);
+}
+
 static emacs_value
 module_make_user_ptr (emacs_env *env, emacs_finalizer fin, void *ptr)
 {
@@ -1464,6 +1476,7 @@ initialize_environment (emacs_env *env, struct emacs_env_private *priv)
   env->make_float = module_make_float;
   env->copy_string_contents = module_copy_string_contents;
   env->make_string = module_make_string;
+  env->make_unibyte_string = module_make_unibyte_string;
   env->make_user_ptr = module_make_user_ptr;
   env->get_user_ptr = module_get_user_ptr;
   env->set_user_ptr = module_set_user_ptr;
index 97c7787da343d13352ef9ddba04cf57dc05cc773..01c06d5400d764b810cc4cbc1f7e760252787f28 100644 (file)
                              const char *str, ptrdiff_t len)
     EMACS_ATTRIBUTE_NONNULL(1, 2);
 
+  /* Create a unibyte Lisp string from a string.  */
+  emacs_value (*make_unibyte_string) (emacs_env *env,
+                                     const char *str, ptrdiff_t len)
+    EMACS_ATTRIBUTE_NONNULL(1, 2);
+
   /* Embedded pointer type.  */
   emacs_value (*make_user_ptr) (emacs_env *env,
                                void (*fin) (void *) EMACS_NOEXCEPT,
index da298d4e3984e6c4509d9685b959a826d859b31e..258a679b207086a6c58b548feb0ccad083b28ed3 100644 (file)
@@ -268,6 +268,16 @@ Fmod_test_string_a_to_b (emacs_env *env, ptrdiff_t nargs, emacs_value args[],
 }
 
 
+/* Return a unibyte string.  */
+static emacs_value
+Fmod_test_return_unibyte (emacs_env *env, ptrdiff_t nargs, emacs_value args[],
+                         void *data)
+{
+  const char *string = "foo\x00zot";
+  return env->make_unibyte_string (env, string, 7);
+}
+
+
 /* Embedded pointers in lisp objects.  */
 
 /* C struct (pointer to) that will be embedded.  */
@@ -750,6 +760,7 @@ emacs_module_init (struct emacs_runtime *ert)
   DEFUN ("mod-test-globref-reordered", Fmod_test_globref_reordered, 0, 0, NULL,
          NULL);
   DEFUN ("mod-test-string-a-to-b", Fmod_test_string_a_to_b, 1, 1, NULL, NULL);
+  DEFUN ("mod-test-return-unibyte", Fmod_test_return_unibyte, 0, 0, NULL, NULL);
   DEFUN ("mod-test-userptr-make", Fmod_test_userptr_make, 1, 1, NULL, NULL);
   DEFUN ("mod-test-userptr-get", Fmod_test_userptr_get, 1, 1, NULL, NULL);
   DEFUN ("mod-test-vector-fill", Fmod_test_vector_fill, 2, 2, NULL, NULL);
index 1eebb418cf3c85ea04f6fac28d9a960c82887c22..621229c62aa9c7ea962d66bd5e8fa5e649f8b0a5 100644 (file)
@@ -500,4 +500,10 @@ See Bug#36226."
   (should (eq (mod-test-identity 123) 123))
   (should-not (call-interactively #'mod-test-identity)))
 
+(ert-deftest module/unibyte ()
+  (let ((result (mod-test-return-unibyte)))
+    (should (stringp result))
+    (should (not (multibyte-string-p (mod-test-return-unibyte))))
+    (should (equal result "foo\x00zot"))))
+
 ;;; emacs-module-tests.el ends here