home *** CD-ROM | disk | FTP | other *** search
/ The Net: Ultimate Internet Guide / WWLCD1.ISO / pc / java / in4wjcxu / other / irc / common / dbuf.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-08-14  |  7.4 KB  |  375 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. #define    valloc malloc
  49. #endif
  50.  
  51. int    dbufalloc = 0, dbufblocks = 0;
  52. static    dbufbuf    *freelist = NULL;
  53.  
  54. /* This is a dangerous define because a broken compiler will set DBUFSIZ
  55. ** to 4, which will work but will be very inefficient. However, there
  56. ** are other places where the code breaks badly if this is screwed
  57. ** up, so... -- Wumpus
  58. */
  59.  
  60. #define DBUFSIZ sizeof(((dbufbuf *)0)->data)
  61.  
  62. /*
  63. ** dbuf_alloc - allocates a dbufbuf structure either from freelist or
  64. ** creates a new one.
  65. */
  66. static dbufbuf *dbuf_alloc()
  67. {
  68. #if defined(VALLOC) && !defined(DEBUGMODE)
  69.     Reg1    dbufbuf    *dbptr, *db2ptr;
  70.     Reg2    int    num;
  71. #else
  72.     Reg1    dbufbuf *dbptr;
  73. #endif
  74.  
  75.     dbufalloc++;
  76.     if ((dbptr = freelist))
  77.         {
  78.         freelist = freelist->next;
  79.         return dbptr;
  80.         }
  81.     if (dbufalloc * DBUFSIZ > BUFFERPOOL)
  82.         {
  83.         dbufalloc--;
  84.         return NULL;
  85.         }
  86.  
  87. #if defined(VALLOC) && !defined(DEBUGMODE)
  88. # if defined(SOL20) || defined(_SC_PAGESIZE)
  89.     num = sysconf(_SC_PAGESIZE)/sizeof(dbufbuf);
  90. # else
  91.     num = getpagesize()/sizeof(dbufbuf);
  92. # endif
  93.     if (num < 0)
  94.         num = 1;
  95.  
  96.     dbufblocks += num;
  97.  
  98.     dbptr = (dbufbuf *)valloc(num*sizeof(dbufbuf));
  99.     if (!dbptr)
  100.         return (dbufbuf *)NULL;
  101.  
  102.     num--;
  103.     for (db2ptr = dbptr; num; num--)
  104.         {
  105.         db2ptr = (dbufbuf *)((char *)db2ptr + sizeof(dbufbuf));
  106.         db2ptr->next = freelist;
  107.         freelist = db2ptr;
  108.         }
  109.     return dbptr;
  110. #else
  111.     dbufblocks++;
  112.     return (dbufbuf *)MyMalloc(sizeof(dbufbuf));
  113. #endif
  114. }
  115. /*
  116. ** dbuf_free - return a dbufbuf structure to the freelist
  117. */
  118. static    void    dbuf_free(ptr)
  119. Reg1    dbufbuf    *ptr;
  120. {
  121.     dbufalloc--;
  122.     ptr->next = freelist;
  123.     freelist = ptr;
  124. }
  125. /*
  126. ** This is called when malloc fails. Scrap the whole content
  127. ** of dynamic buffer and return -1. (malloc errors are FATAL,
  128. ** there is no reason to continue this buffer...). After this
  129. ** the "dbuf" has consistent EMPTY status... ;)
  130. */
  131. static int dbuf_malloc_error(dyn)
  132. dbuf *dyn;
  133.     {
  134.     dbufbuf *p;
  135.  
  136.     dyn->length = 0;
  137.     dyn->offset = 0;
  138.     while ((p = dyn->head) != NULL)
  139.         {
  140.         dyn->head = p->next;
  141.         dbuf_free(p);
  142.         }
  143.     return -1;
  144.     }
  145.  
  146.  
  147. int    dbuf_put(dyn, buf, length)
  148. dbuf    *dyn;
  149. char    *buf;
  150. int    length;
  151. {
  152.     Reg1    dbufbuf    **h, *d;
  153.     Reg2    int    nbr, off;
  154.     Reg3    int    chunk;
  155.  
  156.     off = (dyn->offset + dyn->length) % DBUFSIZ;
  157.     nbr = (dyn->offset + dyn->length) / DBUFSIZ;
  158.     /*
  159.     ** Locate the last non-empty buffer. If the last buffer is
  160.     ** full, the loop will terminate with 'd==NULL'. This loop
  161.     ** assumes that the 'dyn->length' field is correctly
  162.     ** maintained, as it should--no other check really needed.
  163.     */
  164.     for (h = &(dyn->head); (d = *h) && --nbr >= 0; h = &(d->next));
  165.     /*
  166.     ** Append users data to buffer, allocating buffers as needed
  167.     */
  168.     chunk = DBUFSIZ - off;
  169.     dyn->length += length;
  170.     for ( ;length > 0; h = &(d->next))
  171.         {
  172.         if ((d = *h) == NULL)
  173.             {
  174.             if ((d = (dbufbuf *)dbuf_alloc()) == NULL)
  175.                 return dbuf_malloc_error(dyn);
  176.             *h = d;
  177.             d->next = NULL;
  178.             }
  179.         if (chunk > length)
  180.             chunk = length;
  181.         bcopy(buf, d->data + off, chunk);
  182.         length -= chunk;
  183.         buf += chunk;
  184.         off = 0;
  185.         chunk = DBUFSIZ;
  186.         }
  187.     return 1;
  188.     }
  189.  
  190.  
  191. char    *dbuf_map(dyn,length)
  192. dbuf    *dyn;
  193. int    *length;
  194.     {
  195.     if (dyn->head == NULL)
  196.         {
  197.         *length = 0;
  198.         return NULL;
  199.         }
  200.     *length = DBUFSIZ - dyn->offset;
  201.     if (*length > dyn->length)
  202.         *length = dyn->length;
  203.     return (dyn->head->data + dyn->offset);
  204.     }
  205.  
  206. int    dbuf_delete(dyn,length)
  207. dbuf    *dyn;
  208. int    length;
  209.     {
  210.     dbufbuf *d;
  211.     int chunk;
  212.  
  213.     if (length > dyn->length)
  214.         length = dyn->length;
  215.     chunk = DBUFSIZ - dyn->offset;
  216.     while (length > 0)
  217.         {
  218.         if (chunk > length)
  219.             chunk = length;
  220.         length -= chunk;
  221.         dyn->offset += chunk;
  222.         dyn->length -= chunk;
  223.         if (dyn->offset == DBUFSIZ || dyn->length == 0)
  224.             {
  225.             d = dyn->head;
  226.             dyn->head = d->next;
  227.             dyn->offset = 0;
  228.             dbuf_free(d);
  229.             }
  230.         chunk = DBUFSIZ;
  231.         }
  232.     if (dyn->head == (dbufbuf *)NULL)
  233.         dyn->length = 0;
  234.     return 0;
  235.     }
  236.  
  237. int    dbuf_get(dyn, buf, length)
  238. dbuf    *dyn;
  239. char    *buf;
  240. int    length;
  241.     {
  242.     int    moved = 0;
  243.     int    chunk;
  244.     char    *b;
  245.  
  246.     while (length > 0 && (b = dbuf_map(dyn, &chunk)) != NULL)
  247.         {
  248.         if (chunk > length)
  249.             chunk = length;
  250.         bcopy(b, buf, (int)chunk);
  251.         (void)dbuf_delete(dyn, chunk);
  252.         buf += chunk;
  253.         length -= chunk;
  254.         moved += chunk;
  255.         }
  256.     return moved;
  257.     }
  258.  
  259. /*
  260. int    dbuf_copy(dyn, buf, length)
  261. dbuf    *dyn;
  262. register char    *buf;
  263. int    length;
  264. {
  265.     register dbufbuf    *d = dyn->head;
  266.     register char    *s;
  267.     register int    chunk, len = length, dlen = dyn->length;
  268.  
  269.     s = d->data + dyn->offset;
  270.     chunk = MIN(DBUFSIZ - dyn->offset, dlen);
  271.  
  272.     while (len > 0)
  273.         {
  274.         if (chunk > dlen)
  275.             chunk = dlen;
  276.         if (chunk > len)
  277.             chunk = len;
  278.  
  279.         bcopy(s, buf, chunk);
  280.         buf += chunk;
  281.         len -= chunk;
  282.         dlen -= chunk;
  283.  
  284.         if (dlen > 0 && (d = d->next))
  285.             {
  286.             chunk = DBUFSIZ;
  287.             s = d->data;
  288.             }
  289.         else
  290.             break;
  291.         }
  292.     return length - len;
  293. }
  294. */
  295.  
  296. /*
  297. ** dbuf_getmsg
  298. **
  299. ** Check the buffers to see if there is a string which is terminted with
  300. ** either a \r or \n prsent.  If so, copy as much as possible (determined by
  301. ** length) into buf and return the amount copied - else return 0.
  302. */
  303. int    dbuf_getmsg(dyn, buf, length)
  304. dbuf    *dyn;
  305. char    *buf;
  306. register int    length;
  307. {
  308.     dbufbuf    *d;
  309.     register char    *s;
  310.     register int    dlen;
  311.     register int    i;
  312.     int    copy;
  313.  
  314. getmsg_init:
  315.     d = dyn->head;
  316.     dlen = dyn->length;
  317.     i = DBUFSIZ - dyn->offset;
  318.     if (i <= 0)
  319.         return -1;
  320.     copy = 0;
  321.     if (d && dlen)
  322.         s = dyn->offset + d->data;
  323.     else
  324.         return 0;
  325.  
  326.     if (i > dlen)
  327.         i = dlen;
  328.     while (length > 0 && dlen > 0)
  329.         {
  330.         dlen--;
  331.         if (*s == '\n' || *s == '\r')
  332.             {
  333.             copy = dyn->length - dlen;
  334.             /*
  335.             ** Shortcut this case here to save time elsewhere.
  336.             ** -avalon
  337.             */
  338.             if (copy == 1)
  339.                 {
  340.                 (void)dbuf_delete(dyn, 1);
  341.                 goto getmsg_init;
  342.                 }
  343.             break;
  344.             }
  345.         length--;
  346.         if (!--i)
  347.             {
  348.             if ((d = d->next))
  349.                 {
  350.                 s = d->data;
  351.                 i = MIN(DBUFSIZ, dlen);
  352.                 }
  353.             }
  354.         else
  355.             s++;
  356.         }
  357.  
  358.     if (copy <= 0)
  359.         return 0;
  360.  
  361.     /*
  362.     ** copy as much of the message as wanted into parse buffer
  363.     */
  364.     i = dbuf_get(dyn, buf, MIN(copy, length));
  365.     /*
  366.     ** and delete the rest of it!
  367.     */
  368.     if (copy - i > 0)
  369.         (void)dbuf_delete(dyn, copy - i);
  370.     if (i >= 0)
  371.         *(buf+i) = '\0';    /* mark end of messsage */
  372.  
  373.     return i;
  374. }
  375.