181 lines
5.2 KiB

/*
* read_lab_file.cpp
*
* Created on: 10.09.2012
* Author: Thomas Heinemann
*/
#include "parser.h"
#include "read_lab_file.h"
#include "src/exceptions/wrong_file_format.h"
#include "src/exceptions/file_IO_exception.h"
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <pantheios/pantheios.hpp>
#include <pantheios/inserters/integer.hpp>
#ifdef WIN32
# define STRTOK_FUNC strtok_s
#else
# define STRTOK_FUNC strtok_r
#endif
// Disable C4996 - This function or variable may be unsafe.
#pragma warning(disable:4996)
namespace mrmc {
namespace parser {
/*!
* Reads a .lab file and puts the result in a labeling structure.
*
* Labelings created with this method have to be freed with the delete operator.
* @param node_count the number of states.
* @param filename input .lab file's name.
* @return The pointer to the created labeling object.
*/
mrmc::models::AtomicPropositionsLabeling * read_lab_file(int node_count, const char * filename)
{
/* Note that this function uses strtok_r on char-array s.
* This function will modify this string.
* However, as only the result of its tokenization is used, this is not a problem.
*
* Thread-safety is ensured by using strtok_r instead of strtok.
*/
FILE *P;
//TODO (Thomas Heinemann): handle files with lines that are longer than BUFFER_SIZE
//TODO (Thomas Heinemann): Throw errors if fgets return NULL in the declaration. (fixed by Philipp. Or?)
char s[BUFFER_SIZE]; //String buffer
char *saveptr = NULL; //Buffer for strtok_r
char sep[] = " \n\t"; //Separators for the tokens
P = fopen(filename, "r");
if (P == NULL) {
pantheios::log_ERROR("File could not be opened.");
throw mrmc::exceptions::file_IO_exception();
return NULL;
}
if (!fgets(s, BUFFER_SIZE, P) || strcmp(s, "#DECLARATION\n")) {
fclose(P);
pantheios::log_ERROR("Wrong declaration section (\"#DECLARATION\" missing).");
throw mrmc::exceptions::wrong_file_format();
return NULL;
}
uint_fast32_t buffer_size_count = 1;
uint_fast32_t buffer_start = 0;
char* decl_buffer = new char[buffer_size_count*BUFFER_SIZE];
bool need_next_iteration = true;
do {
decl_buffer[buffer_size_count*BUFFER_SIZE - 1] = '\xff';
if (fgets(decl_buffer + buffer_start, buffer_size_count*BUFFER_SIZE - buffer_start, P)) {
if ((decl_buffer[buffer_size_count*BUFFER_SIZE - 1] != '\xff') &&
(decl_buffer[buffer_size_count*BUFFER_SIZE - 2] != '\n')) {
//fgets changed the last bit -> read string has maximum length
//AND line is longer than size of decl_buffer
char* temp_buffer = decl_buffer;
decl_buffer = NULL;
buffer_size_count++;
decl_buffer = new char[buffer_size_count*BUFFER_SIZE];
buffer_start = (buffer_size_count - 1) * BUFFER_SIZE;
memcpy(decl_buffer, temp_buffer, buffer_start - 1);
delete[] temp_buffer;
} else {
need_next_iteration = false;
}
} else {
pantheios::log_ERROR("EOF in the declaration section");
throw mrmc::exceptions::wrong_file_format();
delete[] decl_buffer;
return NULL;
}
} while (need_next_iteration);
uint_fast32_t proposition_count = 0;
char * proposition;
int pos = 0;
if (decl_buffer[pos] != ' ' && decl_buffer[pos] != '\t' && decl_buffer[pos] != '\0') {
proposition_count++;
}
while (decl_buffer[pos] != '\0') {
if ((decl_buffer[pos] == ' ' || decl_buffer[pos] == '\t') &&
(decl_buffer[pos + 1] != ' ' && decl_buffer[pos + 1] != '\t' && decl_buffer[pos + 1] != '\0')) {
proposition_count++;
}
pos++;
}
mrmc::models::AtomicPropositionsLabeling* result = new mrmc::models::AtomicPropositionsLabeling(node_count, proposition_count);
//Here, all propositions are to be declared...
for (proposition = STRTOK_FUNC(decl_buffer, sep, &saveptr);
proposition != NULL;
proposition = STRTOK_FUNC(NULL, sep, &saveptr)) {
result -> addAtomicProposition(proposition);
}
// Free decl_buffer
delete[] decl_buffer;
saveptr = NULL; //resetting save pointer for strtok_r
if (!fgets(s, BUFFER_SIZE, P) || strcmp(s, "#END\n")) {
fclose(P);
delete result;
pantheios::log_ERROR("Wrong declaration section (\"#END\" missing).");
throw mrmc::exceptions::wrong_file_format();
return NULL;
}
while (fgets(s, BUFFER_SIZE, P)) {
char * token = NULL;
uint_fast32_t node = 0;
/* First token has to be a number identifying the node,
* hence it is treated differently from the other tokens.
*/
token = STRTOK_FUNC(s, sep, &saveptr);
if (sscanf(token, "%u", &node) == 0) {
fclose(P);
delete result;
pantheios::log_ERROR("Line assigning propositions does not start with a node number.");
throw mrmc::exceptions::wrong_file_format();
return NULL;
}
do {
token = STRTOK_FUNC(NULL, sep, &saveptr);
if (token == NULL) {
break;
}
result->addAtomicPropositionToState(token, node);
} while (token != NULL);
}
fclose(P);
return result;
}
} //namespace parser
} //namespace mrmc