|
|
1.1 root 1: /* ringbuf.c */
2:
3: /* Synchronet ring buffer routines */
4:
5: /* $Id: ringbuf.c,v 1.1.1.1 2000/10/10 11:26:23 rswindell Exp $ */
6:
7: /****************************************************************************
8: * @format.tab-size 4 (Plain Text/Source Code File Header) *
9: * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) *
10: * *
11: * Copyright 2000 Rob Swindell - http://www.synchro.net/copyright.html *
12: * *
13: * This program is free software; you can redistribute it and/or *
14: * modify it under the terms of the GNU General Public License *
15: * as published by the Free Software Foundation; either version 2 *
16: * of the License, or (at your option) any later version. *
17: * See the GNU General Public License for more details: gpl.txt or *
18: * http://www.fsf.org/copyleft/gpl.html *
19: * *
20: * Anonymous FTP access to the most recent released source is available at *
21: * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net *
22: * *
23: * Anonymous CVS access to the development source and modification history *
24: * is available at cvs.synchro.net:/cvsroot/sbbs, example: *
25: * cvs -d :pserver:[email protected]:/cvsroot/sbbs login *
26: * (just hit return, no password is necessary) *
27: * cvs -d :pserver:[email protected]:/cvsroot/sbbs checkout src *
28: * *
29: * For Synchronet coding style and modification guidelines, see *
30: * http://www.synchro.net/source.html *
31: * *
32: * You are encouraged to submit any modifications (preferably in Unix diff *
33: * format) via e-mail to [email protected] *
34: * *
35: * Note: If this box doesn't appear square, then you need to fix your tabs. *
36: ****************************************************************************/
37:
38: /* Pre-define RINGBUF_USE_STD_RTL to use standard C runtime library symbols
39: * for malloc, free, and memcpy
40: */
41:
42: #ifdef VTOOLSD
43: #include <vtoolsd.h>
44: #include LOCKED_CODE_SEGMENT
45: #include LOCKED_DATA_SEGMENT
46: #endif
47:
48: #include "ringbuf.h"
49:
50: #ifdef RINGBUF_USE_STD_RTL
51:
52: #ifndef VTOOLSD
53: #include <malloc.h> /* malloc prototype */
54: #include <string.h> /* memcpy prototype */
55: #endif
56:
57: #define os_malloc malloc
58: #define rb_malloc malloc
59: #define os_free free
60: #define rb_free free
61: #define os_memcpy memcpy
62: #define rb_memcpy memcpy
63:
64: #else
65:
66: void (*rb_free)(void *);
67: void *(*rb_memcpy)(void *, const void *, size_t);
68:
69: #endif
70: /****************************************************************************/
71: /* Returns 0 on success, non-zero on failure */
72: /****************************************************************************/
73: int RINGBUFCALL RingBufInit( RingBuf* rb, DWORD size
74: #ifndef RINGBUF_USE_STD_RTL
75: ,void *(os_malloc)(size_t)
76: ,void (os_free)(void *)
77: ,void *(os_memcpy)(void *, const void *, size_t)
78: #endif
79: )
80: {
81: if((rb->pStart=(BYTE *)os_malloc(size))==NULL)
82: return(-1);
83: #ifndef RINGBUF_USE_STD_RTL
84: rb_free=os_free;
85: rb_memcpy=os_memcpy;
86: #endif
87: rb->pHead=rb->pTail=rb->pStart;
88: rb->pEnd=rb->pStart+size-1;
89: rb->size=size;
90: return(0);
91: }
92:
93: void RINGBUFCALL RingBufDispose( RingBuf* rb)
94: {
95: if(rb->pStart!=NULL)
96: os_free(rb->pStart);
97: memset(rb,0,sizeof(RingBuf));
98: }
99:
100: DWORD RINGBUFCALL RingBufFull( RingBuf* rb )
101: {
102: DWORD head,tail,retval;
103:
104: head = (DWORD) rb->pHead;
105: tail = (DWORD) rb->pTail;
106:
107: if(head >= tail)
108: retval = head - tail;
109: else
110: retval = rb->size - (tail - head);
111:
112: return(retval);
113: }
114:
115: DWORD RINGBUFCALL RingBufFree( RingBuf* rb )
116: {
117: DWORD retval;
118:
119: retval = (rb->size - RingBufFull( rb ))-1;
120:
121: return(retval);
122: }
123:
124: DWORD RINGBUFCALL RingBufWrite( RingBuf* rb, BYTE* src, DWORD cnt )
125: {
126: DWORD max, first, remain;
127:
128: if(rb->pStart==NULL)
129: return(0);
130:
131: /* allowed to write at pEnd */
132: max = (((DWORD) rb->pEnd) - ((DWORD) rb->pHead)) + 1;
133:
134: /*
135: * we assume the caller has checked that there is enough room. For this reason
136: * we do not have to worry about head wrapping past the tail
137: */
138:
139: if( max >= cnt ) {
140: first = cnt;
141: remain = 0;
142: } else {
143: first = max;
144: remain = cnt - first;
145: }
146:
147: rb_memcpy( rb->pHead, src, first );
148: rb->pHead += first;
149: src += first;
150:
151: if(remain) {
152:
153: rb->pHead = rb->pStart;
154: rb_memcpy(rb->pHead, src, remain);
155: rb->pHead += remain;
156: }
157:
158: if(rb->pHead > rb->pEnd)
159: rb->pHead = rb->pStart;
160:
161: return(cnt);
162: }
163:
164: /* Pass NULL dst to just foward pointer (after Peek) */
165: DWORD RINGBUFCALL RingBufRead( RingBuf* rb, BYTE* dst, DWORD cnt )
166: {
167: DWORD max, first, remain, len;
168:
169: len = RingBufFull( rb );
170: if( len == 0 )
171: return(0);
172:
173: if( len < cnt )
174: cnt = len;
175:
176: /* allowed to read at pEnd */
177: max = (((DWORD) rb->pEnd) - ((DWORD) rb->pTail)) + 1;
178:
179: if( max >= cnt ) {
180: first = cnt;
181: remain = 0;
182: } else {
183: first = max;
184: remain = cnt - first;
185: }
186:
187: if(dst!=NULL) {
188: rb_memcpy( dst, rb->pTail, first );
189: dst += first;
190: }
191: rb->pTail += first;
192:
193: if( remain ){
194:
195: rb->pTail = rb->pStart;
196: if(dst!=NULL)
197: rb_memcpy( dst, rb->pTail, remain );
198: rb->pTail += remain;
199: }
200:
201: if(rb->pTail > rb->pEnd)
202: rb->pTail = rb->pStart;
203:
204: return(cnt);
205: }
206:
207: DWORD RINGBUFCALL RingBufPeek( RingBuf* rb, BYTE* dst, DWORD cnt)
208: {
209: DWORD max, first, remain, len;
210:
211: len = RingBufFull( rb );
212: if( len == 0 )
213: return(0);
214:
215: if( len < cnt )
216: cnt = len;
217:
218: /* allowed to read at pEnd */
219: max = (((DWORD) rb->pEnd) - ((DWORD) rb->pTail)) + 1;
220:
221: if( max >= cnt ) {
222: first = cnt;
223: remain = 0;
224: } else {
225: first = max;
226: remain = cnt - first;
227: }
228:
229: rb_memcpy( dst, rb->pTail, first );
230: dst += first;
231:
232: if(remain) {
233: rb_memcpy( dst, rb->pStart, remain );
234: }
235:
236: return(cnt);
237: }
238:
239: /* Reset head and tail pointers */
240: void RINGBUFCALL RingBufReInit(RingBuf* rb)
241: {
242: rb->pHead = rb->pTail = rb->pStart;
243: }
244:
245: /* End of RINGBUF.C */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.