/// \file
/// Default implementation of CommonTokenStream
///

// [The "BSD licence"]
// Copyright (c) 2005-2009 Jim Idle, Temporal Wave LLC
// http://www.temporal-wave.com
// http://www.linkedin.com/in/jimidle
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// 1. Redistributions of source code must retain the above copyright
//    notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in the
//    documentation and/or other materials provided with the distribution.
// 3. The name of the author may not be used to endorse or promote products
//    derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
// NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include    <antlr3tokenstream.h>

#ifdef  ANTLR3_WINDOWS
#pragma warning( disable : 4100 )
#endif

// COMMON_TOKEN_STREAM API
//
static void             setTokenTypeChannel     (pANTLR3_COMMON_TOKEN_STREAM cts, ANTLR3_UINT32 ttype, ANTLR3_UINT32 channel);
static void             discardTokenType        (pANTLR3_COMMON_TOKEN_STREAM cts, ANTLR3_INT32 ttype);
static void             discardOffChannel       (pANTLR3_COMMON_TOKEN_STREAM cts, ANTLR3_BOOLEAN discard);
static pANTLR3_VECTOR   getTokens               (pANTLR3_COMMON_TOKEN_STREAM cts);
static pANTLR3_LIST     getTokenRange           (pANTLR3_COMMON_TOKEN_STREAM cts, ANTLR3_UINT32 start, ANTLR3_UINT32 stop);
static pANTLR3_LIST     getTokensSet            (pANTLR3_COMMON_TOKEN_STREAM cts, ANTLR3_UINT32 start, ANTLR3_UINT32 stop, pANTLR3_BITSET types);
static pANTLR3_LIST     getTokensList           (pANTLR3_COMMON_TOKEN_STREAM cts, ANTLR3_UINT32 start, ANTLR3_UINT32 stop, pANTLR3_LIST list);
static pANTLR3_LIST     getTokensType           (pANTLR3_COMMON_TOKEN_STREAM cts, ANTLR3_UINT32 start, ANTLR3_UINT32 stop, ANTLR3_UINT32 type);
static void             reset                   (pANTLR3_COMMON_TOKEN_STREAM cts);

// TOKEN_STREAM API
//
static pANTLR3_COMMON_TOKEN tokLT               (pANTLR3_TOKEN_STREAM ts, ANTLR3_INT32 k);
static pANTLR3_COMMON_TOKEN dbgTokLT            (pANTLR3_TOKEN_STREAM ts, ANTLR3_INT32 k);
static pANTLR3_COMMON_TOKEN get                 (pANTLR3_TOKEN_STREAM ts, ANTLR3_UINT32 i);
static pANTLR3_TOKEN_SOURCE getTokenSource      (pANTLR3_TOKEN_STREAM ts);
static void                 setTokenSource      (pANTLR3_TOKEN_STREAM ts, pANTLR3_TOKEN_SOURCE tokenSource);
static pANTLR3_STRING       toString            (pANTLR3_TOKEN_STREAM ts);
static pANTLR3_STRING       toStringSS          (pANTLR3_TOKEN_STREAM ts, ANTLR3_UINT32 start, ANTLR3_UINT32 stop);
static pANTLR3_STRING       toStringTT          (pANTLR3_TOKEN_STREAM ts, pANTLR3_COMMON_TOKEN start, pANTLR3_COMMON_TOKEN stop);
static void                 setDebugListener    (pANTLR3_TOKEN_STREAM ts, pANTLR3_DEBUG_EVENT_LISTENER debugger);

// INT STREAM API
//
static void                 consume                     (pANTLR3_INT_STREAM is);
static void                 dbgConsume                  (pANTLR3_INT_STREAM is);
static ANTLR3_UINT32        _LA                         (pANTLR3_INT_STREAM is, ANTLR3_INT32 i);
static ANTLR3_UINT32        dbgLA                       (pANTLR3_INT_STREAM is, ANTLR3_INT32 i);
static ANTLR3_MARKER        mark                        (pANTLR3_INT_STREAM is);
static ANTLR3_MARKER        dbgMark                     (pANTLR3_INT_STREAM is);
static void                 release                     (pANTLR3_INT_STREAM is, ANTLR3_MARKER mark);
static ANTLR3_UINT32        size                        (pANTLR3_INT_STREAM is);
static ANTLR3_MARKER        tindex                      (pANTLR3_INT_STREAM is);
static void                 rewindStream                (pANTLR3_INT_STREAM is, ANTLR3_MARKER marker);
static void                 dbgRewindStream             (pANTLR3_INT_STREAM is, ANTLR3_MARKER marker);
static void                 rewindLast                  (pANTLR3_INT_STREAM is);
static void                 dbgRewindLast               (pANTLR3_INT_STREAM is);
static void                 seek                        (pANTLR3_INT_STREAM is, ANTLR3_MARKER index);
static void                 dbgSeek                     (pANTLR3_INT_STREAM is, ANTLR3_MARKER index);
static pANTLR3_STRING       getSourceName               (pANTLR3_INT_STREAM is);
static void                 antlr3TokenStreamFree       (pANTLR3_TOKEN_STREAM       stream);
static void                 antlr3CTSFree               (pANTLR3_COMMON_TOKEN_STREAM    stream);

// Helpers
//
static void                 fillBuffer                  (pANTLR3_COMMON_TOKEN_STREAM tokenStream);
static ANTLR3_UINT32        skipOffTokenChannels        (pANTLR3_COMMON_TOKEN_STREAM tokenStream, ANTLR3_INT32 i);
static ANTLR3_UINT32        skipOffTokenChannelsReverse (pANTLR3_COMMON_TOKEN_STREAM tokenStream, ANTLR3_INT32 i);
static pANTLR3_COMMON_TOKEN LB                          (pANTLR3_COMMON_TOKEN_STREAM tokenStream, ANTLR3_INT32 i);

ANTLR3_API pANTLR3_TOKEN_STREAM
antlr3TokenStreamNew()
{
    pANTLR3_TOKEN_STREAM stream;

    // Memory for the interface structure
    //
    stream  = (pANTLR3_TOKEN_STREAM) ANTLR3_MALLOC(sizeof(ANTLR3_TOKEN_STREAM));

    if  (stream == NULL)
    {
                return  NULL;
    }

    // Install basic API
    //
    stream->free    =  antlr3TokenStreamFree;


    return stream;
}

static void
antlr3TokenStreamFree(pANTLR3_TOKEN_STREAM stream)
{
    ANTLR3_FREE(stream);
}

static void
antlr3CTSFree       (pANTLR3_COMMON_TOKEN_STREAM stream)
{
        // We only free up our subordinate interfaces if they belong
        // to us, otherwise we let whoever owns them deal with them.
        //
        if      (stream->tstream->super == stream)
        {
                if      (stream->tstream->istream->super == stream->tstream)
                {
                        stream->tstream->istream->free(stream->tstream->istream);
                        stream->tstream->istream = NULL;
                }
                stream->tstream->free(stream->tstream);
        }

        // Now we free our own resources
        //
        if      (stream->tokens != NULL)
        {
                stream->tokens->free(stream->tokens);
                stream->tokens  = NULL;
        }
        if      (stream->discardSet != NULL)
        {
                stream->discardSet->free(stream->discardSet);
                stream->discardSet  = NULL;
        }
        if      (stream->channelOverrides != NULL)
        {
                stream->channelOverrides->free(stream->channelOverrides);
                stream->channelOverrides = NULL;
        }

        // Free our memory now
        //
        ANTLR3_FREE(stream);
}

// Reset a token stream so it can be used again and can reuse it's
// resources.
//
static void
reset   (pANTLR3_COMMON_TOKEN_STREAM cts)
{

    // Free any resources that ar most like specifc to the
    // run we just did.
    //
    if  (cts->discardSet != NULL)
    {
        cts->discardSet->free(cts->discardSet);
        cts->discardSet  = NULL;
    }
    if  (cts->channelOverrides != NULL)
    {
        cts->channelOverrides->free(cts->channelOverrides);
        cts->channelOverrides = NULL;
    }

    // Now, if there were any existing tokens in the stream,
    // then we just reset the vector count so that it starts
    // again. We must traverse the entries unfortunately as
    // there may be free pointers for custom token types and
    // so on. However that is just a quick NULL check on the
    // vector entries.
    //
    if  (cts->tokens != NULL)
    {
        cts->tokens->clear(cts->tokens);
    }
    else
    {
        /* Install the token tracking tables
         */
        cts->tokens  = antlr3VectorNew(0);
    }

    // Reset to defaults
    //
    cts->discardOffChannel  = ANTLR3_FALSE;
    cts->channel            = ANTLR3_TOKEN_DEFAULT_CHANNEL;
    cts->p                  = -1;
}

ANTLR3_API pANTLR3_COMMON_TOKEN_STREAM
antlr3CommonTokenDebugStreamSourceNew(ANTLR3_UINT32 hint, pANTLR3_TOKEN_SOURCE source, pANTLR3_DEBUG_EVENT_LISTENER debugger)
{
    pANTLR3_COMMON_TOKEN_STREAM stream;

        // Create a standard token stream
        //
        stream = antlr3CommonTokenStreamSourceNew(hint, source);

        // Install the debugger object
        //
        stream->tstream->debugger = debugger;

        // Override standard token stream methods with debugging versions
        //
        stream->tstream->initialStreamState     = ANTLR3_FALSE;

        stream->tstream->_LT                            = dbgTokLT;

        stream->tstream->istream->consume               = dbgConsume;
        stream->tstream->istream->_LA                   = dbgLA;
        stream->tstream->istream->mark                  = dbgMark;
        stream->tstream->istream->rewind                = dbgRewindStream;
        stream->tstream->istream->rewindLast    = dbgRewindLast;
        stream->tstream->istream->seek                  = dbgSeek;

        return stream;
}

ANTLR3_API pANTLR3_COMMON_TOKEN_STREAM
antlr3CommonTokenStreamSourceNew(ANTLR3_UINT32 hint, pANTLR3_TOKEN_SOURCE source)
{
    pANTLR3_COMMON_TOKEN_STREAM stream;

    stream = antlr3CommonTokenStreamNew(hint);

    stream->channel = ANTLR3_TOKEN_DEFAULT_CHANNEL;

    stream->channelOverrides    = NULL;
    stream->discardSet          = NULL;
    stream->discardOffChannel   = ANTLR3_FALSE;

    stream->tstream->setTokenSource(stream->tstream, source);

    stream->free                =  antlr3CTSFree;
    return  stream;
}

ANTLR3_API pANTLR3_COMMON_TOKEN_STREAM
antlr3CommonTokenStreamNew(ANTLR3_UINT32 hint)
{
    pANTLR3_COMMON_TOKEN_STREAM stream;

    /* Memory for the interface structure
     */
    stream  = (pANTLR3_COMMON_TOKEN_STREAM) ANTLR3_MALLOC(sizeof(ANTLR3_COMMON_TOKEN_STREAM));

    if  (stream == NULL)
    {
        return  NULL;
    }

    /* Create space for the token stream interface
     */
    stream->tstream         = antlr3TokenStreamNew();
    stream->tstream->super  =  stream;

    /* Create space for the INT_STREAM interfacce
     */
    stream->tstream->istream                =  antlr3IntStreamNew();
    stream->tstream->istream->super         =  (stream->tstream);
    stream->tstream->istream->type          = ANTLR3_TOKENSTREAM;

    /* Install the token tracking tables
     */
    stream->tokens  = antlr3VectorNew(0);

    /* Defaults
     */
    stream->p       = -1;

    /* Install the common token stream API
     */
    stream->setTokenTypeChannel     = setTokenTypeChannel;
    stream->discardTokenType        = discardTokenType;
    stream->discardOffChannelToks   = discardOffChannel;
    stream->getTokens               = getTokens;
    stream->getTokenRange           = getTokenRange;
    stream->getTokensSet            = getTokensSet;
    stream->getTokensList           = getTokensList;
    stream->getTokensType           = getTokensType;
    stream->reset                   = reset;

    /* Install the token stream API
     */
    stream->tstream->_LT                        =  tokLT;
    stream->tstream->get                        =  get;
    stream->tstream->getTokenSource             =  getTokenSource;
    stream->tstream->setTokenSource             =  setTokenSource;
    stream->tstream->toString                   =  toString;
    stream->tstream->toStringSS                 =  toStringSS;
    stream->tstream->toStringTT                 =  toStringTT;
    stream->tstream->setDebugListener           =  setDebugListener;

    /* Install INT_STREAM interface
     */
    stream->tstream->istream->_LA       =  _LA;
    stream->tstream->istream->mark      =  mark;
    stream->tstream->istream->release   =  release;
    stream->tstream->istream->size      =  size;
    stream->tstream->istream->index     =  tindex;
    stream->tstream->istream->rewind    =  rewindStream;
    stream->tstream->istream->rewindLast=  rewindLast;
    stream->tstream->istream->seek      =  seek;
    stream->tstream->istream->consume   =  consume;
    stream->tstream->istream->getSourceName = getSourceName;

    return  stream;
}

// Install a debug listener adn switch to debug mode methods
//
static void
setDebugListener        (pANTLR3_TOKEN_STREAM ts, pANTLR3_DEBUG_EVENT_LISTENER debugger)
{
                // Install the debugger object
        //
        ts->debugger = debugger;

        // Override standard token stream methods with debugging versions
        //
        ts->initialStreamState  = ANTLR3_FALSE;

        ts->_LT                         = dbgTokLT;

        ts->istream->consume            = dbgConsume;
        ts->istream->_LA                        = dbgLA;
        ts->istream->mark                       = dbgMark;
        ts->istream->rewind                     = dbgRewindStream;
        ts->istream->rewindLast         = dbgRewindLast;
        ts->istream->seek                       = dbgSeek;
}

/** Get the ith token from the current position 1..n where k=1 is the
*  first symbol of lookahead.
*/
static pANTLR3_COMMON_TOKEN
tokLT  (pANTLR3_TOKEN_STREAM ts, ANTLR3_INT32 k)
{
        ANTLR3_INT32    i;
        ANTLR3_INT32    n;
        pANTLR3_COMMON_TOKEN_STREAM cts;

        cts         = (pANTLR3_COMMON_TOKEN_STREAM)ts->super;

        if      (k < 0)
        {
                return LB(cts, -k);
        }

        if      (cts->p == -1)
        {
                fillBuffer(cts);
        }

        // Here we used to check for k == 0 and return 0, but this seems
        // a superfluous check to me. LT(k=0) is therefore just undefined
        // and we won't waste the clock cycles on the check
        //

        if      ((cts->p + k - 1) >= (ANTLR3_INT32)ts->istream->cachedSize)
        {
                pANTLR3_COMMON_TOKEN    teof = &(ts->tokenSource->eofToken);

                teof->setStartIndex (teof, ts->istream->index       (ts->istream));
                teof->setStopIndex  (teof, ts->istream->index       (ts->istream));
                return  teof;
        }

        i       = cts->p;
        n       = 1;

        /* Need to find k good tokens, skipping ones that are off channel
        */
        while   ( n < k)
        {
                /* Skip off-channel tokens */
                i = skipOffTokenChannels(cts, i+1); /* leave p on valid token    */
                n++;
        }
        if      ( (ANTLR3_UINT32) i >= ts->istream->cachedSize)
        {
                pANTLR3_COMMON_TOKEN    teof = &(ts->tokenSource->eofToken);

                teof->setStartIndex (teof, ts->istream->index(ts->istream));
                teof->setStopIndex  (teof, ts->istream->index(ts->istream));
                return  teof;
        }

        // Here the token must be in the input vector. Rather then incur
        // function call penalty, we just return the pointer directly
        // from the vector
        //
        return  (pANTLR3_COMMON_TOKEN)cts->tokens->elements[i].element;
        //return  (pANTLR3_COMMON_TOKEN)cts->tokens->get(cts->tokens, i);
}

/// Debug only method to flag consumption of initial off-channel
/// tokens in the input stream
///
static void
consumeInitialHiddenTokens(pANTLR3_INT_STREAM is)
{
        ANTLR3_MARKER   first;
        ANTLR3_INT32    i;
        pANTLR3_TOKEN_STREAM    ts;

        ts          = (pANTLR3_TOKEN_STREAM)        is->super;
        first   = is->index(is);

        for     (i=0; i<first; i++)
        {
                ts->debugger->consumeHiddenToken(ts->debugger, ts->get(ts, i));
        }

        ts->initialStreamState = ANTLR3_FALSE;

}

/// As per the normal tokLT but sends information to the debugger
///
static pANTLR3_COMMON_TOKEN
dbgTokLT  (pANTLR3_TOKEN_STREAM ts, ANTLR3_INT32 k)
{
        if      (ts->initialStreamState == ANTLR3_TRUE)
        {
                consumeInitialHiddenTokens(ts->istream);
        }
        return tokLT(ts, k);
}

#ifdef  ANTLR3_WINDOWS
        /* When fully optimized VC7 complains about non reachable code.
         * Not yet sure if this is an optimizer bug, or a bug in the flow analysis
         */
#pragma warning( disable : 4702 )
#endif

static pANTLR3_COMMON_TOKEN
LB(pANTLR3_COMMON_TOKEN_STREAM cts, ANTLR3_INT32 k)
{
    ANTLR3_INT32 i;
    ANTLR3_INT32 n;

    if (cts->p == -1)
    {
        fillBuffer(cts);
    }
    if (k == 0)
    {
        return NULL;
    }
    if ((cts->p - k) < 0)
    {
        return NULL;
    }

    i = cts->p;
    n = 1;

    /* Need to find k good tokens, going backwards, skipping ones that are off channel
     */
    while (n <= (ANTLR3_INT32) k)
    {
        /* Skip off-channel tokens
         */

        i = skipOffTokenChannelsReverse(cts, i - 1); /* leave p on valid token    */
        n++;
    }
    if (i < 0)
    {
        return NULL;
    }
        // Here the token must be in the input vector. Rather then incut
        // function call penalty, we jsut return the pointer directly
        // from the vector
        //
        return  (pANTLR3_COMMON_TOKEN)cts->tokens->elements[i].element;
}

static pANTLR3_COMMON_TOKEN
get (pANTLR3_TOKEN_STREAM ts, ANTLR3_UINT32 i)
{
    pANTLR3_COMMON_TOKEN_STREAM cts;

    cts     = (pANTLR3_COMMON_TOKEN_STREAM)ts->super;

    return  (pANTLR3_COMMON_TOKEN)(cts->tokens->get(cts->tokens, i));  /* Token index is zero based but vectors are 1 based */
}

static pANTLR3_TOKEN_SOURCE
getTokenSource  (pANTLR3_TOKEN_STREAM ts)
{
    return  ts->tokenSource;
}

static void
setTokenSource  (   pANTLR3_TOKEN_STREAM ts,
                    pANTLR3_TOKEN_SOURCE tokenSource)
{
    ts->tokenSource     = tokenSource;
}

static pANTLR3_STRING
toString    (pANTLR3_TOKEN_STREAM ts)
{
    pANTLR3_COMMON_TOKEN_STREAM cts;

    cts     = (pANTLR3_COMMON_TOKEN_STREAM)ts->super;

    if  (cts->p == -1)
    {
        fillBuffer(cts);
    }

    return  ts->toStringSS(ts, 0, ts->istream->size(ts->istream));
}

static pANTLR3_STRING
toStringSS(pANTLR3_TOKEN_STREAM ts, ANTLR3_UINT32 start, ANTLR3_UINT32 stop)
{
    pANTLR3_STRING string;
    pANTLR3_TOKEN_SOURCE tsource;
    pANTLR3_COMMON_TOKEN tok;
    ANTLR3_UINT32 i;
    pANTLR3_COMMON_TOKEN_STREAM cts;

    cts = (pANTLR3_COMMON_TOKEN_STREAM) ts->super;

    if (cts->p == -1)
    {
        fillBuffer(cts);
    }
    if (stop >= ts->istream->size(ts->istream))
    {
        stop = ts->istream->size(ts->istream) - 1;
    }

    /* Who is giving us these tokens?
     */
    tsource = ts->getTokenSource(ts);

    if (tsource != NULL && cts->tokens != NULL)
    {
        /* Finally, let's get a string
         */
        string = tsource->strFactory->newRaw(tsource->strFactory);

        for (i = start; i <= stop; i++)
        {
            tok = ts->get(ts, i);
            if (tok != NULL)
            {
                string->appendS(string, tok->getText(tok));
            }
        }

        return string;
    }
    return NULL;

}

static pANTLR3_STRING
toStringTT  (pANTLR3_TOKEN_STREAM ts, pANTLR3_COMMON_TOKEN start, pANTLR3_COMMON_TOKEN stop)
{
        if      (start != NULL && stop != NULL)
        {
                return  ts->toStringSS(ts, (ANTLR3_UINT32)start->getTokenIndex(start), (ANTLR3_UINT32)stop->getTokenIndex(stop));
        }
        else
        {
                return  NULL;
        }
}

/** Move the input pointer to the next incoming token.  The stream
 *  must become active with LT(1) available.  consume() simply
 *  moves the input pointer so that LT(1) points at the next
 *  input symbol. Consume at least one token.
 *
 *  Walk past any token not on the channel the parser is listening to.
 */
static void
consume (pANTLR3_INT_STREAM is)
{
        pANTLR3_COMMON_TOKEN_STREAM cts;
        pANTLR3_TOKEN_STREAM    ts;

        ts          = (pANTLR3_TOKEN_STREAM)        is->super;
        cts         = (pANTLR3_COMMON_TOKEN_STREAM) ts->super;

        if      ((ANTLR3_UINT32)cts->p < cts->tokens->count)
        {
                cts->p++;
                cts->p  = skipOffTokenChannels(cts, cts->p);
        }
}


/// As per ordinary consume but notifies the debugger about hidden
/// tokens and so on.
///
static void
dbgConsume      (pANTLR3_INT_STREAM is)
{
        pANTLR3_TOKEN_STREAM    ts;
        ANTLR3_MARKER                   a;
        ANTLR3_MARKER                   b;
        pANTLR3_COMMON_TOKEN    t;

        ts          = (pANTLR3_TOKEN_STREAM)        is->super;

        if      (ts->initialStreamState == ANTLR3_TRUE)
        {
                consumeInitialHiddenTokens(is);
        }

        a = is->index(is);              // Where are we right now?
        t = ts->_LT(ts, 1);             // Current token from stream

        consume(is);                    // Standard consumer

        b = is->index(is);              // Where are we after consuming 1 on channel token?

        ts->debugger->consumeToken(ts->debugger, t);    // Tell the debugger that we consumed the first token

        if      (b>a+1)
        {
                // The standard consume caused the index to advance by more than 1,
                // which can only happen if it skipped some off-channel tokens.
                // we need to tell the debugger about those tokens.
                //
                ANTLR3_MARKER   i;

                for     (i = a+1; i<b; i++)
                {
                        ts->debugger->consumeHiddenToken(ts->debugger, ts->get(ts, (ANTLR3_UINT32)i));
                }

        }
}

/** A simple filter mechanism whereby you can tell this token stream
 *  to force all tokens of type ttype to be on channel.  For example,
 *  when interpreting, we cannot execute actions so we need to tell
 *  the stream to force all WS and NEWLINE to be a different, ignored,
 *  channel.
 */
static void
setTokenTypeChannel (pANTLR3_COMMON_TOKEN_STREAM tokenStream, ANTLR3_UINT32 ttype, ANTLR3_UINT32 channel)
{
    if  (tokenStream->channelOverrides == NULL)
    {
        tokenStream->channelOverrides   = antlr3ListNew(10);
    }

    /* We add one to the channel so we can distinguish NULL as being no entry in the
     * table for a particular token type.
     */
    tokenStream->channelOverrides->put(tokenStream->channelOverrides, ttype, ANTLR3_FUNC_PTR((ANTLR3_UINT32)channel + 1), NULL);
}

static void
discardTokenType    (pANTLR3_COMMON_TOKEN_STREAM tokenStream, ANTLR3_INT32 ttype)
{
    if  (tokenStream->discardSet == NULL)
    {
        tokenStream->discardSet = antlr3ListNew(31);
    }

    /* We add one to the channel so we can distinguish NULL as being no entry in the
     * table for a particular token type. We could use bitsets for this I suppose too.
     */
    tokenStream->discardSet->put(tokenStream->discardSet, ttype, ANTLR3_FUNC_PTR((ANTLR3_UINT32)ttype + 1), NULL);
}

static void
discardOffChannel   (pANTLR3_COMMON_TOKEN_STREAM tokenStream, ANTLR3_BOOLEAN discard)
{
    tokenStream->discardOffChannel  = discard;
}

static pANTLR3_VECTOR
getTokens   (pANTLR3_COMMON_TOKEN_STREAM tokenStream)
{
    if  (tokenStream->p == -1)
    {
        fillBuffer(tokenStream);
    }

    return  tokenStream->tokens;
}

static pANTLR3_LIST
getTokenRange   (pANTLR3_COMMON_TOKEN_STREAM tokenStream, ANTLR3_UINT32 start, ANTLR3_UINT32 stop)
{
    return tokenStream->getTokensSet(tokenStream, start, stop, NULL);
}
/** Given a start and stop index, return a List of all tokens in
 *  the token type BitSet.  Return null if no tokens were found.  This
 *  method looks at both on and off channel tokens.
 */
static pANTLR3_LIST
getTokensSet    (pANTLR3_COMMON_TOKEN_STREAM tokenStream, ANTLR3_UINT32 start, ANTLR3_UINT32 stop, pANTLR3_BITSET types)
{
    pANTLR3_LIST            filteredList;
    ANTLR3_UINT32           i;
    ANTLR3_UINT32           n;
    pANTLR3_COMMON_TOKEN    tok;

    if  (tokenStream->p == -1)
    {
        fillBuffer(tokenStream);
    }
    if  (stop > tokenStream->tstream->istream->size(tokenStream->tstream->istream))
    {
        stop = tokenStream->tstream->istream->size(tokenStream->tstream->istream);
    }
    if  (start > stop)
    {
        return NULL;
    }

    /* We have the range set, now we need to iterate through the
     * installed tokens and create a new list with just the ones we want
     * in it. We are just moving pointers about really.
     */
    filteredList    = antlr3ListNew((ANTLR3_UINT32)tokenStream->tstream->istream->size(tokenStream->tstream->istream));

    for (i = start, n = 0; i<= stop; i++)
    {
        tok = tokenStream->tstream->get(tokenStream->tstream, i);

        if  (      types == NULL
                || types->isMember(types, tok->getType(tok) == ANTLR3_TRUE)
            )
        {
            filteredList->put(filteredList, n++, (void *)tok, NULL);
        }
    }

    /* Did we get any then?
     */
    if  (filteredList->size(filteredList) == 0)
    {
        filteredList->free(filteredList);
        filteredList    = NULL;
    }

    return  filteredList;
}

static pANTLR3_LIST
getTokensList   (pANTLR3_COMMON_TOKEN_STREAM tokenStream, ANTLR3_UINT32 start, ANTLR3_UINT32 stop, pANTLR3_LIST list)
{
    pANTLR3_BITSET  bitSet;
    pANTLR3_LIST    newlist;

    bitSet  = antlr3BitsetList(list->table);

    newlist    = tokenStream->getTokensSet(tokenStream, start, stop, bitSet);

    bitSet->free(bitSet);

    return  newlist;

}

static pANTLR3_LIST
getTokensType   (pANTLR3_COMMON_TOKEN_STREAM tokenStream, ANTLR3_UINT32 start, ANTLR3_UINT32 stop, ANTLR3_UINT32 type)
{
    pANTLR3_BITSET  bitSet;
    pANTLR3_LIST    newlist;

    bitSet  = antlr3BitsetOf(type, -1);
    newlist = tokenStream->getTokensSet(tokenStream, start, stop, bitSet);

    bitSet->free(bitSet);

    return  newlist;
}

static ANTLR3_UINT32
_LA  (pANTLR3_INT_STREAM is, ANTLR3_INT32 i)
{
        pANTLR3_TOKEN_STREAM    ts;
        pANTLR3_COMMON_TOKEN    tok;

        ts          = (pANTLR3_TOKEN_STREAM)        is->super;

        tok         =  ts->_LT(ts, i);

        if      (tok != NULL)
        {
                return  tok->getType(tok);
        }
        else
        {
                return  ANTLR3_TOKEN_INVALID;
        }
}

/// As per _LA() but for debug mode.
///
static ANTLR3_UINT32
dbgLA  (pANTLR3_INT_STREAM is, ANTLR3_INT32 i)
{
    pANTLR3_TOKEN_STREAM    ts;

    ts      = (pANTLR3_TOKEN_STREAM)        is->super;

        if      (ts->initialStreamState == ANTLR3_TRUE)
        {
                consumeInitialHiddenTokens(is);
        }
        ts->debugger->LT(ts->debugger, i, tokLT(ts, i));
        return  _LA(is, i);
}

static ANTLR3_MARKER
mark    (pANTLR3_INT_STREAM is)
{
    is->lastMarker = is->index(is);
    return  is->lastMarker;
}

/// As per mark() but with a call to tell the debugger we are doing this
///
static ANTLR3_MARKER
dbgMark (pANTLR3_INT_STREAM is)
{
    pANTLR3_TOKEN_STREAM    ts;

    ts      = (pANTLR3_TOKEN_STREAM)        is->super;

        is->lastMarker = is->index(is);
        ts->debugger->mark(ts->debugger, is->lastMarker);

    return  is->lastMarker;
}

static void
release (pANTLR3_INT_STREAM is, ANTLR3_MARKER mark)
{
    return;
}

static ANTLR3_UINT32
size    (pANTLR3_INT_STREAM is)
{
    pANTLR3_COMMON_TOKEN_STREAM cts;
    pANTLR3_TOKEN_STREAM        ts;

    if (is->cachedSize > 0)
    {
        return  is->cachedSize;
    }
    ts      = (pANTLR3_TOKEN_STREAM)        is->super;
    cts     = (pANTLR3_COMMON_TOKEN_STREAM) ts->super;

    is->cachedSize =  cts->tokens->count;
    return  is->cachedSize;
}

static ANTLR3_MARKER
tindex  (pANTLR3_INT_STREAM is)
{
    pANTLR3_COMMON_TOKEN_STREAM cts;
    pANTLR3_TOKEN_STREAM        ts;

    ts      = (pANTLR3_TOKEN_STREAM)        is->super;
    cts     = (pANTLR3_COMMON_TOKEN_STREAM) ts->super;

    return  cts->p;
}

static void
dbgRewindLast   (pANTLR3_INT_STREAM is)
{
        pANTLR3_TOKEN_STREAM    ts;

    ts      = (pANTLR3_TOKEN_STREAM)        is->super;

        ts->debugger->rewindLast(ts->debugger);

    is->rewind(is, is->lastMarker);
}
static void
rewindLast      (pANTLR3_INT_STREAM is)
{
    is->rewind(is, is->lastMarker);
}
static void
rewindStream    (pANTLR3_INT_STREAM is, ANTLR3_MARKER marker)
{
    is->seek(is, (ANTLR3_UINT32)(marker));
}
static void
dbgRewindStream (pANTLR3_INT_STREAM is, ANTLR3_MARKER marker)
{
    pANTLR3_TOKEN_STREAM        ts;

    ts      = (pANTLR3_TOKEN_STREAM)        is->super;

        ts->debugger->rewind(ts->debugger, marker);

    is->seek(is, (ANTLR3_UINT32)(marker));
}

static void
seek    (pANTLR3_INT_STREAM is, ANTLR3_MARKER index)
{
    pANTLR3_COMMON_TOKEN_STREAM cts;
    pANTLR3_TOKEN_STREAM        ts;

    ts      = (pANTLR3_TOKEN_STREAM)        is->super;
    cts     = (pANTLR3_COMMON_TOKEN_STREAM) ts->super;

    cts->p  = (ANTLR3_UINT32)index;
}
static void
dbgSeek (pANTLR3_INT_STREAM is, ANTLR3_MARKER index)
{
        // TODO: Implement seek in debugger when Ter adds it to Java
        //
        seek(is, index);
}
ANTLR3_API void
fillBufferExt(pANTLR3_COMMON_TOKEN_STREAM tokenStream)
{
    fillBuffer(tokenStream);
}
static void
fillBuffer(pANTLR3_COMMON_TOKEN_STREAM tokenStream) {
    ANTLR3_UINT32 index;
    pANTLR3_COMMON_TOKEN tok;
    ANTLR3_BOOLEAN discard;
    void * channelI;

    /* Start at index 0 of course
     */
    index = 0;

    /* Pick out the next token from the token source
     * Remember we just get a pointer (reference if you like) here
     * and so if we store it anywhere, we don't set any pointers to auto free it.
     */
    tok = tokenStream->tstream->tokenSource->nextToken(tokenStream->tstream->tokenSource);

    while (tok != NULL && tok->type != ANTLR3_TOKEN_EOF)
    {
        discard = ANTLR3_FALSE; /* Assume we are not discarding */

        /* I employ a bit of a trick, or perhaps hack here. Rather than
         * store a pointer to a structure in the override map and discard set
         * we store the value + 1 cast to a void *. Hence on systems where NULL = (void *)0
         * we can distinguish "not being there" from "being channel or type 0"
         */

        if (tokenStream->discardSet != NULL
            && tokenStream->discardSet->get(tokenStream->discardSet, tok->getType(tok)) != NULL)
        {
            discard = ANTLR3_TRUE;
        }
        else if (   tokenStream->discardOffChannel == ANTLR3_TRUE
                 && tok->getChannel(tok) != tokenStream->channel
                 )
        {
            discard = ANTLR3_TRUE;
        }
        else if (tokenStream->channelOverrides != NULL)
        {
            /* See if this type is in the override map
             */
            channelI = tokenStream->channelOverrides->get(tokenStream->channelOverrides, tok->getType(tok) + 1);

            if (channelI != NULL)
            {
                /* Override found
                 */
                tok->setChannel(tok, ANTLR3_UINT32_CAST(channelI) - 1);
            }
        }

        /* If not discarding it, add it to the list at the current index
         */
        if (discard == ANTLR3_FALSE)
        {
            /* Add it, indicating that we will delete it and the table should not
             */
            tok->setTokenIndex(tok, index);
            tokenStream->p++;
            tokenStream->tokens->add(tokenStream->tokens, (void *) tok, NULL);
            index++;
        }

        tok = tokenStream->tstream->tokenSource->nextToken(tokenStream->tstream->tokenSource);
    }

    /* Cache the size so we don't keep doing indirect method calls. We do this as
     * early as possible so that anything after this may utilize the cached value.
     */
    tokenStream->tstream->istream->cachedSize = tokenStream->tokens->count;

    /* Set the consume pointer to the first token that is on our channel
     */
    tokenStream->p = 0;
    tokenStream->p = skipOffTokenChannels(tokenStream, tokenStream->p);

}

/// Given a starting index, return the index of the first on-channel
///  token.
///
static ANTLR3_UINT32
skipOffTokenChannels(pANTLR3_COMMON_TOKEN_STREAM tokenStream, ANTLR3_INT32 i) {
    ANTLR3_INT32 n;
    pANTLR3_COMMON_TOKEN tok;

    n = tokenStream->tstream->istream->cachedSize;

    while (i < n)
    {
        tok =  (pANTLR3_COMMON_TOKEN)tokenStream->tokens->elements[i].element;

        if (tok->channel!= tokenStream->channel)
        {
            i++;
        }
        else
        {
            return i;
        }
    }
    return i;
}

static ANTLR3_UINT32
skipOffTokenChannelsReverse(pANTLR3_COMMON_TOKEN_STREAM tokenStream, ANTLR3_INT32 x)
{
    pANTLR3_COMMON_TOKEN tok;

    while (x >= 0)
    {
        tok =  (pANTLR3_COMMON_TOKEN)tokenStream->tokens->elements[x].element;

        if ((tok->channel != tokenStream->channel))
        {
            x--;
        }
        else
        {
            return x;
        }
    }
    return x;
}

/// Return a string that represents the name assoicated with the input source
///
/// /param[in] is The ANTLR3_INT_STREAM interface that is representing this token stream.
///
/// /returns
/// /implements ANTLR3_INT_STREAM_struct::getSourceName()
///
static pANTLR3_STRING
getSourceName                           (pANTLR3_INT_STREAM is)
{
        // Slightly convoluted as we must trace back to the lexer's input source
        // via the token source. The streamName that is here is not initialized
        // because this is a token stream, not a file or string stream, which are the
        // only things that have a context for a source name.
        //
        return ((pANTLR3_TOKEN_STREAM)(is->super))->tokenSource->fileName;
}
