ring.c
上传用户:sddyfurun
上传日期:2007-01-04
资源大小:525k
文件大小:8k
源码类别:

代理服务器

开发平台:

Unix_Linux

  1. /*
  2.  * Copyright (c) 1988, 1993
  3.  * The Regents of the University of California.  All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  * This product includes software developed by the University of
  16.  * California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33. #ifdef SHOW_SCCSIDS
  34. static char sccsid[] = "@(#)ring.c 8.2 (Berkeley) 5/30/95";
  35. #endif
  36. /*
  37.  * This defines a structure for a ring buffer.
  38.  *
  39.  * The circular buffer has two parts:
  40.  *(((
  41.  * full: [consume, supply)
  42.  * empty: [supply, consume)
  43.  *]]]
  44.  *
  45.  */
  46. #include <stdio.h>
  47. #include <errno.h>
  48. #ifdef size_t
  49. #undef size_t
  50. #endif
  51. #include        "config.h"
  52. #ifdef HAVE_STRING_H
  53. #include <string.h>
  54. #endif
  55. #if !defined(STDC_HEADERS) && defined(HAVE_MEMORY_H)
  56. #include <memory.h>
  57. #endif
  58. #ifdef HAVE_STRINGS_H
  59. #include <strings.h>
  60. #endif
  61. #include <sys/types.h>
  62. #ifndef FILIO_H
  63. #include <sys/ioctl.h>
  64. #endif
  65. #include <sys/socket.h>
  66. #include "ring.h"
  67. #include "general.h"
  68. /* Internal macros */
  69. #ifndef MIN
  70. #define MIN(a,b) (((a)<(b))? (a):(b))
  71. #endif /* !defined(MIN) */
  72. #define ring_subtract(d,a,b) (((a)-(b) >= 0)? 
  73. (a)-(b): (((a)-(b))+(d)->size))
  74. #define ring_increment(d,a,c) (((a)+(c) < (d)->top)? 
  75. (a)+(c) : (((a)+(c))-(d)->size))
  76. #define ring_decrement(d,a,c) (((a)-(c) >= (d)->bottom)? 
  77. (a)-(c) : (((a)-(c))-(d)->size))
  78. /*
  79.  * The following is a clock, used to determine full, empty, etc.
  80.  *
  81.  * There is some trickiness here.  Since the ring buffers are initialized
  82.  * to ZERO on allocation, we need to make sure, when interpreting the
  83.  * clock, that when the times are EQUAL, then the buffer is FULL.
  84.  */
  85. static u_long ring_clock = 0;
  86. #define ring_empty(d) (((d)->consume == (d)->supply) && 
  87. ((d)->consumetime >= (d)->supplytime))
  88. #define ring_full(d) (((d)->supply == (d)->consume) && 
  89. ((d)->supplytime > (d)->consumetime))
  90. /* Buffer state transition routines */
  91.     int 
  92. ring_init(ring, buffer, count)
  93.     Ring *ring;
  94.     unsigned char *buffer;
  95.     int count;
  96. {
  97.     memset((char *)ring, 0, sizeof *ring);
  98.     ring->size = count;
  99.     ring->supply = ring->consume = ring->bottom = buffer;
  100.     ring->top = ring->bottom+ring->size;
  101.     return 1;
  102. }
  103. /* Mark routines */
  104. /*
  105.  * Mark the most recently supplied byte.
  106.  */
  107.     void
  108. ring_mark(ring)
  109.     Ring *ring;
  110. {
  111.     ring->mark = ring_decrement(ring, ring->supply, 1);
  112. }
  113. /*
  114.  * Is the ring pointing to the mark?
  115.  */
  116.     int
  117. ring_at_mark(ring)
  118.     Ring *ring;
  119. {
  120.     if (ring->mark == ring->consume) {
  121. return 1;
  122.     } else {
  123. return 0;
  124.     }
  125. }
  126. /*
  127.  * Clear any mark set on the ring.
  128.  */
  129.     void
  130. ring_clear_mark(ring)
  131.     Ring *ring;
  132. {
  133.     ring->mark = 0;
  134. }
  135. /*
  136.  * Add characters from current segment to ring buffer.
  137.  */
  138.     void
  139. ring_supplied(ring, count)
  140.     Ring *ring;
  141.     int count;
  142. {
  143.     ring->supply = ring_increment(ring, ring->supply, count);
  144.     ring->supplytime = ++ring_clock;
  145. }
  146. /*
  147.  * We have just consumed "c" bytes.
  148.  */
  149.     void
  150. ring_consumed(ring, count)
  151.     Ring *ring;
  152.     int count;
  153. {
  154.     if (count == 0) /* don't update anything */
  155. return;
  156.     if (ring->mark &&
  157. (ring_subtract(ring, ring->mark, ring->consume) < count)) {
  158. ring->mark = 0;
  159.     }
  160.     ring->consume = ring_increment(ring, ring->consume, count);
  161.     ring->consumetime = ++ring_clock;
  162.     /*
  163.      * Try to encourage "ring_empty_consecutive()" to be large.
  164.      */
  165.     if (ring_empty(ring)) {
  166. ring->consume = ring->supply = ring->bottom;
  167.     }
  168. }
  169. /* Buffer state query routines */
  170. /* Number of bytes that may be supplied */
  171.     int
  172. ring_empty_count(ring)
  173.     Ring *ring;
  174. {
  175.     if (ring_empty(ring)) { /* if empty */
  176.     return ring->size;
  177.     } else {
  178. return ring_subtract(ring, ring->consume, ring->supply);
  179.     }
  180. }
  181. /* number of CONSECUTIVE bytes that may be supplied */
  182.     int
  183. ring_empty_consecutive(ring)
  184.     Ring *ring;
  185. {
  186.     if ((ring->consume < ring->supply) || ring_empty(ring)) {
  187.     /*
  188.      * if consume is "below" supply, or empty, then
  189.      * return distance to the top
  190.      */
  191. return ring_subtract(ring, ring->top, ring->supply);
  192.     } else {
  193.     /*
  194.      * else, return what we may.
  195.      */
  196. return ring_subtract(ring, ring->consume, ring->supply);
  197.     }
  198. }
  199. /* Return the number of bytes that are available for consuming
  200.  * (but don't give more than enough to get to cross over set mark)
  201.  */
  202.     int
  203. ring_full_count(ring)
  204.     Ring *ring;
  205. {
  206.     if ((ring->mark == 0) || (ring->mark == ring->consume)) {
  207. if (ring_full(ring)) {
  208.     return ring->size; /* nothing consumed, but full */
  209. } else {
  210.     return ring_subtract(ring, ring->supply, ring->consume);
  211. }
  212.     } else {
  213. return ring_subtract(ring, ring->mark, ring->consume);
  214.     }
  215. }
  216. /*
  217.  * Return the number of CONSECUTIVE bytes available for consuming.
  218.  * However, don't return more than enough to cross over set mark.
  219.  */
  220.     int
  221. ring_full_consecutive(ring)
  222.     Ring *ring;
  223. {
  224.     if ((ring->mark == 0) || (ring->mark == ring->consume)) {
  225. if ((ring->supply < ring->consume) || ring_full(ring)) {
  226.     return ring_subtract(ring, ring->top, ring->consume);
  227. } else {
  228.     return ring_subtract(ring, ring->supply, ring->consume);
  229. }
  230.     } else {
  231. if (ring->mark < ring->consume) {
  232.     return ring_subtract(ring, ring->top, ring->consume);
  233. } else { /* Else, distance to mark */
  234.     return ring_subtract(ring, ring->mark, ring->consume);
  235. }
  236.     }
  237. }
  238. /*
  239.  * Move data into the "supply" portion of of the ring buffer.
  240.  */
  241.     void
  242. ring_supply_data(ring, buffer, count)
  243.     Ring *ring;
  244.     unsigned char *buffer;
  245.     int count;
  246. {
  247.     int i;
  248.     while (count) {
  249. i = MIN(count, ring_empty_consecutive(ring));
  250. memmove(ring->supply, buffer, i);
  251. ring_supplied(ring, i);
  252. count -= i;
  253. buffer += i;
  254.     }
  255. }
  256. #ifdef notdef
  257. /*
  258.  * Move data from the "consume" portion of the ring buffer
  259.  */
  260.     void
  261. ring_consume_data(ring, buffer, count)
  262.     Ring *ring;
  263.     unsigned char *buffer;
  264.     int count;
  265. {
  266.     int i;
  267.     while (count) {
  268. i = MIN(count, ring_full_consecutive(ring));
  269. memmove(buffer, ring->consume, i);
  270. ring_consumed(ring, i);
  271. count -= i;
  272. buffer += i;
  273.     }
  274. }
  275. #endif