"Fossies" - the Fresh Open Source Software Archive

Member "netbiff-0.9.18/buffer.c" (21 Sep 2003, 4020 Bytes) of package /linux/privat/old/netbiff-0.9.18.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 #include "buffer.h"
    2 #include "xlib.h"
    3 
    4 #include <stdlib.h>
    5 #include <string.h>
    6 
    7 void buffer_init(Buffer *b) {
    8   b->size = 0;
    9   b->head = b->tail = NULL;
   10 }
   11 
   12 void buffer_finish(Buffer *b) {
   13   BufferChunk *bc, *next;
   14 
   15   for(bc = b->head; bc; bc = next) {
   16     next= bc->next;
   17     free(bc->buf);
   18     free(bc);
   19   }
   20   b->head = b->tail = NULL;
   21   b->size = 0;
   22 }
   23 
   24 void buffer_put(Buffer *b, const char *s, unsigned long len) {
   25   BufferChunk *bc;
   26 
   27   bc = xmalloc(sizeof(BufferChunk));
   28   bc->len = len;
   29   bc->buf = xmalloc(len + 1);
   30   memcpy(bc->buf, s, len);
   31   bc->buf[len] = '\0';
   32   bc->next = NULL;
   33 
   34   if(b->tail)
   35     b->tail->next = bc;
   36   else
   37     b->head = bc;
   38   b->tail = bc;
   39 
   40   b->size += len;
   41 }
   42 
   43 static void compact_buffer_to_lines(Buffer *b) {
   44   BufferChunk *old;
   45   int in_line_flag;
   46 
   47   old = b->head;
   48   b->head = b->tail = NULL;
   49 
   50   in_line_flag = 0;
   51   while(old) {
   52     BufferChunk *next = old->next;
   53 
   54     /* If the old chunk was a line, we steal it. */
   55     if(!in_line_flag && 
   56         memchr(old->buf, '\n', old->len) == old->buf + old->len - 1) {
   57       old->next = NULL;
   58       if(b->tail)
   59         b->tail->next = old;
   60       else
   61         b->head = old;
   62       b->tail = old;
   63     }
   64     /* Otherwise, add all lines */
   65     else {
   66       char *p = old->buf;
   67       while(p) {
   68         char *q;
   69         unsigned long len;
   70 
   71         /* If there are no more complete lines, save what we have
   72          * and quit. */
   73         q = memchr(p, '\n', old->len - (p - old->buf));
   74         if(!q)
   75           len = old->len - (p - old->buf);
   76         else
   77           len = q - p + 1;
   78 
   79         /* No point in adding 0 bytes */
   80         if(len) {
   81           /* Add to the last if we're continuing a line. */
   82           if(in_line_flag) {
   83             unsigned long prevlen = b->tail->len;
   84             b->tail->len += len;
   85             b->tail->buf = xrealloc(b->tail->buf, b->tail->len + 1);
   86             memcpy(b->tail->buf + prevlen, p, len);
   87             b->tail->buf[b->tail->len] = '\0';
   88           }
   89           else {
   90             BufferChunk *c;
   91             c = xmalloc(sizeof(BufferChunk));
   92             c->len = len;
   93             c->buf = xmalloc(len + 1);
   94             memcpy(c->buf, p, len);
   95             c->buf[len] = '\0';
   96             c->next = NULL;
   97             if(b->tail) 
   98               b->tail->next = c;
   99             else
  100               b->head = c;
  101             b->tail = c;
  102           }
  103         }
  104 
  105         p = q;
  106         if(!q) {
  107           if(len)
  108             in_line_flag = 1;
  109         }
  110         else {
  111           in_line_flag = 0;
  112           p++;
  113         }
  114       }
  115       free(old->buf);
  116       free(old);
  117     }
  118     old = next;
  119   }
  120 }
  121 
  122 char *buffer_get_line(Buffer *b) {
  123   BufferChunk *bc;
  124 
  125   /* If we have no data, we have no lines. */
  126   bc = b->head;
  127   if(!bc)
  128     return NULL;
  129 
  130   /* If our first chunk is a single, complete line,
  131    * we were probably just compacted. Return the line. */
  132   if(memchr(bc->buf, '\n', bc->len) == bc->buf + bc->len - 1) {
  133     char *buf;
  134     b->head = bc->next;
  135     if(!b->head)
  136       b->tail = NULL;
  137     buf = bc->buf;
  138     b->size -= bc->len;
  139     free(bc);
  140     return buf;
  141   }
  142 
  143   /* Otherwise we need to reorganize the data in lines. */
  144   compact_buffer_to_lines(b);
  145 
  146   /* Each chunk should now be either a line *or* part of a line
  147    * but never multiple lines. Note that bc is no longer valid
  148    * after compacting.  */
  149   bc = b->head;
  150   if(!bc)
  151     return NULL;
  152   if(bc->buf[bc->len - 1] == '\n') {
  153     char *buf;
  154     b->head = bc->next;
  155     if(!b->head)
  156       b->tail = NULL;
  157     buf = bc->buf;
  158     b->size -= bc->len;
  159     return buf;
  160   }
  161 
  162   /* If we're part of a line, we have no line. */
  163   return NULL;
  164 }
  165 
  166 int buffer_get(Buffer *b, char **dest) {
  167   BufferChunk *bc;
  168   BufferChunk *next;
  169   char *pos;
  170 
  171   if(!b->size) {
  172     *dest = NULL;
  173     return 0;
  174   }
  175   
  176   pos = *dest = xmalloc(b->size);
  177   for(bc = b->head; bc; bc = next) {
  178     next = bc->next;
  179 
  180     memcpy(pos, bc->buf, bc->len);
  181     pos += bc->len;
  182     free(bc->buf);
  183     free(bc);
  184   }
  185   b->size = 0;
  186   b->head = b->tail = NULL;
  187   return pos - *dest;
  188 }
  189 
  190