From e5186dace2ce5c13c2a178b67507a3f917f4ed25 Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Thu, 4 May 2017 20:40:55 -0700 Subject: ffi: new bstr type. The bstr type is like str, but doesn't perform UTF-8 conversion. The C data is assumed to be null terminated byte strings representing code points U+0000 through U+00FF. * ffi.c (bstr_s, bstr_d_s): New symbol variables. (ffi_bstr_put, ffi_bstr_get, ffi_bstr_d_get): New static functions. (ffi_init_types): Register bstr and bstr-d types. (ffi_init): Initialize bstr_s and bstr_d_s. * ffi.h (bstr_s, bstr_d_s): Declared. * lib.c (chk_strdup_8bit, string_8bit): New function. * lib.h (chk_strdup_8bit, string_8bit): Declared. --- ffi.c | 36 +++++++++++++++++++++++++++++++++++- ffi.h | 2 +- lib.c | 24 ++++++++++++++++++++++++ lib.h | 2 ++ 4 files changed, 62 insertions(+), 2 deletions(-) diff --git a/ffi.c b/ffi.c index 7d51327a..8b3f30db 100644 --- a/ffi.c +++ b/ffi.c @@ -73,7 +73,7 @@ val array_s, zarray_s; val struct_s; -val str_d_s, wstr_s, wstr_d_s; +val str_d_s, wstr_s, wstr_d_s, bstr_s, bstr_d_s; val buf_d_s; @@ -622,6 +622,32 @@ static val ffi_wstr_d_get(struct txr_ffi_type *tft, mem_t *src, val self) return p ? string_own(p) : nil; } +static void ffi_bstr_put(struct txr_ffi_type *tft, val s, mem_t *dst, + val self) +{ + if (s == nil) { + *coerce(unsigned char **, dst) = 0; + } else { + const wchar_t *ws = c_str(s); + unsigned char *u8s = chk_strdup_8bit(ws); + *coerce(unsigned char **, dst) = u8s; + } +} + +static val ffi_bstr_get(struct txr_ffi_type *tft, mem_t *src, val self) +{ + unsigned char *p = *coerce(unsigned char **, src); + return p ? string_8bit(p) : nil; +} + +static val ffi_bstr_d_get(struct txr_ffi_type *tft, mem_t *src, val self) +{ + unsigned char *p = *coerce(unsigned char **, src); + val ret = p ? string_8bit(p) : nil; + free(p); + return ret; +} + static void ffi_buf_put(struct txr_ffi_type *tft, val buf, mem_t *dst, val self) { @@ -1442,6 +1468,12 @@ static void ffi_init_types(void) ffi_typedef(wstr_d_s, make_ffi_type_builtin(wstr_d_s, str_s, sizeof (mem_t *), &ffi_type_pointer, ffi_wstr_d_put, ffi_wstr_d_get)); + ffi_typedef(bstr_s, make_ffi_type_builtin(bstr_s, str_s, + sizeof (mem_t *), &ffi_type_pointer, + ffi_bstr_put, ffi_bstr_get)); + ffi_typedef(bstr_d_s, make_ffi_type_builtin(bstr_d_s, str_s, + sizeof (mem_t *), &ffi_type_pointer, + ffi_bstr_put, ffi_bstr_d_get)); { val iter; @@ -1802,6 +1834,8 @@ void ffi_init(void) str_d_s = intern(lit("str-d"), user_package); wstr_s = intern(lit("wstr"), user_package); wstr_d_s = intern(lit("wstr-d"), user_package); + bstr_s = intern(lit("bstr"), user_package); + bstr_d_s = intern(lit("bstr-d"), user_package); buf_d_s = intern(lit("buf-d"), user_package); ptr_in_s = intern(lit("ptr-in"), user_package); ptr_out_s = intern(lit("ptr-out"), user_package); diff --git a/ffi.h b/ffi.h index 3f9f421d..c598044f 100644 --- a/ffi.h +++ b/ffi.h @@ -41,7 +41,7 @@ extern val array_s, zarray_s; extern val struct_s; -extern val str_d_s, wstr_s, wstr_d_s; +extern val str_d_s, wstr_s, wstr_d_s, bstr_s, bstr_d_s; extern val buf_d_s; diff --git a/lib.c b/lib.c index a38ac973..86485e3c 100644 --- a/lib.c +++ b/lib.c @@ -2673,6 +2673,21 @@ char *chk_strdup_utf8(const char *str) return copy; } +unsigned char *chk_strdup_8bit(const wchar_t *str) +{ + size_t nchar = wcslen(str) + 1, i; + unsigned char *copy = coerce(unsigned char *, chk_malloc(nchar)); + for (i = 0; i < nchar; i++) { + if (str[i] < 0 || str[i] > 255) { + free(copy); + uw_throwf(error_s, lit("cannot coerce ~s to 8 bit"), + string(str), nao); + } + copy[i] = str[i]; + } + return copy; +} + mem_t *chk_copy_obj(mem_t *orig, size_t size) { mem_t *copy = chk_malloc(size); @@ -3276,6 +3291,15 @@ val string_utf8(const char *str) return obj; } +val string_8bit(const unsigned char *str) +{ + size_t l = strlen(coerce(const char *, str)), i; + wchar_t *wstr = chk_wmalloc(l + 1); + for (i = 0; i <= l; i++) + wstr[i] = str[i]; + return string_own(wstr); +} + val mkstring(val len, val ch) { size_t l = c_num(len); diff --git a/lib.h b/lib.h index 5c74abf5..4875ef2a 100644 --- a/lib.h +++ b/lib.h @@ -605,6 +605,7 @@ mem_t *chk_manage_vec(mem_t *old, size_t oldfilled, size_t newfilled, wchar_t *chk_wmalloc(size_t nwchar); wchar_t *chk_strdup(const wchar_t *str); char *chk_strdup_utf8(const char *str); +unsigned char *chk_strdup_8bit(const wchar_t *str); mem_t *chk_copy_obj(mem_t *orig, size_t size); val cons(val car, val cdr); val make_lazy_cons(val func); @@ -724,6 +725,7 @@ val maskv(struct args *bits); val string_own(wchar_t *str); val string(const wchar_t *str); val string_utf8(const char *str); +val string_8bit(const unsigned char *str); val mkstring(val len, val ch); val mkustring(val len); /* must initialize immediately with init_str! */ val init_str(val str, const wchar_t *); -- cgit v1.2.3