"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. For more information about "buffer.c" see the Fossies "Dox" file reference documentation.

    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