init
This commit is contained in:
345
common/dbuf.c
Normal file
345
common/dbuf.c
Normal file
@@ -0,0 +1,345 @@
|
||||
/************************************************************************
|
||||
* IRC - Internet Relay Chat, common/dbuf.c
|
||||
* Copyright (C) 1990 Markku Savela
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 1, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* 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. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/* -- Jto -- 20 Jun 1990
|
||||
* extern void free() fixed as suggested by
|
||||
* gruner@informatik.tu-muenchen.de
|
||||
*/
|
||||
|
||||
/* -- Jto -- 10 May 1990
|
||||
* Changed memcpy into bcopy and removed the declaration of memset
|
||||
* because it was unnecessary.
|
||||
* Added the #includes for "struct.h" and "sys.h" to get bcopy/memcpy
|
||||
* work
|
||||
*/
|
||||
|
||||
/*
|
||||
** For documentation of the *global* functions implemented here,
|
||||
** see the header file (dbuf.h).
|
||||
**
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)dbuf.c 2.17 1/30/94 (C) 1990 Markku Savela";
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include "struct.h"
|
||||
#include "common.h"
|
||||
#include "sys.h"
|
||||
|
||||
#if !defined(VALLOC) && !defined(valloc)
|
||||
#define valloc malloc
|
||||
#endif
|
||||
|
||||
int dbufalloc = 0, dbufblocks = 0;
|
||||
static dbufbuf *freelist = NULL;
|
||||
|
||||
/* This is a dangerous define because a broken compiler will set DBUFSIZ
|
||||
** to 4, which will work but will be very inefficient. However, there
|
||||
** are other places where the code breaks badly if this is screwed
|
||||
** up, so... -- Wumpus
|
||||
*/
|
||||
|
||||
#define DBUFSIZ sizeof(((dbufbuf *)0)->data)
|
||||
|
||||
/*
|
||||
** dbuf_alloc - allocates a dbufbuf structure either from freelist or
|
||||
** creates a new one.
|
||||
*/
|
||||
static dbufbuf *dbuf_alloc()
|
||||
{
|
||||
#if defined(VALLOC) && !defined(DEBUGMODE)
|
||||
Reg1 dbufbuf *dbptr, *db2ptr;
|
||||
Reg2 int num;
|
||||
#else
|
||||
Reg1 dbufbuf *dbptr;
|
||||
#endif
|
||||
|
||||
dbufalloc++;
|
||||
if ((dbptr = freelist))
|
||||
{
|
||||
freelist = freelist->next;
|
||||
return dbptr;
|
||||
}
|
||||
if (dbufalloc * DBUFSIZ > BUFFERPOOL)
|
||||
{
|
||||
dbufalloc--;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if defined(VALLOC) && !defined(DEBUGMODE)
|
||||
# if defined(SOL20) || defined(_SC_PAGESIZE)
|
||||
num = sysconf(_SC_PAGESIZE)/sizeof(dbufbuf);
|
||||
# else
|
||||
num = getpagesize()/sizeof(dbufbuf);
|
||||
# endif
|
||||
if (num < 0)
|
||||
num = 1;
|
||||
|
||||
dbufblocks += num;
|
||||
|
||||
dbptr = (dbufbuf *)valloc(num*sizeof(dbufbuf));
|
||||
if (!dbptr)
|
||||
return (dbufbuf *)NULL;
|
||||
|
||||
num--;
|
||||
for (db2ptr = dbptr; num; num--)
|
||||
{
|
||||
db2ptr = (dbufbuf *)((char *)db2ptr + sizeof(dbufbuf));
|
||||
db2ptr->next = freelist;
|
||||
freelist = db2ptr;
|
||||
}
|
||||
return dbptr;
|
||||
#else
|
||||
dbufblocks++;
|
||||
return (dbufbuf *)MyMalloc(sizeof(dbufbuf));
|
||||
#endif
|
||||
}
|
||||
/*
|
||||
** dbuf_free - return a dbufbuf structure to the freelist
|
||||
*/
|
||||
static void dbuf_free(ptr)
|
||||
Reg1 dbufbuf *ptr;
|
||||
{
|
||||
dbufalloc--;
|
||||
ptr->next = freelist;
|
||||
freelist = ptr;
|
||||
}
|
||||
/*
|
||||
** This is called when malloc fails. Scrap the whole content
|
||||
** of dynamic buffer and return -1. (malloc errors are FATAL,
|
||||
** there is no reason to continue this buffer...). After this
|
||||
** the "dbuf" has consistent EMPTY status... ;)
|
||||
*/
|
||||
static int dbuf_malloc_error(dyn)
|
||||
dbuf *dyn;
|
||||
{
|
||||
dbufbuf *p;
|
||||
|
||||
dyn->length = 0;
|
||||
dyn->offset = 0;
|
||||
while ((p = dyn->head) != NULL)
|
||||
{
|
||||
dyn->head = p->next;
|
||||
dbuf_free(p);
|
||||
}
|
||||
dyn->tail = dyn->head;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int dbuf_put(dyn, buf, length)
|
||||
dbuf *dyn;
|
||||
char *buf;
|
||||
int length;
|
||||
{
|
||||
Reg1 dbufbuf **h, *d;
|
||||
Reg2 int off;
|
||||
Reg3 int chunk;
|
||||
|
||||
off = (dyn->offset + dyn->length) % DBUFSIZ;
|
||||
/*
|
||||
** Locate the last non-empty buffer. If the last buffer is
|
||||
** full, the loop will terminate with 'd==NULL'. This loop
|
||||
** assumes that the 'dyn->length' field is correctly
|
||||
** maintained, as it should--no other check really needed.
|
||||
*/
|
||||
if (!dyn->length) h = &(dyn->head);
|
||||
else {
|
||||
if (off) h = &(dyn->tail);
|
||||
else h = &(dyn->tail->next);
|
||||
}
|
||||
/*
|
||||
** Append users data to buffer, allocating buffers as needed
|
||||
*/
|
||||
chunk = DBUFSIZ - off;
|
||||
dyn->length += length;
|
||||
for ( ;length > 0; h = &(d->next))
|
||||
{
|
||||
if ((d = *h) == NULL)
|
||||
{
|
||||
if ((d = (dbufbuf *)dbuf_alloc()) == NULL)
|
||||
return dbuf_malloc_error(dyn);
|
||||
dyn->tail = d;
|
||||
*h = d;
|
||||
d->next = NULL;
|
||||
}
|
||||
if (chunk > length)
|
||||
chunk = length;
|
||||
bcopy(buf, d->data + off, chunk);
|
||||
length -= chunk;
|
||||
buf += chunk;
|
||||
off = 0;
|
||||
chunk = DBUFSIZ;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
char *dbuf_map(dyn,length)
|
||||
dbuf *dyn;
|
||||
int *length;
|
||||
{
|
||||
if (dyn->head == NULL)
|
||||
{
|
||||
dyn->tail = NULL;
|
||||
*length = 0;
|
||||
return NULL;
|
||||
}
|
||||
*length = DBUFSIZ - dyn->offset;
|
||||
if (*length > dyn->length)
|
||||
*length = dyn->length;
|
||||
return (dyn->head->data + dyn->offset);
|
||||
}
|
||||
|
||||
int dbuf_delete(dyn,length)
|
||||
dbuf *dyn;
|
||||
int length;
|
||||
{
|
||||
dbufbuf *d;
|
||||
int chunk;
|
||||
|
||||
if (length > dyn->length)
|
||||
length = dyn->length;
|
||||
chunk = DBUFSIZ - dyn->offset;
|
||||
while (length > 0)
|
||||
{
|
||||
if (chunk > length)
|
||||
chunk = length;
|
||||
length -= chunk;
|
||||
dyn->offset += chunk;
|
||||
dyn->length -= chunk;
|
||||
if (dyn->offset == DBUFSIZ || dyn->length == 0)
|
||||
{
|
||||
d = dyn->head;
|
||||
dyn->head = d->next;
|
||||
dyn->offset = 0;
|
||||
dbuf_free(d);
|
||||
}
|
||||
chunk = DBUFSIZ;
|
||||
}
|
||||
if (dyn->head == (dbufbuf *)NULL) {
|
||||
dyn->length = 0;
|
||||
dyn->tail = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dbuf_get(dyn, buf, length)
|
||||
dbuf *dyn;
|
||||
char *buf;
|
||||
int length;
|
||||
{
|
||||
int moved = 0;
|
||||
int chunk;
|
||||
char *b;
|
||||
|
||||
while (length > 0 && (b = dbuf_map(dyn, &chunk)) != NULL)
|
||||
{
|
||||
if (chunk > length)
|
||||
chunk = length;
|
||||
bcopy(b, buf, (int)chunk);
|
||||
(void)dbuf_delete(dyn, chunk);
|
||||
buf += chunk;
|
||||
length -= chunk;
|
||||
moved += chunk;
|
||||
}
|
||||
return moved;
|
||||
}
|
||||
|
||||
/*
|
||||
** dbuf_getmsg
|
||||
**
|
||||
** Check the buffers to see if there is a string which is terminted with
|
||||
** either a \r or \n prsent. If so, copy as much as possible (determined by
|
||||
** length) into buf and return the amount copied - else return 0.
|
||||
*/
|
||||
int dbuf_getmsg(dyn, buf, length)
|
||||
dbuf *dyn;
|
||||
char *buf;
|
||||
register int length;
|
||||
{
|
||||
dbufbuf *d;
|
||||
register char *s;
|
||||
register int dlen;
|
||||
register int i;
|
||||
int copy;
|
||||
|
||||
getmsg_init:
|
||||
d = dyn->head;
|
||||
dlen = dyn->length;
|
||||
i = DBUFSIZ - dyn->offset;
|
||||
if (i <= 0)
|
||||
return -1;
|
||||
copy = 0;
|
||||
if (d && dlen)
|
||||
s = dyn->offset + d->data;
|
||||
else
|
||||
return 0;
|
||||
|
||||
if (i > dlen)
|
||||
i = dlen;
|
||||
while (length > 0 && dlen > 0)
|
||||
{
|
||||
dlen--;
|
||||
if (*s == '\n' || *s == '\r')
|
||||
{
|
||||
copy = dyn->length - dlen;
|
||||
/*
|
||||
** Shortcut this case here to save time elsewhere.
|
||||
** -avalon
|
||||
*/
|
||||
if (copy == 1)
|
||||
{
|
||||
(void)dbuf_delete(dyn, 1);
|
||||
goto getmsg_init;
|
||||
}
|
||||
break;
|
||||
}
|
||||
length--;
|
||||
if (!--i)
|
||||
{
|
||||
if ((d = d->next))
|
||||
{
|
||||
s = d->data;
|
||||
i = MIN(DBUFSIZ, dlen);
|
||||
}
|
||||
}
|
||||
else
|
||||
s++;
|
||||
}
|
||||
|
||||
if (copy <= 0)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
** copy as much of the message as wanted into parse buffer
|
||||
*/
|
||||
i = dbuf_get(dyn, buf, MIN(copy, length));
|
||||
/*
|
||||
** and delete the rest of it!
|
||||
*/
|
||||
if (copy - i > 0)
|
||||
(void)dbuf_delete(dyn, copy - i);
|
||||
if (i >= 0)
|
||||
*(buf+i) = '\0'; /* mark end of messsage */
|
||||
|
||||
return i;
|
||||
}
|
||||
Reference in New Issue
Block a user