Example #1
0
int _flushbuf(int ch, FILE *stream)
{   int flag = stream -> _flag;
    if ((flag & _IOERR+_IOSTRG+_IOWRITE+_IOFP1) != _IOWRITE)
    {   stream->_ocnt = 0;                        /* 2^31 is big but finite */
        seterr(stream);
        return EOF;
    }
/* the next conditional code is ACN's view of that APPEND means seek to     */
/* EOF after EVERY fflush, not just initially.  Hmm, ANSI really should     */
/* clarify - the problem is perhaps that we wish to seek to EOF after       */
/* fflush after read, but not after fflush after write?                     */
    if ((flag & (_IOFP2+_IOSEEK+_IOAPPEND)) == _IOAPPEND)
    {   /* first write to APPEND file after FFLUSH, but not FSEEK nor       */
        /* fopen (does its own FSEEK)                                       */
        fseek(stream, 0L, SEEK_END);
        flag = stream->_flag;
    }
    stream->_flag = (flag |= _IOFP2);             /* we are writing         */
    if ((flag & _IOFBF+_IOSBF+_IONBF+_IOLBF) == 0)
    {   if (_sys_istty_(stream->_file))           /* terminal - unbuffered  */
#ifdef LINE_BUFFERED_TTYIO
            stream->_ptr = stream -> _base = _sys_alloc(LINBUFSIZ),
            stream->_bufsiz = LINBUFSIZ,
            stream->_flag |= (flag |= _IOLBF);
#else
            stream->_ptr = stream->_base = stream->_lilbuf,
            stream->_bufsiz = 1,
            stream->_flag = (flag |= _IONBF);
#endif
        else
            /* allocate default system buffer */
            stream->_ptr = stream->_base = _sys_alloc(BUFSIZ),
            stream->_bufsiz = BUFSIZ,
            stream->_flag |= (flag |= _IOSBF);
    }
/*
    @description:
        Heapify helper for _sort.
*/
void do_heap(uint8_t *base, size_t i, size_t n, size_t size, _cmp_func_t cmp)
{
    /* Not much can be done when size is unknown */
    void *temp = _sys_alloc(size);
    size_t k;

    /* Save the node that's being overwritten below */
    memcpy(temp, &base[i * size], size);

    /* Move all subsequent child nodes into place to maintain the heap property */
    for (k = i * 2 + 1; k < n; k = i * 2 + 1) {
        /* Find the next child node */
        if (k + 1 < n && cmp(&base[k * size], &base[(k + 1) * size]) < 0)
            ++k;

        /* Are we at the saved node's sorted position? */
        if (cmp(temp, &base[k * size]) >= 0)
            break;

        /* Overwrite the parent with one of its children */
        memcpy(&base[i * size], &base[k * size], size);
        i = k;
    }

    /* Copy the saved node into its final resting place */
    memcpy(&base[i * size], temp, size);
    _sys_free(temp);
}
/*
    @description:
        qsort-friendly implementation of heapsort for guaranteed time complexity.
*/
void _sort(void *base, size_t n, size_t size, _cmp_func_t cmp)
{
    /* Not much can be done when size is unknown */
    void *temp = _sys_alloc(size);
    uint8_t *p = (uint8_t*)base;
    int i = n / 2;

    /* Heapify the array */
    while (i-- > 0)
        do_heap(p, i, n, size, cmp);

    /* Extrac the heap max and place it in sorted position */
    while (--n < (size_t)-1) {
        /* Swap the heap max with base[n] */
        memcpy(temp, p, size);
        memcpy(p, &p[n * size], size);
        memcpy(&p[n * size], temp, size);

        /* Re-heapify after removing the heap max */
        do_heap(p, 0, n, size, cmp);
    }

    _sys_free(temp);
}