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