diff options
author | Björn Gustavsson <[email protected]> | 2017-02-01 12:44:04 +0100 |
---|---|---|
committer | Björn Gustavsson <[email protected]> | 2017-02-01 12:44:04 +0100 |
commit | 4c8881fdf397757ee7bdbebf6aa9d0c01d5066ab (patch) | |
tree | 5a9cb98eda8f106a31d8f7bc9c5193c9b7d9529d /erts/emulator/beam/utils.c | |
parent | 3d81b5c93865c621372330ffb826eba157c8d0f7 (diff) | |
parent | 26b59dfe67ef551cd94765557cdd8c79794bcc38 (diff) | |
download | otp-4c8881fdf397757ee7bdbebf6aa9d0c01d5066ab.tar.gz otp-4c8881fdf397757ee7bdbebf6aa9d0c01d5066ab.tar.bz2 otp-4c8881fdf397757ee7bdbebf6aa9d0c01d5066ab.zip |
Merge branch 'josevalim/atu8-chunk/PR-1078/OTP-14178'
* josevalim/atu8-chunk/PR-1078/OTP-14178:
Add new AtU8 beam chunk
Diffstat (limited to 'erts/emulator/beam/utils.c')
-rw-r--r-- | erts/emulator/beam/utils.c | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/erts/emulator/beam/utils.c b/erts/emulator/beam/utils.c index 74a0681dd5..323f61c9f3 100644 --- a/erts/emulator/beam/utils.c +++ b/erts/emulator/beam/utils.c @@ -3671,6 +3671,68 @@ intlist_to_buf(Eterm list, char *buf, Sint len) return -2; /* not enough space */ } +/* Fill buf with the contents of the unicode list. + * Return the number of bytes in the buffer, + * or -1 for type error, + * or -2 for not enough buffer space (buffer contains truncated result). + */ +Sint +erts_unicode_list_to_buf(Eterm list, byte *buf, Sint len) +{ + Eterm* listptr; + Sint sz = 0; + + if (is_nil(list)) { + return 0; + } + if (is_not_list(list)) { + return -1; + } + listptr = list_val(list); + + while (len-- > 0) { + Sint val; + + if (is_not_small(CAR(listptr))) { + return -1; + } + val = signed_val(CAR(listptr)); + if (0 <= val && val < 0x80) { + buf[sz] = val; + sz++; + } else if (val < 0x800) { + buf[sz+0] = 0xC0 | (val >> 6); + buf[sz+1] = 0x80 | (val & 0x3F); + sz += 2; + } else if (val < 0x10000UL) { + if (0xD800 <= val && val <= 0xDFFF) { + return -1; + } + buf[sz+0] = 0xE0 | (val >> 12); + buf[sz+1] = 0x80 | ((val >> 6) & 0x3F); + buf[sz+2] = 0x80 | (val & 0x3F); + sz += 3; + } else if (val < 0x110000) { + buf[sz+0] = 0xF0 | (val >> 18); + buf[sz+1] = 0x80 | ((val >> 12) & 0x3F); + buf[sz+2] = 0x80 | ((val >> 6) & 0x3F); + buf[sz+3] = 0x80 | (val & 0x3F); + sz += 4; + } else { + return -1; + } + list = CDR(listptr); + if (is_nil(list)) { + return sz; + } + if (is_not_list(list)) { + return -1; + } + listptr = list_val(list); + } + return -2; /* not enough space */ +} + /* ** Convert an integer to a byte list ** return pointer to converted stuff (need not to be at start of buf!) |