/**********************************************************************
 
	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	<fcntl.h>
#include	"machine/include.h"
#include	"memory_debug.h"
#include	"recordlist64.h"


int
check_recordlist_ptr64(RECORD_LIST64 * lst);
void _setup_recordlist64(RECORD_LIST64 * lst);
void free_chain_list64(CHAIN_LIST64 * c);


void
set_recordlist_ptr64(RECORD_LIST64 * lst,INTEGER64 body)
{
	if ( lst->header.size > body ) {
		lst->body = 0;
		lst->ptr = 0;
	}
	else {
		lst->body = body;
		lst->ptr = (void*)(((char*)lst->data) + body);
	}
}

int
check_recordlist_ptr64(RECORD_LIST64 * lst)
{
	if ( lst->ptr == 0 )
		return -1;
	if ( ((char*)lst->data) + lst->body > ((char*)lst->ptr) )
		return -1;
	if ( ((char*)lst->data) + lst->header.size <= ((char*)lst->ptr) )
		return 1;
	return 0;
}

void
set_recordlist_chain64(
	RECORD_LIST64 * lst,void * ptr,INTEGER64 len,int free_flag)
{
CHAIN_LIST64 * c;
	c = d_alloc(sizeof(*c));
	c->ptr = ptr;
	c->len = len;
	c->free_flag = free_flag;
	c->next = 0;
	if ( lst->chain_head ) {
		lst->chain_tail->next = c;
		lst->chain_tail = c;
	}
	else lst->chain_head = lst->chain_tail = c;
}


void
set_recordlist_chain64_middle(
	RECORD_LIST64 * lst,CHAIN_LIST64 * before,void * ptr,INTEGER64 len,int free_flag)
{
CHAIN_LIST64 * c;
	c = d_alloc(sizeof(*c));
	c->ptr = ptr;
	c->len = len;
	c->free_flag = free_flag;
	c->next= before->next;
	before->next = c;
}

void
setup_recordlist64_size(RECORD_LIST64 * lst)
{
int size;
CHAIN_LIST64 * c;
PN64_HEADER * hp;
	if ( lst->chain_head == 0 )
		return;
	size = lst->body = lst->header.size;
	for ( c = lst->chain_head ; c ; c = c->next )
		size += c->len;
	hp = (PN64_HEADER*)lst->data;
	hp->size = size;
}

void
_setup_recordlist64(RECORD_LIST64 * lst)
{
int size;
CHAIN_LIST64 * c;
char * ptr;
PN64_HEADER * hp;
	if ( lst->chain_head == 0 )
		return;
	size = lst->body = lst->header.size;
	for ( c = lst->chain_head ; c ; c = c->next )
		size += c->len;
	lst->data = d_re_alloc(lst->data,size);
	c = lst->chain_head;
	for ( ptr = ((char*)lst->data) + lst->body ; c ; c = c->next ) {
		memcpy(ptr,c->ptr,c->len);
		ptr += c->len;
	}
	lst->header.size = size;
	hp = (PN64_HEADER*)lst->data;
	hp->size = size;
	free_chain_list64(lst->chain_head);
	lst->chain_head = lst->chain_tail = 0;
}

void
setup_recordlist64(RECORD_LIST64 * lst)
{
	for ( ; lst ; lst = lst->next )
		_setup_recordlist64(lst);
}

void
free_chain_list64(CHAIN_LIST64 * c)
{
CHAIN_LIST64 * cc;
	for ( ; c ; ) {
		cc = c;
		c = c->next;
		if ( cc->free_flag )
			d_f_ree(cc->ptr);
		d_f_ree(cc);
	}
}

void
free_recordlist64(RECORD_LIST64 * lst)
{
RECORD_LIST64 * r;
	for ( ; lst ; ) {
		r = lst;
		lst = lst->next;
		free_chain_list64(r->chain_head);
		d_f_ree(r->data);
		d_f_ree(r);
	}
}

RECORD_LIST64 *
new_recordlist64(unsigned short type,U_INTEGER64 size)
{
RECORD_LIST64 * ret;
	ret = d_alloc(sizeof(*ret));
	ret->header.type = type;
	ret->header.size = size;
	ret->data = d_alloc(size);
	*((PN64_HEADER*)ret->data) = ret->header;
	ret->ptr = 0;
	ret->chain_head = ret->chain_tail = 0;
	ret->body = size;
	ret->next = 0;
	return ret;
}

