/*********************************************************************** * * ELMER, A Computational Fluid Dynamics Program. * * Copyright 1st April 1995 - , Center for Scientific Computing, * Finland. * * All rights reserved. No part of this program may be used, * reproduced or transmitted in any form or by any means * without the written permission of CSC. * * Address: Center for Scientific Computing * Tietotie 6, P.O. BOX 405 * 02101 Espoo, Finland * Tel. +358 0 457 2001 * Telefax: +358 0 457 2302 * EMail: Jari.Jarvinen@csc.fi ************************************************************************/ /*********************************************************************** Program: ELMER model file (emf) reader Module: frontlib.h Language: C++ Date: 01.10.98 Version: 1.00 Author(s): Martti Verho Revisions: Abstract: Header file for the emf-parser ************************************************************************/ #ifndef _FRONTLIB_ #define _FRONTLIB_ // OK/ERROR codes for Reader #define emf_OK 0 #define emf_ERROR 1 // ************************************************************************* // ************************************************************************* // // START: LibFront namespace definitions // // ************************************************************************* // ************************************************************************* // namespace LibFront { #if defined(WIN32) #define NSP_EXTERN extern #else #define NSP_EXTERN extern #endif // Data value types // ================ enum dataValueType { EMF_INTEGER, EMF_REAL, EMF_LOGICAL, EMF_STRING, EMF_FILE }; // Data values related flags set in the library by the Reader extern bool isFileData; extern bool isIntegerData; extern bool isLogicalData; extern bool isRealData; extern bool isStringData; extern bool isVoidData; extern int* integerData; extern int* logicalData; extern double* realData; extern char* stringData; extern void* voidData; extern int dimension1; extern int dimension2; extern int* dataLengths; // Variables related flags set in the library by the Reader extern bool isRealVariable; extern bool isStringVariable; extern bool isVoidVariable; extern double* realVariable; extern char* stringVariable; extern void* voidVariable; extern int* variableValuesLengths; extern char stringSeparator; // Default '\"'; extern char matcSeparator; // Default = '$'; void setStringSeparator(char sep); void setMatcSeparator(char sep); // Read file into given buffer // NOTE: Buffer is allocated in the function! // Skip empty line, comment lines and eol comments // NOTE: Comments can start with ! or # // Return: nof chars read (= actual buffer size) // extern int readFile(char* filename, char*& buffer, bool skip_comments = true); // Matc utilities // ============== extern void initMatcFrmt(); extern void formatMatcError(char* err_msg); // NOTE: Whitespace must have been trimmed from 'str' before calling // these functions extern bool isMatcDefinition(const char* str); extern bool hasMatcVariables(const char* str); extern bool getMatcName(const char* str, char* name_buffer, int max_len, bool& is_var, bool& is_func); extern bool isMatcError(const char* str); extern char* evalMatcString(const char* str); // Read a Matc-expression from the source, starting from source_pos // Return source-position after reading the expression // NOTE: Source is NOT moved to this position actually, but the client // can use this return value if its wants to advandec the source! // extern int readMatcExpression(char* source, int source_pos, int source_end, char* result, int max_result_len, bool skip_commnets = true); // Data reading utilities for getting data from global // LibFront arries set by the LibFrontReader // =================================================== // // NOTE: These function use global data arries as the source!!! // // Get numeric value data array extern void setNumericData(bool*& target); extern void setNumericData(int*& target); extern void setNumericData(long*& target); extern void setNumericData(float*& target); extern void setNumericData(double*& target); extern void setStringData(char*& buffer); // Get numeric value from data values array by index extern void setNumericData(bool& target, int value_index); extern void setNumericData(int& target, int value_index); extern void setNumericData(long& target, int value_index); extern void setNumericData(float& target, int value_index); extern void setNumericData(double& target, int value_index); extern void setStringData(char* buffer, int value_index); extern void setStringData(int nof_strings, char**& data_strings); // Get numeric value from variable values array by index extern void setNumericVariable(bool& target, int value_index); extern void setNumericVariable(int& target, int value_index); extern void setNumericVariable(long& target, int value_index); extern void setNumericVariable(float& target, int value_index); extern void setNumericVariable(double& target, int value_index); extern void setStringVariable(char* buffer, int value_index); // Misc utilities // ============== // A shorthand for isName(..) bool in(const char* field_name, const char* test_name); // Utilities for indented output extern char* indent(short indent_size, short indent_level); extern ostream& indent(ostream& out, short indent_size, short indent_level); // String utilities extern bool isNumber(const char* str); extern bool ncEqual(char* str1, char* str2); extern bool ncEqualPartial(char* str1, char* str2); extern char* trim(char* buffer, bool trim_nl = false); extern char* trimLeft(char* buffer, bool trim_nl = false); extern char* trimRight(char* buffer, bool trim_nl = false); extern char* toLower(char* buffer); extern char* toLower(const char* source, char* target); extern char* toUpper(char* buffer); extern char* toUpper(const char* source, char* target); // Find start/end of the first/last non-ws character // NOTE: Initial start/end position mus be given in the reference // arguments start_pos/end_pos // NOTE: String itself is NOT modified!!! // extern void trimLeft(const char* str, int max_pos, int& start_pos, bool trim_nl = false); extern void trimRight(const char* str, int min_pos, int& end_pos, bool trim_nl = false); // Data output functions // ===================== // Simple utility for debugging extern ostream& output_data(ostream& out, char* data_type, void* data); // Output a Matc definition // ------------------------ // NOTE: add_dsign <--> add dollar sign // extern ostream& output_matcDef(ostream& out, short indent_size, short indent_level, const char* field_name, const char* field_type, const char* def, bool add_dsign = false); // Output field name properly indented // ----------------------------------- extern ostream& output_string(ostream& out, short indent_size, short indent_level, const char* str, bool output_eol = true); // Output named scalar data // ------------------------ extern ostream& output_scalar(ostream& out, short indent_size, short indent_level, const char* field_name, const char* field_type, const bool data); extern ostream& output_scalar(ostream& out, short indent_size, short indent_level, const char* field_name, const char* field_type, const short data); extern ostream& output_scalar(ostream& out, short indent_size, short indent_level, const char* field_name, const char* field_type, const int data); extern ostream& output_scalar(ostream& out, short indent_size, short indent_level, const char* field_name, const char* field_type, const long data); extern ostream& output_scalar(ostream& out, short indent_size, short indent_level, const char* field_name, const char* field_type, const float data); extern ostream& output_scalar(ostream& out, short indent_size, short indent_level, const char* field_name, const char* field_type, const double data); extern ostream& output_scalar(ostream& out, short indent_size, short indent_level, const char* field_name, const char* field_type, const char* data, bool quoted = true); // Output named vector data // ------------------------ extern ostream& output_vector(ostream& out, short indent_size, short indent_level, const char* field_name, const char* field_type, int dim, const bool* data, bool output_size = true); extern ostream& output_vector(ostream& out, short indent_size, short indent_level, const char* field_name, const char* field_type, int dim, const short* data, bool output_size = true); extern ostream& output_vector(ostream& out, short indent_size, short indent_level, const char* field_name, const char* field_type, int dim, const int* data, bool output_size = true); extern ostream& output_vector(ostream& out, short indent_size, short indent_level, const char* field_name, const char* field_type, int dim, const long* data, bool output_size = true); extern ostream& output_vector(ostream& out, short indent_size, short indent_level, const char* field_name, const char* field_type, int dim, const float* data, bool output_size = true); extern ostream& output_vector(ostream& out, short indent_size, short indent_level, const char* field_name, const char* field_type, int dim, const double* data, bool output_size = true); extern ostream& output_vector(ostream& out, short indent_size, short indent_level, const char* field_name, const char* field_type, int dim, const char** data, bool output_size = true, bool quoted = true); // Output named table data (dim1*dim2) // ----------------------------------- extern ostream& output_table(ostream& out, short indent_size, short indent_level, const char* field_name, const char* field_type, int dim1, int dim2, const bool** data); extern ostream& output_table(ostream& out, short indent_size, short indent_level, const char* field_name, const char* field_type, int dim1, int dim2, const short** data); extern ostream& output_table(ostream& out, short indent_size, short indent_level, const char* field_name, const char* field_type, int dim1, int dim2, const int** data); extern ostream& output_table(ostream& out, short indent_size, short indent_level, const char* field_name, const char* field_type, int dim1, int dim2, const long** data); extern ostream& output_table(ostream& out, short indent_size, short indent_level, const char* field_name, const char* field_type, int dim1, int dim2, const float** data); extern ostream& output_table(ostream& out, short indent_size, short indent_level, const char* field_name, const char* field_type, int dim1, int dim2, const double** data); extern ostream& output_table(ostream& out, short indent_size, short indent_level, const char* field_name, const char* field_type, int dim1, int dim2, const char*** data, bool quoted = true); } // ========================================================================= // END: LibFront namespace definitions // ========================================================================= // ************************************************************************* // ************************************************************************* // // START: Definition for LibFrontReader external interface // // ************************************************************************* // ************************************************************************* extern "C" { // Max length of one single condition when delivered as 'raw' string #define emf_MAX_STRING_LEN 8191 // Max length of object/field names etc #define emf_MAX_NAME_LEN 64 // Max number of groups (name groups separated by ';' like [A B; C] afet object/field names #define emf_MAX_NOF_GROUPS 2 // Max number of names in one group #define emf_MAX_NOF_GROUP_NAMES 24 // Max number of variables in data parameters (like time, temperature etc) #define emf_MAX_NOF_VARIABLES 12 // This struct stores the data for one parameter field // --------------------------------------------------- // struct emf_ObjectData_X { // OBJECT LEVEL RELATED STUFF // -------------------------- // Flag for a new object int is_object_start; // Flag for the end of the object int is_object_end; // Object or section name like: Header, Initial Condition char object_name[emf_MAX_NAME_LEN]; // Actual length of the object-name character array int object_name_length; // Possible id for the object, -1 if no id is used int object_id; // FIELD LEVEL RELATED STUFF // ------------------------- // NOTE: Field name is optional, all the data can also be at object level! // Name for the parameter field: Equation, Velocity1 etc. char field_name[emf_MAX_NAME_LEN]; // Actual length of the field_name character array int field_name_length; // GROUP LEVEL RELATED STUFF // Nof group names (like [H; N O] after object/field name // NOTE: character ';' is groups "grouper", currently we accept two different groups! // NOTE: if you have groups, you have to give same number of data values for each group! // int nof_group_names[emf_MAX_NOF_GROUPS]; // Group names [ H2O N; C] etc. char group_names[emf_MAX_NOF_GROUPS][emf_MAX_NOF_GROUP_NAMES][emf_MAX_NAME_LEN]; // Actual lengths of the group names int group_name_lengths[emf_MAX_NOF_GROUPS][emf_MAX_NOF_GROUP_NAMES]; // DATA VALUES RELATED STUFF // ------------------------- // Name for the data type: Integer, Real, Logical, String, File etc. char data_type[emf_MAX_NAME_LEN]; // Actual length of the data_type character array int data_type_length; // If definition is for a dll-procedure int is_procedure; // Nof entries (rows of variables and data) int nof_entries; // Dimension1 for a data entry (default 1) int dimension1; // Dimension2 for a data entry (default 1) int dimension2; // Lengths for data values. // SIZE: nof_entries * dimension1 * dimension2 // NOTE: Normally each length is 1 (for a nuemric scalar item) // But if data is of string type we normally have variable // length strings and then the length of // each string value can be read from this array // // Actually you have to read string data using these // lengths because there are no sperators between the strings // in the "data" array !!! int* data_lengths; // Length of the data array = Sum(data_lengths), for convenience! int data_length; // Data array of homogenous data type // NOTE: cast to proprer type before using! void* data; // Field data as a string char* dataAsString; // If field data contains matc-variables int dataHasMatcVars; // VARIABLES RELATED STUFF // ----------------------- // Name for the varaible value type. NOTE: Real or String only! char variable_type[emf_MAX_NAME_LEN]; // Length of the variable_type character array int variable_type_length; // Nof argument variables int nof_variables; // Argument variable names (Temperature, Times etc) char variable_names[emf_MAX_NOF_VARIABLES][emf_MAX_NAME_LEN]; // Lengths of the variable-name arrays int variable_name_lengths[emf_MAX_NOF_VARIABLES]; // Lengths for variable values // SIZE = nof_entries * nofVariables // // NOTE: Normally these values are all 1, because a typical // variable value is a (real) scalar. But we can also have // names as variables and then the lengths of these character arries // must be taken from this array (ref. data_lengths!) int* variable_values_lengths; // Total length of the variable values array = Sum(variable_lengths), for convenience! int variable_values_length; // Variable values array of homogenous data type (double or char only!) // NOTE: cast to proprer type before using! void* variable_values; }; // end struct emf_ObjectData_X // Declaration for library interface #ifdef WIN32 #ifdef BUILD_DLL #define EMF_DECL __declspec(dllimport) #else #define EMF_DECL extern #endif #else #define EMF_DECL extern #endif // Pointer to the object data transfer structure. // ---------------------------------------------- // // Library function(s) use this pointer when transferin the data! // Connect this pointer to your the variable which is allocated // in your own module: // declaration: emf_ObjectData_X my_object_data; // allocation: emf_ObjectData = &my_object_data; EMF_DECL struct emf_ObjectData_X* emf_ObjectData; // Buffer for unknown data lines // NOTE: This is dynamically allocated in the library, size: 1 + emf_MAX_STRING_LEN EMF_DECL char* emf_UnknownData; // Interface FUNCTION decalrations // =============================== // This function starts parsing model-file // --------------------------------------- // // Call it first in your module!!! // // Arguments: // model_data_file: full path for the model file // user_data : this data is delivered back in the emf_readDataCB // msg_buffer_size: maximum writeable size for the message buffer // msg_buffer : buffer for getting messages in the emf_messageReadCB // // Remember to allocate msg_buffer! // If it is set NULL, call-back function is not used! // Return values (int): // 0 --> read ok // 1 --> parsing was NOT ok, ERROR!!! EMF_DECL int emf_readData(char* model_data_file, void** user_data, int msg_buffer_size, char* msg_buffer, int expand_matc); // This call-back function does the actual parsing // ----------------------------------------------- // // It returns data using data-structures defined above. // // Connect this function to the call-back function // defined in your module. // // LIKE: int my_read_function (void) {...}; // emf_readDataCB = my_read_function; // // Return values (int): // -1 --> stop reading // anything else --> continue EMF_DECL int (*emf_readDataCB) (void** user_data); // This call-back function to send error messages etc. from the parser. // ------------------------------------------------------------------- // // Connect this function to the call-back function // defined in your module. // // LIKE: void my_msg_function (char* message_buffer) {...}; // emf_readMessageCB = my_msg_function; // // Return values (int) // 1 <--> ok // 0 <--> no success EMF_DECL int (*emf_readMessageCB) (char* msg_buffer); } // end extern "C" // ========================================================================= // END: Definition for LibFrontReader external interface // ========================================================================= // ************************************************************************* // ************************************************************************* // // START: File reader class (= parser for egf/emf type files) // // ************************************************************************* // ************************************************************************* // struct LibFrontReaderFlags { LibFrontReaderFlags(); LibFrontReaderFlags(LibFrontReaderFlags& flags); void copy(LibFrontReaderFlags& flags); void init(); bool nonSizedDataAtEnd; bool canSkipSpace; bool canSkipNewline; bool endsField; bool endsObject; bool equalSignPeeked; bool hasEvaluatedBuffer; bool newlinePeeked; bool hangingFieldNameNumber; bool matcPeeked; bool readingEndMarkedData; bool readingFieldData; bool readingFileName; bool readingGroupNames; bool readingNonSizedData; bool readingProcedureName; bool startsNewField; bool startsNewObject; }; // Max length for LibFrontReader work buffers // (matcBuffer, dataAsStringBuffer etc.) #define MAX_BUFFER_LEN 640000 // LibFrontReader class // ============ class LibFrontReader { public: LibFrontReader(char* filename, void** user_data, int msg_buffer_size, char* msg_buffer, bool is_matc_file = false); ~LibFrontReader(); bool isOk() { return readerOk; } bool start(); protected: bool allocate_data_buffer(int buffer_size, int item_count); bool allocate_variable_buffer(int buffer_size, int item_count); bool appendReadBuffer(char c, int& bufferPos, bool init); bool bufferAtEnd(); void bufferEatWs(); void bufferEatWs(bool& eq_eaten, bool& nl_eaten); bool case_compare(char* str1, char* str2); bool checkReadBuffer(); void constructStringFromTokens(char* buffer, int nof_string_token); bool data_at_end(); void delete_data_buffer(); void delete_variable_buffer(); bool extractSeparator(char sep); bool evalMatcBuffer(char* source); void evalAll(); int evalAndInsertNextMatc(); void evalAndSkipNextMatc(); bool getNextNumber(int& number); bool getNextNumber(double& number); template bool getNextNumber_impl(T& number); int getNextToken(char* buffer); int getNextToken(char* buffer, bool& eq_found, bool& nl_found, bool& matc_found); int getToSeparator(char* buffer, char sep); bool handleEol(); void init_transfer_info(); int insertReadBuffer(char* data); bool is_file_keyword(char* str); bool is_end_keyword(char* str); bool is_keyword(char* str); bool is_number(char* str); bool is_procedure_keyword(char* str); bool is_separated_string(); bool is_size_keyword(char* str); bool is_type_keyword(char* str); bool is_variable_keyword(char* str); bool next_is_end_keyword(); bool next_is_group_names(); bool next_is_keyword(); bool next_is_matc(); bool next_is_number(); bool next_is_separated_string(); bool next_is_size_keyword(); bool next_is_text(char* text); bool next_is_type_keyword(); bool next_is_variable_keyword(); bool next_non_number_is_data_keyword(); bool next_non_number_is_keyword(); bool object_at_end(); bool peek_next_string(char* buffer); bool peek_token(char* buffer); bool peek_field_name_tokens(int& nof_tokens); bool peek_object_name_tokens(int& nof_tokens); void pop_flags(); void push_flags(bool copy_current = true); bool read_entry_data(struct emf_ObjectData_X* pf, int data_count, int data_size, int& total_read_count); bool read_entry_data_values(int old_data_buffer_size, int max_data_buffer_size, int data_count, int* data_sizes, int& total_read_count); bool read_entry_variables(struct emf_ObjectData_X* pf, int var_count, int var_size); bool read_entry_variable_values(int old_var_buffer_size, int max_var_buffer_size, int var_count, int* var_sizes, int& total_read_count); bool read_field(struct emf_ObjectData_X* pf); bool read_field_data_sized(struct emf_ObjectData_X* pf, int var_count, int var_size, int data_count, int data_size, int& total_read_count); bool read_field_data_non_sized(struct emf_ObjectData_X* pf, bool type_given = false); bool read_field_name(struct emf_ObjectData_X* od, char* name_buffer, int buffer_len); bool read_group_names(struct emf_ObjectData_X* pf); bool read_logical_data(int start_pos, int max_pos, int& read_count); bool read_numeric_data(int start_pos, int max_pos, int& read_count); bool read_object(struct emf_ObjectData_X* pf); bool read_object_name(struct emf_ObjectData_X* od, char* name_buffer, int buffer_len); bool read_string_data(int start_pos, int max_pos, int string_count, int* string_sizes, int& read_count); void reset_flags(); int sendMessage(char* msg); void set_transfer_info(); void storeDataAsString(const char* buffer, bool is_matc = false); bool storeNumber(struct emf_ObjectData_X* od, LibFront::dataValueType data_type, void* data); template bool try_to_read(T& data); bool update_data_lengths(int data_count, int* data_sizes); bool update_variable_lengths(int var_count, int* var_sizes); bool readerOk; void* currentBuffer; int currentFlagsIndex; enum LibFront::dataValueType currentBufferType; int currentBufferSize; char dataAsStringBuffer[MAX_BUFFER_LEN]; int dataAsStringPos; void* dataBuffer; bool dataHasMatcVars; enum LibFront::dataValueType dataBufferType; int dataBufferSize; int* dataLengths; int dimension1; int dimension2; int evaluatedBufferEnd; LibFrontReaderFlags* flags; LibFrontReaderFlags flagsStack[32]; double hangingNumber; ifstream inputFile; char* inputFileName; char matcBuffer[MAX_BUFFER_LEN]; bool matcDefsWarned; char matcSeparator; int msgBufferSize; char* msgBuffer; // for readMessageCB function! char* nameBuffer; int nameBufferMaxLen; int nofDataValues; int nofEntries; int nofVariables; int nofVariableValues; char* readBuffer; int readBufferPos; int readBufferLen; char resultBuffer[MAX_BUFFER_LEN]; char stringSeparator; char tokenBuffer[MAX_BUFFER_LEN]; int tokenBufferLen; int tokenBufferMaxLen; void** userData; void* variableBuffer; int variableBufferSize; enum LibFront::dataValueType variableBufferType; int* variableLengths; }; // ========================================================================= // END: File reader (parser( class // ========================================================================= #endif