/**********************************************************************
 
	Copyright (C) 2003 Hirohisa MORI <joshua@nichibun.ac.jp>
 
	This program is free software; you can redistribute it 
	and/or modify it under the terms of the GLOBALBASE 
	Library General Public License (G-LGPL) as published by 

	http://www.globalbase.org/
 
	This program is distributed in the hope that it will be 
	useful, but WITHOUT ANY WARRANTY; without even the 
	implied warranty of MERCHANTABILITY or FITNESS FOR A 
	PARTICULAR PURPOSE.

**********************************************************************/


#include	<errno.h>
#include	"machine/include.h"
#include	"memory_debug.h"
#include	"pdb.h"
#include	"fa.h"

extern void (*change_endian_table_to_host[])();
extern PDB_REQUEST * pr_free_list;
extern int min_size[];

int
delete_request(PDB * p,int (*func_table[])(),void* data)
{
PDB_REQUEST * pr;
FAC_HEADER * h;
int er,len;
int type,size;
int ret;

	if ( p->request == 0 ) {
		p->request = p->next_request;
		p->next_request = 0;
		if ( p->request == 0 ) {
			p->fofs = 0;
			return E_DR_NO_REQUEST;
		}
	}
	pr = p->request;
	p->request = pr->next;

	if ( p->flags & PF_CACHE ) {
		h = search_cache(p->cache,pr->fofs);
		if ( h ) {
			size = h->h.size;
			type = h->h.type;
			goto hit;
		}
	}
	h = d_alloc(sizeof(*h),1656);
	er = d_lseek(p,pr->fofs,SEEK_SET);
	if ( er < 0 ) {
		if ( pr->option )
			d_f_ree(pr->option);
		d_f_ree(pr);
		d_f_ree(h);
		return E_DR_FILE_ACCESS;
	}
	er = d_read(p,&h->h,sizeof(h->h));
	if ( er < sizeof(h->h) ) {
		if ( pr->option )
			d_f_ree(pr->option);
		d_f_ree(pr);
		d_f_ree(h);
		return E_DR_FILE_ACCESS;
	}
	change_endian_header(&h->h);
	size = h->h.size;
	type = h->h.type;

	if ( type < 1 || type >= PNT_POLY_MAX ) {
		return E_DR_UNSUPPORT_SEGMENT_TYPE;
	}
	change_endian_header(&h->h);
	h = d_re_alloc(h,SIZEOF_FAC(size));
	len = size-sizeof(h->h);

	er = d_read(p,(h+1),len);
	if ( er < len ) {
		if ( pr->option )
			d_f_ree(pr->option);
		d_f_ree(pr);
		d_f_ree(h);
		if ( p->request )
			p->fofs = p->request->fofs;
		return E_DR_SEGMENT_ACCESS;
	}
	(*change_endian_table_to_host[type])(&h->h);
	p->fofs = pr->fofs;
	h->offset = pr->fofs;
	if ( p->flags & PF_CACHE )
		if ( insert_cache(p->cache,h) < 0 )
			er_panic("delete_request(1)");
hit:

	ret = (*func_table[type])(p,pr->fofs+size,pr->option,&h->h,data);
	if ( ret == 0 && pr->option )
		d_f_ree(pr->option);
	if ( p->flags & PF_CACHE )
		d_f_ree(h);
	pr->next = pr_free_list;
	pr_free_list = pr;
	return ret;
}
