summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2017-05-11 06:26:18 -0700
committerKaz Kylheku <kaz@kylheku.com>2017-05-11 06:26:18 -0700
commitf226f44490a31e88017b2c3e2032d6926ef1c336 (patch)
treea13c80ccf3354c03bbeeef29457e74a4e1990567
parent39413e2d3568c3d18976d9b1c55af55af7905e4e (diff)
downloadtxr-f226f44490a31e88017b2c3e2032d6926ef1c336.tar.gz
txr-f226f44490a31e88017b2c3e2032d6926ef1c336.tar.bz2
txr-f226f44490a31e88017b2c3e2032d6926ef1c336.zip
ffi: encode-side character array specializations.
If the object being encoded is a string, and the array element type is char, wchar or bchar, then encode a string, honoring null termination flag. Unused space in the destination array is filled with zeros. * ffi.c (ffi_char_array_put, ffi_wchar_array_put, ffi_bchar_array_put): New functions. (ffi_array_put, ffi_array_out): Use new functions under the right conditions.
-rw-r--r--ffi.c67
1 files changed, 65 insertions, 2 deletions
diff --git a/ffi.c b/ffi.c
index fcf74f9e..dae84c3d 100644
--- a/ffi.c
+++ b/ffi.c
@@ -1012,6 +1012,24 @@ static val ffi_char_array_get(struct txr_ffi_type *tft, mem_t *src,
}
}
+static void ffi_char_array_put(struct txr_ffi_type *tft, val str, mem_t *dst,
+ cnum nelem)
+{
+ int nt = tft->null_term;
+ const wchar_t *wstr = c_str(str);
+ size_t needed = utf8_to_buf(0, wstr, nt);
+
+ if (needed <= nelem) {
+ utf8_to_buf(dst, wstr, nt);
+ memset(dst + needed, 0, nelem - needed);
+ } else {
+ char *u8str = utf8_dup_to(wstr);
+ memcpy(dst, u8str, nelem);
+ dst[nelem - 1] = 0;
+ free(u8str);
+ }
+}
+
static val ffi_wchar_array_get(struct txr_ffi_type *tft, mem_t *src,
cnum nelem)
{
@@ -1029,6 +1047,15 @@ static val ffi_wchar_array_get(struct txr_ffi_type *tft, mem_t *src,
}
}
+static void ffi_wchar_array_put(struct txr_ffi_type *tft, val str, mem_t *dst,
+ cnum nelem)
+{
+ const wchar_t *wstr = c_str(str);
+ wcsncpy(coerce(wchar_t *, dst), wstr, nelem);
+ if (tft->null_term)
+ dst[nelem - 1] = 0;
+}
+
static val ffi_bchar_array_get(struct txr_ffi_type *tft, mem_t *src,
cnum nelem)
{
@@ -1043,6 +1070,28 @@ static val ffi_bchar_array_get(struct txr_ffi_type *tft, mem_t *src,
}
}
+static void ffi_bchar_array_put(struct txr_ffi_type *tft, val str, mem_t *dst,
+ cnum nelem, val self)
+{
+ const wchar_t *wstr = c_str(str);
+ cnum i;
+
+ for (i = 0; i < nelem && wstr[i]; i++) {
+ wchar_t wch = wstr[i];
+ if (wch < 0 || wch > 255)
+ uw_throwf(error_s, lit("~a: character ~s out of unsigned 8 bit range"),
+ self, chr(wch), nao);
+ dst[i] = wch;
+ }
+
+ if (i < nelem) {
+ for (; i < nelem; i++)
+ dst[i] = 0;
+ } else if (tft->null_term) {
+ dst[nelem - 1] = 0;
+ }
+}
+
static val ffi_array_in_common(struct txr_ffi_type *tft, int copy,
mem_t *src, val vec, val self, cnum nelem)
{
@@ -1112,7 +1161,14 @@ static void ffi_array_put_common(struct txr_ffi_type *tft, val vec, mem_t *dst,
static void ffi_array_put(struct txr_ffi_type *tft, val vec, mem_t *dst,
val self)
{
- ffi_array_put_common(tft, vec, dst, self, tft->nelem);
+ if (tft->char_conv && stringp(vec))
+ ffi_char_array_put(tft, vec, dst, tft->nelem);
+ else if (tft->wchar_conv && stringp(vec))
+ ffi_wchar_array_put(tft, vec, dst, tft->nelem);
+ else if (tft->bchar_conv && stringp(vec))
+ ffi_bchar_array_put(tft, vec, dst, tft->nelem, self);
+ else
+ ffi_array_put_common(tft, vec, dst, self, tft->nelem);
}
static void ffi_array_out_common(struct txr_ffi_type *tft, int copy, val vec,
@@ -1144,7 +1200,14 @@ static void ffi_array_out_common(struct txr_ffi_type *tft, int copy, val vec,
static void ffi_array_out(struct txr_ffi_type *tft, int copy, val vec,
mem_t *dst, val self)
{
- ffi_array_out_common(tft, copy, vec, dst, self, tft->nelem);
+ if (tft->char_conv && stringp(vec))
+ ffi_char_array_put(tft, vec, dst, tft->nelem);
+ else if (tft->wchar_conv && stringp(vec))
+ ffi_wchar_array_put(tft, vec, dst, tft->nelem);
+ else if (tft->bchar_conv && stringp(vec))
+ ffi_bchar_array_put(tft, vec, dst, tft->nelem, self);
+ else
+ ffi_array_out_common(tft, copy, vec, dst, self, tft->nelem);
}
static val ffi_array_get_common(struct txr_ffi_type *tft, mem_t *src, val self,