| #ifdef UEMF |
| #include "uemf.h" |
| #else |
| #include "basic/basicInternal.h" |
| #endif |
| |
| static int getBinBlockSize(int size); |
| static int ringqGrow(ringq_t *rq); |
| |
| #define RINGQ_LEN(rq) \ |
| ((rq->servp > rq->endp) ? \ |
| (rq->buflen + (rq->endp - rq->servp)) : \ |
| (rq->endp - rq->servp)) |
| |
| |
| |
| int ringqGrowCalls = 0; |
| |
| int ringqOpen(ringq_t *rq, int initSize, int maxsize) |
| { |
| int increment; |
| |
| a_assert(rq); |
| a_assert(initSize >= 0); |
| |
| increment = getBinBlockSize(initSize); |
| if ((rq->buf = balloc(B_L, (increment))) == NULL) { |
| return -1; |
| } |
| rq->maxsize = maxsize; |
| rq->buflen = increment; |
| rq->increment = increment; |
| rq->endbuf = &rq->buf[rq->buflen]; |
| rq->servp = rq->buf; |
| rq->endp = rq->buf; |
| *rq->servp = '\0'; |
| return 0; |
| } |
| |
| int ringqInsertc(ringq_t *rq, char_t c) |
| { |
| char_t *cp; |
| |
| a_assert(rq); |
| a_assert(rq->buflen == (rq->endbuf - rq->buf)); |
| |
| if (ringqPutBlkMax(rq) < (int) sizeof(char_t) && !ringqGrow(rq)) { |
| return -1; |
| } |
| if (rq->servp <= rq->buf) { |
| rq->servp = rq->endbuf; |
| } |
| cp = (char_t*) rq->servp; |
| *--cp = (char_t) c; |
| rq->servp = (unsigned char *) cp; |
| return 0; |
| } |
| |
| int ringqPutc(ringq_t *rq, char_t c) |
| { |
| char_t *cp; |
| |
| a_assert(rq); |
| a_assert(rq->buflen == (rq->endbuf - rq->buf)); |
| |
| if ((ringqPutBlkMax(rq) < (int) sizeof(char_t)) && !ringqGrow(rq)) { |
| return -1; |
| } |
| |
| cp = (char_t*) rq->endp; |
| *cp++ = (char_t) c; |
| rq->endp = (unsigned char *) cp; |
| if (rq->endp >= rq->endbuf) { |
| rq->endp = rq->buf; |
| } |
| return 0; |
| } |
| |
| int ringqGetc(ringq_t *rq) |
| { |
| char_t c; |
| char_t* cp; |
| |
| a_assert(rq); |
| a_assert(rq->buflen == (rq->endbuf - rq->buf)); |
| |
| if (rq->servp == rq->endp) { |
| return -1; |
| } |
| |
| cp = (char_t*) rq->servp; |
| c = *cp++; |
| rq->servp = (unsigned char *) cp; |
| if (rq->servp >= rq->endbuf) { |
| rq->servp = rq->buf; |
| } |
| return (int) ((unsigned char) c); |
| } |
| |
| int ringqLen(ringq_t *rq) |
| { |
| a_assert(rq); |
| a_assert(rq->buflen == (rq->endbuf - rq->buf)); |
| |
| if (rq->servp > rq->endp) { |
| return rq->buflen + rq->endp - rq->servp; |
| } else { |
| return rq->endp - rq->servp; |
| } |
| } |
| |
| void ringqAddNull(ringq_t *rq) |
| { |
| a_assert(rq); |
| a_assert(rq->buflen == (rq->endbuf - rq->buf)); |
| |
| *((char_t*) rq->endp) = (char_t) '\0'; |
| } |
| |
| int ringqPutStr(ringq_t *rq, char_t *str) |
| { |
| int rc; |
| |
| a_assert(rq); |
| a_assert(str); |
| a_assert(rq->buflen == (rq->endbuf - rq->buf)); |
| |
| rc = ringqPutBlk(rq, (unsigned char*) str, gstrlen(str) * sizeof(char_t)); |
| *((char_t*) rq->endp) = (char_t) '\0'; |
| return rc; |
| } |
| |
| |
| void ringqClose(ringq_t *rq) |
| { |
| a_assert(rq); |
| a_assert(rq->buflen == (rq->endbuf - rq->buf)); |
| |
| if (rq == NULL) { |
| return; |
| } |
| |
| ringqFlush(rq); |
| bfree(B_L, (char*) rq->buf); |
| rq->buf = NULL; |
| } |
| |
| |
| void ringqFlush(ringq_t *rq) |
| { |
| a_assert(rq); |
| a_assert(rq->servp); |
| |
| rq->servp = rq->buf; |
| rq->endp = rq->buf; |
| if (rq->servp) { |
| *rq->servp = '\0'; |
| } |
| } |
| |
| |
| #ifdef UNICODE |
| int ringqPutStrA(ringq_t *rq, char *str) |
| { |
| int rc; |
| |
| a_assert(rq); |
| a_assert(str); |
| a_assert(rq->buflen == (rq->endbuf - rq->buf)); |
| |
| rc = ringqPutBlk(rq, (unsigned char*) str, strlen(str)); |
| rq->endp[0] = '\0'; |
| return rc; |
| } |
| |
| int ringqGetcA(ringq_t *rq) |
| { |
| unsigned char c; |
| |
| a_assert(rq); |
| a_assert(rq->buflen == (rq->endbuf - rq->buf)); |
| |
| if (rq->servp == rq->endp) { |
| return -1; |
| } |
| |
| c = *rq->servp++; |
| if (rq->servp >= rq->endbuf) { |
| rq->servp = rq->buf; |
| } |
| return c; |
| } |
| |
| int ringqInsertcA(ringq_t *rq, char c) |
| { |
| a_assert(rq); |
| a_assert(rq->buflen == (rq->endbuf - rq->buf)); |
| |
| if (ringqPutBlkMax(rq) == 0 && !ringqGrow(rq)) { |
| return -1; |
| } |
| if (rq->servp <= rq->buf) { |
| rq->servp = rq->endbuf; |
| } |
| *--rq->servp = (unsigned char) c; |
| return 0; |
| } |
| |
| int ringqPutcA(ringq_t *rq, char c) |
| { |
| a_assert(rq); |
| a_assert(rq->buflen == (rq->endbuf - rq->buf)); |
| |
| if (ringqPutBlkMax(rq) == 0 && !ringqGrow(rq)) { |
| return -1; |
| } |
| |
| *rq->endp++ = (unsigned char) c; |
| if (rq->endp >= rq->endbuf) { |
| rq->endp = rq->buf; |
| } |
| return 0; |
| } |
| |
| #endif /* UNICODE */ |
| |
| void ringqGetBlkAdj(ringq_t *rq, int size) |
| { |
| a_assert(rq); |
| a_assert(rq->buflen == (rq->endbuf - rq->buf)); |
| a_assert(0 < size && size < rq->buflen); |
| |
| rq->servp += size; |
| if (rq->servp >= rq->endbuf) { |
| rq->servp -= rq->buflen; |
| } |
| |
| if (rq->servp >= rq->endbuf) { |
| error(E_L, E_LOG, T("Bad serv pointer")); |
| ringqFlush(rq); |
| } |
| } |
| |
| int ringqGetBlkMax(ringq_t *rq) |
| { |
| int len, in_a_line; |
| |
| a_assert(rq); |
| a_assert(rq->buflen == (rq->endbuf - rq->buf)); |
| |
| len = RINGQ_LEN(rq); |
| in_a_line = rq->endbuf - rq->servp; |
| |
| return min(in_a_line, len); |
| } |
| |
| int ringqGetBlk(ringq_t *rq, unsigned char *buf, int size) |
| { |
| int this, bytes_read; |
| |
| a_assert(rq); |
| a_assert(rq->buflen == (rq->endbuf - rq->buf)); |
| a_assert(buf); |
| a_assert(0 <= size && size < rq->buflen); |
| |
| bytes_read = 0; |
| while (size > 0) { |
| this = ringqGetBlkMax(rq); |
| this = min(this, size); |
| if (this <= 0) { |
| break; |
| } |
| |
| memcpy(buf, rq->servp, this); |
| buf += this; |
| rq->servp += this; |
| size -= this; |
| bytes_read += this; |
| |
| if (rq->servp >= rq->endbuf) { |
| rq->servp = rq->buf; |
| } |
| } |
| return bytes_read; |
| } |
| |
| int ringqPutBlk(ringq_t *rq, unsigned char *buf, int size) |
| { |
| int this, bytes_put; |
| |
| a_assert(rq); |
| a_assert(rq->buflen == (rq->endbuf - rq->buf)); |
| a_assert(buf); |
| a_assert(0 <= size); |
| |
| bytes_put = 0; |
| while (size > 0) { |
| this = min(ringqPutBlkMax(rq), size); |
| if (this <= 0) { |
| if (! ringqGrow(rq)) { |
| break; |
| } |
| this = min(ringqPutBlkMax(rq), size); |
| } |
| |
| memcpy(rq->endp, buf, this); |
| buf += this; |
| rq->endp += this; |
| size -= this; |
| bytes_put += this; |
| |
| if (rq->endp >= rq->endbuf) { |
| rq->endp = rq->buf; |
| } |
| } |
| return bytes_put; |
| } |
| |
| |
| int ringqPutBlkMax(ringq_t *rq) |
| { |
| int space, in_a_line; |
| |
| a_assert(rq); |
| a_assert(rq->buflen == (rq->endbuf - rq->buf)); |
| |
| space = rq->buflen - RINGQ_LEN(rq) - 1; |
| in_a_line = rq->endbuf - rq->endp; |
| |
| return min(in_a_line, space); |
| } |
| |
| |
| void ringqPutBlkAdj(ringq_t *rq, int size) |
| { |
| a_assert(rq); |
| a_assert(rq->buflen == (rq->endbuf - rq->buf)); |
| a_assert(0 <= size && size < rq->buflen); |
| |
| rq->endp += size; |
| if (rq->endp >= rq->endbuf) { |
| rq->endp -= rq->buflen; |
| } |
| |
| if (rq->endp >= rq->endbuf) { |
| error(E_L, E_LOG, T("Bad end pointer")); |
| ringqFlush(rq); |
| } |
| } |
| |
| |
| |
| static int ringqGrow(ringq_t *rq) |
| { |
| int rq_len; |
| unsigned char *reall_buf; |
| |
| |
| a_assert(rq); |
| |
| if (rq->maxsize >= 0 && rq->buflen >= rq->maxsize) { |
| return 0; |
| } |
| |
| rq_len = ringqLen(rq); |
| |
| if ((reall_buf = balloc(B_L, rq->buflen + rq->increment)) == NULL) { |
| return 0; |
| } |
| ringqGetBlk(rq, reall_buf, ringqLen(rq)); |
| bfree(B_L, (char*) rq->buf); |
| |
| #ifdef OLD |
| rq->endp = &reall_buf[endp]; |
| rq->servp = &reall_buf[servp]; |
| rq->endbuf = &reall_buf[rq->buflen]; |
| rq->buf = reall_buf; |
| #endif |
| |
| rq->buflen += rq->increment; |
| rq->endp = reall_buf; |
| rq->servp = reall_buf; |
| rq->buf = reall_buf; |
| rq->endbuf = &rq->buf[rq->buflen]; |
| |
| ringqPutBlk(rq, reall_buf, rq_len); |
| |
| rq->increment = getBinBlockSize(2 * rq->increment); |
| |
| return 1; |
| } |
| |
| static int getBinBlockSize(int size) |
| { |
| int q; |
| |
| size = size >> B_SHIFT; |
| for (q = 0; size; size >>= 1) { |
| q++; |
| } |
| return (1 << (B_SHIFT + q)); |
| } |
| |