diff options
author | Alexey Shchepin <alexey@process-one.net> | 2003-09-26 18:55:01 +0000 |
---|---|---|
committer | Alexey Shchepin <alexey@process-one.net> | 2003-09-26 18:55:01 +0000 |
commit | 8888e2528ca55a9c1c7461f850c6cad2e9c66f22 (patch) | |
tree | 0d9482dfab365b3831521b2fe054a68cce0b0347 /src/stringprep/stringprep_drv.c | |
parent | * src/mod_muc/mod_muc_room.erl: Debug output switched off (diff) |
* src/stringprep/: Support for stringprep (not completed yet)
* src/mod_muc/mod_muc.erl: Replaced io:format calls to ?DEBUG ones
SVN Revision: 141
Diffstat (limited to '')
-rw-r--r-- | src/stringprep/stringprep_drv.c | 147 |
1 files changed, 147 insertions, 0 deletions
diff --git a/src/stringprep/stringprep_drv.c b/src/stringprep/stringprep_drv.c new file mode 100644 index 00000000..e6eb3d37 --- /dev/null +++ b/src/stringprep/stringprep_drv.c @@ -0,0 +1,147 @@ +/* $Id$ */ + +#include <stdio.h> +#include <erl_driver.h> +#include <ei.h> +#include <iconv.h> + +#include "uni_data.c" + +typedef struct { + ErlDrvPort port; +} stringprep_data; + + +static ErlDrvData stringprep_erl_start(ErlDrvPort port, char *buff) +{ + stringprep_data* d = (stringprep_data*)driver_alloc(sizeof(stringprep_data)); + d->port = port; + + set_port_control_flags(port, PORT_CONTROL_FLAG_BINARY); + + return (ErlDrvData)d; +} + +static void stringprep_erl_stop(ErlDrvData handle) +{ + driver_free((char*)handle); +} + +static int stringprep_erl_control(ErlDrvData drv_data, + unsigned int command, + char *buf, int len, + char **rbuf, int rlen) +{ + int i, j=0; + unsigned char c; + int bad = 0; + int uc, ruc; + int size; + int info; + ErlDrvBinary *b; + char *rstring; + + size = len; + + rstring = malloc(size); + + for(i=0; i < len; i++) + { + c = buf[i]; + if(c < 0x80) { + uc = c; + } else if(c < 0xC0) { + bad = 1; + } else if(c < 0xE0) { + if(i+1 < len && (buf[i+1] & 0xC0) == 0x80) { + uc = ((c & 0x1F) << 6) | (buf[i+1] & 0x3F); + i++; + } else { + bad = 1; + } + } else if(c < 0xF0) { + if(i+2 < len && (buf[i+1] & 0xC0) == 0x80 && + (buf[i+2] & 0xC0) == 0x80) { + uc = ((c & 0x1F) << 12) | ((buf[i+1] & 0x1F) << 6) + | (buf[i+2] & 0x3F); + i += 2; + } else { + bad = 1; + } + } else { + // TODO + bad = 1; + } + + if(bad) { + *rbuf = (char*)(b = driver_alloc_binary(1)); + b->orig_bytes[0] = 0; + free(rstring); + return 1; + } + + + info = GetUniCharInfo(uc); + ruc = uc + GetDelta(info); + + if(ruc < 0x80) { + if(j >= size) { + size = 2*size + 1; + rstring = realloc(rstring, size); + } + rstring[j] = (char) ruc; + j++; + } else if(ruc < 0x7FF) { + if(j >= size) { + size = 2*size + 2; + rstring = realloc(rstring, size); + } + rstring[j] = (char) ((ruc >> 6) | 0xC0); + rstring[j+1] = (char) ((ruc | 0x80) & 0xBF); + j += 2; + } else if(ruc < 0xFFFF) { + if(j >= size) { + size = 2*size + 3; + rstring = realloc(rstring, size); + } + rstring[j] = (char) ((ruc >> 12) | 0xE0); + rstring[j+1] = (char) (((ruc >> 6) | 0x80) & 0xBF); + rstring[j+2] = (char) ((ruc | 0x80) & 0xBF); + j += 3; + } + } + + + + *rbuf = (char*)(b = driver_alloc_binary(j)); + memcpy(b->orig_bytes, rstring, j); + free(rstring); + + return j; +} + + + +ErlDrvEntry stringprep_driver_entry = { + NULL, /* F_PTR init, N/A */ + stringprep_erl_start, /* L_PTR start, called when port is opened */ + stringprep_erl_stop, /* F_PTR stop, called when port is closed */ + NULL, /* F_PTR output, called when erlang has sent */ + NULL, /* F_PTR ready_input, called when input descriptor ready */ + NULL, /* F_PTR ready_output, called when output descriptor ready */ + "stringprep_drv", /* char *driver_name, the argument to open_port */ + NULL, /* F_PTR finish, called when unloaded */ + NULL, /* handle */ + stringprep_erl_control, /* F_PTR control, port_command callback */ + NULL, /* F_PTR timeout, reserved */ + NULL /* F_PTR outputv, reserved */ +}; + +#ifdef WIN32 +__declspec(dllexport) +#endif +DRIVER_INIT(stringprep_erl) /* must match name in driver_entry */ +{ + return &stringprep_driver_entry; +} + |