home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload / ShartewareOverload.cdr / progm / ibmcom.zip / CIRC_BUF.C < prev    next >
Text File  |  1987-11-11  |  14KB  |  343 lines

  1. /***************************************************
  2. *                                                  *
  3. *            C I R C _ B U F                       *
  4. *            ===============                       *
  5. *                                                  *
  6. *  Comments: Circluar buffer routines for                *
  7. *                maintenamce,insertion into, and            *
  8. *                 extraction from, status of,etc..        *
  9. *                                                                    *
  10. *    Compilation Instructions:                                *
  11. *        Compile this file with TEST set to FALSE        *
  12. *        to use with your routines. Set TEST to TRUE    *
  13. *        to test these routines by themseleves.            *
  14. *                                                                    *
  15. *    Linking Instructions:                                    *
  16. *        Not a main file (unless you compile with        *
  17. *        TEST set to TRUE).  Must be linked with        *
  18. *        a main().                                                *
  19. *                                                                    *
  20. *    References Used:                                             *
  21. *        Interrupts and the IBM PC Parts 1&2,            *
  22. *        Nov/Dec 83,January 84,PC Tech Journal            *
  23. *                                                                    *          
  24. *                                                                   *
  25. *  Programmer(s):  Al Morgan                       *
  26. *                                                                    *
  27. *  Revision 1.0                                               *
  28. *  Revision Date:09/17/1987                                *
  29. *                                                                    *
  30. *    References Used:                                             *
  31. *                                                                   *
  32. ***************************************************/
  33.  
  34.  
  35.     #include <stdio.h>
  36.     #include <dos.h>
  37.     #include "circ_buf.h"            /* contains circular buffer definitions */
  38.     #define    TRUE    1
  39.     #define    FALSE    0
  40.  
  41.     #define    TEST        FALSE        /* Set to TRUE for testing the routines in this file */ 
  42.  
  43. #if TEST==TRUE
  44.     circ_buffer_description buffer_descript;
  45.  
  46.     char test_buffer[]={"01234567890"};
  47.     void test_cir(void);
  48.     void reset_circ_buffer(circ_buffer_description *);
  49.  
  50. main()
  51. {
  52.     printf("Testing %s\n",__FILE__);
  53.     printf("Version Date: %s, Time: %s\n",__DATE__,__TIME__);
  54.  
  55.     test_cir();
  56. }
  57. void test_cir(void)
  58. {
  59.     char in_string[100],tmp[100];
  60.     int count,i;
  61.  
  62.     /* Test Case 1 */
  63.     for(i=0;i<100;i++)
  64.         in_string[i]='0'+i;
  65.     for(i=0;i<sizeof(test_buffer);i++)
  66.         test_buffer[i]='.';
  67.  
  68.     buffer_descript.head      = test_buffer;
  69.     buffer_descript.tail      = test_buffer;
  70.     buffer_descript.address  = test_buffer;
  71.     buffer_descript.length         = 10;
  72.     buffer_descript.char_count     = 0;
  73.  
  74.     for (i=0;i<10;i++)
  75.     {
  76.         printf("\nCirc_buf Test case %d\n",i);
  77.          print_test_buffer(test_buffer);
  78.         print_bufr_descript(&buffer_descript);
  79.         count = puts_circ_buffer (in_string,3,&buffer_descript);
  80.         if(count != 3)
  81.             printf("Error on puts_circ_buffer()\n");
  82.         if(check_circ_buffer_fill(&buffer_descript) != buffer_descript.char_count)
  83.             printf("Error in check_cir_buffer_fill()\n");
  84.         if (check_circ_buffer_over(&buffer_descript))
  85.             printf("Error in check_cir_over()\n");
  86.         count = gets_circ_buffer(tmp,1,&buffer_descript);
  87.         if(count != 1)
  88.             printf("Error on gets_circ_buffer()\n");
  89.         print_bufr_descript(&buffer_descript);
  90.          print_test_buffer(test_buffer);
  91.     }
  92.     puts("\nReset Circ buffer Test\n");
  93.     reset_circ_buffer(&buffer_descript);
  94.     print_bufr_descript(&buffer_descript);
  95. }
  96.  
  97. print_test_buffer(char *string)
  98. {
  99.     int i;
  100.     for(i=0;i<10;i++)
  101.         printf("%c",string[i]);
  102.     puts("");
  103. }
  104. print_bufr_descript(cb)
  105.     circ_buffer_description *cb;
  106. {
  107.     printf("Head pointer    = %d\n",cb->head);
  108.     printf("Tail pointer    = %d\n",cb->tail);
  109.     printf("Address of buf  = %d\n",cb->address);
  110.     printf("Length of buf   = %d\n",cb->length);
  111.     printf("Character count = %d\n",cb->char_count);
  112.     printf("Overflow flag   = %d\n",cb->overflow_flag);
  113. }
  114.     
  115. #endif
  116. /*****************************************
  117. **                                      **
  118. **     Gets_circ_buffer                 **
  119. **                                                     **
  120. *****************************************/
  121. int gets_circ_buffer(target_buffer, bytes_wanted, cb)
  122.     char *target_buffer;
  123.     int bytes_wanted;
  124.     circ_buffer_description *cb;
  125. {
  126. /*    
  127.     This routine gets a string out of a circular buffer pointed to by
  128.     cb of bytes_wanted size (if there are bytes_wanted characters in
  129.     the circular buffer).  If no characters are in the buffer it returns
  130.     a ZERO. If less characters are in the buffer than what is wanted 
  131.     it only returns the characters in the buffer and indicates to the 
  132.     caller the actual character count returned.
  133.                                                                                             */
  134.     char *circ_buffer_end;
  135.     int bytes_available,left_off;
  136.  
  137.     if(!cb->char_count)    /* if no characters in buffer,don't bother to proceed */
  138.         return(0);
  139.  
  140.     circ_buffer_end = cb->address + cb->length; /* calc where end of circ buffer is */
  141.  
  142.     if (cb->head > cb->tail)    /* Is tail pointer "behind" head,ie. No buffer wrap? */
  143.     {
  144.         /* Case 1:    No buffer 'wrap' */
  145.         #if TEST==TRUE
  146.         puts("Processing a NoWrap condition");
  147.         #endif
  148.         bytes_available = cb->head-cb->tail;            /* number of bytes available is simply distance between head and tail */
  149.         if(bytes_available<bytes_wanted)                    /* Check to see if more bytes are being asked for than what we have */
  150.             bytes_wanted = bytes_available;                 /* if so,reduce request to what we have */
  151.         movmem(cb->tail,target_buffer,bytes_available);    /* move bytes_wanted to begining at tail,to target buffer */
  152.         cb->tail = cb->tail + bytes_wanted;                /* update tail pointer by adding actual bytes given to user */
  153.         disable();                                                /* inhibit interrupts while changing the char count,too avoid concurrent modification */
  154.         cb->char_count-=bytes_wanted;                        /* decrement the char count by number of chars taken out of buffer */
  155.         cb->overflow_flag=0;                                    /* reset overflow flag,incase it was set */
  156.         enable();                                                /* allow interrupts */
  157.         return(bytes_wanted);                                /* let caller know how many bytes where actually returned */
  158.     }
  159.     else
  160.     {
  161.         /* Case 2 ,Head pointer has wrapped around and behind tail pointer */
  162.         #if TEST==TRUE
  163.         puts("Processing a Wrap condition");
  164.           #endif
  165.  
  166.         /* First check if caller only wants the bytes at end of circ_buffer */
  167.         /* IE. callers' request will not cause the tail pntr to wrap around */
  168.         /* to begining of circ_buffer once we give the caller his bytes */
  169.  
  170.         bytes_available = circ_buffer_end - cb->tail;    /* For now say bytes avail is only to end of circ buffer */
  171.         if(bytes_wanted <= bytes_available)    /* Check, if he wants only end of buffer bytes */
  172.         {
  173.             #if TEST==TRUE
  174.             puts("..But no wrapping on extracting");
  175.             #endif
  176.             movmem(cb->tail,target_buffer,bytes_wanted); /* move bytes_wanted to begining at tail,to target buffer */
  177.             cb->tail = cb->tail + bytes_wanted;                /* update tail pointer by adding actual bytes given to user */
  178.             disable();                                                /* inhibit interrupts while changing the char count,too avoid concurrent modification */
  179.             cb->char_count-=bytes_wanted;                        /* decrement the char count by number of chars taken out of buffer */
  180.             cb->overflow_flag=0;                                    /* reset overflow flag,incase it was set */
  181.             enable();                                                /* allow interrupts */
  182.             return(bytes_wanted);                                /* let caller know how many bytes where actually returned */
  183.         }
  184.         else
  185.         {
  186.             #if TEST==TRUE
  187.                 puts("...with extraction wrapping");
  188.             #endif
  189.         /* Nope, Caller wants so many bytes it will wrap past the circ_buffer_end */
  190.         /* and suck up some bytes at the circ_buffer_beginning            */
  191.  
  192.         /* Num of bytes available is the end of buffer bytes (tail-circ_buffer_end) */
  193.         /* plus the begin of buffer bytes(cb->head-cb->address)            */
  194.  
  195.             bytes_available =(circ_buffer_end-cb->tail)+(cb->head-cb->address); 
  196.             if(bytes_available<bytes_wanted)                 /* if caller wants more than we have.. */
  197.                 bytes_wanted=bytes_available;                    /* only give the caller what we have */
  198.             movmem(cb->tail,target_buffer,circ_buffer_end-cb->tail); /* move the bytes at circ_buffer's end */
  199.             left_off = circ_buffer_end-cb->tail;            /* calc what we just gave him (so far) */
  200.             cb->tail = cb->address;                                /* temporarily say tail is the circ_buufer start */
  201.             movmem(cb->tail,target_buffer+left_off,bytes_wanted-left_off); /* give the caller the bytes at the begin of buffer */
  202.             cb->tail = cb->tail + (bytes_wanted-left_off); /* adust tail pntr by using what we gave him the second time */
  203.             disable();                                                /* inhibit interrupts while changing the char count,too avoid concurrent modification */
  204.             cb->char_count-=bytes_wanted;                        /* decrement the char count by number of chars taken out of buffer */
  205.             cb->overflow_flag=0;                                    /* reset overflow flag,incase it was set */
  206.             enable();                                                /* allow interrupts */
  207.             return(bytes_wanted);                                /* Tell caller what we actually gave him */
  208.         }
  209.     }
  210. }
  211. /*****************************************
  212. **                                      **
  213. **     Puts_circ_buffer                 **
  214. **                                                     **
  215. *****************************************/
  216. int puts_circ_buffer(source_buffer, bytes_to_move, cb)
  217.     char *source_buffer;
  218.     int bytes_to_move;
  219.     circ_buffer_description *cb;
  220. {
  221. /*
  222.     This routine accepts a string of characters (bytes_to_move) and
  223.     places them into the buffer pointed to by cb.  If the buffer is not
  224.     big enough the routine will not accept the string and return ZERO
  225.     to indicate to the caller this has happened.  Otherwise it will accept
  226.     the string and return the number of characters accepted.
  227.                                                                                             */
  228.     char *circ_buffer_end;
  229.     int bytes_available,left_off;
  230.  
  231.     if(cb->char_count+bytes_to_move > cb->length)    /* if not enough room left in buffer,don't bother to proceed */
  232.         return(0);
  233.     circ_buffer_end = cb->address + cb->length; /* calc where end of circ buffer is */
  234.  
  235.     if (cb->head >= cb->tail)    /* Is tail pointer "behind" head,ie. buffer wrap? */
  236.     {
  237.         #if TEST==TRUE
  238.         puts("Processing a Potential Wrap condition");
  239.         #endif
  240.  
  241.         /* First check if caller only wants to move bytes into the end of circ_buffer */
  242.         /* IE. callers' request will not cause the head pntr to wrap around */
  243.         /* to begining of circ_buffer once we get the caller's bytes */
  244.  
  245.         bytes_available = circ_buffer_end - cb->head;    /* For now say bytes avail is only to end of circ buffer */
  246.         if(bytes_to_move <= bytes_available)                /* Check, if he wants to put at end of buffer */
  247.         {
  248.             #if TEST==TRUE
  249.             puts("..But no wrapping on insertion");
  250.             #endif
  251.             movmem(source_buffer,cb->head,bytes_to_move); /* move bytes_to_move to begining at tail,to target buffer */
  252.             cb->head = cb->head + bytes_to_move;            /* update tail pointer by adding actual bytes given to user */
  253.             disable();                                                /* inhibit interrupts while changing the char count,too avoid concurrent modification */
  254.             cb->char_count+=bytes_to_move;                    /* update character count */
  255.             enable();                                                /* allow interrupts */
  256.             return(bytes_to_move);                                /* let caller know how many bytes where actually returned */
  257.         }
  258.         else
  259.         {
  260.             #if TEST==TRUE
  261.                 puts("...with insertion wrapping");
  262.             #endif
  263.         /* Nope, Caller wants to put in so many bytes it will wrap past */
  264.         /* the circ_buffer_end and use up some bytes at the */
  265.         /* circ_buffer_beginning    */
  266.  
  267.         /* Num of bytes available is the end of buffer bytes (head-circ_buffer_end) */
  268.         /* plus the begin of buffer bytes(cb->tail-cb->address)            */
  269.  
  270.             bytes_available =(circ_buffer_end-cb->head) + (cb->tail-cb->address); 
  271.             movmem(source_buffer,cb->head,circ_buffer_end-cb->head); /* move the bytes at circ_buffer's end */
  272.             left_off = circ_buffer_end-cb->head;            /* calc what we just gave him (so far) */
  273.             cb->head = cb->address;                                  /* temporarily say head is the circ_buufer start */
  274.             movmem(source_buffer+left_off,cb->head,bytes_to_move-left_off); /* give the caller the bytes at the begin of buffer */
  275.             cb->head = cb->head + (bytes_to_move-left_off); /* adust head pntr by using what we gave him the second time */
  276.             disable();                                                /* inhibit interrupts while changing the char count,too avoid concurrent modification */
  277.             cb->char_count+=bytes_to_move;                    /* update character count */
  278.             enable();                                                /* allow interrupts */
  279.             return(bytes_to_move);                                /* Tell caller what we actually gave him */
  280.         }
  281.     }
  282.     else
  283.     {
  284.         /* Case 1:    No buffer 'wrap' */
  285.         #if TEST==TRUE
  286.         puts("Processing a NoWrap condition");
  287.         #endif
  288.         movmem(source_buffer,cb->head,bytes_to_move);    /* move bytes_to_move to begining at head,to target buffer */
  289.         cb->head = cb->head + bytes_to_move;                /* update head pointer by adding actual bytes given to user */
  290.         disable();                                                    /* inhibit interrupts while changing the char count,too avoid concurrent modification */
  291.         cb->char_count+=bytes_to_move;                        /* update character count */
  292.         enable();                                                    /* allow interrupts */
  293.         return(bytes_to_move);                                    /* let caller know how many bytes where actually returned */
  294.      }
  295. }
  296. /*****************************************
  297. **                                      **
  298. **     Reset_circ_buffer                **
  299. **                                                     **
  300. *****************************************/
  301. void reset_circ_buffer(cb)
  302.     circ_buffer_description *cb;
  303. {
  304.     disable();                        /* disable interrupts, to avoid concurrent mods */
  305.     cb->head      = cb->address;
  306.     cb->tail      = cb->head;
  307.     cb->char_count     = 0;
  308.     cb->overflow_flag = 0;
  309.     enable();                        /* allow interrupts to occur */
  310. }
  311. /*****************************************
  312. **                                      **
  313. **     Check_circ_buffer_fill           **
  314. **                                                     **
  315. *****************************************/
  316. int check_circ_buffer_fill(cb)
  317.     circ_buffer_description *cb;
  318. {
  319. /* 
  320.     This routine returns the number of characters in the circular
  321.     buffer pointed to by the passed circular buffer description.
  322.  
  323.                                                                                             */
  324.     return(cb->char_count);
  325. }
  326. /*****************************************
  327. **                                      **
  328. **     Check_circ_buffer_over           **
  329. **                                                     **
  330. *****************************************/
  331. int check_circ_buffer_over(cb)
  332.     circ_buffer_description *cb;
  333. {
  334. /* 
  335.     This routine returns the overflow flag for the circular
  336.     buffer pointed to by the passed circular buffer description.
  337.  
  338.                                                                                             */
  339.     return(cb->overflow_flag);
  340. }
  341.  
  342.  
  343.