/* * cache.c: Rotines to handle the page-cache (in RAM, not the one on the videotext-decoder!) * * $Id: cache.c,v 1.1 1996/10/13 23:02:35 mb Exp mb $ * * Copyright (c) 1994-96 Martin Buck * Read COPYING for more information * */ #include #include #include #include "safe_malloc.h" #include "misc.h" #include "vtxtools.h" #include "cache.h" static cache_t *cache[800]; /* Inserts (or updates) a raw page into the cache */ void cache_insert(const byte_t *buffer, const vtx_pageinfo_t *info) { cache_t **cache_ptr, *new; if (!vtx_chkpgnum(info->pagenum, FALSE)) return; cache_ptr = cache + vtx_hex2dec(info->pagenum) - 100; while (*cache_ptr && (**cache_ptr).info.minute < info->minute) { cache_ptr = &(**cache_ptr).next; } if (!*cache_ptr || (**cache_ptr).info.minute != info->minute) { new = smalloc(sizeof(cache_t)); new->next = *cache_ptr; new->subpages_complete = FALSE; /* Only used in first element of linked list */ *cache_ptr = new; } memcpy((**cache_ptr).buf, buffer, VTX_PAGESIZE); (**cache_ptr).info = *info; } /* Sets the subpages_complete-flag for a given page in cache */ void cache_mark_complete(int page) { if (vtx_chkpgnum(page, FALSE)) { page = vtx_hex2dec(page) - 100; if (cache[page]) { cache[page]->subpages_complete = TRUE; } } } /* Returns 0 if page is not in cache, 1 if at least one matching subpage is in cache, 2 if all * subpages are in cache (if subpage == -1). Also returns page-data and -info, if pointers != NULL * The returned page-data starts with line 1, not with 0! */ int cache_query(int page, int subpage, int offset, byte_t *buffer, vtx_pageinfo_t *info) { cache_t *cache_ptr; int complete = FALSE; if (!vtx_chkpgnum(page, FALSE)) return 0; if ((cache_ptr = cache[vtx_hex2dec(page) - 100])) { complete = cache_ptr->subpages_complete; } while (cache_ptr) { if (cache_ptr->info.pagenum == page && (subpage == -1 || cache_ptr->info.minute == subpage)) { if (buffer) memcpy(buffer, cache_ptr->buf + offset, VTX_PAGESIZE - offset); if (info) *info = cache_ptr->info; return (complete ? 2 : 1); } cache_ptr = cache_ptr->next; } return 0; } /* Returns the number of subpages available in cache for a given page */ int cache_count_subpg(int page) { int subpages = 0; cache_t *cache_ptr; if (!vtx_chkpgnum(page, FALSE)) return 0; cache_ptr = cache[vtx_hex2dec(page) - 100]; while (cache_ptr) { subpages++; cache_ptr = cache_ptr->next; } return subpages; } /* Find next subpage in cache for page. * Returns -1 if not found, subpage-number otherwise */ int cache_next_subpage(int page, int subpage) { cache_t *cache_ptr; if (!vtx_chkpgnum(page, FALSE)) return -1; cache_ptr = cache[vtx_hex2dec(page) - 100]; while (cache_ptr) { if (cache_ptr->info.minute >= subpage) return cache_ptr->info.minute; cache_ptr = cache_ptr->next; } return -1; } /* Clears all pages in cache */ void cache_reset(void) { int entry; cache_t *current, *next; for (entry = 0; entry <= 799; entry++) { current = cache[entry]; cache[entry] = NULL; while (current) { next = current->next; free(current); current = next; } } } /* Loop through all pages in cache, return TRUE if page was found or FALSE if no more pages are * available. Also return page-data and -info if pointers != NULL. * The first argument is used to find the next page on the next call and must be passed unmodified. * last->page must be initialized with -1 on the first call. */ int cache_loop(cache_loop_t *last, byte_t *buffer, vtx_pageinfo_t *info) { if (last->page < 0) { last->page = 0; last->subpg_ptr = NULL; } while (last->page < 800) { if (cache[last->page]) { if (!last->subpg_ptr) { last->subpg_ptr = cache[last->page]; } else { last->subpg_ptr = last->subpg_ptr->next; } if (last->subpg_ptr) { if (buffer) { memcpy(buffer, last->subpg_ptr->buf, VTX_PAGESIZE); } if (info) { *info = last->subpg_ptr->info; } return TRUE; } } last->page++; } last->page = -1; return FALSE; }