/*
 * Project: MoleCuilder
 * Description: creates and alters molecular systems
 * Copyright (C)  2010-2012 University of Bonn. All rights reserved.
 * 
 *
 *   This file is part of MoleCuilder.
 *
 *    MoleCuilder is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation, either version 2 of the License, or
 *    (at your option) any later version.
 *
 *    MoleCuilder 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
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with MoleCuilder.  If not, see .
 */
/*
 * PcpParser_helper.cpp
 *
 *  Created on: Oct 27, 2011
 *      Author: heber
 */
// include config.h
#ifdef HAVE_CONFIG_H
#include 
#endif
#include "CodePatterns/MemDebug.hpp"
#include 
#include 
#include 
#include "CodePatterns/Log.hpp"
#include "Element/element.hpp"
#include "Element/periodentafel.hpp"
#include "Helpers/helpers.hpp"
#include "molecule.hpp"
#include "Parser/ConfigFileBuffer.hpp"
/** Reads parameter from a parsed file.
 * The file is either parsed for a certain keyword or if null is given for
 * the value in row yth and column xth. If the keyword was necessity#critical,
 * then an error is thrown and the programme aborted.
 * \warning value is modified (both in contents and position)!
 * \param verbose 1 - print found value to stderr, 0 - don't
 * \param *file file to be parsed
 * \param name Name of value in file (at least 3 chars!)
 * \param sequential 1 - do not reset file pointer to begin of file, 0 - set to beginning
 *        (if file is sequentially parsed this can be way faster! However, beware of multiple values per line, as whole line is read -
 *         best approach: 0 0 0 1 (not resetted only on last value of line) - and of yth, which is now
 *         counted from this unresetted position!)
 * \param xth Which among a number of parameters it is (in grid case it's row number as grid is read as a whole!)
 * \param yth In grid case specifying column number, otherwise the yth \a name matching line
 * \param type Type of the Parameter to be read
 * \param value address of the value to be read (must have been allocated)
 * \param repetition determines, if the keyword appears multiply in the config file, which repetition shall be parsed, i.e. 1 if not multiply
 * \param critical necessity of this keyword being specified (optional, critical)
 * \return 1 - found, 0 - not found
 * \note Routine is taken from the pcp project and hack-a-slack adapted to C++
 */
int ParseForParameter(const int verbose, ifstream * const file, const char * const name, const int sequential, const int xth, const int yth, const int type, void * value, const int repetition, const int critical) {
  int i = 0;
  int j = 0;  // loop variables
  int length = 0;
  int maxlength = -1;
  long file_position = file->tellg(); // mark current position
  char *dummy1 = NULL;
  char *dummy = NULL;
  char free_dummy[MAXSTRINGSIZE];    // pointers in the line that is read in per step
  dummy1 = free_dummy;
  //fprintf(stderr,"Parsing for %s\n",name);
  if (repetition == 0)
    //Error(SomeError, "ParseForParameter(): argument repetition must not be 0!");
    return 0;
  int line = 0; // marks line where parameter was found
  int found = (type >= grid) ? 0 : (-yth + 1);  // marks if yth parameter name was found
  while((found != repetition)) {
    dummy1 = dummy = free_dummy;
    do {
      file->getline(dummy1, 256); // Read the whole line
      if (file->eof()) {
        if ((critical) && (found == 0)) {
          //Error(InitReading, name);
          fprintf(stderr,"Error:InitReading, critical %s not found\n", name);
          exit(255);
        } else {
          //if (!sequential)
          file->clear();
          file->seekg(file_position, ios::beg);  // rewind to start position
          return 0;
        }
      }
      line++;
    } while (dummy != NULL && dummy1 != NULL && ((dummy1[0] == '#') || (dummy1[0] == '\0'))); // skip commentary and empty lines
    // C++ getline removes newline at end, thus re-add
    if ((dummy1 != NULL) && (strchr(dummy1,'\n') == NULL)) {
      i = strlen(dummy1);
      dummy1[i] = '\n';
      dummy1[i+1] = '\0';
    }
    //fprintf(stderr,"line %i ends at %i, newline at %i\n", line, strlen(dummy1), strchr(dummy1,'\n')-free_dummy);
    if (dummy1 == NULL) {
      if (verbose) fprintf(stderr,"Error reading line %i\n",line);
    } else {
      //fprintf(stderr,"Now parsing the line %i: %s\n", line, dummy1);
    }
    // Seek for possible end of keyword on line if given ...
    if (name != NULL) {
      dummy = strchr(dummy1,'\t');  // set dummy on first tab or space which ever's nearer
      if (dummy == NULL) {
        dummy = strchr(dummy1, ' ');  // if not found seek for space
        while ((dummy != NULL) && ((*dummy == '\t') || (*dummy == ' ')))    // skip some more tabs and spaces if necessary
          dummy++;
      }
      if (dummy == NULL) {
        dummy = strchr(dummy1, '\n'); // set on line end then (whole line = keyword)
        //fprintf(stderr,"Error: Cannot find tabs or spaces on line %i in search for %s\n", line, name);
        //Error(FileOpenParams, NULL);
      } else {
        //fprintf(stderr,"found tab at %i\n",(char *)dummy-(char *)dummy1);
      }
    } else dummy = dummy1;
    // ... and check if it is the keyword!
    //fprintf(stderr,"name %p, dummy %i/%c, dummy1 %i/%c, strlen(name) %i\n", &name, dummy, *dummy, dummy1, *dummy1, strlen(name));
    if ((name == NULL) || (((dummy-dummy1 >= 3) && (strncmp(dummy1, name, strlen(name)) == 0)) && ((unsigned int)(dummy-dummy1) == strlen(name)))) {
      found++; // found the parameter!
      //fprintf(stderr,"found %s at line %i between %i and %i\n", name, line, dummy1, dummy);
      if (found == repetition) {
        for (i=0;i= grid) {
            // grid structure means that grid starts on the next line, not right after keyword
            dummy1 = dummy = free_dummy;
            do {
              file->getline(dummy1, 256); // Read the whole line, skip commentary and empty ones
              if (file->eof()) {
                if ((critical) && (found == 0)) {
                  //Error(InitReading, name);
                  fprintf(stderr,"Error:InitReading, critical %s not found\n", name);
                  exit(255);
                } else {
                  //if (!sequential)
                  file->clear();
                  file->seekg(file_position, ios::beg);  // rewind to start position
                  return 0;
                }
              }
              line++;
            } while ((dummy1[0] == '#') || (dummy1[0] == '\n'));
            if (dummy1 == NULL){
              if (verbose) fprintf(stderr,"Error reading line %i\n", line);
            } else {
              //fprintf(stderr,"Reading next line %i: %s\n", line, dummy1);
            }
          } else { // simple int, strings or doubles start in the same line
            while ((*dummy == '\t') || (*dummy == ' '))   // skip interjacent tabs and spaces
              dummy++;
          }
          // C++ getline removes newline at end, thus re-add
          if ((dummy1 != NULL) && (strchr(dummy1,'\n') == NULL)) {
            j = strlen(dummy1);
            dummy1[j] = '\n';
            dummy1[j+1] = '\0';
          }
          int start = (type >= grid) ? 0 : yth-1 ;
          for (j=start;j j) && (type == upper_trigrid)) || ((j > i) && (type == lower_trigrid))) {
              *((double *)value) = 0.0;
              fprintf(stderr,"%f\t",*((double *)value));
              value = (void *)((long)value + sizeof(double));
              //value += sizeof(double);
            } else {
              // otherwise we must skip all interjacent tabs and spaces and find next value
              dummy1 = dummy;
              dummy = strchr(dummy1, '\t'); // seek for tab or space
              if (dummy == NULL)
                dummy = strchr(dummy1, ' ');  // if not found seek for space
              if (dummy == NULL) { // if still zero returned ...
                dummy = strchr(dummy1, '\n');  // ... at line end then
                if ((j < yth-1) && (type < 4)) {  // check if xth value or not yet
                  if (critical) {
                    if (verbose) fprintf(stderr,"Error: EoL at %i and still missing %i value(s) for parameter %s\n", line, yth-j, name);
                    //return 0;
                    exit(255);
                    //Error(FileOpenParams, NULL);
                  } else {
                    //if (!sequential)
                    file->clear();
                    file->seekg(file_position, ios::beg);  // rewind to start position
                    return 0;
                  }
                }
              } else {
                //fprintf(stderr,"found tab at %i\n",(char *)dummy-(char *)free_dummy);
              }
              if (*dummy1 == '#') {
                // found comment, skipping rest of line
                //if (verbose) fprintf(stderr,"Error: '#' at %i and still missing %i value(s) for parameter %s\n", line, yth-j, name);
                if (!sequential) { // here we need it!
                  file->seekg(file_position, ios::beg);  // rewind to start position
                }
                return 0;
              }
              //fprintf(stderr,"value from %i to %i\n",(char *)dummy1-(char *)free_dummy,(char *)dummy-(char *)free_dummy);
              switch(type) {
                case (row_int):
                  *((int *)value) = atoi(dummy1);
                  if ((verbose) && (i==0) && (j==0)) fprintf(stderr,"%s = ", name);
                  if (verbose) fprintf(stderr,"%i\t",*((int *)value));
                    value = (void *)((long)value + sizeof(int));
                    //value += sizeof(int);
                  break;
                case(row_double):
                case(grid):
                case(lower_trigrid):
                case(upper_trigrid):
                  *((double *)value) = atof(dummy1);
                  if ((verbose) && (i==0) && (j==0)) fprintf(stderr,"%s = ", name);
                  if (verbose) fprintf(stderr,"%lg\t",*((double *)value));
                  value = (void *)((long)value + sizeof(double));
                  //value += sizeof(double);
                  break;
                case(double_type):
                  *((double *)value) = atof(dummy1);
                  if ((verbose) && (i == xth-1)) fprintf(stderr,"%s = %lg\n", name, *((double *) value));
                  //value += sizeof(double);
                  break;
                case(int_type):
                  *((int *)value) = atoi(dummy1);
                  if ((verbose) && (i == xth-1)) fprintf(stderr,"%s = %i\n", name, *((int *) value));
                  //value += sizeof(int);
                  break;
                default:
                case(string_type):
                  if (value != NULL) {
                    //if (maxlength == -1) maxlength = strlen((char *)value); // get maximum size of string array
                    maxlength = MAXSTRINGSIZE;
                    length = maxlength > (dummy-dummy1) ? (dummy-dummy1) : maxlength; // cap at maximum
                    strncpy((char *)value, dummy1, length);  // copy as much
                    ((char *)value)[length] = '\0';  // and set end marker
                    if ((verbose) && (i == xth-1)) fprintf(stderr,"%s is '%s' (%i chars)\n",name,((char *) value), length);
                    //value += sizeof(char);
                  } else {
                  }
                break;
              }
            }
            while (*dummy == '\t')
              dummy++;
          }
        }
      }
    }
  }
  if ((type >= row_int) && (verbose))
    fprintf(stderr,"\n");
  if (!sequential) {
    file->clear();
    file->seekg(file_position, ios::beg);  // rewind to start position
  }
  //fprintf(stderr, "End of Parsing\n\n");
  return (found); // true if found, false if not
}
/** Reads parameter from a parsed file.
 * The file is either parsed for a certain keyword or if null is given for
 * the value in row yth and column xth. If the keyword was necessity#critical,
 * then an error is thrown and the programme aborted.
 * \warning value is modified (both in contents and position)!
 * \param verbose 1 - print found value to stderr, 0 - don't
 * \param *FileBuffer pointer to buffer structure
 * \param name Name of value in file (at least 3 chars!)
 * \param sequential 1 - do not reset file pointer to begin of file, 0 - set to beginning
 *        (if file is sequentially parsed this can be way faster! However, beware of multiple values per line, as whole line is read -
 *         best approach: 0 0 0 1 (not resetted only on last value of line) - and of yth, which is now
 *         counted from this unresetted position!)
 * \param xth Which among a number of parameters it is (in grid case it's row number as grid is read as a whole!)
 * \param yth In grid case specifying column number, otherwise the yth \a name matching line
 * \param type Type of the Parameter to be read
 * \param value address of the value to be read (must have been allocated)
 * \param repetition determines, if the keyword appears multiply in the config file, which repetition shall be parsed, i.e. 1 if not multiply
 * \param critical necessity of this keyword being specified (optional, critical)
 * \return 1 - found, 0 - not found
 * \note Routine is taken from the pcp project and hack-a-slack adapted to C++
 */
int ParseForParameter(const int verbose, struct ConfigFileBuffer * const FileBuffer, const char * const name, const int sequential, const int xth, const int yth, const int type, void * value, const int repetition, const int critical) {
  int i = 0;
  int j = 0;  // loop variables
  int length = 0;
  int maxlength = -1;
  int OldCurrentLine = FileBuffer->CurrentLine;
  char *dummy1 = NULL;
  char *dummy = NULL;    // pointers in the line that is read in per step
  char *free_dummy = NULL;
  if (verbose) fprintf(stderr,"Begin of Parsing for %s\n",name);
  if (repetition == 0)
    //Error(SomeError, "ParseForParameter(): argument repetition must not be 0!");
    return 0;
  int found = (type >= grid) ? 0 : (-yth + 1);  // marks if yth parameter name was found
  while((found != repetition)) {
    dummy1 = dummy = NULL;
    do {
      if (FileBuffer->CurrentLine < FileBuffer->NoLines)
        free_dummy = dummy1 = FileBuffer->buffer[ FileBuffer->LineMapping[FileBuffer->CurrentLine++] ];
      if (FileBuffer->CurrentLine >= FileBuffer->NoLines) {
        if ((critical) && (found == 0)) {
          //Error(InitReading, name);
          fprintf(stderr,"Error:InitReading, critical %s not found\n", name);
          return 0;
        } else {
          //fprintf(stdout,"Rewinding to OldCurrentLine due to search till end of file.\n");
          FileBuffer->CurrentLine = OldCurrentLine; // rewind to start position
          return 0;
        }
      }
      if (dummy1 == NULL) {
        if (verbose) fprintf(stderr,"Error reading line %i\n",FileBuffer->CurrentLine);
      } else {
        if (verbose) fprintf(stderr,"Now parsing the line %i: %s\n", FileBuffer->CurrentLine, dummy1);
      }
      //FileBuffer->CurrentLine++;
    } while (dummy1 != NULL && ((dummy1[0] == '#') || (dummy1[0] == '\0'))); // skip commentary and empty lines
    // Seek for possible end of keyword on line if given ...
    if (name != NULL) {
      dummy = strchr(dummy1,'\t');  // set dummy on first tab or space which ever's nearer
      if (dummy == NULL) {
        dummy = strchr(dummy1, ' ');  // if not found seek for space
        while ((dummy != NULL) && ((*dummy == '\t') || (*dummy == ' ')))    // skip some more tabs and spaces if necessary
          dummy++;
      }
      if (dummy == NULL) {
        dummy = strchr(dummy1, '\n'); // set on line end then (whole line = keyword)
        //fprintf(stderr,"Error: Cannot find tabs or spaces on line %i in search for %s\n", line, name);
        //Error(FileOpenParams, NULL);
      } else {
        if (verbose) fprintf(stderr,"found tab at line %i at position %li\n",FileBuffer->CurrentLine, (char *)dummy-(char *)dummy1);
      }
    } else dummy = dummy1;
    // ... and check if it is the keyword!
    //fprintf(stderr,"name %p, dummy %i/%c, dummy1 %i/%c, strlen(name) %i\n", &name, dummy, *dummy, dummy1, *dummy1, strlen(name));
    if ((name == NULL) || (((dummy-dummy1 >= 3) && (strncmp(dummy1, name, strlen(name)) == 0)) && ((unsigned int)(dummy-dummy1) == strlen(name)))) {
      found++; // found the parameter!
      if (verbose) fprintf(stderr,"found %s at line %i between %li and %li\n", name, FileBuffer->CurrentLine, (unsigned long)dummy1, (unsigned long)dummy);
      if (found == repetition) {
        for (i=0;i= grid) {
            // grid structure means that grid starts on the next line, not right after keyword
            dummy1 = dummy = NULL;
            do {
              dummy1 = FileBuffer->buffer[ FileBuffer->LineMapping[ FileBuffer->CurrentLine++] ];
              if (FileBuffer->CurrentLine >= FileBuffer->NoLines) {
                if ((critical) && (found == 0)) {
                  //Error(InitReading, name);
                  fprintf(stderr,"Error:InitReading, critical %s not found\n", name);
                  exit(255);
                } else {
                  //fprintf(stdout,"Rewinding to OldCurrentLine due to search till end of line.\n");
                  FileBuffer->CurrentLine = OldCurrentLine; // rewind to start position
                  return 0;
                }
              }
              if (dummy1 == NULL) {
                if (verbose) fprintf(stderr,"Error reading line %i\n", FileBuffer->CurrentLine);
              } else {
                if (verbose) fprintf(stderr,"Reading next line %i: %s\n", FileBuffer->CurrentLine, dummy1);
              }
              //FileBuffer->CurrentLine++;
            } while ((dummy1 != NULL) && ((dummy1[0] == '#') || (dummy1[0] == '\n')));
            dummy = dummy1;
          } else { // simple int, strings or doubles start in the same line
            while ((*dummy == '\t') || (*dummy == ' '))  // skip interjacent tabs and spaces
              dummy++;
          }
          for (j=((type >= grid) ? 0 : yth-1);j j) && (type == upper_trigrid)) || ((j > i) && (type == lower_trigrid))) {
              *((double *)value) = 0.0;
              fprintf(stderr,"%f\t",*((double *)value));
              value = (void *)((long)value + sizeof(double));
              //value += sizeof(double);
            } else {
              // otherwise we must skip all interjacent tabs and spaces and find next value
              dummy1 = dummy;
              dummy = strchr(dummy1, '\t'); // seek for tab or space
              if (dummy == NULL)
                dummy = strchr(dummy1, ' ');  // if not found seek for space
              if (dummy == NULL) { // if still zero returned ...
                dummy = strchr(dummy1, '\n'); // ... at line end then
                if ((j < yth-1) && (type < 4)) {  // check if xth value or not yet
                  if (critical) {
                    if (verbose) fprintf(stderr,"Error: EoL at %i and still missing %i value(s) for parameter %s\n", FileBuffer->CurrentLine, yth-j, name);
                    //return 0;
                    exit(255);
                    //Error(FileOpenParams, NULL);
                  } else {
                    if (!sequential) { // here we need it!
                      //fprintf(stdout,"Rewinding to OldCurrentLine due to end of line and sequential %d.\n", sequential);
                      FileBuffer->CurrentLine = OldCurrentLine; // rewind to start position
                    }
                    return 0;
                  }
                }
              } else {
                if (verbose) fprintf(stderr,"found tab at line %i at position %li\n",FileBuffer->CurrentLine, (char *)dummy-(char *)free_dummy);
              }
              if (*dummy1 == '#') {
                // found comment, skipping rest of line
                //if (verbose) fprintf(stderr,"Error: '#' at %i and still missing %i value(s) for parameter %s\n", line, yth-j, name);
                if (!sequential) { // here we need it!
                  //fprintf(stdout,"Rewinding to OldCurrentLine due to comment and sequential %d.\n", sequential);
                  FileBuffer->CurrentLine = OldCurrentLine; // rewind to start position
                }
                return 0;
              }
              if (verbose) fprintf(stderr,"value from %li to %li\n",(char *)dummy1-(char *)free_dummy,(char *)dummy-(char *)free_dummy);
              switch(type) {
                case (row_int):
                  *((int *)value) = atoi(dummy1);
                  if ((verbose) && (i==0) && (j==0)) fprintf(stderr,"%s = ", name);
                  if (verbose) fprintf(stderr,"%i\t",*((int *)value));
                    value = (void *)((long)value + sizeof(int));
                    //value += sizeof(int);
                  break;
                case(row_double):
                case(grid):
                case(lower_trigrid):
                case(upper_trigrid):
                  *((double *)value) = atof(dummy1);
                  if ((verbose) && (i==0) && (j==0)) fprintf(stderr,"%s = ", name);
                  if (verbose) fprintf(stderr,"%lg\t",*((double *)value));
                  value = (void *)((long)value + sizeof(double));
                  //value += sizeof(double);
                  break;
                case(double_type):
                  *((double *)value) = atof(dummy1);
                  if ((verbose) && (i == xth-1)) fprintf(stderr,"%s = %lg\n", name, *((double *) value));
                  //value += sizeof(double);
                  break;
                case(int_type):
                  *((int *)value) = atoi(dummy1);
                  if ((verbose) && (i == xth-1)) fprintf(stderr,"%s = %i\n", name, *((int *) value));
                  //value += sizeof(int);
                  break;
                default:
                case(string_type):
                  if (value != NULL) {
                    //if (maxlength == -1) maxlength = strlen((char *)value); // get maximum size of string array
                    maxlength = MAXSTRINGSIZE;
                    length = maxlength > (dummy-dummy1) ? (dummy-dummy1) : maxlength; // cap at maximum
                    strncpy((char *)value, dummy1, length); // copy as much
                    ((char *)value)[length] = '\0'; // and set end marker
                    if ((verbose) && (i == xth-1)) fprintf(stderr,"%s is '%s' (%i chars)\n",name,((char *) value), length);
                    //value += sizeof(char);
                  } else {
                  }
                break;
              }
            }
            while (*dummy == '\t')
              dummy++;
          }
        }
      }
    }
  }
  if ((type >= row_int) && (verbose)) fprintf(stderr,"\n");
  if (!sequential) {
    //fprintf(stdout,"Rewinding to OldCurrentLine due to sequential %d.\n", sequential);
    FileBuffer->CurrentLine = OldCurrentLine; // rewind to start position
  }
  if (verbose) fprintf(stderr, "End of Parsing for %s\n\n",name);
  return (found); // true if found, false if not
}
/** Loads a molecule from a ConfigFileBuffer.
 * \param *mol molecule to load
 * \param *FileBuffer ConfigFileBuffer to use
 * \param *periode periodentafel for finding elements
 * \param FastParsing whether to parse trajectories or not
 */
void LoadMolecule(molecule * const &mol, struct ConfigFileBuffer * const &FileBuffer, const periodentafel * const periode, const bool FastParsing)
{
  int MaxTypes = 0;
  const element *elementhash[MAX_ELEMENTS];
  char name[MAXSTRINGSIZE];
  int Z = -1;
  int No[MAX_ELEMENTS];
  int verbose = DoLog(4);
  double value[3];
  if (mol == NULL) {
    ELOG(0, "Molecule is not allocated in LoadMolecule(), exit.");
    performCriticalExit();
  }
  ParseForParameter(verbose,FileBuffer,"MaxTypes", 0, 1, 1, int_type, &(MaxTypes), 1, critical);
  if (MaxTypes == 0) {
    ELOG(1, "There are no atoms according to MaxTypes in this config file." << endl);
    //performCriticalExit();
  } else {
    // prescan number of ions per type
    LOG(0, "STATUS: Prescanning ions per type: " << endl);
    int NoAtoms = 0;
    for (int i=0; i < MaxTypes; i++) {
      sprintf(name,"Ion_Type%i",i+1);
      ParseForParameter(verbose,FileBuffer, (const char*)name, 0, 1, 1, int_type, &No[i], 1, critical);
      ParseForParameter(verbose,FileBuffer, name, 0, 2, 1, int_type, &Z, 1, critical);
      elementhash[i] = periode->FindElement(Z);
      LOG(1, i << ". Z = " << elementhash[i]->getAtomicNumber() << " with " << No[i] << " ions.");
      NoAtoms += No[i];
    }
    int repetition = -1; // which repeated keyword shall be read
    // sort the lines via the LineMapping
    sprintf(name,"Ion_Type%i",MaxTypes);
    if (!ParseForParameter(verbose,FileBuffer, (const char*)name, 1, 1, 1, int_type, &value[0], 1, critical)) {
      ELOG(0, "There are no atoms in the config file!" << endl);
      performCriticalExit();
      return;
    }
    FileBuffer->CurrentLine++;  // skip to next line
    FileBuffer->MapIonTypesInBuffer(NoAtoms);
    for (int i=FileBuffer->CurrentLine; iNoLines;++i) {
      LOG(4, FileBuffer->buffer[ FileBuffer->LineMapping[i] ]);
    }
    map AtomList[MaxTypes];
    map LinearList;
    atom *neues = NULL;
    Vector tempVector;
    int _fixedion;
    typedef boost::tokenizer >
        tokenizer;
    boost::char_separator sep("\t ");
    ConvertTo toDouble;
    ConvertTo toInt;
    for (int i=0; i < MaxTypes; i++) {
      for(int j=0;jbuffer[ FileBuffer->LineMapping[FileBuffer->CurrentLine] ]);
          const std::string line_without_comment = line.substr(0,line.find("#"));
          tokenizer tokens(line_without_comment, sep);
          if (tokens.begin() != tokens.end()) {
            tokenizer::iterator tok_iter = tokens.begin();
            const std::string token = *tok_iter++;
            if (token == keyword) {
              LOG(3, "INFO: Found keyword " << keyword << " in line " << FileBuffer->CurrentLine << std::endl);
              if (step == 0) {
                neues = World::getInstance().createAtom();
                AtomList[i][j] = neues;
                LOG(4, "Filling LinearList [ (FileBuffer->LineMapping[" << FileBuffer->CurrentLine << "]) = " << FileBuffer->LineMapping[FileBuffer->CurrentLine] << " with " << neues << endl);
                LinearList[ FileBuffer->LineMapping[FileBuffer->CurrentLine] ] = neues;
                neues->setType(elementhash[i]); // find element type
              } else
                neues = AtomList[i][j];
              // count tokens
              size_t tokens_size = 0;
              for (tokenizer::iterator tokiter = tokens.begin(); tokiter != tokens.end(); ++tokiter)
                ++tokens_size;
              LOG(3, "INFO: Line contains " << tokens_size << " tokens." << std::endl);
              // and parse
              tempVector.Zero();
              if (tokens_size >= 5) { // only AtomicPosition and FixedIon
                for (int i=0;isetPositionAtStep(step, tempVector);
                _fixedion = toInt(*tok_iter++);
                neues->setFixedIon(_fixedion == 1);
                LOG(3, "INFO: Parsing AtomicPosition " << tempVector << " and FixedIon " << _fixedion << "." << std::endl);
              }
              tempVector.Zero();
              if (tokens_size >= 8) { // AtomicVelocity
                for (int i=0;isetAtomicVelocityAtStep(step, tempVector);
              tempVector.Zero();
              if (tokens_size >= 11) {  // AtomicForce
                LOG(3, "INFO: Parsing AtomicForce" << std::endl);
                for (int i=0;isetAtomicForceAtStep(step, tempVector);
              std::stringstream output;
              output << "Parsed position of step " << (step+1) << ": ";
              output << neues->getPositionAtStep(step);          // next step
              output << "\t";
              output << (neues->getFixedIon() ? "true" : "false");
              output << "\t";
              output << neues->getAtomicVelocityAtStep(step);          // next step
              output << "\t";
              output << neues->getAtomicForceAtStep(step);          // next step
              LOG(2, output.str());
              step++;
            } else {
              if ((repetition > step) || (repetition == -1))
                repetition = step;
              break;
            }
          }
          FileBuffer->CurrentLine++;
        }
      }
    }
    if (repetition <= 1)  // if onyl one step, desactivate use of trajectories
      mol->MDSteps = 0;
    else {
      LOG(0, "Found " << repetition << " trajectory step(s).");
      mol->MDSteps = repetition;
    }
    // put atoms into the molecule in their original order
    for(map::iterator runner = LinearList.begin(); runner != LinearList.end(); ++runner) {
      mol->AddAtom(runner->second);
    }
  }
}