-
Notifications
You must be signed in to change notification settings - Fork 14
/
MemGrow.c
78 lines (69 loc) · 1.76 KB
/
MemGrow.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#include "MemGrow.h"
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#include <fcntl.h>
#include <unistd.h>
#ifndef PAGE_SIZE
#define PAGE_SIZE 4096
#endif
void mem_init(MG* mem) {
memset(mem, 0, sizeof *mem);
}
void mem_free(MG* mem) {
if(mem->mem) free(mem->mem);
mem_init(mem);
}
/* returns 1 if realloc was necessary, -1 if no realloc was necessary, 0 when realloc failed */
int mem_grow_if_needed(MG *mem, size_t newsize) {
if(newsize > mem->capa) {
size_t nucap = mem->capa * 2;
if(newsize > nucap) {
nucap = newsize;
if(nucap & (PAGE_SIZE -1)) {
nucap += PAGE_SIZE;
nucap &= ~(PAGE_SIZE -1);
}
}
void *nu = realloc(mem->mem, nucap);
if(!nu) return 0;
mem->mem = nu;
mem->capa = nucap;
return 1;
}
return -1;
}
int mem_write(MG *mem, size_t offset, void* data, size_t size) {
int ret;
size_t needed = offset + size;
if(needed < offset) return 0; /* overflow */
if((ret = mem_grow_if_needed(mem, needed))) {
memcpy((char*) mem->mem + offset, data, size);
if(needed > mem->used) mem->used = needed;
}
return ret;
}
int mem_append(MG *mem, void* data, size_t size) {
return mem_write(mem, mem->used, data, size);
}
void* mem_getptr(MG* mem, size_t offset, size_t byteswanted) {
if(!mem->mem || offset + byteswanted > mem->used) return 0;
return (char*)mem->mem + offset;
}
void mem_set(MG* mem, void* data, size_t used, size_t allocated) {
mem->mem = data;
mem->used = used;
mem->capa = allocated;
}
int mem_write_stream(MG* mem, FILE* out) {
if(!mem->mem || !mem->used) return 0;
int ret = (fwrite(mem->mem, 1, mem->used, out) == mem->used);
return ret;
}
int mem_write_file(MG* mem, char* fn) {
FILE *out = fopen(fn, "wb");
if(!out) return 0;
int ret = mem_write_stream(mem, out);
fclose(out);
return ret;
}