-static int stringprep_prep(lua_State *L, const Stringprep_profile *profile)
-{
- size_t len;
- const char *s;
- char string[1024];
- int ret;
- if(!lua_isstring(L, 1)) {
- lua_pushnil(L);
- return 1;
+#define MAXUNICODE 0x10FFFF
+
+/*
+ * Decode one UTF-8 sequence, returning NULL if byte sequence is invalid.
+ */
+static const char* utf8_decode(const char* o, int* val) {
+ static unsigned int limits[] = {0xFF, 0x7F, 0x7FF, 0xFFFF};
+ const unsigned char* s = (const unsigned char*)o;
+ unsigned int c = s[0];
+ unsigned int res = 0; /* final result */
+
+ if(c < 0x80) { /* ascii? */
+ res = c;
+ } else {
+ int count = 0; /* to count number of continuation bytes */
+
+ while(c & 0x40) { /* still have continuation bytes? */
+ int cc = s[++count]; /* read next byte */
+
+ if((cc & 0xC0) != 0x80) { /* not a continuation byte? */
+ return NULL; /* invalid byte sequence */
+ }
+
+ res = (res << 6) | (cc & 0x3F); /* add lower 6 bits from cont. byte */
+ c <<= 1; /* to test next bit */
+ }
+
+ res |= ((c & 0x7F) << (count * 5)); /* add first byte */
+
+ if(count > 3 || res > MAXUNICODE || res <= limits[count] || (0xd800 <= res && res <= 0xdfff)) {
+ return NULL; /* invalid byte sequence */
+ }
+
+ s += count; /* skip continuation bytes read */