- fbx: parser working now. Drop shared_ptr's in favour of raw pointers to reduce memory overhead (a pity - I want unique_ptr and move semantics in C++03).

This commit is contained in:
Alexander Gessler
2012-06-25 23:03:06 +02:00
parent ff995307ac
commit c9d9fcdfd1
8 changed files with 293 additions and 53 deletions

View File

@@ -47,38 +47,107 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "FBXTokenizer.h"
#include "FBXParser.h"
#include "FBXUtil.h"
using namespace Assimp;
using namespace Assimp::FBX;
namespace Assimp {
template<> const std::string LogFunctions<Assimp::FBX::Parser>::log_prefix = "FBX-Parse: ";
namespace {
// ------------------------------------------------------------------------------------------------
// signal parsing error, this is always unrecoverable. Throws DeadlyImportError.
void ParseError(const std::string& message, TokenPtr token)
{
throw DeadlyImportError(token ? Util::AddTokenText("FBX-Parse",message,token) : ("FBX-Parse " + message));
}
}
// ------------------------------------------------------------------------------------------------
Element::Element(Parser& parser)
{
TokenPtr n = NULL;
do {
n = parser.AdvanceToNextToken();
if(!n) {
ParseError("unexpected end of file, expected closing bracket",parser.LastToken());
}
if (n->Type() == TokenType_DATA) {
tokens.push_back(n);
n = parser.AdvanceToNextToken();
if(!n) {
ParseError("unexpected end of file, expected bracket, comma or key",parser.LastToken());
}
const TokenType ty = n->Type();
if (ty != TokenType_OPEN_BRACKET && ty != TokenType_CLOSE_BRACKET && ty != TokenType_COMMA && ty != TokenType_KEY) {
ParseError("unexpected token; expected bracket, comma or key",n);
}
}
if (n->Type() == TokenType_OPEN_BRACKET) {
compound.reset(new Scope(parser));
// compound scopes must appear at the end of an element, so TOK_CLOSE_BRACKET should be next
n = parser.CurrentToken();
ai_assert(n);
if (n->Type() != TokenType_CLOSE_BRACKET) {
ParseError("expected closing bracket",n);
}
}
}
while(n->Type() != TokenType_KEY);
}
// ------------------------------------------------------------------------------------------------
Element::~Element()
{
std::for_each(tokens.begin(),tokens.end(),Util::delete_fun<Token>());
}
// ------------------------------------------------------------------------------------------------
Scope::Scope(Parser& parser)
Scope::Scope(Parser& parser,bool topLevel)
{
TokenPtr t = parser.GetNextToken();
if (t->Type() != TokenType_OPEN_BRACKET) {
parser.ThrowException("Expected open bracket");
if(!topLevel) {
TokenPtr t = parser.CurrentToken();
if (t->Type() != TokenType_OPEN_BRACKET) {
ParseError("expected open bracket",t);
}
}
// XXX parse members
TokenPtr n = parser.AdvanceToNextToken();
if(n == NULL) {
ParseError("unexpected end of file",NULL);
}
do {
if (n->Type() != TokenType_KEY) {
ParseError("unexpected token, expected TOK_KEY",n);
}
elements.insert(ElementMap::value_type(n->StringContents(),new_Element(parser)));
// Element() should stop at the next Key (or Close) token
n = parser.CurrentToken();
if(n == NULL) {
if (topLevel) {
return;
}
ParseError("unexpected end of file",parser.LastToken());
}
}
while(n->Type() != TokenType_CLOSE_BRACKET);
}
// ------------------------------------------------------------------------------------------------
Scope::~Scope()
{
BOOST_FOREACH(ElementMap::value_type& v, elements) {
delete v.second;
}
}
@@ -86,8 +155,10 @@ Scope::~Scope()
Parser::Parser (const TokenList& tokens)
: tokens(tokens)
, cursor(tokens.begin())
, current()
, last()
{
root = boost::scoped_ptr<Scope>(new Scope(*this));
root.reset(new Scope(*this,true));
}
@@ -98,24 +169,30 @@ Parser::~Parser()
// ------------------------------------------------------------------------------------------------
TokenPtr Parser::GetNextToken()
TokenPtr Parser::AdvanceToNextToken()
{
last = current;
if (cursor == tokens.end()) {
return TokenPtr(NULL);
current = NULL;
}
return *cursor++;
else {
current = *cursor++;
}
return current;
}
// ------------------------------------------------------------------------------------------------
TokenPtr Parser::PeekNextToken()
TokenPtr Parser::CurrentToken() const
{
if (cursor == tokens.end()) {
return TokenPtr(NULL);
}
return current;
}
return *cursor;
// ------------------------------------------------------------------------------------------------
TokenPtr Parser::LastToken() const
{
return last;
}