OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rtems/] [c/] [src/] [libnetworking/] [rtems_webserver/] [ringq.c] - Blame information for rev 1767

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 158 chris
/*
2
 * ringq.c -- Ring queue buffering module
3
 *
4
 * Copyright (c) GoAhead Software Inc., 1995-1999. All Rights Reserved.
5
 *
6
 * See the file "license.txt" for usage and redistribution license requirements
7
 */
8
 
9
/******************************** Description *********************************/
10
 
11
/*
12
 *      A ring queue allows maximum utilization of memory for data storage and is
13
 *      ideal for input/output buffering.  This module provides a highly effecient
14
 *      implementation and a vehicle for dynamic strings.
15
 *
16
 *      WARNING:  This is a public implementation and callers have full access to
17
 *      the queue structure and pointers.  Change this module very carefully.
18
 *
19
 *      This module follows the open/close model.
20
 *
21
 *      Operation of a ringq where rq is a pointer to a ringq :
22
 *
23
 *              rq->buflen contains the size of the buffer.
24
 *              rq->buf will point to the start of the buffer.
25
 *              rq->servp will point to the first (un-consumed) data byte.
26
 *              rq->endp will point to the next free location to which new data is added
27
 *              rq->endbuf will point to one past the end of the buffer.
28
 *
29
 *      Eg. If the ringq contains the data "abcdef", it might look like :
30
 *
31
 *      +-------------------------------------------------------------------+
32
 *  |   |   |   |   |   |   |   | a | b | c | d | e | f |   |   |   |   |
33
 *      +-------------------------------------------------------------------+
34
 *    ^                           ^                       ^               ^
35
 *    |                           |                       |               |
36
 *  rq->buf                    rq->servp               rq->endp      rq->enduf
37
 *
38
 *      The queue is empty when servp == endp.  This means that the queue will hold
39
 *      at most rq->buflen -1 bytes.  It is the fillers responsibility to ensure
40
 *      the ringq is never filled such that servp == endp.
41
 *
42
 *      It is the fillers responsibility to "wrap" the endp back to point to
43
 *      rq->buf when the pointer steps past the end.  Correspondingly it is the
44
 *      consumers responsibility to "wrap" the servp when it steps to rq->endbuf.
45
 *      The ringqPutc and ringqGetc routines will do this automatically.
46
 */
47
 
48
/********************************* Includes ***********************************/
49
 
50
#if UEMF
51
        #include        "uemf.h"
52
#else
53
        #include        "basic/basicInternal.h"
54
#endif
55
 
56
/*********************************** Defines **********************************/
57
/*
58
 *      Faster than a function call
59
 */
60
 
61
#define RINGQ_LEN(rq) \
62
        ((rq->servp > rq->endp) ? \
63
                (rq->buflen + (rq->endp - rq->servp)) : \
64
                (rq->endp - rq->servp))
65
 
66
/***************************** Forward Declarations ***************************/
67
 
68
static int ringq_grow(ringq_t *rq);
69
 
70
/*********************************** Code *************************************/
71
/*
72
 *      Create a new ringq. "increment" is the amount to increase the size of the
73
 *      ringq should it need to grow to accomodate data being added. "maxsize" is
74
 *      an upper limit (sanity level) beyond which the q must not grow. Set maxsize
75
 *      to -1 to imply no upper limit. The buffer for the ringq is always
76
 *      dynamically allocated. Set maxsize
77
 */
78
 
79
int ringqOpen(ringq_t *rq, int increment, int maxsize)
80
{
81
        a_assert(rq);
82
        a_assert(increment >= 0);
83
 
84
        if ((rq->buf = balloc(B_L, increment)) == NULL) {
85
                return -1;
86
        }
87
        rq->maxsize = maxsize;
88
        rq->buflen = increment;
89
        rq->increment = increment;
90
        rq->endbuf = &rq->buf[rq->buflen];
91
        rq->servp = rq->buf;
92
        rq->endp = rq->buf;
93
        *rq->servp = '\0';
94
        return 0;
95
}
96
 
97
/******************************************************************************/
98
/*
99
 *      Delete a ringq and free the ringq buffer.
100
 */
101
 
102
void ringqClose(ringq_t *rq)
103
{
104
        a_assert(rq);
105
        a_assert(rq->buflen == (rq->endbuf - rq->buf));
106
 
107
        if (rq == NULL) {
108
                return;
109
        }
110
 
111
        ringqFlush(rq);
112
        bfree(B_L, (char*) rq->buf);
113
        rq->buf = NULL;
114
}
115
 
116
/******************************************************************************/
117
/*
118
 *      Return the length of the ringq. Users must fill the queue to a high
119
 *      water mark of at most one less than the queue size.
120
 */
121
 
122
int ringqLen(ringq_t *rq)
123
{
124
        a_assert(rq);
125
        a_assert(rq->buflen == (rq->endbuf - rq->buf));
126
 
127
        if (rq->servp > rq->endp) {
128
                return rq->buflen + rq->endp - rq->servp;
129
        }
130
        else {
131
                return rq->endp - rq->servp;
132
        }
133
}
134
 
135
/******************************************************************************/
136
/*
137
 *      Get a byte from the queue
138
 */
139
 
140
int ringqGetc(ringq_t *rq)
141
{
142
        char_t  c;
143
        char_t* cp;
144
 
145
        a_assert(rq);
146
        a_assert(rq->buflen == (rq->endbuf - rq->buf));
147
 
148
        if (rq->servp == rq->endp) {
149
                return -1;
150
        }
151
 
152
        cp = (char_t*) rq->servp;
153
        c = *cp++;
154
        rq->servp = (unsigned char *) cp;
155
        if (rq->servp >= rq->endbuf) {
156
                rq->servp = rq->buf;
157
        }
158
        return c;
159
}
160
 
161
/******************************************************************************/
162
/*
163
 *      Add a char to the queue. Note if being used to store wide strings
164
 *      this does not add a trailing '\0'. Grow the q as required.
165
 */
166
 
167
int ringqPutc(ringq_t *rq, char_t c)
168
{
169
        char_t* cp;
170
 
171
        a_assert(rq);
172
        a_assert(rq->buflen == (rq->endbuf - rq->buf));
173
 
174
        if (ringqPutBlkMax(rq) < (int) sizeof(char_t) && !ringq_grow(rq)) {
175
                return -1;
176
        }
177
 
178
        cp = (char_t*) rq->endp;
179
        *cp++ = (char_t) c;
180
        rq->endp = (unsigned char *) cp;
181
        if (rq->endp >= rq->endbuf) {
182
                rq->endp = rq->buf;
183
        }
184
        return 0;
185
}
186
 
187
/******************************************************************************/
188
/*
189
 *      Insert a wide character at the front of the queue
190
 */
191
 
192
int ringqInsertc(ringq_t *rq, char_t c)
193
{
194
        char_t* cp;
195
 
196
        a_assert(rq);
197
        a_assert(rq->buflen == (rq->endbuf - rq->buf));
198
 
199
        if (ringqPutBlkMax(rq) < (int) sizeof(char_t) && !ringq_grow(rq)) {
200
                return -1;
201
        }
202
        if (rq->servp <= rq->buf) {
203
                rq->servp = rq->endbuf;
204
        }
205
        cp = (char_t*) rq->servp;
206
        *--cp = (char_t) c;
207
        rq->servp = (unsigned char *) cp;
208
        return 0;
209
}
210
 
211
/******************************************************************************/
212
/*
213
 *      Add a string to the queue. Add a trailing wide null (two nulls)
214
 */
215
 
216
int ringqPutstr(ringq_t *rq, char_t *str)
217
{
218
        int             rc;
219
 
220
        a_assert(rq);
221
        a_assert(str);
222
        a_assert(rq->buflen == (rq->endbuf - rq->buf));
223
 
224
        rc = ringqPutBlk(rq, (unsigned char*) str, gstrlen(str) * sizeof(char_t));
225
        *((char_t*) rq->endp) = (char_t) '\0';
226
        return rc;
227
}
228
 
229
/******************************************************************************/
230
#if UNICODE
231
/*
232
 *      Get a byte from the queue
233
 */
234
 
235
int ringqGetcA(ringq_t *rq)
236
{
237
        unsigned char   c;
238
 
239
        a_assert(rq);
240
        a_assert(rq->buflen == (rq->endbuf - rq->buf));
241
 
242
        if (rq->servp == rq->endp) {
243
                return -1;
244
        }
245
 
246
        c = *rq->servp++;
247
        if (rq->servp >= rq->endbuf) {
248
                rq->servp = rq->buf;
249
        }
250
        return c;
251
}
252
 
253
/******************************************************************************/
254
/*
255
 *      Add a byte to the queue. Note if being used to store strings this does not
256
 *      add a trailing '\0'. Grow the q as required.
257
 */
258
 
259
int ringqPutcA(ringq_t *rq, char c)
260
{
261
        a_assert(rq);
262
        a_assert(rq->buflen == (rq->endbuf - rq->buf));
263
 
264
        if (ringqPutBlkMax(rq) == 0 && !ringq_grow(rq)) {
265
                return -1;
266
        }
267
 
268
        *rq->endp++ = (unsigned char) c;
269
        if (rq->endp >= rq->endbuf) {
270
                rq->endp = rq->buf;
271
        }
272
        return 0;
273
}
274
 
275
/******************************************************************************/
276
/*
277
 *      Insert a byte at the front of the queue
278
 */
279
 
280
int ringqInsertcA(ringq_t *rq, char c)
281
{
282
        a_assert(rq);
283
        a_assert(rq->buflen == (rq->endbuf - rq->buf));
284
 
285
        if (ringqPutBlkMax(rq) == 0 && !ringq_grow(rq)) {
286
                return -1;
287
        }
288
        if (rq->servp <= rq->buf) {
289
                rq->servp = rq->endbuf;
290
        }
291
        *--rq->servp = (unsigned char) c;
292
        return 0;
293
}
294
 
295
/******************************************************************************/
296
/*
297
 *      Add a string to the queue. Add a trailing null (not really in the q).
298
 *      ie. beyond the last valid byte.
299
 */
300
 
301
int ringqPutstrA(ringq_t *rq, char *str)
302
{
303
        int             rc;
304
 
305
        a_assert(rq);
306
        a_assert(str);
307
        a_assert(rq->buflen == (rq->endbuf - rq->buf));
308
 
309
        rc = ringqPutBlk(rq, (unsigned char*) str, strlen(str));
310
        rq->endp[0] = '\0';
311
        return rc;
312
}
313
 
314
#endif /* UNICODE */
315
/******************************************************************************/
316
/*
317
 *      Add a block of data to the ringq. Return the number of bytes added.
318
 *      Grow the q as required.
319
 */
320
 
321
int ringqPutBlk(ringq_t *rq, unsigned char *buf, int size)
322
{
323
        int             this, bytes_put;
324
 
325
        a_assert(rq);
326
        a_assert(rq->buflen == (rq->endbuf - rq->buf));
327
        a_assert(buf);
328
        a_assert(0 <= size);
329
 
330
/*
331
 *      Loop adding the maximum bytes we can add in a single straight line copy
332
 */
333
        bytes_put = 0;
334
        while (size > 0) {
335
                this = min(ringqPutBlkMax(rq), size);
336
                if (this <= 0) {
337
                        if (! ringq_grow(rq)) {
338
                                break;
339
                        }
340
                        this = min(ringqPutBlkMax(rq), size);
341
                }
342
 
343
                memcpy(rq->endp, buf, this);
344
                buf += this;
345
                rq->endp += this;
346
                size -= this;
347
                bytes_put += this;
348
 
349
                if (rq->endp >= rq->endbuf) {
350
                        rq->endp = rq->buf;
351
                }
352
        }
353
        return bytes_put;
354
}
355
 
356
/******************************************************************************/
357
/*
358
 *      Get a block of data from the ringq. Return the number of bytes returned.
359
 */
360
 
361
int ringqGetBlk(ringq_t *rq, unsigned char *buf, int size)
362
{
363
        int             this, bytes_read;
364
 
365
        a_assert(rq);
366
        a_assert(rq->buflen == (rq->endbuf - rq->buf));
367
        a_assert(buf);
368
        a_assert(0 <= size && size < rq->buflen);
369
 
370
/*
371
 *      Loop getting the maximum bytes we can get in a single straight line copy
372
 */
373
        bytes_read = 0;
374
        while (size > 0) {
375
                this = ringqGetBlkMax(rq);
376
                this = min(this, size);
377
                if (this <= 0) {
378
                        break;
379
                }
380
 
381
                memcpy(buf, rq->servp, this);
382
                buf += this;
383
                rq->servp += this;
384
                size -= this;
385
                bytes_read += this;
386
 
387
                if (rq->servp >= rq->endbuf) {
388
                        rq->servp = rq->buf;
389
                }
390
        }
391
        return bytes_read;
392
}
393
 
394
/******************************************************************************/
395
/*
396
 *      Return the maximum number of bytes the ring q can accept via a single
397
 *      block copy. Useful if the user is doing their own data insertion.
398
 */
399
 
400
int ringqPutBlkMax(ringq_t *rq)
401
{
402
        int             space, in_a_line;
403
 
404
        a_assert(rq);
405
        a_assert(rq->buflen == (rq->endbuf - rq->buf));
406
 
407
        space = rq->buflen - RINGQ_LEN(rq) - 1;
408
        in_a_line = rq->endbuf - rq->endp;
409
 
410
        return min(in_a_line, space);
411
}
412
 
413
/******************************************************************************/
414
/*
415
 *      Return the maximum number of bytes the ring q can provide via a single
416
 *      block copy. Useful if the user is doing their own data retrieval.
417
 */
418
 
419
int ringqGetBlkMax(ringq_t *rq)
420
{
421
        int             len, in_a_line;
422
 
423
        a_assert(rq);
424
        a_assert(rq->buflen == (rq->endbuf - rq->buf));
425
 
426
        len = RINGQ_LEN(rq);
427
        in_a_line = rq->endbuf - rq->servp;
428
 
429
        return min(in_a_line, len);
430
}
431
 
432
/******************************************************************************/
433
/*
434
 *      Adjust the endp pointer after the user has copied data into the queue.
435
 */
436
 
437
void ringqPutBlkAdj(ringq_t *rq, int size)
438
{
439
        a_assert(rq);
440
        a_assert(rq->buflen == (rq->endbuf - rq->buf));
441
        a_assert(0 <= size && size < rq->buflen);
442
 
443
        rq->endp += size;
444
        if (rq->endp >= rq->endbuf) {
445
                rq->endp -= rq->buflen;
446
        }
447
/*
448
 *      Flush the queue if the endp pointer is corrupted via a bad size
449
 */
450
        if (rq->endp >= rq->endbuf) {
451
                error(E_L, E_LOG, T("Bad end pointer"));
452
                ringqFlush(rq);
453
        }
454
}
455
 
456
/******************************************************************************/
457
/*
458
 *      Adjust the servp pointer after the user has copied data from the queue.
459
 */
460
 
461
void ringqGetBlkAdj(ringq_t *rq, int size)
462
{
463
        a_assert(rq);
464
        a_assert(rq->buflen == (rq->endbuf - rq->buf));
465
        a_assert(0 < size && size < rq->buflen);
466
 
467
        rq->servp += size;
468
        if (rq->servp >= rq->endbuf) {
469
                rq->servp -= rq->buflen;
470
        }
471
/*
472
 *      Flush the queue if the servp pointer is corrupted via a bad size
473
 */
474
        if (rq->servp >= rq->endbuf) {
475
                error(E_L, E_LOG, T("Bad serv pointer"));
476
                ringqFlush(rq);
477
        }
478
}
479
 
480
/******************************************************************************/
481
/*
482
 *      Flush all data in a ring q.  Reset the pointers.
483
 */
484
 
485
void ringqFlush(ringq_t *rq)
486
{
487
        a_assert(rq);
488
 
489
        rq->servp = rq->buf;
490
        rq->endp = rq->buf;
491
        *rq->servp = '\0';
492
}
493
 
494
/******************************************************************************/
495
/*
496
 *      Grow the buffer. Return true if the buffer can be grown. Grow using
497
 *      the increment size specified when opening the ringq. Don't grow beyond
498
 *      the maximum possible size.
499
 */
500
 
501
static int ringq_grow(ringq_t *rq)
502
{
503
        unsigned char   *newbuf;
504
        int                     len;
505
 
506
        a_assert(rq);
507
 
508
        if (rq->maxsize >= 0 && rq->buflen >= rq->maxsize) {
509
                return 0;
510
        }
511
 
512
        len = ringqLen(rq);
513
 
514
        if ((newbuf = balloc(B_L, rq->buflen + rq->increment)) == NULL) {
515
                return 0;
516
        }
517
        ringqGetBlk(rq, newbuf, ringqLen(rq));
518
        bfree(B_L, (char*) rq->buf);
519
 
520
#if OLD
521
        rq->endp = &newbuf[endp];
522
        rq->servp = &newbuf[servp];
523
        rq->endbuf = &newbuf[rq->buflen];
524
        rq->buf = newbuf;
525
#endif
526
 
527
        rq->buflen += rq->increment;
528
        rq->endp = newbuf;
529
        rq->servp = newbuf;
530
        rq->buf = newbuf;
531
        rq->endbuf = &rq->buf[rq->buflen];
532
 
533
        ringqPutBlk(rq, newbuf, len);
534
        return 1;
535
}
536
 
537
/******************************************************************************/

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.