[IRCServices Coding] svcs5 - request

v13 at priest.com v13 at priest.com
Sun Jan 6 15:42:09 PST 2002


On Sunday 06 January 2002 23:05, Finny Merrill wrote:
> On Sun, 6 Jan 2002, Ben Goldstein wrote:
> 
> Well the thing is, you would need a pointer to a function
> that prints it to a file, as we dont know whether it contains
> ints, chars, shorts, longs, or whatever.

This is the needed code.. I hope that there are no faults.. Use it if you 
like.. The struct contains a filed named 'type' This indicates that buf is an 
char buffer, an array of 16 bit values, or an array of 32 bit values.
The types that are used, are uint8,16 and 32. This means that this should 
make the databases portable from 32bit machines to 64 bit machines as long as 
the head is not written to the database (I believe that pointers are 64 bit 
long on every 64bit machine and 32bit long on 32bit machines)

The read/write routines are ready to be added to services4 database 
read/write functions. I don't know what are the plans for the new database 
format. 

1st Define this struct

struct ext_list {
	struct ext_list	*next;
	uint32		id;
	uint32		size;
	uint8		type;
	void		*buf;
};

2nd add to the desired existing structures this:
e.x.

struct NickInfo {
...
	struct ext_list head;	/* Yes.. not a pointer. Just make sure that this has */
				/* id==0, size==0, buf==NULL, next==NULL on startup */
				/* Use el_clear provided below to do this el_clear(&ni->head) */
};

3rd define:

#define EL_AS_IS	1
#define EL_8BIT		EL_AS_IS
#define EL_16BIT	2
#define EL_32BIT	3

#define EL_SIZE(x)	( (x)==EL_8BIT ? 1 : ((x)==EL_16_BIT ? 2 : 4 ) )

void el_clear(struct ext_list *el) {
	el->next=NULL;
	el->id=0;
	el->size=0;
	el->buf=NULL;
	el->type=EL_AS_IS;
};

3rd add those generic functions:

/*
	Allocate and return a new ext_list
*/
struct ext_list *new_el() {
	struct ext_list	*el;

	el=(struct ext_list *)malloc(sizeof(struct ext_list));
	el_clear(el);

	return(el);
}

/*
	Return the desired el, or NULL if not found
*/
struct ext_list *get_el_memb(struct ext_list *head, uint32 id) {
	struct ext_list *el;
	el=head->next;	/* Ignore the head */

	while ((el!=NULL) && (el->id!=id))
		el=el->next;

	return(el);
}

/*
	Update or add an el
*/
void update_el_memb(struct ext_list *head, uint32 id, uint32 size, void *buf,
			uint8 type) {
	struct ext_list	*el;

	el=get_el_memb(head,id);	/* Check if it exists allready */
	if (el==NULL) {
		el=new_el();	/* if not, create it */
		el->id=id;
		el->next=head->next;	/* Update the list */
		head->next=el;
	} else {
		if (el->buf!=NULL)	/* Else free the old data */
			free(el->buf);
	}

	el->size=size;
	el->type=type;
	if (size>0) {	/* if there are data */
		el->buf=malloc(size);
		memcpy(el->buf, buf, size);	/* Copy the new data */
	} else el->buf=NULL;
}

/*
	Delete an el from a list
*/
void delete_el_memb(struct ext_list *head, uint32 id) {
	struct ext_list	*el,*prev;

	prev=&head
	el=head->next;
	while ((el!=NULL) && (el->id!=id)) {
		prev=el;
		el=el->next;
	}
	if (el!=NULL) {
		if (el->buf!=NULL)
			free(el->buf);
		prev->next=el->next;	/* prev always exists, becaus of head */
		free(el);
	}
}

/*
	Delete a whole list
*/
void delete_all_el(struct ext_list *head) {
	struct ext_list *el,*tmp;

	el=head->next;
	while (el!=NULL) {
		if (el->buf!=NULL)
			free(el->buf);
		tmp=el;
		el=el->next;
		free(tmp);
	}

	head->next=NULL;
}

/*
	Write the el list to f
*/
void el_write(FILE *f, struct ext_list *head) {
	struct ext_list *el;
	int		n,m;
	uint8		*p8;
	uint16		*p16;
	uint32		*p32;
	
	el=head->next;	/* Ignore the head */

	while (el!=NULL) {
		SAFE(write_int32(el->id,f));	/* First it is written the ID */
		SAFE(write_int32(el->size,f));
		SAFE(write_int8(el->type,f));

		if (el->size>0)	{ /* if there are data, write them too */
			switch(el->type) {
				case EL_8BIT:
					m=size;
					p8=(uint8 *)buf;
					break;
				case EL_16BIT:
					m=size/2;
					p16=(uint16 *)buf;
					break;
				case EL_32BIT:
					m=size/4;
					p32=(uint16 *)buf;
					break;
			}
			for (n=0;n<m;m++) {
				switch(el->type) {
					case EL_8BIT:
						SAFE(write_int8(p8[n],f);
						break;
					case EL_16BIT:
						SAFE(write_int16(p16[n],f);
						break;
					case EL_32BIT:
						SAFE(write_int32(p32[n],f);
						break;
				}
			}
		}

		el=el->next;
	}
	SAFE(write_int32(0,f)); /* Now write an ID==0 to indicate the end */
}

/*
	Read from f and append to head
*/
void el_read(FILE *f, struct ext_list *head) {
	struct ext_list el
	void		*buf;
	uint8		i8,*p8;
	uint16		i16,*p16;
	uint32		i32,*p32;
	int		n,m;

	SAFE(read_int32(&i32,f));
	while (i32!=0) {
		el.id=i32;
		SAFE(read_int32(&i32,f));
		el.size=i32;
		SAFE(read_int8(&i8,f));
		el.type=i8;

		if (el.size>0) { /* if there are data */
			buf=malloc(el.size);

			switch(el->type) {
				case EL_8BIT:
					m=size;
					p8=(uint8 *)buf;
					break;
				case EL_16BIT:
					m=size/2;
					p16=(uint16 *)buf;
					break;
				case EL_32BIT:
					m=size/4;
					p32=(uint16 *)buf;
					break;
			}

			for (n=0;n<m;m++) {	/* read them */
				switch(el->type) {
					case EL_8BIT:
						SAFE(read_int8(&(p8[n]),f);
						break;
					case EL_16BIT:
						SAFE(read_int16(&(p16[n]),f);
						break;
					case EL_32BIT:
						SAFE(read_int32(&(p32[n]),f);
						break;
				}
			}

			update_el_memb(head,el.id,el.size,buf); /* add them to the list */
			free(buf);	/* free the buffer */
		} else {
			update_el_memb(head,el.id,0,NULL); /* add them to the list */
		}
	}
}

<<V13>>

p.s. Sorry for the tabs :)