mirror of
https://github.com/ilyakooo0/Idris-dev.git
synced 2024-09-11 08:55:23 +03:00
Otherwise, we're just guessing on the size, and that way lies segfaults. It turns out the size in Buffer.idr might have been correct once, but isn't now, and so unless we're lucky registering the pointer will copy memory we don't have access to. If the RTS does the registering of the pointer, at least it knows the size. (It's likely this is doable without the malloc, using iallocate directly, but this required fewer changes.)
147 lines
3.4 KiB
C
147 lines
3.4 KiB
C
#include "idris_rts.h"
|
|
#include "idris_buffer.h"
|
|
|
|
typedef struct {
|
|
int size;
|
|
uint8_t data[0];
|
|
} Buffer;
|
|
|
|
VAL idris_newBuffer(VM* vm, int bytes) {
|
|
size_t size = sizeof(Buffer) + bytes*sizeof(uint8_t);
|
|
|
|
Buffer* buf = malloc(size);
|
|
if (buf == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
buf->size = bytes;
|
|
memset(buf->data, 0, bytes);
|
|
|
|
void* retbuf = MKMPTR(vm, buf, size);
|
|
free(buf);
|
|
return retbuf;
|
|
}
|
|
|
|
void idris_copyBuffer(void* from, int start, int len,
|
|
void* to, int loc) {
|
|
Buffer* bfrom = from;
|
|
Buffer* bto = to;
|
|
|
|
if (loc >= 0 && loc+len <= bto->size) {
|
|
memcpy(bto->data + loc, bfrom->data + start, len);
|
|
}
|
|
}
|
|
|
|
int idris_getBufferSize(void* buffer) {
|
|
return ((Buffer*)buffer)->size;
|
|
}
|
|
|
|
void idris_setBufferByte(void* buffer, int loc, uint8_t byte) {
|
|
Buffer* b = buffer;
|
|
if (loc >= 0 && loc < b->size) {
|
|
b->data[loc] = byte;
|
|
}
|
|
}
|
|
|
|
void idris_setBufferInt(void* buffer, int loc, int val) {
|
|
Buffer* b = buffer;
|
|
if (loc >= 0 && loc+3 < b->size) {
|
|
b->data[loc] = val & 0xff;
|
|
b->data[loc+1] = (val >> 8) & 0xff;
|
|
b->data[loc+2] = (val >> 16) & 0xff;
|
|
b->data[loc+3] = (val >> 24) & 0xff;
|
|
}
|
|
}
|
|
|
|
void idris_setBufferDouble(void* buffer, int loc, double val) {
|
|
Buffer* b = buffer;
|
|
// I am not proud of this
|
|
if (loc >= 0 && loc + sizeof(double) <= b->size) {
|
|
unsigned char* c = (unsigned char*)(& val);
|
|
int i;
|
|
for (i = 0; i < sizeof(double); ++i) {
|
|
b->data[loc+i] = c[i];
|
|
}
|
|
}
|
|
}
|
|
|
|
void idris_setBufferString(void* buffer, int loc, char* str) {
|
|
Buffer* b = buffer;
|
|
int len = strlen(str);
|
|
|
|
if (loc >= 0 && loc+len <= b->size) {
|
|
memcpy((b->data)+loc, str, len);
|
|
}
|
|
}
|
|
|
|
uint8_t idris_getBufferByte(void* buffer, int loc) {
|
|
Buffer* b = buffer;
|
|
if (loc >= 0 && loc < b->size) {
|
|
return b->data[loc];
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
int idris_getBufferInt(void* buffer, int loc) {
|
|
Buffer* b = buffer;
|
|
if (loc >= 0 && loc+3 < b->size) {
|
|
return b->data[loc] +
|
|
(b->data[loc+1] << 8) +
|
|
(b->data[loc+2] << 16) +
|
|
(b->data[loc+3] << 24);
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
double idris_getBufferDouble(void* buffer, int loc) {
|
|
Buffer* b = buffer;
|
|
double d;
|
|
// I am even less proud of this
|
|
unsigned char *c = (unsigned char*)(& d);
|
|
if (loc >= 0 && loc + sizeof(double) <= b->size) {
|
|
int i;
|
|
for (i = 0; i < sizeof(double); ++i) {
|
|
c[i] = b->data[loc+i];
|
|
}
|
|
return d;
|
|
}
|
|
else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
VAL idris_getBufferString(void* buffer, int loc, int len) {
|
|
Buffer* b = buffer;
|
|
char * s = (char*)(b->data + loc);
|
|
size_t sz = loc >= 0 && loc+len <= b->size? len : 0;
|
|
return MKSTRlen(get_vm(), s, sz);
|
|
}
|
|
|
|
int idris_readBuffer(FILE* h, void* buffer, int loc, int max) {
|
|
Buffer* b = buffer;
|
|
size_t len;
|
|
|
|
if (loc >= 0 && loc < b->size) {
|
|
if (loc + max > b->size) {
|
|
max = b->size - loc;
|
|
}
|
|
len = fread((b->data)+loc, sizeof(uint8_t), (size_t)max, h);
|
|
return len;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
void idris_writeBuffer(FILE* h, void* buffer, int loc, int len) {
|
|
Buffer* b = buffer;
|
|
|
|
if (loc >= 0 && loc < b->size) {
|
|
if (loc + len > b->size) {
|
|
len = b->size - loc;
|
|
}
|
|
fwrite((b->data)+loc, sizeof(uint8_t), len, h);
|
|
}
|
|
}
|