Download | Plain Text | Line Numbers


/**
 * @module cscriptparser
 * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348)
 * @brief  class for parsing simple scriptfiles
 * @date   17.04.2009
 */
 
#include <fstream>
#include <boost/tokenizer.hpp>
#include <boost/algorithm/string.hpp>
#include "cscriptparser.h"
#include "cwindowsbitmap.h"
#include "cpixmap.h"
 
using namespace std;
using namespace boost;
 
CScriptparser::CScriptparser(const std::string& scriptfile)
  : m_scriptfile(scriptfile), m_handler(NULL)
{
  /* add our handlers */
  m_handlers.insert(new CWindowsBitmap);
  m_handlers.insert(new CPixmap);
}
 
/*----------------------------------------------------------------------------*/
 
CScriptparser::~CScriptparser()
{
  /* delete image handlers */
  set<CFile *>::iterator it;
  for (it = m_handlers.begin(); it != m_handlers.end(); it++)
    delete *it;
  m_handler = NULL;
}
 
/*----------------------------------------------------------------------------*/
 
void CScriptparser::parse()
{
  /* open and read file */
  ifstream file(m_scriptfile.c_str(), ios::in);
  if (!file)
    throw ParserError("Unable to open scriptfile '" + m_scriptfile + "'.");
 
  while (!file.eof() && file.good())
  {
    /* read file pre line */
    getline(file, m_curline);
    if (m_curline.empty())
      continue;
 
    trim(m_curline);
 
    /* ignore comments */
    if (m_curline.find_first_of('#') == 0)
      continue;
 
    /* line has no function call */
    size_t pos1 = m_curline.find_first_of('(');
    size_t pos2 = m_curline.find_last_of(')');
    if (pos1 == string::npos || pos2 == string::npos)
      throw ParserError("Invalid syntax. Not a function", m_curline);
 
    /* first parse function name and tokenize all parameters */
    string func = m_curline.substr(0, pos1);
    string params = m_curline.substr(pos1 + 1, pos2 - pos1 - 1);
    list<string> funcparams;
    tokenizer< char_separator<char> > tokens(params, char_separator<char>(","));
    /* BOOST_FOREACH isn't available on OOP-servers... */
    for (tokenizer< char_separator<char> >::iterator it = tokens.begin();
        it != tokens.end();
        it++)
    {
      string tok(*it);
      trim(tok);
      if (tok.find_first_of(' ') != string::npos)
      {
        if (tok.find_first_of('"') == string::npos)
          throw ParserError("Invalid syntax", m_curline);
      }
      trim_if(tok, is_any_of("\""));
      funcparams.push_back(tok);
    }
 
    /* then call the corresponding function */
    callFunc(func, funcparams);
  }
 
  file.close();
}
 
/*----------------------------------------------------------------------------*/
 
void CScriptparser::callFunc(const std::string& func, const std::list<std::string>& funcparams)
{
  if (func.empty())
    throw ParserError("Function name is empty.", m_curline);
 
  if (func == "read")
    read(funcparams);
  else if (func == "write")
    write(funcparams);
  else
  {
    if (m_handler == NULL)
      throw ParserError("No image is being processed.", m_curline);
 
    /* call function from handler */
    try
    {
      m_handler->callFunc(func, funcparams);
    }
    catch(CFile::FileError& ex)
    {
      throw ParserError(ex.what(), m_curline);
    }
  }
}
 
/*----------------------------------------------------------------------------*/
 
void CScriptparser::read(std::list<std::string> funcparams)
{
  /* check prerequirements */
  if (funcparams.size() != 2)
    throw ParserError("Invalid number of function parameters (must be 2).", m_curline);
  if (m_handler != NULL)
    throw ParserError("An image is already being processed. Unable to open another.", m_curline);
 
  string type = funcparams.front();
  to_upper(type);
  funcparams.pop_front();
  string filename = funcparams.front();
 
  /* fetch image handler supporting requested filetype */
  m_handler = NULL;
  set<CFile *>::iterator it;
  for (it = m_handlers.begin(); it != m_handlers.end(); it++)
  {
    if ((*it)->supportsType(type))
    {
      m_handler = *it;
      break;
    }
  }
  if (m_handler == NULL)
    throw ParserError("Unknown filetype.", m_curline);
 
  /* open file in binary mode */
  ifstream file(filename.c_str(), ios::in | ios::binary);
  if (!file)
    throw ParserError("Unable to read file.", m_curline);
 
  /* let handlers read() parse the file */
  try
  {
    m_handler->read(file);
    if (!file.good())
      throw ParserError("Error while reading image file.", m_curline);
    file.close();
  }
  catch(CFile::FileError& ex)
  {
    file.close();
    throw ParserError(ex.what(), m_curline);
  }
}
 
/*----------------------------------------------------------------------------*/
 
void CScriptparser::write(std::list<std::string> funcparams)
{
  /* check prerequirements */
  if (funcparams.size() != 2)
    throw ParserError("Invalid number of function parameters (must be 2).", m_curline);
  if (m_handler == NULL)
    throw ParserError("No image is being processed.", m_curline);
 
  string type = funcparams.front();
  to_upper(type);
  funcparams.pop_front();
  string filename = funcparams.front();
 
  /* do we have an image handler supporting the filetype? */
  if (!m_handler->supportsType(type))
    throw ParserError("Unknown filetype.", m_curline);
 
  /* open file in binary mode */
  ofstream file(filename.c_str(), ios::out | ios::binary);
  if (!file)
    throw ParserError("Unable to open file.", m_curline);
 
  /* let handlers write() parse the file */
  try
  {
    m_handler->write(file);
    if (!file.good())
      throw ParserError("Error while writing image file.", m_curline);
    file.close();
    m_handler = NULL;
  }
  catch(CFile::FileError& ex)
  {
    file.close();
    m_handler = NULL;
    throw ParserError(ex.what(), m_curline);
  }
}
 
/* vim: set et sw=2 ts=2: */