/* * 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