1 /* radare - LGPL - Copyright 2013-2020 - pancake */
2
3 // XXX: should use the same code as libr/io/cache.c
4 // one malloc per write
5 #include <r_util.h>
6 // TODO: optimize reallocs.. store RBuffer info.. wait. extend r_buf_ for that?
7
r_cache_new(void)8 R_API RCache *r_cache_new(void) {
9 RCache *c = R_NEW0 (RCache);
10 if (!c) {
11 return NULL;
12 }
13 c->buf = NULL;
14 c->base = 0;
15 c->len = 0;
16 return c;
17 }
18
r_cache_free(RCache * c)19 R_API void r_cache_free(RCache *c) {
20 if (c) {
21 free (c->buf);
22 }
23 free (c);
24 }
25
r_cache_get(RCache * c,ut64 addr,int * len)26 R_API const ut8 *r_cache_get(RCache *c, ut64 addr, int *len) {
27 if (!c->buf) {
28 return NULL;
29 }
30 if (len) {
31 *len = c->base - addr;
32 }
33 if (addr < c->base) {
34 return NULL;
35 }
36 if (addr > (c->base + c->len)) {
37 return NULL;
38 }
39 if (len) {
40 *len = c->len - (addr - c->base);
41 }
42 // eprintf ("4 - %d\n", (addr-c->base));
43 return c->buf + (addr - c->base);
44 }
45
r_cache_set(RCache * c,ut64 addr,const ut8 * buf,int len)46 R_API int r_cache_set(RCache *c, ut64 addr, const ut8 *buf, int len) {
47 if (!c) {
48 return 0;
49 }
50 if (!c->buf) {
51 c->buf = malloc (len);
52 if (!c->buf) {
53 return 0;
54 }
55 memcpy (c->buf, buf, len);
56 c->base = addr;
57 c->len = len;
58 } else if (addr < c->base) {
59 ut8 *b;
60 int baselen = (c->base - addr);
61 int newlen = baselen + ((len > c->len)? len: c->base);
62 // XXX expensive heap usage. must simplify
63 b = malloc (newlen);
64 if (!b) {
65 return 0;
66 }
67 memset (b, 0xff, newlen);
68 memcpy (b + baselen, c->buf, c->len);
69 memcpy (b, buf, len);
70 free (c->buf);
71 c->buf = b;
72 c->base = addr;
73 c->len = newlen;
74 } else if ((addr + len) > (c->base + c->len)) {
75 ut8 *b;
76 int baselen = (addr - c->base);
77 int newlen = baselen + len;
78 b = realloc (c->buf, newlen);
79 if (!b) {
80 return 0;
81 }
82 memcpy (b + baselen, buf, len);
83 c->buf = b;
84 c->len = newlen;
85 } else {
86 memcpy (c->buf, buf, len);
87 }
88 return c->len;
89 }
90
r_cache_flush(RCache * c)91 R_API void r_cache_flush(RCache *c) {
92 if (c) {
93 c->base = 0;
94 c->len = 0;
95 R_FREE (c->buf);
96 }
97 }
98