コード例 #1
0
NimLexer::Token NimLexer::onDefaultState()
{
    while (!m_stream->isEnd())
    {
        if (isSkipChar(m_stream)) {
            m_stream->move();
            continue;
        }
        if (isOperator(m_stream))
            return readOperator(m_stream);
        if (matchDocumentationStart(m_stream))
            return readDocumentation(m_stream);
        if (matchCommentStart(m_stream))
            return readComment(m_stream);
        if (matchMultiLineStringLiteralStart(m_stream))
            return readMultiLineStringLiteral(m_stream, true);
        if (matchStringLiteralStart(m_stream))
            return readStringLiteral(m_stream);
        if (matchIdentifierOrKeywordStart(m_stream))
            return readIdentifierOrKeyword(m_stream);
        m_stream->move();
    }

    return Token {0,0, TokenType::EndOfText };
}
コード例 #2
0
bool patternRecognitionPCA::importPCA(char * filename)
{
	int i, intRead1, intRead2;
	float floatRead;

	FILE * fp = fopen(filename, "r");
	if(fp == NULL) return false;

	readComment(fp);
	fscanf(fp, "%d %d ", &intRead1, &intRead2);
	inputDim = intRead1;
	outputDim = intRead2;

	if(mean != NULL) delete [] mean;
	mean = new double[inputDim];
	readComment(fp);
	for(i = 0; i < inputDim; i++) 
	{
		fscanf(fp, "%f ", &floatRead);
		mean[i] = floatRead;
	}

	if(reductionMatrix != NULL) delete [] reductionMatrix;
	reductionMatrix = new double[inputDim*outputDim];
	readComment(fp);
	for(i = 0; i < inputDim*outputDim; i++) 
	{
		fscanf(fp, "%f ", &floatRead);
		reductionMatrix[i] = floatRead;
	}

	if(eigenvalues != NULL) delete [] eigenvalues;
	eigenvalues = new double[outputDim];
	readComment(fp);
	for(i = 0; i < outputDim; i++)
	{
		fscanf(fp, "%f ", &floatRead);
		eigenvalues[i] = floatRead;
	}

	fclose(fp);

	return true;
}
コード例 #3
0
ファイル: routecommentsdlg.cpp プロジェクト: allenck/mapper
void RouteCommentsDlg::setDate(QDate dt)
{
    _date = dt;
    ui->dateEdit->setDate(dt);

    readComment(0);

    bDateChanged = false;

}
コード例 #4
0
ファイル: gifdecoder.c プロジェクト: dennis-xlc/ORDER
GIF_RETVAL readExtension(JNIEnv *env, GifDecoder *decoder, jobject currBlock) {
    unsigned char extensionSize = *(decoder->inputPtr+2);
    unsigned char extensionType;

    if(decoder->bytesInBuffer < extensionSize + 3) { // Stop, we need more data
        return STATUS_BUFFER_EMPTY;
    }

    decoder->inputPtr++; // Skip extension introducer

    extensionType = *(decoder->inputPtr);
    decoder->inputPtr += 2; // Skip size, already got it
    decoder->bytesInBuffer -= 3; // Decrease buffer size as we advanced

    switch(extensionType) {
    case GRAPHIC_CONTROL_EXTENSION:
        readGraphicControl(env, decoder, currBlock);
        break;

    case COMMENT_EXTENSION: {
        decoder->inputPtr -= 1; // No extension size, usual sub-blocks, go back
        decoder->bytesInBuffer += 1;
        decoder->state = STATE_READING_COMMENT;
        return readComment(env, decoder);
    }

    case APPLICATION_EXTENSION:
        if(extensionSize == SIZE_NETSCAPE_EXT &&
                !strncmp(decoder->inputPtr, "NETSCAPE2.0", SIZE_NETSCAPE_EXT)) {
            if(*(decoder->inputPtr + extensionSize) == 3) { // Magic size of the sub-block in netscape ext
                unsigned short loopCount;
                decoder->inputPtr += extensionSize;
                decoder->bytesInBuffer -= extensionSize;
                loopCount = *((unsigned short *) (decoder->inputPtr+2));
                (*env)->SetIntField(env, decoder->jDataStream, img_GIF_ds_loopCountID, loopCount);
                return skipData(decoder);
            } // If the extension is invalid proceed to default
        }

    case PLAIN_TEXT_EXTENSION:
    default:
        decoder->inputPtr += extensionSize;
        decoder->bytesInBuffer -= extensionSize;
        if(!(*(decoder->inputPtr))) { // No additional data
            decoder->inputPtr++;
            decoder->bytesInBuffer--;
            decoder->state = STATE_BLOCK_BEGINNING;
        } else {
            decoder->state = STATE_SKIPPING_BLOCKS;
            return skipData(decoder);
        }
    }

    return STATUS_OK;
}
コード例 #5
0
void CvrpFileReader::processLine(QStringList l_wordList, QString l_line)
{
    switch (Utils::findEnumForKeyword(l_wordList[0]))
    {
        case Utils::e_keywords::NAME:
            readName(l_wordList);
            break;
        case Utils::e_keywords::COMMENT:
            readComment(l_line);
            break;
        case Utils::e_keywords::TYPE:
            readVrpType(l_wordList);
            break;
        case Utils::e_keywords::DIMENSION:
            readDimension(l_wordList);
            break;
        case Utils::e_keywords::EDGE_WEIGHT_TYPE:
            readEdgesType(l_wordList);
            break;
        case Utils::e_keywords::CAPACITY:
            readCapacity(l_wordList);
            break;
        case Utils::e_keywords::NODE_COORD_SECTION:
            readCoordinates();
            break;
        case Utils::e_keywords::DEMAND_SECTION:
            readDemands();
            break;
        case Utils::e_keywords::DEPOT_SECTION:
            readDepots();
            break;
        case Utils::e_keywords::END:
            break;
        case Utils::e_keywords::EDGE_WEIGHT_FORMAT:
        case Utils::e_keywords::EDGE_DATA_FORMAT:
        case Utils::e_keywords::NODE_COORD_TYPE:
        case Utils::e_keywords::DISPLAY_DATA_TYPE:
        case Utils::e_keywords::EDGE_DATA_SECTION:
        case Utils::e_keywords::FIXED_EDGE_SECTION:
        case Utils::e_keywords::DISPLAY_DATA_SECTION:
        case Utils::e_keywords::TOUR_SECTION:
        case Utils::e_keywords::EDGE_WEIGHT_SECTION:
        case Utils::e_keywords::UNDEFINED:
            throw std::runtime_error(std::string("Unimplemented token!"));
        default:
            throw std::runtime_error(std::string("Undefined token!"));
    }
}
コード例 #6
0
ファイル: routecommentsdlg.cpp プロジェクト: allenck/mapper
void RouteCommentsDlg::OnRouteLeave()
{
 if(bRouteChanged)
 {
  outputChanges();

  _route = ui->txtRoute->text().toInt();
  ui->txtRouteAlpha->setText(sql->getAlphaRoute(_route, _companyKey));
  ui->txtComments->clear();

  if(readComment(0))
  {
   setDirty(true);
  }
 }
 bRouteChanged = false;
}
コード例 #7
0
ファイル: routecommentsdlg.cpp プロジェクト: allenck/mapper
void RouteCommentsDlg::OnDateLeave()
{
 QDate date = ui->dateEdit->date();
 if(!bDateChanged)
     return;
 outputChanges();

 _date = date;
 ui->dateEdit->setDate(date);
 bDateChanged = false;
 ui->txtComments->clear();
 ui->txtComments->setFontPointSize(9);

 ui->txtTags->clear();
 setDirty(false);

 readComment(0);
}
コード例 #8
0
ファイル: ogg.cpp プロジェクト: queile/peca-android-upnp
// -----------------------------------
void OggVorbisSubStream::procHeaders(Channel *ch)
{
	unsigned int packPtr=0;

	for(int i=0; i<pack.numPackets; i++)
	{
		MemoryStream vin(&pack.body[packPtr],pack.packetSizes[i]);

		packPtr += pack.packetSizes[i];

		char id[8];

		vin.read(id,7);
		id[7]=0;

		switch (id[0])
		{
			case 1:	// ident
				LOG_CHANNEL("OGG Vorbis Header: Ident (%d bytes)",vin.len);
				readIdent(vin,ch->info);
				break;
			case 3: // comment
				{
					LOG_CHANNEL("OGG Vorbis Header: Comment (%d bytes)",vin.len);
					ChanInfo newInfo = ch->info;
					readComment(vin,newInfo);
					ch->updateInfo(newInfo);
				}
				break;
			case 5: // setup
				LOG_CHANNEL("OGG Vorbis Header: Setup (%d bytes)",vin.len);
				//readSetup(vin);
				break;
			default:
				throw StreamException("Unknown Vorbis packet header type");
				break;
		}
	}

}
コード例 #9
0
bool 
Reader::readToken( Token &token )
{
   skipSpaces();
   token.start_ = current_;
   Char c = getNextChar();
   bool ok = true;
   switch ( c )
   {
   case '{':
      token.type_ = tokenObjectBegin;
      break;
   case '}':
      token.type_ = tokenObjectEnd;
      break;
   case '[':
      token.type_ = tokenArrayBegin;
      break;
   case ']':
      token.type_ = tokenArrayEnd;
      break;
   case '"':
      token.type_ = tokenString;
      ok = readString();
      break;
   case '/':
      token.type_ = tokenComment;
      ok = readComment();
      break;
   case '0':
   case '1':
   case '2':
   case '3':
   case '4':
   case '5':
   case '6':
   case '7':
   case '8':
   case '9':
   case '-':
      token.type_ = tokenNumber;
      readNumber();
      break;
   case 'T':
   case 't':
      token.type_ = tokenTrue;
      ok = match( "rue", 3 );
      break;
   case 'F':
   case 'f':
      token.type_ = tokenFalse;
      ok = match( "alse", 4 );
      break;
   case 'N':
   case 'n':
      token.type_ = tokenNull;
      ok = match( "ull", 3 );
      break;
   case ',':
      token.type_ = tokenArraySeparator;
      break;
   case ':':
      token.type_ = tokenMemberSeparator;
      break;
   case 0:
      token.type_ = tokenEndOfStream;
      break;
   default:
      ok = false;
      break;
   }
   if ( !ok )
      token.type_ = tokenError;
   token.end_ = current_;
   return true;
}
コード例 #10
0
ファイル: mlex.cpp プロジェクト: LaMaisonOrchard/Sire
Ttoken *Tmlex::getToken()
{
    Ttoken        *token   = NULL;
    TstrBuf        text    = "";
    unsigned long  textIdx = 0;
    int            found = 0;

    if (NULL != (token = popToken()))
    {
        return(token);
    }
    else
    {
        token = new Ttoken;
    }

    token->setType(TOK_ILLEGAL);

    while (!found)
    {
        int ch = Dinput.get();
        if (EOF != ch) text[textIdx++] = ch;

        if (EOF == ch)
        {
            // End of file
            token->setType(TOK_END);
            token->setText("");
            token->setPosn(Dinput.posn());
            found = 1;
        }
        else if ('\n' == ch)
        {
            token->setType(TOK_EOL);
            token->setText("");
            found = 1;
        }
        else if (isspace(ch))
        {
            // Ignore white space
        }
        else if (SEP_ESC == ch)
        {
            // excape
            ch = Dinput.get();

            if ('\n' == ch)
            {
                // ignore the end-of-line
            }
            else if (SEP_ESC == ch)
            {
                // Litteral
                Dinput.putBack(ch);
                token->setPosn(Dinput.posn());
                found = readIdent(*token);
            }
            else
            {
                // Excaped charactor
                Dinput.putBack(ch);
            }
        }
        else if ('#' == ch)
        {
            // Check for comment
            token->setPosn(Dinput.posn());
            ch = Dinput.get();

            found = readComment(*token);
        }
        else if (SEP_TEXT == ch)
        {
            // Text
            token->setPosn(Dinput.posn());
            found = readText(*token);
        }
        else if (SEP_S_VAR == ch)
        {
            // Start an evaluated variable (define)
            readVar();
        }
        else if (SEP_CALL == ch)
        {
            // Call
            token->setPosn(Dinput.posn());
            found = readCall(*token);
        }
        else if (isSymb(ch))
        {
            // Symbol
            token->setPosn(Dinput.posn());
            Dinput.putBack(ch);
            found = readSymb(*token);
        }
        else if (isIdent(ch))
        {
            // Ident
            token->setPosn(Dinput.posn());
            Dinput.putBack(ch);
            found = readIdent(*token);
        }
        else
        {
            while ((EOF != ch) && !isspace(ch)) ch = Dinput.get();
            if (EOF != ch) Dinput.putBack(ch);
        }
    }

    return(token);
}
コード例 #11
0
ファイル: routecommentsdlg.cpp プロジェクト: allenck/mapper
void RouteCommentsDlg::OnBtnPrev()
{
    outputChanges();

    readComment(-1);
}
コード例 #12
0
ファイル: driverparse.c プロジェクト: Fat-Zer/tdelibs
int parseMaticFile(const char *driver, FILE *output)
{
	FILE	*drFile;
	char	name[32] = {0},
			make[64] = {0},
			model[64] = {0},
			tag[32] = {0},
			recomm[64] = {0},
			comment[4096] = {0},
			comment2[4096] = {0},
			pnpmake[64] = {0},
			pnpmodel[64] = {0};
	char	id[128];
	char	path[256], *c;

	drFile = fopen(driver, "r");
	if (drFile == NULL)
		return 0;
	strncpy(path, driver, 255);
        path[ 255 ] = '\0';
	if ((c = strstr(path, "/driver/")) != NULL)
		*c = 0;
	c = comment;
	while (!feof(drFile))
	{
		tag[0] = 0;
		nextTag(drFile, tag, 32);
		if (tag[0])
		{
			if (strcmp(tag, "name") == 0)
				readValue(drFile, name, 32);
			else if (strcmp(tag, "comments") == 0)
				readComment(drFile, c, 4096);
			else if (strcmp(tag, "printers") == 0)
				c = comment2;
			else if (strcmp(tag, "printer") == 0)
			{
				id[0] = 0;
				comment2[0] = 0;
			}
			else if (strcmp(tag, "id") == 0)
				readValue(drFile, id, 128);
			else if (strcmp(tag, "/printer") == 0 && id[0])
			{
				fprintf(output, "FILE=foomatic/%s/%s\n", id+8, name);
				make[0] = 0;
				model[0] = 0;
				recomm[0] = 0;
				pnpmake[0] = 0;
				pnpmodel[0] = 0;
				getMaticPrinterInfos(path, id, make, model, recomm, NULL, pnpmake, pnpmodel);
				fprintf(output, "MANUFACTURER=%s\n", make);
				fprintf(output, "MODELNAME=%s\n", model);
				fprintf(output, "MODEL=%s\n", model);
				fprintf(output, "DESCRIPTION=%s %s (Foomatic + %s)\n", make, model, name);
				if (recomm[0] && strcmp(name, recomm) == 0)
					fprintf(output, "RECOMMANDED=yes\n");
				if (comment[0] || comment2[0])
				{
					fprintf(output, "DRIVERCOMMENT=");
					if (comment2[0])
					{
						fprintf(output, "&lt;h3&gt;Printer note&lt;/h3&gt;%s", comment2);
					}
					if (comment[0])
						fprintf(output, "&lt;h3&gt;General driver note&lt;/h3&gt;%s", comment);
					fprintf(output, "\n");
				}
				if ( pnpmake[0] )
					fprintf( output, "PNPMANUFACTURER=%s\n", pnpmake );
				if ( pnpmodel[0] )
					fprintf( output, "PNPMODEL=%s\n", pnpmodel );
				fprintf(output, "\n");
			}
			else if (strcmp(tag, "/printers") == 0)
				break;
		}
	}
	fclose(drFile);
	return 1;
}
コード例 #13
0
ファイル: driverparse.c プロジェクト: Fat-Zer/tdelibs
int getMaticPrinterInfos(const char *base, const char *id, char *make, char *model, char *recomm, char *comment, char *pnpmake, char *pnpmodel)
{
	char	filePath[256];
	FILE	*xmlFile;
	char	tag[32] = {0};
	int	n = 0;
	int in_autodetect = 0;

	snprintf(filePath, 256, "%s/%s.xml", base, id);
	if ( access( filePath, F_OK ) != 0 )
	{
		/* file doesn't seem to exists, see if Foomatic ID translation file can help */
		const char *c;
		char ID1[ 256 ], ID2[ 256 ];
		int found = 0;

		/* Locate the actual ID part in the given "id" argument whose format is "printer/<ID>" */
		c = id;
		while ( *c && *c != '/' )
			c++;
		c++;
		/* Translation file is usually /usr/share/foomatic/db/oldprinterids */
		snprintf( filePath, 256, "%s/../oldprinterids", base );
		if ( ( xmlFile = fopen( filePath, "r" ) ) == NULL )
			return 0;
		/* Look for possible translated ID */
		while ( !feof( xmlFile ) )
		{
			if ( fscanf( xmlFile, "%256s %256s", ID1, ID2 ) == 2 )
			{
				if ( strcmp( c, ID1 ) == 0 )
				{
					snprintf( filePath, 256, "%s/printer/%s.xml", base, ID2 );
					found = 1;
					break;
				}
			}
			else
				break;
		}
		fclose( xmlFile );
		if ( !found )
			return 0;
	}
	xmlFile = fopen(filePath, "r");
	if (xmlFile == NULL)
		return 0;
	while (!feof(xmlFile) && n < 6)
	{
		tag[0] = 0;
		nextTag(xmlFile, tag, 32);
		if (tag[0])
		{
			char	*c;
			
			if ( strcmp( tag, "autodetect" ) == 0 )
			{
				in_autodetect = 1;
				continue;
			}
			else if ( strcmp( tag, "/autodetect" ) == 0 )
			{
				in_autodetect = 0;
				continue;
			}
			else if (!make[0] && strcmp(tag, "make") == 0)
				c = make;
			else if (strcmp(tag, "model") == 0)
			{
				if ( in_autodetect && !pnpmodel[ 0 ] )
					c = pnpmodel;
				else if ( !in_autodetect && !model[ 0 ] )
					c = model;
				else
					continue;
			}
			else if ( !pnpmake[0] && in_autodetect && strcmp( tag, "manufacturer" ) == 0 )
				c = pnpmake;
			else if (!recomm[0] && strcmp(tag, "driver") == 0)
				c = recomm;
			else if (comment && !comment[0] && strcmp(tag, "comments") == 0)
			{
				readComment(xmlFile, comment, 4096);
				n++;
				continue;
			}
			else
				continue;
			n++;
			readValue(xmlFile, c, 64);
		}
	}
	fclose(xmlFile);
	return 1;
}
コード例 #14
0
ファイル: CssTokenizer.cpp プロジェクト: smalyshev/clessc
Token::Type CssTokenizer::readNextToken(){
  if (in == NULL) {
    currentToken.type = Token::EOS;
    return Token::EOS;
  }

  currentToken.clear();
  switch (lastRead) {
  case '@':
    currentToken.type = Token::ATKEYWORD;
    currentToken.add(lastRead);
    readChar();
    if (!readIdent()) {
      currentToken.type = Token::OTHER;
    }
    break;
    
  case '#':
    currentToken.type = Token::HASH;
    currentToken.add(lastRead);
    readChar();
    if (!readName()) {
      throw new ParseException(&lastRead,
                               "name following '#'");
    }
    break;
    
  case '-':
    currentToken.add(lastRead);
    readChar();
    if (readNum(true)) {
      currentToken.type = Token::NUMBER;
      readNumSuffix();
    } else if (readIdent()) {
      currentToken.type = Token::IDENTIFIER;
    } else
      currentToken.type = Token::OTHER;
    break;
    
  case '~':
    currentToken.add(lastRead);
    readChar();
    if (lastRead == '=') {
      currentToken.add(lastRead);
      readChar();
      currentToken.type = Token::INCLUDES;
    } else
      currentToken.type = Token::OTHER;
    break;
    
  case '|':
    currentToken.add(lastRead);
    readChar();
    if (lastRead == '=') {
      currentToken.add(lastRead);
      readChar();
      currentToken.type = Token::DASHMATCH;
    } else
      currentToken.type = Token::OTHER;
    break;
    
  case '/':
    currentToken.add(lastRead);
    readChar();
    if (readComment()) 
      currentToken.type = Token::COMMENT;
    else
      currentToken.type = Token::OTHER;
    break;
    
  case ';':
    currentToken.type = Token::DELIMITER;
    currentToken.add(lastRead);
    readChar();
    break;
  case ':':
    currentToken.type = Token::COLON;
    currentToken.add(lastRead);
    readChar();
    break;
  case '{':
    currentToken.type = Token::BRACKET_OPEN;
    currentToken.add(lastRead);
    readChar();
    break;
  case '}':
    currentToken.type = Token::BRACKET_CLOSED;
    currentToken.add(lastRead);
    readChar();
    break;
  case '(':
    currentToken.type = Token::PAREN_OPEN;
    currentToken.add(lastRead);
    readChar();
    break;
  case ')':
    currentToken.type = Token::PAREN_CLOSED;
    currentToken.add(lastRead);
    readChar();
    break;
  case '[':
    currentToken.type = Token::BRACE_OPEN;
    currentToken.add(lastRead);
    readChar();
    break;
  case ']':
    currentToken.type = Token::BRACE_CLOSED;
    currentToken.add(lastRead);
    readChar();
    break;
    
  case '.':
    currentToken.add(lastRead);
    readChar();
    if (readNum(false)) {
      currentToken.type = Token::NUMBER;
      readNumSuffix();
    } 
    break;

  default:
    if (readString()) 
      currentToken.type = Token::STRING;
    else if (readNum(true)) {
      currentToken.type = Token::NUMBER;
      readNumSuffix();

    } else if (readIdent()) {
      currentToken.type = Token::IDENTIFIER;

      if (currentToken.str == "url" && readUrl())
        currentToken.type = Token::URL;
      else if (currentToken.str == "u" && lastReadEq('+')) {
        currentToken.add(lastRead);
        readChar();
        currentToken.type = Token::UNICODE_RANGE;
        readUnicodeRange();
      }
    } else if (readWhitespace()) {
      currentToken.type = Token::WHITESPACE;
      while (readWhitespace()) {};
    } else {
      currentToken.add(lastRead);
      readChar();
    }
    break;
  }

  return currentToken.type;
}
コード例 #15
0
Token Scanner::onDefaultState()
{
    QChar first = m_src.peek();
    m_src.move();

    // Ignore new lines
    bool hasNewLine = false;
    while (isLineFeed(first)) {
        hasNewLine = true;
        m_line++;
        m_lineStartOffset = m_src.position();
        first = m_src.peek();
        m_src.setAnchor();
        m_src.move();
    }
    if (hasNewLine)
        m_tokenSequence.clear();

    Token token;

    if (first.isDigit()) {
        token = readFloatNumber();
    } else if (first == '\'' || first == '\"' || first == '`') {
        token = readStringLiteral(first, State_String);
    } else if (m_methodPattern.match(m_tokenSequence).hasMatch()) {
        token = readMethodDefinition();
    } else if (first.isLetter() || first == '_' || first == '@'
               || first == '$' || (first == ':' && m_src.peek() != ':')) {
        token = readIdentifier();
    } else if (first.isDigit()) {
        token = readNumber();
    } else if (first == '#') {
        token = readComment();
    } else if (first == '/') {
        token = readRegexp();
    } else if (first.isSpace()) {
        token = readWhiteSpace();
    } else if (first == ',') {
        token = Token(Token::OperatorComma, m_src.anchor(), m_src.length());
    } else if (first == '.') {
        token = Token(Token::OperatorDot, m_src.anchor(), m_src.length());
    } else if (first == '=' && m_src.peek() != '=') {
        token = Token(Token::OperatorAssign, m_src.anchor(), m_src.length());
    } else if (first == ';') {
        token = Token(Token::OperatorSemiColon, m_src.anchor(), m_src.length());
    } else if (first == '%') {
        token = readPercentageNotation();
    } else if (first == '{') {
        token = Token(Token::OpenBraces, m_src.anchor(), m_src.length());
    } else if (first == '}') {
        token = Token(Token::CloseBraces, m_src.anchor(), m_src.length());
    } else if (first == '[') {
        token = Token(Token::OpenBrackets, m_src.anchor(), m_src.length());
    } else if (first == ']') {
        token = Token(Token::CloseBrackets, m_src.anchor(), m_src.length());
        // For historic reasons, ( and ) are the Operator token, this will
        // be changed soon.
    } else if (first == '(' || first == ')') {
        token = Token(Token::Operator, m_src.anchor(), m_src.length());
    } else {
        token = readOperator(first);
    }

    m_tokenSequence += QString::number(token.kind);
    m_tokenSequence += '_';

    return token;
}
コード例 #16
0
ファイル: gifdecoder.c プロジェクト: dennis-xlc/ORDER
/*
 * Class:     org_apache_harmony_awt_gl_image_GifDecoder
 * Method:    decode
 * Signature: ([BIJLorg/apache/harmony/awt/gl/image/GifDecoder$GifDataStream;Lorg/apache/harmony/awt/gl/image/GifDecoder$GifGraphicBlock;)I
 */
JNIEXPORT jint JNICALL Java_org_apache_harmony_awt_gl_image_GifDecoder_decode
(JNIEnv *env,
 jobject obj,
 jbyteArray jInput,
 jint bytesInBuffer,
 jlong hDecoder,
 jobject dataStream,
 jobject currBlock) {

    GIF_RETVAL retval = STATUS_OK;
    GifDecoder *decoder = getDecoder(env, obj, dataStream, (GifDecoder*) ((IDATA)hDecoder));
    int scanlinesDecoded;

    decoder->input = decoder->inputPtr =
                         (*env)->GetPrimitiveArrayCritical(env, jInput, 0);
    decoder->bytesInBuffer += bytesInBuffer;
    bytesInBuffer = decoder->bytesInBuffer;

    while(retval == STATUS_OK && decoder->bytesInBuffer > 0) {
        switch(decoder->state) {
        case STATE_INIT: {
            retval = readHeader(env, decoder);
            break;
        }

        case STATE_AT_GLOBAL_COLOR_TABLE: {
            retval = loadColorTable(env, decoder->jGlobalColorTable, decoder);
            break;
        }

        case STATE_AT_LOCAL_COLOR_TABLE: {
            retval = loadColorTable(env, NULL, decoder);
            break;
        }

        case STATE_BLOCK_BEGINNING: {
            unsigned char blockLabel = *(decoder->inputPtr);
            switch(blockLabel) {
            case EXTENSION_INTRODUCER:
                retval = readExtension(env, decoder, currBlock);
                break;
            case IMAGE_SEPARATOR:
                retval = readImageDescriptor(env, currBlock, decoder);
                break;
            case GIF_TRAILER:
                retval = STATUS_EOF;
                break;
            }
            break;
        }

        case STATE_STARTING_DECOMPRESSION: {
            retval = initDecompression(env, decoder, currBlock);
            break;
        }

        case STATE_DECOMPRESSING: {
            if(!decoder->interlace)
                retval = decompress(env, currBlock, decoder);
            else
                retval = decompressInterlaced(env, currBlock, decoder);
            break;
        }

        case STATE_READING_COMMENT: {
            retval = readComment(env, decoder);
            break;
        }

        case STATE_SKIPPING_BLOCKS: {
            retval = skipData(decoder);
            break;
        }

        default:
            // Should never execute this!
            break;
        }
    }

    // Copy unconsumed data to the start of the input buffer
    if(decoder->bytesInBuffer > 0) {
        memmove(decoder->input, decoder->inputPtr, decoder->bytesInBuffer);
    }

    (*env)->ReleasePrimitiveArrayCritical(env, jInput, decoder->input, 0);

    (*env)->SetIntField(
        env,
        obj,
        img_GIF_bytesConsumedID,
        bytesInBuffer - decoder->bytesInBuffer
    );

    if(decoder->stateVars.imageDataStarted) {
        if(!decoder->interlace) {
            scanlinesDecoded = decoder->pixelsDecoded / decoder->currentWidth -
                               decoder->oldPixelsDecoded / decoder->currentWidth;
            decoder->oldPixelsDecoded = decoder->pixelsDecoded;
        } else {
            if(retval == STATUS_LINE_COMPLETED && decoder->pass < MAX_PASS) {
                scanlinesDecoded = 1;
                if(decoder->currScanline >= 0)
                    (*env)->SetIntField(env, currBlock, img_GIF_gb_currYID, decoder->currScanline);

                decoder->scanlineOffset = 0;
            } else {
                scanlinesDecoded = 0;
            }
        }
    } else {
        scanlinesDecoded = 0;
    }

    if(retval == STATUS_FRAME_COMPLETED) {
        decoder->oldPixelsDecoded = decoder->pixelsDecoded = 0;
    }

    // Free the decoder if decoding is finished
    if(retval == STATUS_EOF) {
        free(decoder);
        decoder = NULL;
    }

    (*env)->SetLongField(env, obj, img_GIF_hNativeDecoderID, (jlong) ((IDATA)decoder));

    return scanlinesDecoded;
}