[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH] Add a mechanism for passing unibyte strings from lisp to modules
From: |
Brennan Vincent |
Subject: |
[PATCH] Add a mechanism for passing unibyte strings from lisp to modules. |
Date: |
Fri, 21 Jun 2024 14:13:15 -0400 |
From: Brennan Vincent <brennan@umanwizard.com>
* src/data.c
(unibyte-string-p): New function.
* src/emacs-module.c
(module_copy_unibyte_string_contents): New function.
* src/module-env-30.h: Expose the above to modules.
* doc/lispref/internals.texi: Document the above.
---
doc/lispref/internals.texi | 28 ++++++++++++++++++++++++++++
src/data.c | 13 +++++++++++++
src/emacs-module.c | 37 +++++++++++++++++++++++++++++++++++++
src/module-env-30.h | 18 ++++++++++++++++++
4 files changed, 96 insertions(+)
diff --git a/doc/lispref/internals.texi b/doc/lispref/internals.texi
index a5480a9bf8a..282ee5e1746 100644
--- a/doc/lispref/internals.texi
+++ b/doc/lispref/internals.texi
@@ -1725,6 +1725,34 @@ Module Values
the text copying.
@end deftypefn
+@deftypefn Function bool copy_unibyte_string_contents (emacs_env *@var{env},
emacs_value @var{arg}, char *@var{buf}, ptrdiff_t *@var{len})
+This function stores the raw bytes of a unibyte Lisp string specified
+by @var{arg} in the array of @code{char} pointed by @var{buf}, which
+should have enough space to hold at least @code{*@var{len}} bytes,
+including the terminating null byte. The argument @var{len} must not
+be a @code{NULL} pointer, and, when the function is called, it should
+point to a value that specifies the size of @var{buf} in bytes.
+
+If the buffer size specified by @code{*@var{len}} is large enough to
+hold the string's bytes, the function stores in @code{*@var{len}} the
+actual number of bytes copied to @var{buf}, including the terminating
+null byte, and returns @code{true}. If the buffer is too small, the
+function raises the @code{args-out-of-range} error condition, stores
+the required number of bytes in @code{*@var{len}}, and returns
+@code{false}. @xref{Module Nonlocal}, for how to handle pending error
+conditions.
+
+The argument @var{buf} can be a @code{NULL} pointer, in which case the
+function stores in @code{*@var{len}} the number of bytes required for
+storing the contents of @var{arg}, and returns @code{true}. This is
+how you can determine the size of @var{buf} needed to store a
+particular string: first call @code{copy_unibyte_string_contents} with
+@code{NULL} as @var{buf}, then allocate enough memory to hold the
+number of bytes stored by the function in @code{*@var{len}}, and call
+the function again with non-@code{NULL} @var{buf} to actually perform
+the text copying.
+@end deftypefn
+
@deftypefn Function emacs_value vec_get (emacs_env *@var{env}, emacs_value
@var{vector}, ptrdiff_t @var{index})
This function returns the element of @var{vector} at @var{index}. The
@var{index} of the first vector element is zero. The function raises
diff --git a/src/data.c b/src/data.c
index 3490d4985c9..7d8d5a46779 100644
--- a/src/data.c
+++ b/src/data.c
@@ -429,6 +429,17 @@ DEFUN ("multibyte-string-p", Fmultibyte_string_p,
Smultibyte_string_p,
return Qnil;
}
+DEFUN("unibyte-string-p", Funibyte_string_p, Sunibyte_string_p,
+ 1, 1, 0,
+ doc: /* Return t if OBJECT is a unibyte string.
+Return nil if OBJECT is either a multibyte string, or not a string. */)
+ (Lisp_Object object)
+{
+ if (STRINGP (object) && !STRING_MULTIBYTE (object))
+ return Qt;
+ return Qnil;
+}
+
DEFUN ("char-table-p", Fchar_table_p, Schar_table_p, 1, 1, 0,
doc: /* Return t if OBJECT is a char-table. */)
(Lisp_Object object)
@@ -4023,6 +4034,7 @@ syms_of_data (void)
DEFSYM (Qnatnump, "natnump");
DEFSYM (Qwholenump, "wholenump");
DEFSYM (Qstringp, "stringp");
+ DEFSYM (Qunibyte_string_p, "unibyte-string-p");
DEFSYM (Qarrayp, "arrayp");
DEFSYM (Qsequencep, "sequencep");
DEFSYM (Qbufferp, "bufferp");
@@ -4219,6 +4231,7 @@ #define PUT_ERROR(sym, tail, msg) \
defsubr (&Skeywordp);
defsubr (&Sstringp);
defsubr (&Smultibyte_string_p);
+ defsubr (&Sunibyte_string_p);
defsubr (&Svectorp);
defsubr (&Srecordp);
defsubr (&Schar_table_p);
diff --git a/src/emacs-module.c b/src/emacs-module.c
index 08db39b0b0d..69192cd7fd2 100644
--- a/src/emacs-module.c
+++ b/src/emacs-module.c
@@ -769,6 +769,42 @@ module_make_float (emacs_env *env, double d)
return value;
}
+static bool
+module_copy_unibyte_string_contents (emacs_env *env, emacs_value value, char
*buf,
+ ptrdiff_t *len)
+{
+ MODULE_FUNCTION_BEGIN (false);
+ Lisp_Object lisp_str = value_to_lisp (value);
+ CHECK_TYPE (STRINGP (lisp_str) && !STRING_MULTIBYTE (lisp_str),
+ Qunibyte_string_p, lisp_str);
+
+ ptrdiff_t raw_size = SBYTES (lisp_str);
+ ptrdiff_t required_buf_size = raw_size + 1;
+
+ if (buf == NULL)
+ {
+ *len = required_buf_size;
+ MODULE_INTERNAL_CLEANUP();
+ return true;
+ }
+
+ if (*len < required_buf_size)
+ {
+ ptrdiff_t actual = *len;
+ *len = required_buf_size;
+ args_out_of_range_3 (INT_TO_INTEGER (actual),
+ INT_TO_INTEGER (required_buf_size),
+ INT_TO_INTEGER (PTRDIFF_MAX));
+ }
+
+ *len = required_buf_size;
+ memcpy(buf, SDATA (lisp_str), required_buf_size);
+
+ MODULE_INTERNAL_CLEANUP();
+ return true;
+}
+
+
static bool
module_copy_string_contents (emacs_env *env, emacs_value value, char *buf,
ptrdiff_t *len)
@@ -1568,6 +1604,7 @@ initialize_environment (emacs_env *env, struct
emacs_env_private *priv)
env->extract_float = module_extract_float;
env->make_float = module_make_float;
env->copy_string_contents = module_copy_string_contents;
+ env->copy_unibyte_string_contents = module_copy_unibyte_string_contents;
env->make_string = module_make_string;
env->make_unibyte_string = module_make_unibyte_string;
env->make_user_ptr = module_make_user_ptr;
diff --git a/src/module-env-30.h b/src/module-env-30.h
index e75210c7f8e..5837bfbf195 100644
--- a/src/module-env-30.h
+++ b/src/module-env-30.h
@@ -1,3 +1,21 @@
/* Add module environment functions newly added in Emacs 30 here.
Before Emacs 30 is released, remove this comment and start
module-env-31.h on the master branch. */
+
+ /* Copy the content of the Lisp string VALUE to BUFFER as an utf8
+ null-terminated string.
+
+ SIZE must point to the total size of the buffer. If BUFFER is
+ NULL or if SIZE is not big enough, write the required buffer size
+ to SIZE and return true.
+
+ Note that SIZE must include the last null byte (e.g. "abc" needs
+ a buffer of size 4).
+
+ Return true if the string was successfully copied. */
+
+ bool (*copy_unibyte_string_contents) (emacs_env *env,
+ emacs_value value,
+ char *buf,
+ ptrdiff_t *len)
+ EMACS_ATTRIBUTE_NONNULL(1, 4);
--
2.41.0
- [PATCH] Add a mechanism for passing unibyte strings from lisp to modules., Brennan Vincent, 2024/06/21
- [PATCH] Add a mechanism for passing unibyte strings from lisp to modules.,
Brennan Vincent <=
- Re: [PATCH] Add a mechanism for passing unibyte strings from lisp to modules., Eli Zaretskii, 2024/06/21
- Re: [PATCH] Add a mechanism for passing unibyte strings from lisp to modules., Brennan Vincent, 2024/06/21
- Re: [PATCH] Add a mechanism for passing unibyte strings from lisp to modules., Eli Zaretskii, 2024/06/22
- Message not available
- Re: [PATCH] Add a mechanism for passing unibyte strings from lisp to modules., Eli Zaretskii, 2024/06/22
- Re: [PATCH] Add a mechanism for passing unibyte strings from lisp to modules., Andrea Corallo, 2024/06/23
- Re: [PATCH] Add a mechanism for passing unibyte strings from lisp to modules., Eli Zaretskii, 2024/06/24
- Re: [PATCH] Add a mechanism for passing unibyte strings from lisp to modules., Brennan Vincent, 2024/06/25
- Re: [PATCH] Add a mechanism for passing unibyte strings from lisp to modules., Eli Zaretskii, 2024/06/26
- Re: [PATCH] Add a mechanism for passing unibyte strings from lisp to modules., tomas, 2024/06/26
- Re: [PATCH] Add a mechanism for passing unibyte strings from lisp to modules., Eli Zaretskii, 2024/06/26