home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 35 Internet / 35-Internet.zip / ircd4652.zip / ircd-df-4.6.5-os2 / src / dbuf.c < prev    next >
C/C++ Source or Header  |  1997-12-28  |  7KB  |  352 lines

  1. /************************************************************************
  2.  *   IRC - Internet Relay Chat, common/dbuf.c
  3.  *   Copyright (C) 1990 Markku Savela
  4.  *
  5.  *   This program is free software; you can redistribute it and/or modify
  6.  *   it under the terms of the GNU General Public License as published by
  7.  *   the Free Software Foundation; either version 1, or (at your option)
  8.  *   any later version.
  9.  *
  10.  *   This program is distributed in the hope that it will be useful,
  11.  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  *   GNU General Public License for more details.
  14.  *
  15.  *   You should have received a copy of the GNU General Public License
  16.  *   along with this program; if not, write to the Free Software
  17.  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  */
  19.  
  20. /* -- Jto -- 20 Jun 1990
  21.  * extern void free() fixed as suggested by
  22.  * gruner@informatik.tu-muenchen.de
  23.  */
  24.  
  25. /* -- Jto -- 10 May 1990
  26.  * Changed memcpy into bcopy and removed the declaration of memset
  27.  * because it was unnecessary.
  28.  * Added the #includes for "struct.h" and "sys.h" to get bcopy/memcpy
  29.  * work
  30.  */
  31.  
  32. /*
  33. ** For documentation of the *global* functions implemented here,
  34. ** see the header file (dbuf.h).
  35. **
  36. */
  37.  
  38. #ifndef lint
  39. static  char sccsid[] = "@(#)dbuf.c    2.17 1/30/94 (C) 1990 Markku Savela";
  40. #endif
  41.  
  42. #include <stdio.h>
  43. #include "struct.h"
  44. #include "common.h"
  45. #include "sys.h"
  46.  
  47. #if !defined(VALLOC) && !defined(valloc)
  48. # ifndef _WIN32
  49. #  define    valloc malloc
  50. # else
  51. #  define    valloc MyMalloc
  52. # endif
  53. #endif
  54.  
  55. int    dbufalloc = 0, dbufblocks = 0;
  56. static    dbufbuf    *freelist = NULL;
  57.  
  58. /* This is a dangerous define because a broken compiler will set DBUFSIZ
  59. ** to 4, which will work but will be very inefficient. However, there
  60. ** are other places where the code breaks badly if this is screwed
  61. ** up, so... -- Wumpus
  62. */
  63.  
  64. #define DBUFSIZ sizeof(((dbufbuf *)0)->data)
  65.  
  66. /*
  67. ** dbuf_alloc - allocates a dbufbuf structure either from freelist or
  68. ** creates a new one.
  69. */
  70. static dbufbuf *dbuf_alloc()
  71. {
  72. #if defined(VALLOC) && !defined(DEBUGMODE)
  73.     Reg1    dbufbuf    *dbptr, *db2ptr;
  74.     Reg2    int    num;
  75. #else
  76.     Reg1    dbufbuf *dbptr;
  77. #endif
  78.  
  79.     dbufalloc++;
  80.     if ((dbptr = freelist))
  81.         {
  82.         freelist = freelist->next;
  83.         return dbptr;
  84.         }
  85.     if (dbufalloc * DBUFSIZ > BUFFERPOOL)
  86.         {
  87.         dbufalloc--;
  88.         return NULL;
  89.         }
  90.  
  91. #if defined(VALLOC) && !defined(DEBUGMODE)
  92. # if defined(SOL20) || defined(_SC_PAGESIZE)
  93.     num = sysconf(_SC_PAGESIZE)/sizeof(dbufbuf);
  94. # else
  95.     num = getpagesize()/sizeof(dbufbuf);
  96. # endif
  97.     if (num < 0)
  98.         num = 1;
  99.  
  100.     dbufblocks += num;
  101.  
  102.     dbptr = (dbufbuf *)valloc(num*sizeof(dbufbuf));
  103.     if (!dbptr)
  104.         return (dbufbuf *)NULL;
  105.  
  106.     num--;
  107.     for (db2ptr = dbptr; num; num--)
  108.         {
  109.         db2ptr = (dbufbuf *)((char *)db2ptr + sizeof(dbufbuf));
  110.         db2ptr->next = freelist;
  111.         freelist = db2ptr;
  112.         }
  113.     return dbptr;
  114. #else
  115.     dbufblocks++;
  116.     return (dbufbuf *)MyMalloc(sizeof(dbufbuf));
  117. #endif
  118. }
  119. /*
  120. ** dbuf_free - return a dbufbuf structure to the freelist
  121. */
  122. static    void    dbuf_free(ptr)
  123. Reg1    dbufbuf    *ptr;
  124. {
  125.     dbufalloc--;
  126.     ptr->next = freelist;
  127.     freelist = ptr;
  128. }
  129. /*
  130. ** This is called when malloc fails. Scrap the whole content
  131. ** of dynamic buffer and return -1. (malloc errors are FATAL,
  132. ** there is no reason to continue this buffer...). After this
  133. ** the "dbuf" has consistent EMPTY status... ;)
  134. */
  135. static int dbuf_malloc_error(dyn)
  136. dbuf *dyn;
  137.     {
  138.     dbufbuf *p;
  139.  
  140.     dyn->length = 0;
  141.     dyn->offset = 0;
  142.     while ((p = dyn->head) != NULL)
  143.         {
  144.         dyn->head = p->next;
  145.         dbuf_free(p);
  146.         }
  147.     dyn->tail = dyn->head;
  148.     return -1;
  149.     }
  150.  
  151.  
  152. int    dbuf_put(dyn, buf, length)
  153. dbuf    *dyn;
  154. char    *buf;
  155. int    length;
  156. {
  157.     Reg1    dbufbuf    **h, *d;
  158.     Reg2    int     off;
  159.     Reg3    int    chunk;
  160.  
  161.     if(!length) return 1; /* Nothing to do */
  162.  
  163.     off = (dyn->offset + dyn->length) % DBUFSIZ;
  164.     /*
  165.     ** Locate the last non-empty buffer. If the last buffer is
  166.     ** full, the loop will terminate with 'd==NULL'. This loop
  167.     ** assumes that the 'dyn->length' field is correctly
  168.     ** maintained, as it should--no other check really needed.
  169.     */
  170.     if (!dyn->length) h = &(dyn->head);
  171.     else {
  172.       if (off) h = &(dyn->tail);
  173.       else h = &(dyn->tail->next);
  174.     }
  175.     /*
  176.     ** Append users data to buffer, allocating buffers as needed
  177.     */
  178.     chunk = DBUFSIZ - off;
  179.     dyn->length += length;
  180.     for ( ;length > 0; h = &(d->next))
  181.         {
  182.         if ((d = *h) == NULL)
  183.             {
  184.             if ((d = (dbufbuf *)dbuf_alloc()) == NULL)
  185.                 return dbuf_malloc_error(dyn);
  186.             dyn->tail = d;
  187.             *h = d;
  188.             d->next = NULL;
  189.             }
  190.         if (chunk > length)
  191.             chunk = length;
  192.         bcopy(buf, d->data + off, chunk);
  193.         length -= chunk;
  194.         buf += chunk;
  195.         off = 0;
  196.         chunk = DBUFSIZ;
  197.         }
  198.     return 1;
  199.     }
  200.  
  201.  
  202. char    *dbuf_map(dyn,length)
  203. dbuf    *dyn;
  204. int    *length;
  205.     {
  206.     if (dyn->head == NULL)
  207.         {
  208.         dyn->tail = NULL;
  209.         *length = 0;
  210.         return NULL;
  211.         }
  212.     *length = DBUFSIZ - dyn->offset;
  213.     if (*length > dyn->length)
  214.         *length = dyn->length;
  215.     return (dyn->head->data + dyn->offset);
  216.     }
  217.  
  218. int    dbuf_delete(dyn,length)
  219. dbuf    *dyn;
  220. int    length;
  221.     {
  222.     dbufbuf *d;
  223.     int chunk;
  224.  
  225.     if (length > dyn->length)
  226.         length = dyn->length;
  227.     chunk = DBUFSIZ - dyn->offset;
  228.     while (length > 0)
  229.         {
  230.         if (chunk > length)
  231.             chunk = length;
  232.         length -= chunk;
  233.         dyn->offset += chunk;
  234.         dyn->length -= chunk;
  235.         if (dyn->offset == DBUFSIZ || dyn->length == 0)
  236.             {
  237.             d = dyn->head;
  238.             dyn->head = d->next;
  239.             dyn->offset = 0;
  240.             dbuf_free(d);
  241.             }
  242.         chunk = DBUFSIZ;
  243.         }
  244.     if (dyn->head == (dbufbuf *)NULL) {
  245.         dyn->length = 0;
  246.         dyn->tail = 0;
  247.     }
  248.     return 0;
  249.     }
  250.  
  251. int    dbuf_get(dyn, buf, length)
  252. dbuf    *dyn;
  253. char    *buf;
  254. int    length;
  255.     {
  256.     int    moved = 0;
  257.     int    chunk;
  258.     char    *b;
  259.  
  260.     while (length > 0 && (b = dbuf_map(dyn, &chunk)) != NULL)
  261.         {
  262.         if (chunk > length)
  263.             chunk = length;
  264.         bcopy(b, buf, (int)chunk);
  265.         (void)dbuf_delete(dyn, chunk);
  266.         buf += chunk;
  267.         length -= chunk;
  268.         moved += chunk;
  269.         }
  270.     return moved;
  271.     }
  272.  
  273. /*
  274. ** dbuf_getmsg
  275. **
  276. ** Check the buffers to see if there is a string which is terminted with
  277. ** either a \r or \n prsent.  If so, copy as much as possible (determined by
  278. ** length) into buf and return the amount copied - else return 0.
  279. */
  280. int    dbuf_getmsg(dyn, buf, length)
  281. dbuf    *dyn;
  282. char    *buf;
  283. register int    length;
  284. {
  285.     dbufbuf    *d;
  286.     register char    *s;
  287.     register int    dlen;
  288.     register int    i;
  289.     int    copy;
  290.  
  291. getmsg_init:
  292.     d = dyn->head;
  293.     dlen = dyn->length;
  294.     i = DBUFSIZ - dyn->offset;
  295.     if (i <= 0)
  296.         return -1;
  297.     copy = 0;
  298.     if (d && dlen)
  299.         s = dyn->offset + d->data;
  300.     else
  301.         return 0;
  302.  
  303.     if (i > dlen)
  304.         i = dlen;
  305.     while (length > 0 && dlen > 0)
  306.         {
  307.         dlen--;
  308.         if (*s == '\n' || *s == '\r')
  309.             {
  310.             copy = dyn->length - dlen;
  311.             /*
  312.             ** Shortcut this case here to save time elsewhere.
  313.             ** -avalon
  314.             */
  315.             if (copy == 1)
  316.                 {
  317.                 (void)dbuf_delete(dyn, 1);
  318.                 goto getmsg_init;
  319.                 }
  320.             break;
  321.             }
  322.         length--;
  323.         if (!--i)
  324.             {
  325.             if ((d = d->next))
  326.                 {
  327.                 s = d->data;
  328.                 i = MIN(DBUFSIZ, dlen);
  329.                 }
  330.             }
  331.         else
  332.             s++;
  333.         }
  334.  
  335.     if (copy <= 0)
  336.         return 0;
  337.  
  338.     /*
  339.     ** copy as much of the message as wanted into parse buffer
  340.     */
  341.     i = dbuf_get(dyn, buf, MIN(copy, length));
  342.     /*
  343.     ** and delete the rest of it!
  344.     */
  345.     if (copy - i > 0)
  346.         (void)dbuf_delete(dyn, copy - i);
  347.     if (i >= 0)
  348.         *(buf+i) = '\0';    /* mark end of messsage */
  349.  
  350.     return i;
  351. }
  352.