1
0
Fork 0
forked from len0rd/rockbox

move the statically allocated tokens array into the skin buffer. this is done with a little bit of magic with the buffer... explanation in the comments but breifly, tokens + images are stored at the front of the buffer, everything else (constant sizes) are stored at the back, the 2 ends meet when the buffer is full.

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@22418 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Jonathan Gordon 2009-08-19 04:19:08 +00:00
parent 2492e258fa
commit 98756fe492
4 changed files with 104 additions and 22 deletions

View file

@ -38,6 +38,15 @@
* MAIN_ and REMOTE_BUFFER are just for reasonable size calibration, * MAIN_ and REMOTE_BUFFER are just for reasonable size calibration,
* both screens can use the whole buffer as they need; it's not split * both screens can use the whole buffer as they need; it's not split
* between screens * between screens
*
* Buffer can be allocated from either "end" of the global buffer.
* items with unknown sizes get allocated from the start (0->) (data)
* items with known sizes get allocated from the end (<-buf_size) (tokens)
* After loading 2 skins the buffer will look like this:
* |tokens skin1|images skin2|---SPACE---|data skin2|data skin1|
* Make sure to never start allocating from the beginning before letting us know
* how much was used. and RESPECT THE buf_free RETURN VALUES!
*
*/ */
@ -55,63 +64,93 @@
#define SKIN_BUFFER_SIZE (MAIN_BUFFER + REMOTE_BUFFER) #define SKIN_BUFFER_SIZE (MAIN_BUFFER + REMOTE_BUFFER)
static unsigned char buffer_start[SKIN_BUFFER_SIZE], *buffer_pos = NULL; static unsigned char buffer[SKIN_BUFFER_SIZE];
static unsigned char *buffer_front = NULL; /* start of the free space,
increases with allocation*/
static unsigned char *buffer_back = NULL; /* end of the free space
decreases with allocation */
static size_t buf_size = SKIN_BUFFER_SIZE; static size_t buf_size = SKIN_BUFFER_SIZE;
void skin_buffer_init(void) void skin_buffer_init(void)
{ {
#if 0 /* this will go in again later probably */ #if 0 /* this will go in again later probably */
if (buffer_start == NULL) if (buffer == NULL)
{ {
buf_size = SKIN_BUFFER_SIZE;/* global_settings.skin_buf_size */ buf_size = SKIN_BUFFER_SIZE;/* global_settings.skin_buf_size */
buffer_start = buffer_alloc(buf_size); buffer = buffer_alloc(buf_size);
buffer_pos = buffer_start; buffer_front = buffer;
buffer_back = bufer + buf_size;
} }
else else
#endif #endif
{ {
/* reset the buffer.... */ /* reset the buffer.... */
buffer_pos = buffer_start; buffer_front = buffer;
buffer_back = buffer + buf_size;
} }
} }
/* get the number of bytes currently being used */ /* get the number of bytes currently being used */
size_t skin_buffer_usage(void) size_t skin_buffer_usage(void)
{ {
return buffer_pos-buffer_start; return buf_size - (buffer_back-buffer_front);
} }
/* Allocate size bytes from the buffer */ size_t skin_buffer_freespace(void)
{
return buffer_back-buffer_front;
}
/* Allocate size bytes from the buffer
* allocates from the back end (data end)
*/
void* skin_buffer_alloc(size_t size) void* skin_buffer_alloc(size_t size)
{ {
void* retval = buffer_pos; if (skin_buffer_freespace() <= size)
if (skin_buffer_usage()+size >= buf_size)
{ {
return NULL; return NULL;
} }
buffer_pos += size; buffer_back -= size;
/* 32-bit aligned */ /* 32-bit aligned */
buffer_pos = (void *)(((unsigned long)buffer_pos + 3) & ~3); buffer_back = (void *)(((unsigned long)buffer_back) & ~3);
return retval; return buffer_back;
} }
/* Get a pointer to the skin buffer and the count of how much is free /* Get a pointer to the skin buffer and the count of how much is free
* used to do your own buffer management. * used to do your own buffer management.
* Any memory used will be overwritten next time wps_buffer_alloc() * Any memory used will be overwritten next time wps_buffer_alloc()
* is called unless skin_buffer_increment() is called first * is called unless skin_buffer_increment() is called first
*
* This is from the start of the buffer, it is YOUR responsility to make
* sure you dont ever use more then *freespace, and bear in mind this will only
* be valid untill skin_buffer_alloc() is next called...
* so call skin_buffer_increment() and skin_buffer_freespace() regularly
*/ */
void* skin_buffer_grab(size_t *freespace) void* skin_buffer_grab(size_t *freespace)
{ {
*freespace = buf_size - skin_buffer_usage(); *freespace = buf_size - skin_buffer_usage();
return buffer_pos; return buffer_front;
} }
/* Use after skin_buffer_grab() to specify how much buffer was used */ /* Use after skin_buffer_grab() to specify how much buffer was used */
void skin_buffer_increment(size_t used) void skin_buffer_increment(size_t used, bool align)
{ {
buffer_pos += used; buffer_front += used;
/* 32-bit aligned */ if (align)
buffer_pos = (void *)(((unsigned long)buffer_pos + 3) & ~3); {
/* 32-bit aligned */
buffer_front = (void *)(((unsigned long)buffer_front + 3) & ~3);
}
} }
/* free previously skin_buffer_increment()'ed space. This just moves the pointer
* back 'used' bytes so make sure you actually want to do this */
void skin_buffer_free_from_front(size_t used)
{
buffer_front -= used;
/* 32-bit aligned */
buffer_front = (void *)(((unsigned long)buffer_front + 3) & ~3);
}

View file

@ -33,6 +33,7 @@ void skin_buffer_init(void);
/* get the number of bytes currently being used */ /* get the number of bytes currently being used */
size_t skin_buffer_usage(void); size_t skin_buffer_usage(void);
size_t skin_buffer_freespace(void);
/* Allocate size bytes from the buffer */ /* Allocate size bytes from the buffer */
void* skin_buffer_alloc(size_t size); void* skin_buffer_alloc(size_t size);
@ -42,10 +43,22 @@ void* skin_buffer_alloc(size_t size);
* used to do your own buffer management. * used to do your own buffer management.
* Any memory used will be overwritten next time wps_buffer_alloc() * Any memory used will be overwritten next time wps_buffer_alloc()
* is called unless skin_buffer_increment() is called first * is called unless skin_buffer_increment() is called first
*
* This is from the start of the buffer, it is YOUR responsility to make
* sure you dont ever use more then *freespace, and bear in mind this will only
* be valid untill skin_buffer_alloc() is next called...
* so call skin_buffer_increment() and skin_buffer_freespace() regularly
*/ */
void* skin_buffer_grab(size_t *freespace); void* skin_buffer_grab(size_t *freespace);
/* Use after skin_buffer_grab() to specify how much buffer was used */ /* Use after skin_buffer_grab() to specify how much buffer was used.
void skin_buffer_increment(size_t used); * align should always be true unless there is a possibility that you will need
* more space *immediatly* after the previous allocation. (i.e in an array).
* NEVER leave the buffer unaligned */
void skin_buffer_increment(size_t used, bool align);
/* free previously skin_buffer_increment()'ed space. This just moves the pointer
* back 'used' bytes so make sure you actually want to do this */
void skin_buffer_free_from_front(size_t used);
#endif /* _SKIN_BUFFER_H_ */ #endif /* _SKIN_BUFFER_H_ */

View file

@ -1274,18 +1274,44 @@ static int parse_token(const char *wps_bufptr, struct wps_data *wps_data)
data is the pointer to the structure where the parsed WPS should be stored. data is the pointer to the structure where the parsed WPS should be stored.
It is initialised. It is initialised.
wps_bufptr points to the string containing the WPS tags */ wps_bufptr points to the string containing the WPS tags */
#define TOKEN_BLOCK_SIZE 128
static bool wps_parse(struct wps_data *data, const char *wps_bufptr) static bool wps_parse(struct wps_data *data, const char *wps_bufptr)
{ {
if (!data || !wps_bufptr || !*wps_bufptr) if (!data || !wps_bufptr || !*wps_bufptr)
return false; return false;
enum wps_parse_error fail = PARSE_OK; enum wps_parse_error fail = PARSE_OK;
int ret; int ret;
int max_tokens = TOKEN_BLOCK_SIZE;
size_t buf_free = 0;
line = 1; line = 1;
level = -1; level = -1;
/* allocate enough RAM for a reasonable skin, grow as needed.
* Free any used RAM before loading the images to be 100% RAM efficient */
data->tokens = (struct wps_token *)skin_buffer_grab(&buf_free);
if (sizeof(struct wps_token)*max_tokens >= buf_free)
return false;
skin_buffer_increment(max_tokens * sizeof(struct wps_token), false);
data->num_tokens = 0;
while(*wps_bufptr && !fail && data->num_tokens < WPS_MAX_TOKENS - 1 while(*wps_bufptr && !fail
&& data->num_lines < WPS_MAX_LINES) && data->num_lines < WPS_MAX_LINES)
{ {
/* first make sure there is enough room for tokens */
if (max_tokens -1 == data->num_tokens)
{
int extra_tokens = TOKEN_BLOCK_SIZE;
size_t needed = extra_tokens * sizeof(struct wps_token);
/* do some smarts here to grow the array a bit */
if (skin_buffer_freespace() < needed)
{
fail = PARSE_FAIL_LIMITS_EXCEEDED;
break;
}
skin_buffer_increment(needed, false);
max_tokens += extra_tokens;
}
switch(*wps_bufptr++) switch(*wps_bufptr++)
{ {
@ -1482,6 +1508,10 @@ static bool wps_parse(struct wps_data *data, const char *wps_bufptr)
/* one of the limits of the while loop was exceeded */ /* one of the limits of the while loop was exceeded */
fail = PARSE_FAIL_LIMITS_EXCEEDED; fail = PARSE_FAIL_LIMITS_EXCEEDED;
/* Success! */
/* freeup unused tokens */
skin_buffer_free_from_front(sizeof(struct wps_token)
* (max_tokens - data->num_tokens));
curr_vp->last_line = data->num_lines - 1; curr_vp->last_line = data->num_lines - 1;
#if defined(DEBUG) || defined(SIMULATOR) #if defined(DEBUG) || defined(SIMULATOR)
@ -1528,7 +1558,7 @@ static bool load_skin_bmp(struct wps_data *wps_data, struct bitmap *bitmap, char
if (ret > 0) if (ret > 0)
{ {
skin_buffer_increment(ret); skin_buffer_increment(ret, true);
loaded = true; loaded = true;
} }
else else

View file

@ -276,7 +276,7 @@ struct wps_data
/* Total number of tokens in the WPS. During WPS parsing, this is /* Total number of tokens in the WPS. During WPS parsing, this is
the index of the token being parsed. */ the index of the token being parsed. */
int num_tokens; int num_tokens;
struct wps_token tokens[WPS_MAX_TOKENS]; struct wps_token *tokens;
struct skin_token_list *strings; struct skin_token_list *strings;