| /* Created 07/March/2004 Chandrashekhar Mullaparthi |
| |
| $Id: ibrowse_drv.c,v 1.1 2005/05/05 22:28:28 chandrusf Exp $ |
| |
| Erlang Linked in driver to URL encode a set of data |
| */ |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include "erl_driver.h" |
| |
| static ErlDrvData ibrowse_drv_start(ErlDrvPort port, char* buff); |
| static void ibrowse_drv_stop(ErlDrvData handle); |
| static void ibrowse_drv_command(ErlDrvData handle, char *buff, int bufflen); |
| static void ibrowse_drv_finish(void); |
| static int ibrowse_drv_control(ErlDrvData handle, unsigned int command, |
| char* buf, int count, char** res, int res_size); |
| |
| /* The driver entry */ |
| static ErlDrvEntry ibrowse_driver_entry = { |
| NULL, /* init, N/A */ |
| ibrowse_drv_start, /* start, called when port is opened */ |
| ibrowse_drv_stop, /* stop, called when port is closed */ |
| NULL, /* output, called when erlang has sent */ |
| NULL, /* ready_input, called when input descriptor |
| ready */ |
| NULL, /* ready_output, called when output |
| descriptor ready */ |
| "ibrowse_drv", /* char *driver_name, the argument |
| to open_port */ |
| NULL, /* finish, called when unloaded */ |
| NULL, /* void * that is not used (BC) */ |
| ibrowse_drv_control, /* control, port_control callback */ |
| NULL, /* timeout, called on timeouts */ |
| NULL, /* outputv, vector output interface */ |
| NULL, |
| NULL, |
| NULL, /* call, synchronous call to driver */ |
| NULL |
| }; |
| |
| typedef struct ibrowse_drv_data { |
| unsigned int count; |
| void *alloc_ptr; |
| } State; |
| |
| static State *ibrowse_drv_data; |
| |
| DRIVER_INIT(ibrowse_drv) |
| { |
| ibrowse_drv_data = NULL; |
| return &ibrowse_driver_entry; |
| } |
| |
| static ErlDrvData ibrowse_drv_start(ErlDrvPort port, char *buff) |
| { |
| State *state; |
| |
| state = driver_alloc(sizeof(State)); |
| state->count = 0; |
| state->alloc_ptr = NULL; |
| |
| ibrowse_drv_data = state; |
| return ((ErlDrvData) state); |
| } |
| |
| void ibrowse_drv_stop(ErlDrvData desc) |
| { |
| return; |
| } |
| |
| static int ibrowse_drv_control(ErlDrvData handle, unsigned int command, |
| char *buf, int bufflen, char **rbuf, int rlen) |
| { |
| State* state = (State *) handle; |
| unsigned int j = 0, i = 0; |
| unsigned int temp = 0, rlen_1 = 0; |
| char* replybuf; |
| |
| fprintf(stderr, "alloc_ptr -> %d\n", state->alloc_ptr); |
| /* if(state->alloc_ptr != NULL) */ |
| /* { */ |
| /* driver_free(state->alloc_ptr); */ |
| /* } */ |
| |
| /* Calculate encoded length. If same as bufflen, it means there is |
| no encoding to do. Do return an empty list */ |
| rlen_1 = calc_encoded_length(buf, bufflen); |
| if(rlen_1 == bufflen) |
| { |
| *rbuf = NULL; |
| state->alloc_ptr = NULL; |
| return 0; |
| } |
| *rbuf = driver_alloc(rlen_1); |
| state->alloc_ptr = *rbuf; |
| fprintf(stderr, "*rbuf -> %d\n", *rbuf); |
| replybuf = *rbuf; |
| |
| for(i=0;i<bufflen;i++) |
| { |
| temp = buf[i]; |
| if( 'a' <= temp && temp <= 'z' |
| || 'A' <= temp && temp <= 'Z' |
| || '0' <= temp && temp <= '9' |
| || temp == '-' || temp == '_' || temp == '.' ) |
| { |
| replybuf[j++] = temp; |
| /* printf("j -> %d\n", j); */ |
| } |
| else |
| { |
| replybuf[j++] = 37; |
| /* printf("temp -> %d\n", temp); |
| printf("d2h(temp >> 4) -> %d\n", d2h(temp >> 4)); |
| printf("d2h(temp & 15) -> %d\n", d2h(temp & 15)); */ |
| replybuf[j++] = d2h(temp >> 4); |
| replybuf[j++] = d2h(temp & 15); |
| /* printf("j -> %d\n", j); */ |
| } |
| } |
| return rlen_1; |
| } |
| |
| /* Calculates the length of the resulting buffer if a string is URL encoded */ |
| int calc_encoded_length(char* buf, int bufflen) |
| { |
| unsigned int count=0, i=0, temp=0; |
| |
| for(i=0;i<bufflen;i++) |
| { |
| temp = buf[i]; |
| if( 'a' <= temp && temp <= 'z' |
| || 'A' <= temp && temp <= 'Z' |
| || '0' <= temp && temp <= '9' |
| || temp == '-' || temp == '_' || temp == '.' ) |
| { |
| count++; |
| } |
| else |
| { |
| count = count+3; |
| } |
| } |
| return count; |
| } |
| |
| /* Converts an integer in the range 1-15 into it's ascii value |
| 1 -> 49 (ascii value of 1) |
| 10 -> 97 (ascii value of a) |
| */ |
| int d2h(unsigned int i) |
| { |
| if( i < 10 ) |
| { |
| return i + 48; |
| } |
| else |
| { |
| return i + 97 - 10; |
| } |
| } |