OpenSceneGraph/src/osgDB/FieldReader.cpp
Robert Osfield 21686c27af From Mathias Froehlich, "I did some performance test runs with the development gcc-4.4 version.
To make it compiel with future gcc's we sppear to need the attached missing
includes ..."
2008-09-18 10:52:35 +00:00

341 lines
8.3 KiB
C++

/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
*
* This library is open source and may be redistributed and/or modified under
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
* (at your option) any later version. The full license is in LICENSE file
* included with this distribution, and on the openscenegraph.org website.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* OpenSceneGraph Public License for more details.
*/
#include <osgDB/Field>
#include <osgDB/FieldReader>
#include <stdio.h>
using namespace osgDB;
FieldReader::FieldReader()
{
_init();
}
FieldReader::FieldReader(const FieldReader& ic)
{
_copy(ic);
}
FieldReader::~FieldReader()
{
_free();
}
FieldReader& FieldReader::operator = (const FieldReader& ic)
{
if (this==&ic) return *this;
_free();
_copy(ic);
return *this;
}
void FieldReader::_free()
{
// free all data
_init();
}
void FieldReader::_init()
{
_fin = NULL;
_eof = true;
_noNestedBrackets = 0;
int i;
for(i=0;i<256;++i) _delimiterEatLookUp[i]=false;
_delimiterEatLookUp[int(' ')] = true;
_delimiterEatLookUp[int('\t')] = true;
_delimiterEatLookUp[int('\n')] = true;
_delimiterEatLookUp[int('\r')] = true;
for(i=0;i<256;++i) _delimiterKeepLookUp[i]=false;
_delimiterKeepLookUp[int('{')] = true;
_delimiterKeepLookUp[int('}')] = true;
_delimiterKeepLookUp[int('"')] = true;
_delimiterKeepLookUp[int('\'')] = true;
}
void FieldReader::_copy(const FieldReader& ic)
{
_fin = ic._fin;
_eof = ic._eof;
_noNestedBrackets = ic._noNestedBrackets;
int i;
for(i=0;i<256;++i) _delimiterEatLookUp[i]=ic._delimiterEatLookUp[i];
for(i=0;i<256;++i) _delimiterKeepLookUp[i]=ic._delimiterKeepLookUp[i];
}
void FieldReader::attach(std::istream* input)
{
_fin = input;
if (_fin)
{
_eof = _fin->eof()!=0;
}
else
{
_eof = true;
}
}
void FieldReader::detach()
{
_fin = NULL;
_eof = true;
}
bool FieldReader::eof() const
{
return _eof;
}
bool FieldReader::findStartOfNextField()
{
int ch = 0;
while (true)
{
ch = _fin->peek();
if (ch==EOF)
{
_eof = true;
return false;
}
else if (_delimiterEatLookUp[ch])
{
_fin->ignore(1);
}
else
{
return true;
}
}
}
bool FieldReader::readField(Field& fieldPtr)
{
return _readField(&fieldPtr);
}
void FieldReader::ignoreField()
{
_readField(NULL);
}
bool FieldReader::_readField(Field* fieldPtr)
{
if (fieldPtr) fieldPtr->reset();
if (!eof() && findStartOfNextField())
{
int ch = _fin->peek();
if (ch==EOF)
{
_eof = true;
if (fieldPtr) fieldPtr->setNoNestedBrackets(getNoNestedBrackets());
return fieldPtr && fieldPtr->getNoCharacters()!=0;
}
else if (ch=='"')
{
if (fieldPtr)
{
fieldPtr->setWithinQuotes(true);
fieldPtr->setNoNestedBrackets(getNoNestedBrackets());
}
_fin->ignore(1);
char c;
bool escape = false; // use the escape character sequence \" to allow " to included in strings.
while (true)
{
ch = _fin->peek();
if (ch==EOF)
{
_eof = true;
return fieldPtr && fieldPtr->getNoCharacters()!=0;
}
c = ch;
if (ch=='\\')
{
if (escape)
{
escape = false;
_fin->get(c);
if (fieldPtr) fieldPtr->addChar(c);
}
else
{
escape = true;
_fin->ignore(1);
}
}
else if (ch=='"')
{
if (escape)
{
escape = false;
_fin->get(c);
if (fieldPtr) fieldPtr->addChar(c);
}
else
{
_fin->ignore(1);
//return fieldPtr && fieldPtr->getNoCharacters()!=0;
return fieldPtr!=NULL;
}
}
else
{
if (escape)
{
escape = false;
if (fieldPtr) fieldPtr->addChar('\\');
}
_fin->get(c);
if (fieldPtr) fieldPtr->addChar(c);
}
}
}
else if (ch=='\'')
{
if (fieldPtr)
{
fieldPtr->setWithinQuotes(true);
fieldPtr->setNoNestedBrackets(getNoNestedBrackets());
}
_fin->ignore(1);
char c;
bool escape = false; // use the escape character sequence \' to allow ' to included in strings.
while (true)
{
ch = _fin->peek();
if (ch==EOF)
{
_eof = true;
return fieldPtr && fieldPtr->getNoCharacters()!=0;
}
c = ch;
if (ch=='\\' && !escape)
{
if (escape)
{
escape = false;
_fin->get(c);
if (fieldPtr) fieldPtr->addChar(c);
}
else
{
escape = true;
_fin->ignore(1);
}
}
else if (ch=='\'')
{
if (escape)
{
escape = false;
_fin->get(c);
if (fieldPtr) fieldPtr->addChar(c);
}
else
{
_fin->ignore(1);
//return fieldPtr && fieldPtr->getNoCharacters()!=0;
return fieldPtr!=NULL;
}
}
else
{
if (escape)
{
escape = false;
if (fieldPtr) fieldPtr->addChar('\\');
}
_fin->get(c);
if (fieldPtr) fieldPtr->addChar(c);
}
}
}
else if (_delimiterKeepLookUp[ch])
{
char c;
_fin->get(c);
if (fieldPtr) fieldPtr->addChar(c);
if (c=='{') ++_noNestedBrackets;
else if (c=='}') --_noNestedBrackets;
if (fieldPtr) fieldPtr->setNoNestedBrackets(getNoNestedBrackets());
return fieldPtr && fieldPtr->getNoCharacters()!=0;
}
else
{
if (fieldPtr) fieldPtr->setNoNestedBrackets(getNoNestedBrackets());
char c;
while (true)
{
ch = _fin->peek();
if (ch==EOF)
{
_eof = true;
return fieldPtr && fieldPtr->getNoCharacters()!=0;
}
c = ch;
if (_delimiterEatLookUp[int(c)])
{
_fin->ignore(1);
return fieldPtr && fieldPtr->getNoCharacters()!=0;
}
if (_delimiterKeepLookUp[int(c)])
{
return fieldPtr && fieldPtr->getNoCharacters()!=0;
}
else
{
_fin->get(c);
if (fieldPtr) fieldPtr->addChar(c);
}
}
}
}
else
{
return false;
}
}
int FieldReader::getNoNestedBrackets() const
{
return _noNestedBrackets;
}