diff --git a/samples/server2.noja b/samples/server2.noja index 9456c46..26b513c 100644 --- a/samples/server2.noja +++ b/samples/server2.noja @@ -21,7 +21,13 @@ fun startServer(callbacks, port, backlog) return none; } - if net.bind(fd, {sin_family: net.AF_INET, sin_port: net.htons(port), sin_addr: {s_addr: net.htonl(net.INADDR_ANY)}}) != 0: + if net.bind(fd, { + sin_family: net.AF_INET, + sin_port: net.htons(port), + sin_addr: { + s_addr: net.htonl(net.INADDR_ANY) + } + }) != 0: { print('Failed to bind.\n'); return none; @@ -33,15 +39,25 @@ fun startServer(callbacks, port, backlog) return none; } - on_datain = callbacks.on_datain; - on_connect = callbacks.on_connect; - on_disconnect = callbacks.on_disconnect; + { + on_datain = callbacks.on_datain; + on_connect = callbacks.on_connect; + on_disconnect = callbacks.on_disconnect; - if on_datain == none: fun on_datain() none; - if on_connect == none: fun on_connect() none; - if on_disconnect == none: fun on_disconnect() none; + if on_datain == none: + fun on_datain() + none; - buffer = newBuffer(16); + if on_connect == none: + fun on_connect() + none; + + if on_disconnect == none: + fun on_disconnect() + none; + } + + buffer = newBuffer(1024); while true: { @@ -67,7 +83,7 @@ fun startServer(callbacks, port, backlog) else if n == 0: on_disconnect(addr_str); else - on_datain(addr_str, buffer, n); + on_datain(addr_str, sliceBuffer(buffer, 0, n)); } while n > 0; } @@ -78,9 +94,9 @@ fun on_connect(addr) print(addr, ' connected.\n'); } -fun on_datain(addr, buf, len) +fun on_datain(addr, data) { - print('Received ', len, ' bytes from ', addr); + print('Received ', count(data), ' bytes from ', addr, '\n'); } fun on_disconnect(addr) diff --git a/src/o_builtins.c b/src/o_builtins.c index 28d4fc8..a424008 100644 --- a/src/o_builtins.c +++ b/src/o_builtins.c @@ -14,6 +14,7 @@ static Object *bin_count (Runtime *runtime, Object **argv, unsigned int argc, Er static Object *bin_assert(Runtime *runtime, Object **argv, unsigned int argc, Error *error); static Object *bin_strcat(Runtime *runtime, Object **argv, unsigned int argc, Error *error); static Object *bin_newBuffer(Runtime *runtime, Object **argv, unsigned int argc, Error *error); +static Object *bin_sliceBuffer(Runtime *runtime, Object **argv, unsigned int argc, Error *error); typedef struct { Object base; @@ -79,6 +80,14 @@ static Object *select_(Object *self, Object *key, Heap *heap, Error *err) return NULL; } + case PAIR(sizeof("sliceBuffer")-1, 's'): + { + if(!strcmp(s, "sliceBuffer")) + return Object_FromNativeFunction(bm->runtime, bin_sliceBuffer, 3, heap, err); + + return NULL; + } + case PAIR(sizeof("net")-1, 'n'): { if(!strcmp(s, "net")) @@ -210,10 +219,23 @@ static Object *bin_newBuffer(Runtime *runtime, Object **argv, unsigned int argc, { assert(argc == 1); - int size = Object_ToInt(argv[0], error); + long long int size = Object_ToInt(argv[0], error); if(error->occurred == 1) return NULL; return Object_NewBuffer(size, Runtime_GetHeap(runtime), error); +} + +static Object *bin_sliceBuffer(Runtime *runtime, Object **argv, unsigned int argc, Error *error) +{ + assert(argc == 3); + + long long int offset = Object_ToInt(argv[1], error); + if(error->occurred == 1) return NULL; + + long long int length = Object_ToInt(argv[2], error); + if(error->occurred == 1) return NULL; + + return Object_SliceBuffer(argv[0], offset, length, Runtime_GetHeap(runtime), error); } \ No newline at end of file diff --git a/src/objects/o_buffer.c b/src/objects/o_buffer.c index 7ed68e8..833965f 100644 --- a/src/objects/o_buffer.c +++ b/src/objects/o_buffer.c @@ -4,9 +4,15 @@ #include "objects.h" typedef struct { - Object base; - int size; - unsigned char *body; + int size, + refs; + unsigned char data[]; +} BufferBody; + +typedef struct { + Object base; + BufferBody *body; + int offset, length; } BufferObject; static Object *select(Object *self, Object *key, Heap *heap, Error *err); @@ -36,18 +42,57 @@ Object *Object_NewBuffer(int size, Heap *heap, Error *error) if(obj == NULL) return NULL; - obj->size = size; - obj->body = Heap_RawMalloc(heap, sizeof(unsigned char) * size, error); + obj->offset = 0; + obj->length = size; + obj->body = Heap_RawMalloc(heap, sizeof(BufferBody) + sizeof(unsigned char) * size, error); if(obj->body == NULL) return NULL; - memset(obj->body, 0, size); + obj->body->size = size; + obj->body->refs = 1; + memset(obj->body->data, 0, size); } return (Object*) obj; } +Object *Object_SliceBuffer(Object *buffer, int offset, int length, Heap *heap, Error *error) +{ + if(buffer->type != &t_buffer) + { + Error_Report(error, 0, "Not a buffer"); + return NULL; + } + + BufferObject *original = (BufferObject*) buffer; + BufferObject *slice = (BufferObject*) Heap_Malloc(heap, &t_buffer, error); + + if(offset < 0 || offset >= original->length) + { + Error_Report(error, 0, "offset out of range"); + return NULL; + } + + if(length < 0 || length >= original->length) + { + Error_Report(error, 0, "length out of range"); + return NULL; + } + + if(offset + length > original->length) + { + Error_Report(error, 0, "slice out of range"); + return NULL; + } + + slice->offset = original->offset + offset; + slice->length = length; + slice->body = original->body; + slice->body->refs += 1; + return (Object*) slice; +} + void *Object_GetBufferAddrAndSize(Object *obj, int *size, Error *error) { if(obj->type != &t_buffer) @@ -59,8 +104,8 @@ void *Object_GetBufferAddrAndSize(Object *obj, int *size, Error *error) BufferObject *buf = (BufferObject*) obj; if(size) - *size = buf->size; - return buf->body; + *size = buf->length; + return buf->body->data + buf->offset; } static Object *select(Object *self, Object *key, Heap *heap, Error *error) @@ -82,13 +127,13 @@ static Object *select(Object *self, Object *key, Heap *heap, Error *error) BufferObject *buffer = (BufferObject*) self; - if(idx < 0 || idx >= buffer->size) + if(idx < 0 || idx >= buffer->length) { Error_Report(error, 0, "Out of range index"); return NULL; } - unsigned char byte = buffer->body[idx]; + unsigned char byte = buffer->body->data[buffer->offset + idx]; return Object_FromInt(byte, heap, error); } @@ -113,7 +158,7 @@ static _Bool insert(Object *self, Object *key, Object *val, Heap *heap, Error *e int idx = Object_ToInt(key, error); assert(error->occurred == 0); - if(idx < 0 || idx >= buffer->size) + if(idx < 0 || idx >= buffer->length) { Error_Report(error, 0, "Out of range index"); return NULL; @@ -124,7 +169,7 @@ static _Bool insert(Object *self, Object *key, Object *val, Heap *heap, Error *e if(error->occurred == 1) return 0; - buffer->body[idx] = byte; + buffer->body->data[buffer->offset + idx] = byte; return 1; } @@ -132,7 +177,7 @@ static int count(Object *self) { BufferObject *buffer = (BufferObject*) self; - return buffer->size; + return buffer->length; } static void print(Object *self, FILE *fp) @@ -141,11 +186,11 @@ static void print(Object *self, FILE *fp) fprintf(fp, "["); - for(int i = 0; i < buffer->size; i += 1) + for(int i = 0; i < buffer->length; i += 1) { unsigned char byte, low, high; - byte = buffer->body[i]; + byte = buffer->body->data[buffer->offset + i]; low = byte & 0xf; high = byte >> 4; @@ -159,7 +204,7 @@ static void print(Object *self, FILE *fp) fprintf(fp, "%c%c", c1, c2); - if(i+1 < buffer->size) + if(i+1 < buffer->length) fprintf(fp, ", "); } fprintf(fp, "]"); diff --git a/src/objects/objects.h b/src/objects/objects.h index aed5774..22dd5e7 100644 --- a/src/objects/objects.h +++ b/src/objects/objects.h @@ -89,6 +89,7 @@ Object* Object_NewList(int capacity, Heap *heap, Error *error); Object* Object_NewNone(Heap *heap, Error *error); Object* Object_NewBuffer(int size, Heap *heap, Error *error); Object* Object_NewClosure(Object *parent, Object *new_map, Heap *heap, Error *error); +Object* Object_SliceBuffer(Object *buffer, int offset, int length, Heap *heap, Error *error); Object* Object_FromInt (long long int val, Heap *heap, Error *error); Object* Object_FromBool (_Bool val, Heap *heap, Error *error);