/***********************************************************************
*
* 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 <class T> 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 <class T> 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
syntax highlighted by Code2HTML, v. 0.9.1