/***********************************************************************
*
* 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..cpp
Language: C++
Date: 01.10.98
Version: 1.00
Author(s): Martti Verho
Revisions:
Abstract: Implementation: Parser for ELMER model file (.emf files).
************************************************************************/
using namespace std;
#include <ctype.h>
#include <string.h>
#include <iostream>
#include <fstream>
#include <strstream>
#include <iomanip>
#include "frontlib.h"
// Elmer MATC do-math call
extern "C" char* mtc_domath(char* s);
// *************************************************************************
// *************************************************************************
//
// START: Library globals
//
// *************************************************************************
// *************************************************************************
//
// Global interface variables
//
EMF_DECL int emf_ReadMode = 1;
EMF_DECL struct emf_ObjectData_X* emf_ObjectData = 0;
EMF_DECL char* emf_UnknownData = new char[1 + emf_MAX_STRING_LEN];
// CallBack functions
//
extern "C" int (*emf_readDataCB) (void** user_data) = 0;
extern "C" int (*emf_readMessageCB) (char* msg_buffer) = 0;
// Global function definitions
// This function creates the reader and starts it
// NOTE: It is called by the user!
//
EMF_DECL int emf_readData(char* in_file_name, void** user_data,
int msg_buffer_size, char* msg_buffer,
int evaluate_only_matc)
{
bool eval_only_matc = ( 0 != evaluate_only_matc);
LibFrontReader* reader = new LibFrontReader(in_file_name, user_data,
msg_buffer_size, msg_buffer,
eval_only_matc);
int rc = 0; // Ok
if ( eval_only_matc ) return rc;
if ( reader == NULL || !reader->isOk() || !reader->start() ) {
rc = 1; // Error
}
delete reader;
return rc;
}
// This function is called from the reader.
// It calls the CallBack function given by the user
// and thus informs about new available data.
//
int sendData(void** user_data)
{
return emf_readDataCB(user_data);
}
// =========================================================================
// END: Library globals
// =========================================================================
// *************************************************************************
// *************************************************************************
// START Library locals
// *************************************************************************
// *************************************************************************
// Data handling functions
// -----------------------
//-Data arries
template <class T> void
setNumericData_impl(T*& target)
{
if (LibFront::isLogicalData)
target = (T*) LibFront::logicalData;
else if (LibFront::isIntegerData)
target = (T*) LibFront::integerData;
else if (LibFront::isRealData)
target = (T*) LibFront::realData;
}
//-Data values by index
template <class T> void
setNumericData_impl(T& target, int value_index)
{
if (LibFront::isLogicalData)
target = (T) LibFront::logicalData[value_index];
else if (LibFront::isIntegerData)
target = (T) LibFront::integerData[value_index];
else if (LibFront::isRealData)
target = (T) LibFront::realData[value_index];
}
//-Variable values
template <class T> void
setNumericVariable_impl(T& target, int value_index)
{
if (LibFront::isRealVariable)
target = (T) LibFront::realVariable[value_index];
}
// Data output functions
// ---------------------
// Scalar data
//
template <class T> ostream&
output_scalar_impl(ostream& out, short indent_size, short indent_level,
const char* field_name, const char* field_type,
const T data, bool quoted)
{
char QM = '\"';
// Field name
if ( field_name != NULL ) {
LibFront::output_string(out, indent_size, indent_level, field_name, false);
}
// Field type
if ( field_type != NULL ) {
out << endl;
LibFront::output_string(out, indent_size, 1 + indent_level, field_type, false);
}
// If no name/type was output
if ( field_name == NULL && field_type == NULL ) {
LibFront::indent(out, indent_size, indent_level);
// Data right after name/type string
} else {
out << " ";
}
//---Possible starting quote
if (quoted)
out << QM;
// Null strings cannot be printed!
if ( !(LibFront::ncEqual((char*)field_type, "string")) ||
data != 0
) {
//---Logical value as True/False
if (LibFront::ncEqual((char*)field_type, "logical")) {
if (data)
out << "True";
else
out << "False";
}
//---Other data types
else {
out << data;
}
}
//---Possible ending quote
if (quoted)
out << QM;
out << endl;
return out;
}
// Vector data
//
template <class T> ostream&
output_vector_impl(ostream& out, short indent_size, short indent_level,
const char* field_name, const char* field_type,
int dim, const T* data, bool output_size, bool quoted)
{
char QM = '\"';
// Field name
if ( field_name != NULL ) {
LibFront::output_string(out, indent_size, indent_level, field_name, false);
}
// Field size
if (output_size) {
out << endl;
LibFront::indent(out, indent_size, 1 + indent_level);
out << "Size " << dim << endl;
}
// Field type
if (field_type != NULL ) {
// If Size is not printed, we need a newline
if (!output_size)
out << endl;
LibFront::output_string(out, indent_size, 2 + indent_level, field_type, false);
}
if (data == NULL) {
return out;
}
// If no name/type was output
if ( field_name == NULL && field_type == NULL ) {
LibFront::indent(out, indent_size, indent_level);
// Data right after name/type string
} else {
out << " ";
}
// Field data after type
for (short i = 0; i < dim; i++) {
//---Possible starting quote
if (quoted)
out << QM;
// Null strings cannot be printed!
if ( !(LibFront::ncEqual((char*)field_type, "string")) ||
data[i] != 0
) {
//---Logical value as True/Flase
if (LibFront::ncEqual((char*)field_type, "logical")) {
if ( data[i] )
out << "True";
else
out << "False";
}
//---Other data types
else {
out << data[i];
}
}
//---Possible ending quote
if (quoted)
out << QM;
out << ' ';
}
out << endl;
return out;
}
// Table data
template <class T> ostream&
output_table_impl(ostream& out, short indent_size, short indent_level,
const char* field_name, const char* field_type,
int dim1, int dim2, const T** data, bool quoted)
{
char QM = '\"';
// Field name
LibFront::output_string(out, indent_size, indent_level, field_name, true);
// Field size
LibFront::indent(out, indent_size, 1 + indent_level);
out << "Size " << dim1 << " " << dim2 << endl;
// Field type
if (field_type != NULL )
LibFront::output_string(out, indent_size, 2 + indent_level, field_type, true);
if (data == NULL) {
return out;
}
// Data lines after type line
for (int i = 0; i < dim1; i++) {
LibFront::indent(out, indent_size, 3 + indent_level);
for (short j = 0; j < dim2; j++) {
out << " ";
// Possible starting quote
if (quoted)
out << QM;
// Null strings cannot be printed!
if ( !(LibFront::ncEqual((char*)field_type, "string")) ||
data[i][j] != 0
) {
//---Logical value as True/Flase
if (LibFront::ncEqual((char*)field_type, "logical")) {
if ( data[i][j] )
out << "True";
else
out << "False";
}
//---Other data types
else {
out << data[i][j];
}
// Possible ending quote
if (quoted)
out << QM;
} // If data_ij != NULL
} // For dim2
out << endl;
} // For dim1
return out;
}
ostream& output_data(ostream& out, char* data_type, void* data)
{
if (data == NULL) {
out << "NULL" << endl;
return out;
}
// Associate to the data according to the data type
if ( LibFront::ncEqual(data_type, "logical") ) {
out << (int*)data;
}
else if ( LibFront::ncEqual(data_type, "integer") ) {
out << (int*)data;
}
else if ( LibFront::ncEqual(data_type, "real") ) {
out << (double*)data;
}
else if ( LibFront::ncEqual(data_type, "string") ) {
out << (char*)data;
}
else if ( LibFront::ncEqual(data_type, "file") ) {
out << (char*)data;
}
else {
out << "Unknown datatype: " << data_type;
}
out << endl;
return out;
}
// =========================================================================
// END: Library locals
// =========================================================================
// *************************************************************************
// *************************************************************************
//
// START: LibFront namespace implementation
//
// *************************************************************************
// *************************************************************************
//
// Data values related flags set in the library by the Reader and
// LibFront global data used to transfer data
//
bool LibFront::isFileData = false;
bool LibFront::isIntegerData = false;
bool LibFront::isLogicalData = false;
bool LibFront::isRealData = false;
bool LibFront::isStringData = false;
bool LibFront::isVoidData = false;
int* LibFront::integerData = NULL;
int* LibFront::logicalData = NULL;
double* LibFront::realData = NULL;
char* LibFront::stringData = NULL;
void* LibFront::voidData = NULL;
int LibFront::dimension1 = NULL;
int LibFront::dimension2 = NULL;
int* LibFront::dataLengths = NULL;
// Variables related flags set in the library by the Reader and
// LibFront global data used to transfer variables
//
bool LibFront::isRealVariable = false;
bool LibFront::isStringVariable = false;
bool LibFront::isVoidVariable = false;
double* LibFront::realVariable = NULL;
char* LibFront::stringVariable = NULL;
void* LibFront::voidVariable = NULL;
int* LibFront::variableValuesLengths = NULL;
char LibFront::stringSeparator = '\"';
char LibFront::matcSeparator = '$';
void
LibFront::setStringSeparator(char sep)
{
stringSeparator = sep;
}
void
LibFront::setMatcSeparator(char sep)
{
matcSeparator = sep;
}
// Read file into given buffer
//
// NOTE: Buffer is allocated in the function!
// Skip empty line, comment lines and eol comments
// Return: nof chars read or -1 if file not found
//
int
LibFront::readFile(char* filename, char*& buffer, bool skip_comments)
{
// Initial size
int bufferLen = 10000;
int bufferPos = 0;
buffer = new char[bufferLen];
ifstream inputFile;
inputFile.open(filename, ios::in );
if ( inputFile.fail() ) return -1;
bool is_string = false;
bool skipping_comment = false;
bool connecting_line = false;
bool is_matc = false;
int matc_start = -1;
int fcount = 0;
char c[1];
// Read file until end-of-file
//
while ( !inputFile.eof() ) {
c[0] = '\0';
inputFile.read(c, 1);
if ( c[0] == '\0' ) break;
// Continuation marker (slash) irrelevant in a string and in comments
if ( c[0] == '/' && !is_string && !skipping_comment) {
connecting_line = true;
}
// String marker irrelevant in comments and after continuation marker
if ( c[0] == stringSeparator && !(skipping_comment || connecting_line) ) {
is_string = !is_string;
}
// Comment symbols irrelevant in strings
if ( (c[0] == '!' || c[0] == '#') && skip_comments && !is_string) {
skipping_comment = true;
}
// What newline means
if ( c[0] == '\n' && skip_comments) {
skipping_comment = false;
// If we are connecting strings or we have an open string,
// do not store the newline character
if (connecting_line || is_string) {
connecting_line = false;
continue;
}
}
// Skip carrage returns
// NOTE: This way wwe can read dos-files (CR-LF) also in Unix
// NOTE: Keep this after newline-handling, so that Dos files
// are not ruined under Win32!
if ( c[0] == '\r' && skip_comments) {
continue;
}
// Comments and characters after continuation marker
// in the same line can be skipped!
if ( skipping_comment || connecting_line ) {
continue;
}
// Allocate larget buffer is needed
if ( fcount >= bufferLen - 1 ) {
char* tmp = new char[bufferLen + 5000];
for (int i = 0; i < bufferLen; i++)
tmp[i] = buffer[i];
bufferLen += 5000;
delete[] buffer;
buffer = tmp;
}
// Copy storable character to the buffer
buffer[fcount++] = c[0];
} // While !eof
inputFile.close();
// Check that data ends with eol!
if ( buffer[fcount-1] != '\n' ) {
buffer[fcount++] = '\n';
}
// Actual buffer size
buffer[fcount] = '\0';
return fcount;
}
// 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!
//
int
LibFront::readMatcExpression(char* source, int source_pos, int source_end, char* result, int max_result_len, bool skip_comments)
{
int i,j;
static char matc_peek_buffer[10001];
bool is_string = false;
bool skipping_comment = false;
bool connecting_line = false;
bool is_matc_end = false;
bool is_matc_def = false;
bool is_matc_func = false;
bool check_matc_func = false;
bool check_matc_end = false;
int read_count = 0;
int result_pos = 0;
int matc_peek_pos = 0;
int matc_lb_count = 0;
int matc_rb_count = 0;
int matc_lp_count = 0;
int matc_rp_count = 0;
char c_1 = '\0'; // Previous character
char c = '\0'; // Current character
// Read matc-expression in the result-buffer
// advance the source-buffer to the end of the expression
//
while (true) {
if ( source_pos >= source_end ) break;
if ( result_pos >= max_result_len ) break;
c = source[source_pos++];
read_count++;
// NOTE: We want to check if first non-blank text after $-sign
// 'function'
if ( matc_peek_pos < 10000 && c != ' ' ) {
matc_peek_buffer[matc_peek_pos++] = c;
}
// Matc marker ($) is irrelevant in comments
if ( c == matcSeparator && !skipping_comment) {
is_matc_end = true;
break;
}
if ( c == '\0' ) {
check_matc_end = true;
}
// Continuation marker (slash) irrelevant in a string and in comments
if ( c == '/' && !is_string && !skipping_comment) {
connecting_line = true;
}
// Matc separators
//
// Left brace
if ( c == '{' ) {
matc_lb_count += 1;
if ( matc_lb_count == 1 ) {
check_matc_func = true;
}
// Right brace
} else if ( c == '}' ) {
matc_rb_count += 1;
check_matc_end = true;
// Left parenthesis
} else if ( c == '(' ) {
matc_lp_count += 1;
if ( matc_lp_count == 1 ) {
check_matc_func = true;
}
// Right parenthesis
} else if ( c == ')' ) {
matc_rp_count += 1;
// Sign '=' is a definition, if lp==rp
} else if ( c == '=' && matc_lp_count == matc_rp_count) {
is_matc_def = true;
// If not a definition, could be at end when lp==rp or when something
// non-ws which is not =-sign
//
} else if ( !is_matc_def &&
(c != '=' && c != ' ' && c != '\t') &&
(c_1 == ' ' || c_1 == '\t' || matc_lp_count > 0) &&
matc_lp_count == matc_rp_count) {
check_matc_end = true;
}
// If we have the 'function'
if ( check_matc_func ) {
matc_peek_buffer[8] = '\0';
if ( LibFront::in("function", matc_peek_buffer) ) {
is_matc_func = true;
}
}
// String marker (toggle)
if ( c == stringSeparator && !(skipping_comment || connecting_line) ) {
is_string = !is_string;
}
// Comment symbols irrelevant in strings
if ( (c == '!' || c == '#') && skip_comments && !is_string) {
skipping_comment = true;
}
// What newline means
if ( c == '\n' ) {
check_matc_end = true;
skipping_comment = false;
// If we are connecting strings or we have an open string,
// do not store the newline character
if (connecting_line || is_string) {
connecting_line = false;
continue;
}
}
// Skip carrage returns
// NOTE: This way we can read dos-files (CR-LF) also in Unix
// NOTE: Keep this test after newline-handling, so that Dos files
// are not ruined under Win32!
if ( c == '\r' ) {
continue;
}
// Comments and characters after continuation marker
// in the same line can be skipped!
if ( skipping_comment || connecting_line ) {
continue;
}
// If the matc-expression is possibly at end
if ( check_matc_end ) {
// If we have the 'function'
matc_peek_buffer[8] = '\0';
if ( LibFront::in("function", matc_peek_buffer) ) {
is_matc_func = true;
}
if ( !is_string &&
( matc_lb_count == matc_rb_count &&
matc_lp_count == matc_rp_count &&
( (is_matc_func && matc_lb_count > 0) ||
!is_matc_func
)
)
) {
is_matc_end = true;
}
// If comments are not skipped, keep also the separating linefeeds!
if ( !skip_comments && read_count == 1 && c == '\n' ) {
result[result_pos++] = c;
break;
}
} // if check matc-end
// When to store the charcter into result
if ( !is_matc_end || c == ')' || c == '}' ) {
result[result_pos++] = c;
}
if ( is_matc_end ) {
// Move source backwards if we have been peeking too much to see
// the end of the expression!!!
//
if ( c != ')' && c != '}' && c_1 == ' ' || c_1 == '\t' ) {
while ( source[source_pos] != ' ' && source[source_pos] != '\t' ) {
source_pos--;
}
}
break;
}
// Store previous character
c_1 = c;
}
result[result_pos] = '\0';
// Return the source position just after the expression
//
return source_pos;
}
// Init Matc output format to 'plain' (ie. no Columns through) mode
// Precision set to 8
//
void LibFront::initMatcFrmt() {
char matc_frmt[] = "format(8,\"rowform\")";
mtc_domath( matc_frmt );
}
// Check that a Matc error message is Tcl-printable
void LibFront::formatMatcError(char* err_msg)
{
// NOTE Tcl does not like [] !!!
for(int i = 0; i < strlen(err_msg); i++) {
if ( err_msg[i] == '[' ) err_msg[i] = ' ';
if ( err_msg[i] == ']' ) err_msg[i] = ' ';
}
}
// Check if the string is a matc function or variable definition
//
// NOTE: Whitespace must have been trimmed from 'str' before calling
// this function
//
bool
LibFront::isMatcDefinition(const char* str)
{
static char buffer[9];
int i;
// Empty string or a comment or lf
if ( str == NULL ||
str[0] == '\0' ||
str[0] == '!' ||
str[0] == '#' ||
str[0] == '\n'
) return false;
char* tmp = (char*)str;
// Skip possible Matc-separator ($)
if ( tmp[0] == matcSeparator ) tmp++;
// Pick first 8 charcaters
for (i = 0; i < 8; i++) {
buffer[i] = tmp[i];
}
buffer[8] = '\0';
toLower(buffer);
// Function definition
if ( 0 == strncmp(buffer, "function", 8) ) return true;
// Variable definition
for (i = 0; i < strlen(tmp); i++) {
if ( tmp[i] == '=' ) return true;
}
return false;
}
// Checks if the string has matc variables
//
// NOTE: Whitespace must have been trimmed from 'str' before calling
// this function
//
bool
LibFront::hasMatcVariables(const char* str)
{
if ( LibFront::isMatcDefinition(str) ) return false;
int i;
// Empty string or a comment or lf
if ( str == NULL ||
str[0] == '\0' ||
str[0] == '!' ||
str[0] == '#' ||
str[0] == '\n'
) return false;
// Contains a variable name
for (i = 0; i < strlen(str); i++) {
if ( isalpha(str[i]) ) return true;
}
return false;
}
// Get a function or variable name from a Matc definition
//
// NOTE: Whitespace must have been trimmed from 'str' before calling
// this function
//
bool
LibFront::getMatcName(const char* str, char* name_buffer, int max_len, bool& is_var, bool& is_func)
{
static char buffer[9];
int i, j;
is_var = false;
is_func = false;
name_buffer[0] = '\0';
if ( !LibFront::isMatcDefinition(str) ) return false;
char* tmp = (char*)str;
// Skip possible Matc-separator ($)
if ( tmp[0] == matcSeparator ) tmp++;
// Pick first 8 characters to check if this
// is a function definition
for (i = 0; i < 8; i++) {
buffer[i] = tmp[i];
}
buffer[8] = '\0';
toLower(buffer);
//--Function definition
if ( 0 == strncmp(buffer, "function", 8) ) {
tmp += 8;
int start_pos = 0;
LibFront::trimLeft(tmp, strlen(tmp), start_pos, true);
tmp += start_pos;
// Find function name end
int len = 0;
while (tmp[len] != '(' &&
tmp[len] != ' ' &&
tmp[len] != '\t' &&
tmp[len] != '\n'
) len++;
// Copy name
for (j = 0; j < len && j < max_len; j++) {
name_buffer[j] = tmp[j];
}
name_buffer[j] = '\0';
is_func = true;
return true;
}
//--Variable definition
for (i = 0; i < strlen(tmp); i++) {
if ( tmp[i] == '=' ) {
// Find function name end
int len = 0;
while (tmp[len] != '=' &&
tmp[len] != ' ' &&
tmp[len] != '\t' &&
tmp[len] != '\n'
) len++;
// Copy name
for (j = 0; j < len && j < max_len; j++) {
name_buffer[j] = tmp[j];
}
name_buffer[j] = '\0';
is_var = true;
return true;
}
}
return false;
}
// Check if result is a Matc error
//
// NOTE: Whitespace must have been trimmed from 'str' before calling
// this function
//
bool
LibFront::isMatcError(const char* str)
{
static char buffer[11];
int i;
if ( str == NULL || str[0] == '\0' ) return false;
int len = 10;
// Pick first 10 charcaters
for (i = 0; i < len; i++) {
buffer[i] = str[i];
}
buffer[len] = '\0';
toUpper(buffer);
if ( 0 == strncmp("MATC ERROR", buffer, len) ) {
return true;
} else {
return false;
}
}
// Evaluate a string containing Matc-expressions
//
//
char*
LibFront::evalMatcString(const char* str)
{
if ( str == NULL || str[0] == '\0' ) return NULL;
int len = strlen(str);
char* buffer = new char[1+len];
strcpy(buffer, str);
for (int i = 0; i < len; i++) {
if ( buffer[i] == matcSeparator ) {
buffer[i] = ' ';
}
}
char* res = mtc_domath(buffer);
delete[] buffer;
if ( isMatcError(res) ) return NULL;
return res;
}
//--Data reading functions
void
LibFront::setNumericData(bool*& target)
{
setNumericData_impl(target);
}
void
LibFront::setNumericData(int*& target)
{
setNumericData_impl(target);
}
void
LibFront::setNumericData(long*& target)
{
setNumericData_impl(target);
}
void
LibFront::setNumericData(float*& target)
{
setNumericData_impl(target);
}
void
LibFront::setNumericData(double*& target)
{
setNumericData_impl(target);
}
void
LibFront::setStringData(char*& buffer)
{
buffer = stringData;
}
void
LibFront::setNumericData(bool& target, int value_index)
{
setNumericData_impl(target, value_index);
}
void
LibFront::setNumericData(int& target, int value_index)
{
setNumericData_impl(target, value_index);
}
void
LibFront::setNumericData(long& target, int value_index)
{
setNumericData_impl(target, value_index);
}
void
LibFront::setNumericData(float& target, int value_index)
{
setNumericData_impl(target, value_index);
}
void
LibFront::setNumericData(double& target, int value_index)
{
setNumericData_impl(target, value_index);
}
// NOTE: Buffer size must be large enough for the result!
//
void
LibFront::setStringData(char* buffer, int value_index)
{
// Starting position in variable values string
int start_pos = 0;
for (int i = 0; i < value_index; i++)
start_pos += dataLengths[i];
// Copy string referred by the value_index
int size = dataLengths[value_index];
char* source = stringData + start_pos;
strncpy(buffer, source, size);
// End mark
buffer[size] = '\0';
}
// NOTE: 'strings' argument is allocated here!
//
void
LibFront::setStringData(int nof_strings, char**& strings)
{
strings = NULL;
if ( nof_strings == 0 )
return;
strings = new char*[nof_strings];
for (int i = 0; i < nof_strings; i++) {
int len = dataLengths[i];
strings[i] = new char[1 + len];
setStringData(strings[i], i);
}
}
void
LibFront::setNumericVariable(bool& target, int value_index)
{
setNumericVariable_impl(target, value_index);
}
void
LibFront::setNumericVariable(int& target, int value_index)
{
setNumericVariable_impl(target, value_index);
}
void
LibFront::setNumericVariable(long& target, int value_index)
{
setNumericVariable_impl(target, value_index);
}
void
LibFront::setNumericVariable(float& target, int value_index)
{
setNumericVariable_impl(target, value_index);
}
void
LibFront::setNumericVariable(double& target, int value_index)
{
setNumericVariable_impl(target, value_index);
}
void
LibFront::setStringVariable(char* buffer, int value_index)
{
// Starting position in varaible values string
int start_pos = 0;
for (int i = 0; i < value_index; i++)
start_pos += variableValuesLengths[i];
// Copy string referred by the value_index
int size = variableValuesLengths[value_index];
char* source = stringVariable + start_pos;
strncpy(buffer, source, size);
// End mark
buffer[size] = '\0';
}
//--Field output functions
// Shorthand for "is_name" function
bool
LibFront::in(const char* field_name, const char* test_name)
{
return LibFront::ncEqual((char*)field_name, (char*)test_name);
}
// Simple strin (field name etc.)
ostream&
LibFront::output_string(ostream& out, short indent_size, short indent_level,
const char* field_name, bool add_eol)
{
LibFront::indent(out, indent_size, indent_level);
out << field_name;
if ( add_eol ) {
out << endl;
}
return out;
}
// Callable cover functions
// ========================
ostream&
LibFront::output_matcDef(ostream& out, short indent_size, short indent_level,
const char* field_name, const char* field_type,
const char* def, bool add_dsign)
{
strstream strm;
if ( add_dsign ) {
strm << '$';
}
strm << def << ends;
return LibFront::output_scalar(out, indent_size, indent_level,
field_name, field_type,
strm.str(), false);
}
// Scalar data
ostream&
LibFront::output_scalar(ostream& out, short indent_size, short indent_level,
const char* field_name, const char* field_type,
const bool data)
{
return output_scalar_impl(out, indent_size, indent_level,
field_name, field_type,
data, false);
}
ostream&
LibFront::output_scalar(ostream& out, short indent_size, short indent_level,
const char* field_name, const char* field_type,
const short data)
{
return output_scalar_impl(out, indent_size, indent_level,
field_name, field_type,
data, false);
}
ostream&
LibFront::output_scalar(ostream& out, short indent_size, short indent_level,
const char* field_name, const char* field_type,
const int data)
{
return output_scalar_impl(out, indent_size, indent_level,
field_name, field_type,
data, false);
}
ostream&
LibFront::output_scalar(ostream& out, short indent_size, short indent_level,
const char* field_name, const char* field_type,
const long data)
{
return output_scalar_impl(out, indent_size, indent_level,
field_name, field_type,
data, false);
}
ostream&
LibFront::output_scalar(ostream& out, short indent_size, short indent_level,
const char* field_name, const char* field_type,
const float data)
{
return output_scalar_impl(out, indent_size, indent_level,
field_name, field_type,
data, false);
}
ostream&
LibFront::output_scalar(ostream& out, short indent_size, short indent_level,
const char* field_name, const char* field_type,
const double data)
{
return output_scalar_impl(out, indent_size, indent_level,
field_name, field_type,
data, false);
}
ostream&
LibFront::output_scalar(ostream& out, short indent_size, short indent_level,
const char* field_name, const char* field_type,
const char* data, bool quoted)
{
return output_scalar_impl(out, indent_size, indent_level,
field_name, field_type,
data, quoted);
}
// Vector data
ostream&
LibFront::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)
{
return output_vector_impl(out, indent_size, indent_level,
field_name, field_type,
dim, data, output_size, false);
}
ostream&
LibFront::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)
{
return output_vector_impl(out, indent_size, indent_level,
field_name, field_type,
dim, data, output_size, false);
}
ostream&
LibFront::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)
{
return output_vector_impl(out, indent_size, indent_level,
field_name, field_type,
dim, data, output_size, false);
}
ostream&
LibFront::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)
{
return output_vector_impl(out, indent_size, indent_level,
field_name, field_type,
dim, data, output_size, false);
}
ostream&
LibFront::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)
{
return output_vector_impl(out, indent_size, indent_level,
field_name, field_type,
dim, data, output_size, false);
}
ostream&
LibFront::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)
{
return output_vector_impl(out, indent_size, indent_level,
field_name, field_type,
dim, data, output_size, false);
}
ostream&
LibFront::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, bool quoted)
{
return output_vector_impl(out, indent_size, indent_level,
field_name, field_type,
dim, data, output_size, quoted);
}
// Table data
ostream&
LibFront::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)
{
return output_table_impl(out, indent_size, indent_level,
field_name, field_type,
dim1, dim2, data, false);
}
ostream&
LibFront::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)
{
return output_table_impl(out, indent_size, indent_level,
field_name, field_type,
dim1, dim2, data, false);
}
ostream&
LibFront::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)
{
return output_table_impl(out, indent_size, indent_level,
field_name, field_type,
dim1, dim2, data, false);
}
ostream&
LibFront::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)
{
return output_table_impl(out, indent_size, indent_level,
field_name, field_type,
dim1, dim2, data, false);
}
ostream&
LibFront::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)
{
return output_table_impl(out, indent_size, indent_level,
field_name, field_type,
dim1, dim2, data, false);
}
ostream&
LibFront::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)
{
return output_table_impl(out, indent_size, indent_level,
field_name, field_type,
dim1, dim2, data, false);
}
ostream&
LibFront::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)
{
return output_table_impl(out, indent_size, indent_level,
field_name, field_type,
dim1, dim2, (const char**)data, quoted);
}
//****************
// Other utilities
//****************
// Check if string is a number using atof
bool
LibFront::isNumber(const char* str)
{
if ( str == NULL || str[0] == '\0' )
return false;
int len = strlen(str);
int index = 0;
char* tmp = (char*)str;
// Skip +/- sign
if (tmp[0] == '-' || tmp[0] == '+' ) {
tmp++;
index++;
}
// Digits before decimal point are missing!
if ( index == len || !isdigit(tmp[0]) )
return false;
// Skip digits before deciaml point
while ( index < len && isdigit(tmp[0]) ) {
tmp++;
index++;
}
// OK: [+-]{digits}
if ( index == len )
return true;
// Skip decimal point
if ( tmp[0] == '.' ) {
tmp++;
index++;
}
// Skip digits after decimal point
while ( index < len && isdigit(tmp[0]) ) {
tmp++;
index++;
}
// OK: [+-]{digits}.{digits}
if ( index == len )
return true;
// Skip exponent indicator
if ( tmp[0] == 'E' ||
tmp[0] == 'e' ||
tmp[0] == 'D' ||
tmp[0] == 'd'
) {
tmp++;
index++;
// Anything else is non-numeric!
} else {
return false;
}
// Digits after exponent are missing!
if ( index == len )
return false;
// Skip +/- exponent's sign
if (tmp[0] == '-' || tmp[0] == '+' ) {
tmp++;
index++;
}
// Digits after exponent's sign are missing!
if ( index == len || !isdigit(tmp[0]) )
return false;
// Skip exponent's digits
while ( index < len && isdigit(tmp[0]) ) {
tmp++;
index++;
}
// Now we should be at the end!
// Not --> Error
if ( index < len )
return false;
// Yes --> OK
else
return true;
}
// Compare two string (non-case sensitive)
// If string are same returns: true
// otherwise: false
bool
LibFront::ncEqual(char* str1, char* str2)
{
if ( str1 == NULL || str2 == NULL ) {
return false;
}
int i;
int len1 = strlen(str1);
int len2 = strlen(str2);
if (len1 != len2)
return false;
for (i = 0; i < len1; i++)
if ( toupper(str1[i]) != toupper(str2[i]) )
return false;
return true;
}
// Compare partially (according to the lengt of str2)
// two strings (non-case sensitive).
// If string are same returns: true
// otherwise: false
bool
LibFront::ncEqualPartial(char* str1, char* str2)
{
int i;
int len1 = strlen(str1);
int len2 = strlen(str2);
if (len1 < len2)
return false;
for (i = 0; i < len2; i++)
if ( toupper(str1[i]) != toupper(str2[i]) )
return false;
return true;
}
// Indent stream by putting spaces into it
ostream&
LibFront::indent(ostream& out, short indent_size, short indent_level)
{
for (int i = 0; i < indent_size * indent_level; i++)
out << ' ';
return out;
}
// Make a "indented" string by putting enough spaces into it
char*
LibFront::indent(short indent_size, short indent_level)
{
const int MAX_INDENT = 80;
static char buffer[1 + MAX_INDENT];
int indent = indent_size * indent_level;
if (indent > MAX_INDENT)
indent = MAX_INDENT;
for (int i = 0; i < indent; i++)
buffer[i] = ' ';
buffer[indent] = '\0';
return buffer;
}
char*
LibFront::trim(char* buffer, bool trim_nl)
{
LibFront::trimLeft(buffer, trim_nl);
LibFront::trimRight(buffer, trim_nl);
return buffer;
}
// Remove leading whitespace
char*
LibFront::trimLeft(char* buffer, bool trim_nl)
{
int len = strlen(buffer);
if ( len == 0)
return buffer;
int pos = 0;
if ( trim_nl ) {
while (buffer[pos] == '\t' || buffer[pos] == ' ' || buffer[pos] == '\n' ) {
if (++pos == len)
break;
}
} else {
while (buffer[pos] == '\t' || buffer[pos] == ' ' ) {
if (++pos == len)
break;
}
}
if (pos == 0)
return buffer;
// Start copying "back" from the first non-space position
strcpy(buffer, buffer + pos);
buffer[len-pos] = '\0';
return buffer;
}
// Remove trailing whitespace
char*
LibFront::trimRight(char* buffer, bool trim_nl)
{
int len = strlen(buffer);
if ( len == 0)
return buffer;
// Put NULL after the last non-spce character in the buffer
int pos = len - 1;
if ( trim_nl ) {
while (buffer[pos] == ' ' || buffer[pos] == '\t' || buffer[pos] == '\n' ) {
buffer[pos] = '\0';
if (--pos < 0)
break;
}
} else {
while (buffer[pos] == '\t' || buffer[pos] == ' ' ) {
buffer[pos] = '\0';
if (--pos < 0)
break;
}
}
return buffer;
}
// Find first non-ws position in the string
//
void
LibFront::trimLeft(const char* str, int max_pos, int& start_pos, bool trim_nl)
{
// Pass by white-space at the end of the string
while (1) {
if (start_pos >= max_pos)
break;
char c = str[start_pos];
if ( trim_nl ) {
if (c != ' ' && c != '\t' && c != '\n' )
break;
} else {
if (c != ' ' && c != '\t' )
break;
}
start_pos++;
}
}
// Find last non-ws position in the string
//
void
LibFront::trimRight(const char* str, int min_pos, int& end_pos, bool trim_nl)
{
// Pass by white-space at the end of the string
while (1) {
if (end_pos <= min_pos)
break;
char c = str[end_pos];
if ( trim_nl ) {
if (c != ' ' && c != '\t' && c != '\n' )
break;
} else {
if (c != ' ' && c != '\t' )
break;
}
end_pos--;
}
}
char*
LibFront::toLower(char* str)
{
int i, len;
len = strlen(str);
for (i =0; i < len; i++) {
str[i] = tolower(str[i]);
}
return str;
}
char*
LibFront::toLower(const char* source, char* target)
{
int i, len;
len = strlen(source);
for (i =0; i <= len; i++) {
target[i] = tolower(source[i]);
}
return target;
}
char*
LibFront::toUpper(char* str)
{
int i, len;
len = strlen(str);
for (i =0; i < len; i++) {
str[i] = toupper(str[i]);
}
return str;
}
char*
LibFront::toUpper(const char* source, char* target)
{
int i, len;
len = strlen(source);
for (i =0; i <= len; i++) {
target[i] = toupper(source[i]);
}
return target;
}
#if 0
// FILL GLOBAL FIELD NAME TABLE
// NOTE: This is strictly internal function
//
bool deleteFieldInfoTable()
{
if (FieldInfoTable == NULL) {
FieldInfoTableSize = 0;
return true;
}
for (int i = 0; i < FieldInfoTableSize; i++)
delete FieldInfoTable[i];
delete[] FieldInfoTable;
FieldInfoTableSize = 0;
return true;
}
bool LibFront::createFieldInfoTable(int table_size)
{
// Delete possible old table
deleteFieldInfoTable();
if (table_size <= 0)
return false;
// Allocate new table
FieldInfoTable = new FieldInfo*[table_size];
FieldInfoTableSize = table_size;
for (int i = 0; i < table_size; i++)
FieldInfoTable[i] = NULL;
return true;
}
#endif
// =========================================================================
// END: LibFront namespace implementation
// =========================================================================
// *************************************************************************
// *************************************************************************
//
// START: LibFrontReaderFlags class implementation
//
// *************************************************************************
// *************************************************************************
//
LibFrontReaderFlags::LibFrontReaderFlags()
{
init();
}
LibFrontReaderFlags::LibFrontReaderFlags(LibFrontReaderFlags& flags)
{
copy(flags);
}
void
LibFrontReaderFlags::copy(LibFrontReaderFlags& flags)
{
nonSizedDataAtEnd = flags.nonSizedDataAtEnd;
canSkipSpace = flags.canSkipSpace;
canSkipNewline = flags.canSkipNewline;
endsField = flags.endsField;
endsObject = flags.endsObject;
equalSignPeeked = flags.equalSignPeeked;
hasEvaluatedBuffer = flags.hasEvaluatedBuffer;
matcPeeked = flags.matcPeeked;
newlinePeeked = flags.newlinePeeked;
hangingFieldNameNumber = flags.hangingFieldNameNumber;
readingEndMarkedData = flags.readingEndMarkedData;
readingFieldData = flags.readingFieldData;
readingFileName = flags.readingFileName;
readingGroupNames = flags.readingGroupNames;
readingNonSizedData = flags.readingNonSizedData;
readingProcedureName = flags.readingProcedureName;
startsNewField = flags.startsNewField;
startsNewObject = flags.startsNewObject;
}
void
LibFrontReaderFlags::init()
{
nonSizedDataAtEnd = false;
canSkipSpace = false;
canSkipNewline = false;
endsField = false;
endsObject = false;
equalSignPeeked = false;
hasEvaluatedBuffer = false;
matcPeeked = false;
newlinePeeked = false;
hangingFieldNameNumber = false;
readingEndMarkedData = false;
readingFieldData = false;
readingFileName = false;
readingGroupNames = false;
readingNonSizedData = false;
readingProcedureName = false;
startsNewField = false;
startsNewObject = false;
}
// =========================================================================
// END: LibFrontReaderFlags class implementation
// =========================================================================
// *************************************************************************
// *************************************************************************
// START: LibFrontReader class implementation
// *************************************************************************
// *************************************************************************
//
LibFrontReader::LibFrontReader(char* filename, void** user_data,
int msg_buffer_size, char* msg_buffer,
bool is_matc_file)
{
readerOk = true;
matcDefsWarned = false;
inputFileName = new char[1 + strlen(filename)];
strcpy(inputFileName, filename);
// Attach stream to the file
inputFile.open(inputFileName);
inputFile.close();
msgBufferSize = msg_buffer_size;
msgBuffer = msg_buffer;
stringSeparator = '\"';
matcSeparator = '$';
// Read file data into the readBuffer array (comments cleaned)
readBufferPos = 0;
readBufferLen = LibFront::readFile(inputFileName, readBuffer);
// Read file data into the readBuffer array (comments cleaned)
if ( readBufferLen <= 0 ) {
readerOk = false;
}
if ( is_matc_file ) {
if ( readerOk ) {
evalMatcBuffer(readBuffer);
}
return;
}
dataBuffer = NULL;
dataBufferSize = 0;
dataLengths = NULL;
dataAsStringBuffer[0] = '\0';
dataAsStringPos = 0;
dimension1 = 1;
dimension2 = 1;
evaluatedBufferEnd = -1;
nameBuffer = new char[1 + emf_MAX_NAME_LEN];
nameBufferMaxLen = emf_MAX_NAME_LEN;
//nameBufferLen = 0;
nofEntries = 0;
nofVariables = 0;
//tokenBuffer = new char[1 + emf_MAX_NAME_LEN];
tokenBufferMaxLen = emf_MAX_NAME_LEN;
tokenBufferLen = 0;
userData = user_data;
variableBuffer = NULL;
variableBufferSize = 0;
variableLengths = NULL;
currentFlagsIndex = 0;
flags = &flagsStack[currentFlagsIndex];
}
LibFrontReader::~LibFrontReader()
{
inputFile.close();
delete[] inputFileName;
delete[] nameBuffer;
delete[] readBuffer;
delete_data_buffer();
delete_variable_buffer();
}
bool
LibFrontReader::allocate_data_buffer(int current_size, int new_size)
{
if (new_size == 0) {
delete_data_buffer();
return true;
}
void* new_buffer = NULL;
int i;
switch (dataBufferType) {
case LibFront::EMF_INTEGER:
case LibFront::EMF_LOGICAL:
{
int* new_data = new int[new_size];
for (i = 0; i < current_size; i++)
new_data[i] = ((int*)dataBuffer)[i];
new_buffer = new_data;
}
break;
case LibFront::EMF_REAL:
{
double* new_data = new double[new_size];
for (i = 0; i < current_size; i++)
new_data[i] = ((double*)dataBuffer)[i];
new_buffer = new_data;
}
break;
case LibFront::EMF_STRING:
case LibFront::EMF_FILE:
{
char* new_data = new char[1 + new_size];
new_data[new_size] = '\0';
for (i = 0; i < current_size; i++)
new_data[i] = ((char*)dataBuffer)[i];
new_buffer = new_data;
}
break;
}
// Delete old buffer and set the new buffer
delete_data_buffer();
dataBufferSize = new_size;
dataBuffer = new_buffer;
return true;
}
// NOTE: Variable values are either Reals or Strings
bool
LibFrontReader::allocate_variable_buffer(int current_size, int new_size)
{
if (new_size == 0) {
delete_variable_buffer();
return true;
}
void* new_buffer = NULL;
int i;
switch (variableBufferType) {
case LibFront::EMF_REAL:
{
double* new_data = new double[new_size];
for (i = 0; i < current_size; i++)
new_data[i] = ((double*)variableBuffer)[i];
new_buffer = new_data;
}
break;
case LibFront::EMF_STRING:
{
char* new_data = new char[1 + new_size];
new_data[new_size] = '\0';
for (i = 0; i < current_size; i++)
new_data[i] = ((char*)variableBuffer)[i];
new_buffer = new_data;
}
break;
}
// Delete old buffer and set new
delete_variable_buffer();
variableBufferSize = new_size;
variableBuffer = new_buffer;
return true;
}
bool
LibFrontReader::appendReadBuffer(char c, int& bufferPos, bool init)
{
int i,j;
char* matc_result;
static char matc_buffer[10001];
static bool is_string = false;
static bool skipping_comment = false;
static bool connecting_line = false;
static bool is_matc = false;
static bool is_matc_def = false;
static bool is_matc_func = false;
static int matc_start = -1;
static int matc_peek_pos = 0;
static int matc_lb_count = 0;
static int matc_rb_count = 0;
static int matc_lp_count = 0;
static int matc_rp_count = 0;
if ( init ) {
is_string = false;
skipping_comment = false;
connecting_line = false;
is_matc = false;
is_matc_func = false;
is_matc_def = false;
matc_start = -1;
matc_peek_pos = 0;
matc_lb_count = 0;
matc_rb_count = 0;
matc_lp_count = 0;
matc_rp_count = 0;
}
bool check_matc_func = false;
bool check_matc_end = false;
bool do_matc = false;
// NOTE: We want to check if first non-blank text after $-sign
// 'function'
if ( is_matc && matc_peek_pos < 10000 && c != ' ' ) {
matc_buffer[matc_peek_pos++] = c;
}
// Matc marker ($) is irrelevant in a string and in comments
//if ( c == '$' && !is_string && !skipping_comment) {
if ( c == '$' && !skipping_comment) {
if ( is_matc ) {
do_matc = true;
}
is_matc = true;
is_matc_def = false;
is_matc_func = false;
matc_start = bufferPos;
matc_lb_count = 0;
matc_rb_count = 0;
matc_lp_count = 0;
matc_rp_count = 0;
matc_peek_pos = 0;
return true;
}
if ( c == '\0' ) {
check_matc_end = true;
if ( is_matc ) {
do_matc = true;
}
}
// Continuation marker (slash) irrelevant in a string and in comments
if ( c == '/' && !is_string && !skipping_comment) {
connecting_line = true;
}
// Matc separators
//
if ( is_matc ) {
// Left brace
if ( c == '{' ) {
matc_lb_count += 1;
if ( matc_lb_count == 1 ) {
check_matc_func = true;
}
// Right brace
} else if ( c == '}' ) {
matc_rb_count += 1;
check_matc_end = true;
// Left parenthesis
} else if ( c == '(' ) {
matc_lp_count += 1;
if ( matc_lp_count == 1 ) {
check_matc_func = true;
}
// Right parenthesis
} else if ( c == ')' ) {
matc_rp_count += 1;
// Sign '=' is a definition, if lp==rp
} else if ( c == '=' && matc_lp_count == matc_rp_count) {
is_matc_def = true;
// If a definition, could be at end when lp==rp
} else if ( !is_matc_def &&
(c != '=' && c != ' ' && c != '\t') &&
matc_lp_count > 0 &&
matc_lp_count == matc_rp_count) {
check_matc_end = true;
}
}
// If we have the 'function' after $-sign
if ( check_matc_func ) {
matc_buffer[8] = '\0';
if ( LibFront::in("function", matc_buffer) ) {
is_matc_func = true;
}
}
// String marker irrelevant in comments and after continuation marker
if ( c == stringSeparator && !(skipping_comment || connecting_line) ) {
if ( is_string && is_matc ) {
do_matc = true;
is_string = false;
} else {
is_string = !is_string;
}
}
// Comment symbols irrelevant in strings
if ( (c == '!' || c == '#') && !is_string) {
skipping_comment = true;
}
// What newline means
if ( c == '\n' ) {
check_matc_end = true;
skipping_comment = false;
// If we are connecting strings or we have an open string,
// do not store the newline character
if (connecting_line || is_string) {
connecting_line = false;
return true;
}
}
// Skip carrage returns
// NOTE: This way we can read dos-files (CR-LF) also in Unix
// NOTE: Keep this test after newline-handling, so that Dos files
// are not ruined under Win32!
if ( c == '\r' ) {
return true;
}
// Comments and characters after continuation marker
// in the same line can be skipped!
if ( skipping_comment || connecting_line ) {
return true;
}
// If the matc-expression is possibly at end
if ( is_matc && check_matc_end ) {
// If we have the 'function' first after $-sign
matc_buffer[8] = '\0';
if ( LibFront::in("function", matc_buffer) ) {
is_matc_func = true;
}
if ( !is_string &&
( matc_lb_count == matc_rb_count &&
matc_lp_count == matc_rp_count &&
( (is_matc_func && matc_lb_count > 0) ||
!is_matc_func
)
)
) {
do_matc = true;
}
}
// Allocate larger buffer is needed
if ( bufferPos >= readBufferLen - 1 ) {
char* tmp = new char[readBufferLen + 5000];
for (int i = 0; i < readBufferLen; i++)
tmp[i] = readBuffer[i];
readBufferLen += 5000;
delete[] readBuffer;
readBuffer = tmp;
}
// Copy storable character to the buffer
readBuffer[bufferPos++] = c;
// Evaluate a Matc-expression
// ------------------------
if ( do_matc ) {
// Copy all matc-stuff to the matc-buffer
for (i = matc_start; i < bufferPos; i++) {
matc_buffer[i-matc_start] = readBuffer[i];
}
matc_buffer[bufferPos - matc_start] = '\0';
// EVALUATE Matc
//
matc_result = mtc_domath(matc_buffer);
// If Matc-ERROR
//
if ( matc_result != NULL && 0 == strncmp(matc_result, "MATC ERROR", 10 ) ) {
// NOTE Tcl does not like [] !!!
for(j = 0; j < strlen(matc_result); j++) {
if ( matc_result[j] == '[' ) matc_result[j] = ' ';
if ( matc_result[j] == ']' ) matc_result[j] = ' ';
}
if ( matc_result != NULL ) {
sendMessage(matc_result);
sendMessage(matc_buffer);
}
is_matc = false;
matc_start = -1;
return false;
}
bufferPos = matc_start;
is_matc = false;
matc_start = -1;
// If a Matc-expression result, insert result into read buffer
// to be read 'normally'
//
for (i = 0; matc_result != NULL && i < strlen(matc_result); i++) {
appendReadBuffer(matc_result[i], bufferPos, false);
}
return true;
}
return true;
}
bool
LibFrontReader::bufferAtEnd()
{
if ( readBufferPos >= readBufferLen ||
readBuffer[readBufferPos] == '\0'
) {
return true;
} else {
return false;
}
}
// NOTE: Equal sign (=) is also considered as white space!
//
void
LibFrontReader::bufferEatWs()
{
// Skip spaces, tabs, newlines and equal sign
//
// NOTE: checkReadBuffer() handles also newlines
while ( checkReadBuffer() &&
( readBuffer[readBufferPos] == ' ' ||
readBuffer[readBufferPos] == '\t' ||
readBuffer[readBufferPos] == '\n' ||
readBuffer[readBufferPos] == '='
)
) {
readBufferPos++;
}
}
// NOTE: Equal sign (=) is also considered as white space!
// NOTE: This version checks if an equal sign (token at end) or
// a newline was eaten (ie. data ended with a newline)
//
void
LibFrontReader::bufferEatWs(bool& eq_eaten, bool& nl_eaten)
{
eq_eaten = false;
nl_eaten = false;
// Skip spaces, tabs, newlines and equal sign
//
// NOTE: checkReadBuffer() handles also newlines
while ( checkReadBuffer() &&
( readBuffer[readBufferPos] == ' ' ||
readBuffer[readBufferPos] == '\t' ||
readBuffer[readBufferPos] == '\n' ||
readBuffer[readBufferPos] == '='
)
) {
if ( readBuffer[readBufferPos] == '=' ) {
eq_eaten = true;
}
if ( readBuffer[readBufferPos] == '\n' ) {
nl_eaten = true;
}
readBufferPos++;
}
}
bool
LibFrontReader::case_compare(char* str1, char* str2)
{
int len1 = strlen(str1);
int len2 = strlen(str2);
if (len1 =! len2)
return false;
for (int i = 0; i < len1; i++) {
if ( str1[i] != str2[i] )
return false;
}
return true;
}
// Check if read buffer is at end
//
bool
LibFrontReader::checkReadBuffer()
{
if ( bufferAtEnd() ) {
return false;
}
bool ok = true;
char c = readBuffer[readBufferPos];
if ( c == '\n' ) {
ok = handleEol();
}
if (bufferAtEnd()) {
return false;
}
return ok;
}
void
LibFrontReader::constructStringFromTokens(char* buffer, int nof_string_tokens)
{
char* tmp = buffer;
for (int i = 0; i < nof_string_tokens; i++) {
int old_len = strlen(tmp);
getNextToken(tmp + old_len);
int new_len = strlen(tmp);
// Add space separator between tokens
if (i < nof_string_tokens - 1) {
tmp[new_len] = ' ';
tmp[++new_len] = '\0';
tmp += new_len - old_len;
}
}
}
bool
LibFrontReader::data_at_end()
{
bool at_end = false;
//-these need two strings
if ( flags->readingFileName || flags->readingProcedureName) {
if (nofEntries == 2)
at_end = true;
//-if data end is marked with "End"
} else if ( flags->readingEndMarkedData ) {
//if ( next_is_text("end") )
if ( next_is_end_keyword() )
at_end = true;
//-if there is not following a string starting with quote
} else if ( !flags->readingEndMarkedData &&
flags->readingNonSizedData
) {
if ( !next_is_text("\"") )
at_end = true;
//-otherwise dimensions define data size
// and it is always read to the end
} else {
at_end = true;
}
return at_end;
}
void
LibFrontReader::delete_data_buffer()
{
if (dataBuffer == NULL)
return;
switch (dataBufferType) {
case LibFront::EMF_INTEGER:
case LibFront::EMF_LOGICAL:
delete[] (int*)dataBuffer;
break;
case LibFront::EMF_REAL:
delete[] (double*)dataBuffer;
break;
case LibFront::EMF_STRING:
case LibFront::EMF_FILE:
delete[] (char*)dataBuffer;
break;
}
dataBuffer = NULL;
dataBufferSize = 0;
}
void
LibFrontReader::delete_variable_buffer()
{
if (variableBuffer == NULL)
return;
switch (dataBufferType) {
case LibFront::EMF_REAL:
delete[] (double*)variableBuffer;
break;
case LibFront::EMF_STRING:
delete[] (char*)variableBuffer;
break;
}
variableBuffer = NULL;
variableBufferSize = 0;
}
// Evalute a source buffer containing possible Matc-expressions.
// Copy source buffer and all evaluated results into result-buffer
//
// NOTE: No $-sign accepted
//
bool
LibFrontReader::evalMatcBuffer(char* source)
{
char matc_buffer[10001];
int source_pos = 0;
int source_len = strlen(source);
// Read source buffer till end
//
while (source_pos < source_len ) {
// Read expression and set new source-pos just after the expression
//
source_pos = LibFront::readMatcExpression(source, source_pos, source_len,
matc_buffer, 10000);
LibFront::trim(matc_buffer);
if ( matc_buffer[0] == '\0' ) continue;
// Evaluate the Matc-expression
//
char* matc_result = mtc_domath(matc_buffer);
// An empty result
if ( matc_result == NULL || matc_result[0] == '\0' ) continue;
// Matc Error
if ( LibFront::isMatcError(matc_result) ) {
strstream strm, strm2;
strm << "***WARNING: Matc evaluation error (" << matc_buffer << ")!" << ends;
sendMessage(strm.str());
strm2 << matc_result<< ends;
sendMessage(strm2.str());
continue;
}
}
return true;
}
int
LibFrontReader::evalAndInsertNextMatc()
{
readBufferPos = LibFront::readMatcExpression(readBuffer, readBufferPos, readBufferLen,
matcBuffer, 10000);
// WARNING: Matc definitions are not stored in the egf file, so a warning is in place!
//
if ( LibFront::isMatcDefinition(matcBuffer) && !matcDefsWarned ) {
strstream strm;
strm << "***WARNING: Matc definitions are not recommended in the egf-file! (" << matcBuffer << ")" << ends;
if ( 1 == sendMessage(strm.str()) ) {
matcDefsWarned = true;
}
}
char* matc_result = mtc_domath(matcBuffer);
if ( matc_result == NULL || matc_result[0] == '\0' ) return 0;
// Matc error
if ( LibFront::isMatcError(matc_result) ) {
// NOTE Tcl does not like [] !!!
for(int i = 0; i < strlen(matc_result); i++) {
if ( matc_result[i] == '[' ) matc_result[i] = ' ';
if ( matc_result[i] == ']' ) matc_result[i] = ' ';
}
if ( matc_result != NULL ) {
sendMessage(matc_result);
sendMessage(matcBuffer);
}
return -1;
}
LibFront::trim(matc_result);
// Insert matc-expression
int eof_insert = insertReadBuffer(matc_result);
// If something was inserted, update eval-end-position
if ( eof_insert > 0 ) {
evaluatedBufferEnd = eof_insert;
}
storeDataAsString(matcBuffer, true);
if ( LibFront::hasMatcVariables(matcBuffer) ) {
dataHasMatcVars = true;
}
return strlen(matcBuffer);
}
void
LibFrontReader::evalAndSkipNextMatc()
{
readBufferPos = LibFront::readMatcExpression(readBuffer, readBufferPos, readBufferLen,
matcBuffer, 10000);
// WARNING: Matc definitions are not stored nowhere if in the body of an egf file!
if ( LibFront::isMatcDefinition(matcBuffer) && !matcDefsWarned ) {
strstream strm;
strm << "***WARNING: Matc definitions are not recommended in the egf-file! (" << matcBuffer << ")" << ends;
if ( 1 == sendMessage(strm.str()) ) {
matcDefsWarned = true;
}
}
char* matc_result = mtc_domath(matcBuffer);
}
bool
LibFrontReader::extractSeparator(char sep)
{
bufferEatWs();
if (bufferAtEnd())
return false;
char c = readBuffer[readBufferPos];
if ( c != sep ) {
return false;
}
else {
readBufferPos++;
return true;
}
}
bool
LibFrontReader::getNextNumber(int& number)
{
return getNextNumber_impl(number);
}
bool
LibFrontReader::getNextNumber(double& number)
{
return getNextNumber_impl(number);
}
template <class T> bool
LibFrontReader::getNextNumber_impl(T& number)
{
if (bufferAtEnd()) {
return false;
}
getNextToken(tokenBuffer);
strstream strm;
strm << tokenBuffer;
return ( strm >> number );
}
// Basic version without any flag arguments
//
int
LibFrontReader::getNextToken(char* buffer)
{
if (bufferAtEnd()) {
return 0;
}
bool store_as_string = true;
if ( !flags->readingFieldData ||
( flags->hasEvaluatedBuffer &&
evaluatedBufferEnd >= readBufferPos
)
) {
store_as_string = false;
}
// A Matc-expression in the input
//
if ( readBuffer[readBufferPos] == matcSeparator ) {
readBufferPos++;
// Evaluate and insert the possible result
//
if ( flags->readingFieldData ) {
int ec = evalAndInsertNextMatc();
// Something as a result
if ( ec > 0 ) {
flags->hasEvaluatedBuffer = true;
// Error, not a definition, but however no result value!
} else if ( ec < 0 ) {
return -1;
}
// Evaluate, but do not insert the possible result
//
} else {
evalAndSkipNextMatc();
}
bufferEatWs();
return getNextToken(buffer);
}
if ( readBuffer[readBufferPos] == stringSeparator ) {
readBufferPos++;
return getToSeparator(buffer, stringSeparator );
}
flags->nonSizedDataAtEnd = false;
buffer[0] = '\0';
int counter = 0;
// Find next token separator
//
while ( checkReadBuffer() ) {
char c = readBuffer[readBufferPos];
// These stop reading (ws + nl + equal sign + $)
if ( c == ' ' ||
c == '\t' ||
c == '\n' ||
c == '=' ||
c == matcSeparator
) {
break;
}
readBufferPos++;
buffer[counter++] = c;
}
// Clean ws from readBuffer
bufferEatWs();
buffer[counter] = '\0';
if ( store_as_string ) {
storeDataAsString(buffer);
}
return strlen(buffer);
}
// NOTE: Checks also if a newline or an equal sign was
// after the token
//
// NOTE: This version inserts only non-data related field items (names etc.) into
// readBuffer, field data related expression are inserted by the 'plain' getNextToken-function
//
// It also evaluates 'loose' Matc-expressions between fields!
//
// It is meant mainly for peeking tokens in the input!
//
int
LibFrontReader::getNextToken(char* buffer, bool& eq_found, bool& nl_found, bool& matc_found)
{
static char matc_buffer[10001];
if (bufferAtEnd()) {
eq_found = false;
nl_found = true;
matc_found = false;
return 0;
}
if ( readBuffer[readBufferPos] == matcSeparator ) {
readBufferPos++;
readBufferPos = LibFront::readMatcExpression(readBuffer, readBufferPos, readBufferLen, matc_buffer, 10000);
char* matc_result = mtc_domath(matc_buffer);
if ( matc_result != NULL && matc_result[0] != '\0' ) {
strstream strm;
strm << matc_result << ends;
strm >> buffer;
matc_found = true;
return strlen(buffer);
} else {
bufferEatWs();
return getNextToken(buffer, eq_found, nl_found, matc_found);
}
}
if ( readBuffer[readBufferPos] == stringSeparator ) {
readBufferPos++;
return getToSeparator(buffer, stringSeparator );
}
flags->nonSizedDataAtEnd = false;
buffer[0] = '\0';
int counter = 0;
// Find next token separator
//
while ( checkReadBuffer() ) {
char c = readBuffer[readBufferPos];
// These stop reading (ws + nl + equal sign + $)
if ( c == ' ' ||
c == '\t' ||
c == '\n' ||
c == '=' ||
c == matcSeparator
) {
matc_found = ( c == matcSeparator );
break;
}
readBufferPos++;
buffer[counter++] = c;
}
// Clean ws from readBuffer
bufferEatWs(eq_found, nl_found);
buffer[counter] = '\0';
return strlen(buffer);
}
int
LibFrontReader::getToSeparator(char* buffer, char sep)
{
buffer[0] = '\0';
if (bufferAtEnd())
return 0;
bool store_as_string = true;
if ( !flags->readingFieldData ||
( flags->hasEvaluatedBuffer &&
evaluatedBufferEnd >= readBufferPos
)
) {
store_as_string = false;
}
flags->nonSizedDataAtEnd = false;
int counter = 0;
while ( checkReadBuffer() ) {
char c = readBuffer[readBufferPos++];
if ( c == sep )
break;
buffer[counter++] = c;
}
bufferEatWs();
buffer[counter] = '\0';
if ( store_as_string ) {
storeDataAsString(buffer);
}
return strlen(buffer);
}
bool
LibFrontReader::handleEol()
{
flags->nonSizedDataAtEnd = true;
//readBufferPos++;
return true;
}
void
LibFrontReader::init_transfer_info()
{
LibFront::isLogicalData = false;
LibFront::isIntegerData = false;
LibFront::isRealData = false;
LibFront::isStringData = false;
LibFront::isFileData = false;
LibFront::isVoidData = false;
LibFront::logicalData = NULL;
LibFront::integerData = NULL;
LibFront::realData = NULL;
LibFront::stringData = NULL;
LibFront::voidData = NULL;
LibFront::dimension1 = 0;
LibFront::dimension2 = 0;
LibFront::dataLengths = NULL;
LibFront::isRealVariable = false;
LibFront::isStringVariable = false;
LibFront::isVoidVariable = false;
LibFront::realVariable = NULL;
LibFront::stringVariable = NULL;
LibFront::variableValuesLengths = NULL;
}
// Insert new data into readBuffer
// This is typically used to insert an evaluated Matc-epxerssion
// into input buffer
//
// Return: end-of-insert position or -1 if nothing was inserted
//
int
LibFrontReader::insertReadBuffer(char* data)
{
int eof_insert = -1;
if ( data == NULL || data[0] == '\0' ) return eof_insert;
int data_len = strlen(data);
eof_insert = readBufferPos + data_len;
// Allocate more space for the new read buffer
char* tmp = new char[readBufferLen + data_len];
int i;
//-Copy old leading data
for (i = 0; i < readBufferPos; i++) {
tmp[i] = readBuffer[i];
}
//-Insert new data
for (i = 0; i < data_len; i++) {
tmp[readBufferPos + i] = data[i];
}
//-Copy old trailing data
for (i = readBufferPos; i < readBufferLen; i++) {
tmp[data_len + i] = readBuffer[i];
}
// Update readBuffer
delete[] readBuffer;
readBuffer = tmp;
readBufferLen += data_len;
return eof_insert;
}
bool
LibFrontReader::is_end_keyword(char* str)
{
LibFront::toLower(str);
if ( 0 == strcmp(str, "end") )
return true;
else
return false;
}
bool
LibFrontReader::is_file_keyword(char* str)
{
if ( 0 == strcmp(str, "file") )
return true;
else
return false;
}
bool
LibFrontReader::is_keyword(char* str)
{
LibFront::toLower(str);
if ( is_size_keyword(str) ||
is_type_keyword(str) ||
is_variable_keyword(str)
)
return true;
else
return false;
}
bool
LibFrontReader::is_number(char* str)
{
if ( str == NULL || str[0] == '\0' ) return false;
return LibFront::isNumber(str);
}
bool
LibFrontReader::is_procedure_keyword(char* str)
{
if ( 0 == strcmp(str, "procedure") )
return true;
else
return false;
}
bool
LibFrontReader::is_separated_string()
{
char c = inputFile.peek();
if ( c == '\"' ) return true;
return false;
}
bool
LibFrontReader::is_size_keyword(char* str)
{
LibFront::toLower(str);
if ( 0 == strcmp(str, "size") )
return true;
else
return false;
}
bool
LibFrontReader::is_type_keyword(char* str)
{
LibFront::toLower(str);
if ( 0 == strcmp(str, "integer") ||
0 == strcmp(str, "real") ||
0 == strcmp(str, "logical") ||
0 == strcmp(str, "string") ||
0 == strcmp(str, "file") ||
0 == strcmp(str, "procedure")
)
return true;
else
return false;
}
bool
LibFrontReader::is_variable_keyword(char* str)
{
LibFront::toLower(str);
if ( 0 == strcmp(str, "variable") )
return true;
else
return false;
}
// NOTE: End keyword must be the last token in the line!!!
//
bool
LibFrontReader::next_is_end_keyword()
{
static char peek_buffer[emf_MAX_STRING_LEN];
if ( !peek_token(peek_buffer) ||
!(flags->newlinePeeked && !flags->equalSignPeeked)
) {
return false;
}
LibFront::toLower(peek_buffer);
if ( is_end_keyword(peek_buffer) )
return true;
else
return false;
}
bool
LibFrontReader::next_is_group_names()
{
static char peek_buffer[emf_MAX_STRING_LEN];
if ( !peek_token(peek_buffer) ) {
return false;
}
if ( peek_buffer[0] == '[' ) {
return true;
} else {
return false;
}
}
bool
LibFrontReader::next_is_keyword()
{
static char peek_buffer[emf_MAX_STRING_LEN];
if ( next_is_end_keyword() ) return true;
if ( !peek_token(peek_buffer) ) {
return false;
}
LibFront::toLower(peek_buffer);
if ( is_keyword(peek_buffer) ) {
return true;
} else {
return false;
}
}
bool
LibFrontReader::next_is_matc()
{
if (bufferAtEnd()) return false;
push_flags();
int old_pos = readBufferPos;
bufferEatWs();
char c = readBuffer[readBufferPos];
readBufferPos = old_pos;
pop_flags();
if ( c == matcSeparator )
return true;
else
return false;
}
bool
LibFrontReader::next_is_number()
{
static char buffer[emf_MAX_STRING_LEN];
if ( !peek_token(buffer) ) return false;
return is_number(buffer);
}
bool
LibFrontReader::next_is_separated_string()
{
if (bufferAtEnd()) return false;
push_flags();
int old_pos = readBufferPos;
bufferEatWs();
char c = readBuffer[readBufferPos];
readBufferPos = old_pos;
pop_flags();
if ( c == stringSeparator )
return true;
else
return false;
}
bool
LibFrontReader::next_is_size_keyword()
{
static char peek_buffer[emf_MAX_STRING_LEN];
if ( !peek_token(peek_buffer) )
return false;
LibFront::toLower(peek_buffer);
if ( is_size_keyword(peek_buffer) )
return true;
else
return false;
}
bool
LibFrontReader::next_is_text(char* text)
{
static char buffer[emf_MAX_STRING_LEN];
if ( !peek_token(buffer) )
return false;
if ( LibFront::ncEqual(buffer, text) )
return true;
else
return false;
}
bool
LibFrontReader::next_is_type_keyword()
{
static char peek_buffer[emf_MAX_STRING_LEN];
if ( !peek_token(peek_buffer) )
return false;
LibFront::toLower(peek_buffer);
if ( is_type_keyword(peek_buffer) )
return true;
else
return false;
}
bool
LibFrontReader::next_is_variable_keyword()
{
static char peek_buffer[emf_MAX_STRING_LEN];
if ( !peek_token(peek_buffer) )
return false;
LibFront::toLower(peek_buffer);
if ( is_variable_keyword(peek_buffer) )
return true;
else
return false;
}
bool
LibFrontReader::next_non_number_is_data_keyword()
{
static char peek_buffer[emf_MAX_STRING_LEN];
if ( !peek_next_string(peek_buffer) )
return false;
LibFront::toLower(peek_buffer);
if ( is_size_keyword(peek_buffer) ||
is_type_keyword(peek_buffer) ||
is_variable_keyword(peek_buffer)
)
return true;
else
return false;
}
bool
LibFrontReader::next_non_number_is_keyword()
{
static char peek_buffer[emf_MAX_STRING_LEN];
if ( next_is_end_keyword() ) return true;
if ( !peek_next_string(peek_buffer) )
return false;
LibFront::toLower(peek_buffer);
if ( is_keyword(peek_buffer) )
return true;
else
return false;
}
bool
LibFrontReader::object_at_end()
{
if (bufferAtEnd())
return false;
if ( next_is_end_keyword() ) {
return true;
} else {
return false;
}
}
// Method checks the number of string tokens before possible TWO
// consecutive numeric tokens.
// NOTE: the total number of numeric tokens is not counted, it is
// enough to know if there is 0, 1 or >= 2 of them!!!
// NOTE: Keywords are accepted as name tokens! ==> a LINEFEED must
// be after the object/field name before a possible keyword!
bool
LibFrontReader::peek_field_name_tokens(int& nof_tokens)
{
nof_tokens = 0;
bool nl_found = false;
bool eq_found = false;
bool mc_found = false;
push_flags();
int old_pos = readBufferPos;
flags->nonSizedDataAtEnd = false;
int nof_picked_tokens = 0;
int nof_name_tokens = 0;
bool next_found = false;
bool tmp = flags->readingFieldData;
flags->readingFieldData = false;
// Read all tokens in the line
while( !bufferAtEnd() && !flags->nonSizedDataAtEnd ) {
if ( next_is_separated_string() ) {
flags->readingNonSizedData = true;
break;
}
// Try to read next token
next_found = ( 0 != getNextToken(tokenBuffer, eq_found, nl_found, mc_found));
// If data at end or next starst with matc-$ sign, field name must end
if ( !next_found || mc_found ) {
break;
}
if ( next_found ) {
nof_picked_tokens++;
}
// If next still was text, add to the field name
//
if ( next_found && !is_number(tokenBuffer) ) {
nof_name_tokens = nof_picked_tokens;
}
// If an equal sign was found, field name must end
if ( eq_found ) {
break;
}
} // while
flags->readingFieldData = tmp;
// If next is keyword, all picked tokens belong to field name!
if ( next_is_keyword() && !next_is_end_keyword() ) {
nof_tokens = nof_picked_tokens;
} else {
nof_tokens = nof_name_tokens;
}
readBufferPos = old_pos;
pop_flags();
return true;
}
// Peeks first "real" string token in readStream, so all numbers are first skipped
bool
LibFrontReader::peek_next_string(char* buffer)
{
buffer[0] = '\0';
if (bufferAtEnd()) {
return false;
}
push_flags();
int old_pos = readBufferPos;
bool tmp = flags->readingFieldData;
flags->readingFieldData = false;
// Skip numbers
double test_number;
while (!bufferAtEnd()) {
getNextToken(tokenBuffer);
strstream strm;
strm << tokenBuffer;
if ( !(strm >> test_number) ) {
break;
}
}
flags->readingFieldData = tmp;
strcpy(buffer, tokenBuffer);
readBufferPos = old_pos;
pop_flags();
if ( strlen(buffer) == 0 ) {
return false;
} else {
return true;
}
}
// Method checks the number of string tokens before possible TWO
// consecutive numeric tokens.
// NOTE: the total number of numeric tokens is not counted, it is
// enough to know if there is 0, 1 or >= 2 of them!!!
// NOTE: Keywords are accepted as name tokens! ==> a LINEFEED must
// be after the object/field name before a possible keyword!
bool
LibFrontReader::peek_object_name_tokens(int& nof_tokens)
{
nof_tokens = 0;
push_flags();
int old_pos = readBufferPos;
flags->nonSizedDataAtEnd = false;
int nof_picked_tokens = 0;
int nof_consecutive_nbr_tokens = 0;
bool tmp = flags->readingFieldData;
flags->readingFieldData = false;
while( !bufferAtEnd() && !flags->nonSizedDataAtEnd ) {
// No separated strings accepted in object name
if ( next_is_separated_string() ) {
return false;
}
getNextToken(tokenBuffer);
nof_picked_tokens++;
// Include keyword is a bit exceptional!!!
//
if ( nof_picked_tokens == 1 && LibFront::in(tokenBuffer, "Include") ) {
break;
}
if ( is_number(tokenBuffer) ) {
nof_consecutive_nbr_tokens++;
} else {
nof_consecutive_nbr_tokens = 0;
}
// Only one number accepted after object name (object id)
if ( nof_consecutive_nbr_tokens > 1 ) {
return false;
}
} // while
flags->readingFieldData = tmp;
nof_tokens = nof_picked_tokens - nof_consecutive_nbr_tokens;
readBufferPos = old_pos;
pop_flags();
return true;
}
// Peeks next token in the readBuffer
// NOTE: Checks also if an equal sign or a newline was ahed
//
bool
LibFrontReader::peek_token(char* buffer)
{
bool eq_found = false;
bool nl_found = false;
bool mc_found = false;
flags->equalSignPeeked = eq_found;
flags->newlinePeeked = nl_found;
flags->matcPeeked = mc_found;
buffer[0] = '\0';
if (bufferAtEnd()) {
return false;
}
push_flags();
int old_pos = readBufferPos;
bool tmp = flags->readingFieldData;
flags->readingFieldData = false;
getNextToken(buffer, eq_found, nl_found, mc_found);
flags->readingFieldData = tmp;
readBufferPos = old_pos;
pop_flags();
flags->equalSignPeeked = eq_found;
flags->newlinePeeked = nl_found;
flags->matcPeeked = mc_found;
if ( strlen(buffer) == 0 ) {
return false;
} else {
return true;
}
}
void
LibFrontReader::pop_flags()
{
currentFlagsIndex--;
flags = &flagsStack[currentFlagsIndex];
}
void
LibFrontReader::push_flags(bool copy_current)
{
currentFlagsIndex++;
if (copy_current)
flagsStack[currentFlagsIndex].copy(flagsStack[currentFlagsIndex - 1]);
else
flagsStack[currentFlagsIndex].init();
flags = &flagsStack[currentFlagsIndex];
}
// Read data in the entry
bool
LibFrontReader::read_entry_data(struct emf_ObjectData_X* od,
int data_alloc_count, int data_size,
int& read_count)
{
// Buffer sizes
int old_data_buffer_size, new_data_buffer_size;
// Extra size allocated for this entry
int data_alloc_size;
data_alloc_size = data_alloc_count * data_size;
old_data_buffer_size = dataBufferSize;
new_data_buffer_size = dataBufferSize + data_alloc_size;
allocate_data_buffer(old_data_buffer_size, new_data_buffer_size);
currentBuffer = dataBuffer;
currentBufferSize = dataBufferSize;
currentBufferType = dataBufferType;
int* read_sizes = new int[data_alloc_count];
// Read values
if ( !read_entry_data_values(old_data_buffer_size, new_data_buffer_size,
data_alloc_count, read_sizes, read_count)
) {
// If no succes: ERROR MSG!
sendMessage("\n");
sendMessage("*** ERROR ***: When reading data for:");
//-- Object name FieldName
{
strstream strm;
strm << "OBJECT: " << od->object_name;
if (od->object_id != -1) {
strm << " " << od->object_id;
}
strm << " FIELD: " << od->field_name;
strm << ends;
sendMessage(strm.str());
}
//--Size info
{
strstream strm;
strm << "Expected size: " << data_alloc_size;
strm << " Actual size: " << read_count;
strm << ends;
sendMessage(strm.str());
}
sendMessage("\n");
return false;
}
#if 0
// Debugging
cerr << endl;
cerr << "Object: " << od->object_name;
if (od->object_id != -1)
cerr << " " << od->object_id;
cerr << endl;
cerr << "Field: " << od->field_name << endl;
cerr << "Datatype: " << od->data_type << endl;
cerr << "Data: ";
output_data(cerr, od->data_type, od->data);
cerr << "Buffer: " << readBuffer << endl;
cerr << "Is sep string: " << isSeparatedStrings << endl;
#endif
nofDataValues += read_count;
int data_read_size = 0;
// Actual total size of the read data
for (int i = 0; i < read_count; i++)
data_read_size += read_sizes[i];
// Remove possible extra DATA entry space (relevant for string data!)
if ( data_read_size < data_alloc_size ) {
new_data_buffer_size += data_read_size - data_alloc_size;
allocate_data_buffer(new_data_buffer_size, new_data_buffer_size);
}
update_data_lengths(read_count, read_sizes);
delete[] read_sizes;
if (bufferAtEnd()) {
return false;
}
return true;
}
bool
LibFrontReader::read_entry_data_values(int old_data_buffer_size, int new_data_buffer_size, int data_count,
int* data_sizes, int& read_count)
{
if (data_count == 0) {
read_count = 0;
return true;
}
// Default data value sizes (for logical and numeric data)
for (int i = 0; i < data_count; i++)
data_sizes[i] = 1;
// Character data
if ( flags->readingProcedureName ||
currentBufferType == LibFront::EMF_STRING ||
currentBufferType == LibFront::EMF_FILE
) {
if ( !read_string_data(old_data_buffer_size, new_data_buffer_size, data_count,
data_sizes, read_count)
) {
return false;
}
// Logical data
} else if ( currentBufferType == LibFront::EMF_LOGICAL ) {
if ( !read_logical_data(old_data_buffer_size, new_data_buffer_size, read_count) ) {
return false;
}
// Numeric data
} else {
if ( !read_numeric_data(old_data_buffer_size, new_data_buffer_size, read_count) ) {
return false;
}
}
return true;
}
// Read variables in the entry
bool
LibFrontReader::read_entry_variables(struct emf_ObjectData_X* od,
int var_alloc_count, int var_size)
{
// Buffer sizes
int old_var_buffer_size, new_var_buffer_size;
// Extra size allocated for this entry
int var_alloc_size;
// Actual nof of read values
int var_read_count;
var_alloc_size = var_alloc_count * var_size;
old_var_buffer_size = variableBufferSize;
new_var_buffer_size = variableBufferSize + var_alloc_size;
allocate_variable_buffer(old_var_buffer_size, new_var_buffer_size);
currentBuffer = variableBuffer;
currentBufferSize = variableBufferSize;
currentBufferType = variableBufferType;
// Sizes of the actually read values (normally 1, but string length for string data)
int* read_sizes = new int[var_alloc_count];
if ( !read_entry_variable_values(old_var_buffer_size, new_var_buffer_size,
var_alloc_count, read_sizes, var_read_count)
) {
// If no succes: ERROR MSG!
sendMessage("\n");
sendMessage("*** ERROR ***: When reading variable data for:");
//--Object name, Field name
{
strstream strm;
strm << "OBJECT: " << od->object_name;
if (od->object_id != -1) {
strm << " " << od->object_id;
}
strm << " FIELD: " << od->field_name;
strm << ends;
sendMessage(strm.str());
}
// Size info
{
strstream strm;
strm << "Expected size: " << var_alloc_size;
strm << " Actual size: " << var_read_count;
strm << ends;
sendMessage(strm.str());
}
sendMessage("\n");
return false;
} else {
#if 0
// Debugging
cerr << endl;
cerr << "Object: " << od->object_name;
if (od->object_id != -1)
cerr << " " << od->object_id;
cerr << endl;
cerr << "Field: " << od->field_name << endl;
cerr << "Datatype: " << od->data_type << endl;
cerr << "Data: ";
output_data(cerr, od->data_type, od->data);
cerr << "Buffer: " << readBuffer << endl;
cerr << "Hanging sep string: " << hangingSeparatedString << endl;
cerr << "Contains sep string: " << containsSeparatedStrings << endl;
#endif
}
nofVariableValues += var_read_count;
int var_read_size = 0;
// Actual total size of the read variable values
for (int i = 0; i < var_read_count; i++)
var_read_size += read_sizes[i];
// Remove possible extra VARIABLE value space (relevant for name variables!)
if ( var_read_size < var_alloc_size ) {
new_var_buffer_size += var_read_size - var_alloc_size;
allocate_variable_buffer(new_var_buffer_size, new_var_buffer_size);
}
update_variable_lengths(var_read_count, read_sizes);
return true;
}
bool
LibFrontReader::read_entry_variable_values(int old_var_buffer_size, int new_var_buffer_size, int var_count,
int* var_sizes, int& read_count)
{
if (var_count == 0) {
read_count = 0;
return true;
}
// Default variable value sizes (for numeric data)
for (int i = 0; i < var_count; i++)
var_sizes[i] = 1;
// Character variable values (a name string!)
if ( currentBufferType == LibFront::EMF_STRING ) {
if ( !read_string_data(old_var_buffer_size, new_var_buffer_size, var_count,
var_sizes, read_count) ) {
return false;
}
// Numeric data
} else {
if ( !read_numeric_data(old_var_buffer_size, new_var_buffer_size, read_count) ) {
return false;
}
}
return true;
}
// Read field name (optional) and data entries
//
bool
LibFrontReader::read_field(struct emf_ObjectData_X* od)
{
static char peek_buffer[emf_MAX_STRING_LEN];
flags->endsField = false;
flags->readingNonSizedData = false;
bool size_given, type_given, variable_given;
if ( flags->startsNewField ) {
dimension1 = 1;
dimension2 = 1;
nofEntries = 0;
nofVariables = 0;
od->field_name[0] = '\0';
od->is_procedure = false;
//---Read field name. NOTE: In some cases name is not needed!
if (! read_field_name(od, od->field_name, emf_MAX_NAME_LEN) )
return false;
od->field_name_length = strlen(od->field_name);
flags->startsNewField = false;
// If there were group names (like [A B C] ) after field name
if ( flags->readingGroupNames )
read_group_names(od);
}
// All field data have been read
if ( flags->endsField ) {
flags->endsField = false;
return true;
}
//---Check if Variable-keyword is given
if (bufferAtEnd())
return false;
variable_given = false;
if ( next_is_variable_keyword() ) {
getNextToken(tokenBuffer);
variable_given = true;
}
//---If Variable given, read variable names
// NOTE: Read until the Size-keyword or a Type keyword comes!
if (variable_given) {
while (1) {
if (bufferAtEnd())
return false;
if (next_is_type_keyword() || next_is_size_keyword() )
break;
getNextToken(od->variable_names[nofVariables]);
od->variable_name_lengths[nofVariables] = strlen(od->variable_names[nofVariables]);
nofVariables++;
if (nofVariables > emf_MAX_NOF_VARIABLES)
return false;
}
}
if ( variable_given && nofVariables == 0 )
return false;
//---Check if Size-keyword is given
if (bufferAtEnd())
return false;
size_given = false;
if ( next_is_size_keyword() ) {
getNextToken(tokenBuffer);
size_given = true;
}
if (bufferAtEnd())
return false;
//---If Size given, read dimensions
if (size_given) {
getNextNumber(dimension1);
// If second (column) dimension is given
// read it from the stream
int test_nbr;
if ( try_to_read(test_nbr) ) {
getNextNumber(dimension2);
}
}
// NOTE: When variable is given, data rows are ended
// by the "end" mark and Size-parameters tell the size of
// the data entry rows!!!
if ( nofVariables > 0 ) flags->readingEndMarkedData = true;
//---Check data type keyword
if (bufferAtEnd()) return false;
type_given = false;
if ( next_is_type_keyword() ) type_given = true;
if ( size_given &&
!type_given
) {
// ERROR MSG
strstream strm;
strm << "UNKNOWN DATA TYPE: " << peek_buffer << ends;
sendMessage(strm.str());
sendMessage("\n");
return false;
}
//---If field-name is not yet resolved
if ( flags->hangingFieldNameNumber ) {
flags->hangingFieldNameNumber = false;
// Hanging number belongs to the field name
if (type_given) {
strstream strm;
strm << od->field_name << ' ' << (int)hangingNumber << ends;
strm >> od->field_name;
od->field_name_length = strlen(od->field_name);
// We had one single data value
} else {
return storeNumber(od, LibFront::EMF_REAL, &hangingNumber);
}
}
//---Read possible data type
if (type_given) {
getNextToken(od->data_type);
LibFront::toLower(od->data_type);
od->data_type_length = strlen(od->data_type);
if ( 0 == strcmp(od->data_type, "procedure") ) {
od->is_procedure = true;
}
}
//---Check if we have a procedure definition (for int,real
// data types
bool read_procedure = false;
if (bufferAtEnd()) return false;
if ( peek_token(peek_buffer) ) {
LibFront::toLower(peek_buffer);
read_procedure = is_procedure_keyword(peek_buffer);
}
//---Set possible data type
if (type_given) {
// integer
if ( 0 == strcmp(od->data_type, "integer") ) {
dataBufferType = LibFront::EMF_INTEGER;
flags->readingProcedureName = read_procedure;
// real
} else if ( 0 == strcmp(od->data_type, "real") ) {
dataBufferType = LibFront::EMF_REAL;
flags->readingProcedureName = read_procedure;
// logical
} else if ( 0 == strcmp(od->data_type, "logical") ) {
dataBufferType = LibFront::EMF_LOGICAL;
flags->readingProcedureName = read_procedure;
// string
} else if ( 0 == strcmp(od->data_type, "string") ) {
dataBufferType = LibFront::EMF_STRING;
flags->readingProcedureName = read_procedure;
// file name
} else if ( 0 == strcmp(od->data_type, "file") ) {
dataBufferType = LibFront::EMF_FILE;
flags->readingFileName = true;
// unknown --> string
} else {
dataBufferType = LibFront::EMF_STRING;
strcpy(od->data_type, "string");
}
}
// Reading field data
// ==================
flags->readingFieldData = true;
dataAsStringBuffer[0] = '\0';
dataAsStringPos = 0;
//---Non-sized data
if (!size_given) {
return read_field_data_non_sized(od, type_given);
}
//---Sized data
od->dimension1 = dimension1;
od->dimension2 = dimension2;
od->nof_variables = nofVariables;
// Default sizes for variable value and data parts
// in the entry row
int var_count = nofVariables;
int var_size = 1;
int data_count = (dimension1 * dimension2);
int data_size = 1;
// Set size info for these data types
if ( 0 == strcmp(od->data_type, "string") ||
0 == strcmp(od->data_type, "file")
) {
data_size = readBufferLen; // we do not know the string size in advance!
}
int read_count = 0;
return read_field_data_sized(od, var_count, var_size, data_count, data_size, read_count);
}
// Read LOOP, read variables and data in the entries
// *_count arguments tell the number of varaible values and data values
// *_size arguments tell the size to allocated for theses values
// NOTE: size is normally 1, but for strings it is the text buffer length
// and this size must be updated when the value is read, because we
// do not know the size in advance!
bool
LibFrontReader::read_field_data_sized(struct emf_ObjectData_X* od,
int var_alloc_count, int var_size,
int data_alloc_count, int data_size,
int& read_count)
{
nofDataValues = 0;
nofEntries = 0;
nofVariableValues = 0;
// Check variable value types (NOTE: Real or String currently!)
if ( nofVariables > 0 ) {
if ( next_is_number() ) {
variableBufferType = LibFront::EMF_REAL;
strcpy(od->variable_type, "real");
od->variable_type_length = strlen(od->variable_type);
} else {
variableBufferType = LibFront::EMF_STRING;
strcpy(od->variable_type, "string");
od->variable_type_length = strlen(od->variable_type);
var_size = readBufferLen;
}
}
delete_data_buffer();
delete_variable_buffer();
// Read LOOP
while (1) {
nofEntries++;
// Read possible variable values
if ( nofVariables > 0) {
if (bufferAtEnd()) {
return false;
}
read_entry_variables(od, var_alloc_count, var_size);
}
if (bufferAtEnd()) {
return false;
}
// Read data values
read_entry_data(od, data_alloc_count, data_size, read_count);
if (bufferAtEnd()) {
return false;
}
if (data_at_end()) {
flags->readingFieldData = false;
// Consume "End" mark for the data
if ( flags->readingEndMarkedData ) {
getNextToken(tokenBuffer);
flags->readingEndMarkedData = false;
}
break;
}
}
// Update transfer data
od->data = dataBuffer;
od->data_length = dataBufferSize;
od->data_lengths = dataLengths;
if ( currentBufferType == LibFront::EMF_STRING ) {
od->nof_entries = read_count;
} else {
od->nof_entries = nofEntries;
}
od->variable_values = variableBuffer;
od->variable_values_length = variableBufferSize;
od->variable_values_lengths = variableLengths;
return true;
}
// Read "simple" data entries when Size,Type is not given
// data type is either Real (for numbers) or String
bool
LibFrontReader::read_field_data_non_sized(struct emf_ObjectData_X* od, bool type_given)
{
flags->readingNonSizedData = true;
flags->nonSizedDataAtEnd = false;
delete_data_buffer();
int data_count = 1024;
int data_size = 1;
od->dimension1 = 1;
od->dimension2 = 1;
od->nof_variables = 0;
if (!type_given) {
if ( next_is_number() ) {
dataBufferType = LibFront::EMF_REAL;
strcpy(od->data_type, "real");
}
else {
dataBufferType = LibFront::EMF_STRING;
strcpy(od->data_type, "string");
data_count = 10; // Max 10 strings per entry!
data_size = readBufferLen;
}
}
od->data_type_length = strlen(od->data_type);
int read_count = 0;
bool rc = read_field_data_sized(od, 0, 0, data_count, data_size, read_count);
od->dimension1 = od->data_length;
return rc;
}
bool
LibFrontReader::read_field_name(struct emf_ObjectData_X* od,
char* name_buffer, int buffer_len)
{
if (bufferAtEnd())
return false;
//-Check if End-keyword is given, then we have
// no field-name or data, just object and its data!!!
if ( next_is_end_keyword() ) {
flags->endsField = true;
return true;
}
//-Check if Type or Variable-keyword is given, then we have
// no field-name just object and data!!!
if ( next_is_type_keyword() || next_is_variable_keyword() ) {
return true;
}
//-We have to check if there is any number in the buffer
// to resolve the the "Fieldname 1" problem
int nbr_of_tokens = 0;
if ( !peek_field_name_tokens(nbr_of_tokens) )
return false;
constructStringFromTokens(name_buffer, nbr_of_tokens);
if ( name_buffer == NULL || name_buffer[0] == '\0' ) {
return false;
} else {
return true;
}
}
bool
LibFrontReader::read_group_names(struct emf_ObjectData_X* od)
{
if (bufferAtEnd())
return false;
char groups_buffer[1024];
char group_buffer[1024];
int len;
// Pick away group starting character '['
readBufferPos++;
// Read until next ']'
getToSeparator(groups_buffer, ']');
LibFront::trim(groups_buffer);
len = strlen(groups_buffer);
// Make input stream from the whole string between []
istrstream groups_strm(groups_buffer, len);
short group_index = 0;
// Split string by group "grouper" characeter ';'
while ( !groups_strm.eof() ) {
groups_strm.getline(group_buffer, 1024, ';');
LibFront::trim(group_buffer);
len = strlen(group_buffer);
// Make input stream from one group string between ';' characters
istrstream group_strm(group_buffer, len);
short name_index = 0;
while( !group_strm.eof() ) {
group_strm >> od->group_names[group_index][name_index];
od->group_name_lengths[group_index][name_index] =
strlen(od->group_names[group_index][name_index]);
od->nof_group_names[group_index] = ++name_index;
}
if (++group_index > emf_MAX_NOF_GROUPS)
break;
}
return true;
}
bool
LibFrontReader::read_logical_data(int start_pos, int max_pos, int& read_count)
{
static char buffer[emf_MAX_STRING_LEN];
int logical_value;
double numeric_value;
read_count = 0;
for (int i = start_pos; i < max_pos; i++) {
if (bufferAtEnd()) {
return false;
}
//---Read logical value
//-text True
if ( next_is_text("True") ) {
logical_value = 1;
getNextToken(buffer);
//-text False
} else if ( next_is_text("False") ) {
logical_value = 0;
getNextToken(buffer);
//-numeric (0/1) value
} else if ( next_is_number() ) {
getNextNumber(numeric_value);
if (numeric_value > 0)
logical_value = 1;
else
logical_value = 0;
//-ERROR
} else {
return false;
}
((int*)currentBuffer)[i] = logical_value;
read_count++;
} // for
return true;
}
bool
LibFrontReader::read_numeric_data(int start_pos, int max_pos, int& read_count)
{
read_count = 0;
for (int i = start_pos; i < max_pos; i++) {
if (bufferAtEnd()) {
return false;
}
if ( flags->readingNonSizedData ) {
if ( flags->nonSizedDataAtEnd || !next_is_number() )
return true;
}
switch (currentBufferType) {
case LibFront::EMF_INTEGER:
case LibFront::EMF_LOGICAL:
int int_number;
if ( !getNextNumber(int_number) ) {
return false;
}
((int*)currentBuffer)[i] = int_number;
break;
case LibFront::EMF_REAL:
// NonSized is always read as doubles and next non-number
// ends the data and we should not try to tread it!!!
// Normal Sized data should always succeed
double dbl_number;
if ( !getNextNumber(dbl_number) ) {
return false;
}
((double*)currentBuffer)[i] = dbl_number;
break;
} // switch
read_count++;
} // for
return true;
}
bool
LibFrontReader::read_object(struct emf_ObjectData_X* od)
{
//---Read object (section) name and a possible (id) number
// or a separated string (data like "string data")
od->object_name[0] = '\0';
od->object_id = -1;
if ( !read_object_name(od, od->object_name, emf_MAX_NAME_LEN) ) {
return false;
}
od->object_name_length = strlen(od->object_name);
//-If there were group names (like [A B C] ) after object name
if ( flags->readingGroupNames ) {
read_group_names(od);
}
#if 0
// For debbugging
cerr << od->object_name;
if (od->object_id != -1)
cerr << " " << od->object_id;
cerr << endl;
#endif
return true;
}
bool
LibFrontReader::read_object_name(struct emf_ObjectData_X* od,
char* name_buffer, int buffer_len)
{
if (next_is_separated_string()) {
return false;
}
int nbr_of_tokens;
if ( !peek_object_name_tokens(nbr_of_tokens) ) {
return false;
}
constructStringFromTokens(name_buffer, nbr_of_tokens);
// Remove white-space from the end of the string
LibFront::trimRight(name_buffer);
// Read possible id
if ( next_is_number() ) {
getNextNumber(od->object_id);
}
return true;
}
bool
LibFrontReader::read_string_data(int start_pos, int max_pos, int string_count,
int* string_sizes, int& read_count)
{
// Result will be put into currentBuffer
char* result_string = (char*)currentBuffer;
read_count = 0;
int string_pos = start_pos;
int string_pos_prev = start_pos;
for (int i = 0; i < string_count; i++) {
bufferEatWs();
if ( !checkReadBuffer() ) {
return false;
}
// New line (ie. lf without continuation mark)
// has stopped non-sized data reading!
if ( flags->readingNonSizedData &&
flags->nonSizedDataAtEnd
)
return true;
// Append next token to the result_string
char* buffer = result_string + string_pos;
if ( -1 == getNextToken(buffer) ) return false;
// Find current end position of the result
//
// NOTE: We will start writing from the NULL character, so
// string-pos must be on that character --> -1.
// If null charcaters are left in the buffer, they will
// truncate the data!
// BE CAREFUL WITH THIS!!!***!!!
//
string_pos = strlen(result_string) - 1;
// Remove white-space from the end of the string
//
// NOTE: This function just tells the position of the last
// non-ws character, it does NOT manipulate the string itself!!!
//
LibFront::trimRight(result_string, start_pos, string_pos);
// This many was actually put into array
int string_size = 1 + string_pos - string_pos_prev;
string_sizes[i] = string_size;
string_pos++;
string_pos_prev = string_pos;
read_count++;
}
return true;
}
void
LibFrontReader::reset_flags()
{
flagsStack[currentFlagsIndex].init();
}
int
LibFrontReader::sendMessage(char* msg)
{
cerr << msg;
if (emf_readMessageCB == NULL || msgBuffer == NULL) return false;
strncpy(msgBuffer, msg, msgBufferSize);
return emf_readMessageCB(msgBuffer);
}
void
LibFrontReader::set_transfer_info()
{
struct emf_ObjectData_X* od = emf_ObjectData;
init_transfer_info();
// Data values
if ( LibFront::ncEqual(od->data_type, "logical") ) {
LibFront::logicalData = (int*) od->data;
LibFront::isLogicalData = true;
}
else if ( LibFront::ncEqual(od->data_type, "integer") ) {
LibFront::integerData = (int*) od->data;
LibFront::isIntegerData = true;
}
else if ( LibFront::ncEqual(od->data_type, "real") ) {
LibFront::realData = (double*) od->data;
LibFront::isRealData = true;
}
else if ( LibFront::ncEqual(od->data_type, "string") ) {
LibFront::stringData = (char*) od->data;
LibFront::isStringData = true;
}
else if ( LibFront::ncEqual(od->data_type, "file") ) {
LibFront::stringData = (char*) od->data;
LibFront::isFileData = true;
}
else {
LibFront::voidData = (void*) od->data;
LibFront::isVoidData = true;
}
LibFront::dimension1 = od->dimension1;
LibFront::dimension2 = od->dimension2;
LibFront::dataLengths = od->data_lengths;
// Variable values
if ( LibFront::ncEqual(od->variable_type, "real") ) {
LibFront::realVariable = (double*) od->variable_values;
LibFront::isRealVariable = true;
}
else if ( LibFront::ncEqual(od->variable_type, "string") ) {
LibFront::stringVariable = (char*) od->variable_values;
LibFront::isStringVariable = true;
}
else {
LibFront::voidVariable = (void*) od->variable_values;
LibFront::isVoidVariable = true;
}
LibFront::variableValuesLengths = od->variable_values_lengths;
}
bool
LibFrontReader::start()
{
struct emf_ObjectData_X* od = emf_ObjectData;
od->dataAsString = NULL;
od->dataHasMatcVars = 0;
init_transfer_info();
flags->startsNewObject = true;
for (int i = 0; i < emf_MAX_NOF_GROUPS; i++) {
od->nof_group_names[i] = 0;
}
bufferEatWs();
if (bufferAtEnd()) {
return false;
}
while ( !bufferAtEnd() ) {
//---New object is started
if ( flags->startsNewObject ) {
od->is_object_start = 1;
od->is_object_end = 0;
if ( !read_object(od) ) {
strstream strm;
strm << "***ERROR When reading object data for object: " << od->object_name << " " << od->object_id;
strm << ends;
sendMessage(strm.str());
sendMessage("\n");
return false;
}
flags->startsNewObject = false;
//---New field for the object
} else {
flags->startsNewField = true;
dataHasMatcVars = false;
if ( !read_field(od) ) {
strstream strm;
strm << "***ERROR When reading field data for object: " << od->object_name << " " << od->object_id;
strm << ". Reading field: " << od->field_name << ends;
sendMessage(strm.str());
sendMessage("\n");
return false;
}
dataAsStringBuffer[dataAsStringPos] = '\0';
flags->readingFieldData = false;
flags->hasEvaluatedBuffer = false;
if ( object_at_end() || LibFront::in(tokenBuffer, "Include") ) {
od->is_object_end = 1;
// Consume the possible object end marker "End"
if ( object_at_end() ) {
getNextToken(tokenBuffer);
}
flags->startsNewObject = true;
}
set_transfer_info();
// Send data after each field
delete[] od->dataAsString;
od->dataAsString = new char[1+dataAsStringPos];
strcpy(od->dataAsString, dataAsStringBuffer);
od->dataHasMatcVars = int(dataHasMatcVars);
int rc = sendData(userData);
// ERROR!!!
if ( rc != emf_OK ) {
return false;
}
od->is_object_start = 0;
// NOTE: Group data is "reset" after each send ==>
// If you want to read object-level group
// info, it must be done when "object-start = 1"!!!
for (int i = 0; i < emf_MAX_NOF_GROUPS; i++)
od-> nof_group_names[i] = 0;
}
flags->nonSizedDataAtEnd = false;
flags->hangingFieldNameNumber = false;
flags->readingNonSizedData = false;
flags->readingFileName = false;
flags->readingFieldData = false;
flags->readingGroupNames = false;
flags->readingProcedureName = false;
}
return true;
}
// Store field input data as a string.
// This is used to store Matc-expressions in input data etc.
//
void
LibFrontReader::storeDataAsString(const char* buffer, bool is_matc)
{
// Add a separator before new data
//
if ( dataAsStringPos > 0 ) {
dataAsStringBuffer[dataAsStringPos++] = ' ';
}
char* tmp = dataAsStringBuffer;
tmp += dataAsStringPos;
// Add $-sign in front of an Matc-expression, so it can be
// used later as an input data!!!
//
if ( is_matc ) {
strncpy(tmp, &matcSeparator, 1);
strcpy(tmp+1, buffer);
} else {
strcpy(tmp, buffer);
}
// Add new data
//
dataAsStringPos += strlen(tmp);
}
// Read one given number
bool
LibFrontReader::storeNumber(struct emf_ObjectData_X* od,
LibFront::dataValueType data_type,
void* data)
{
// Delete old buffer
delete_data_buffer();
// Allocate new with given type
dataBufferType = data_type;
allocate_data_buffer(dataBufferSize ,1);
nofEntries = 1;
nofDataValues = 1;
int data_sizes[1] = {1};
update_data_lengths(1, data_sizes);
switch (data_type) {
case LibFront::EMF_LOGICAL:
strcpy(od->data_type,"logical");
((int*)dataBuffer)[0] = *((int*)data);
break;
case LibFront::EMF_INTEGER:
strcpy(od->data_type, "integer");
((int*)dataBuffer)[0] = *((int*)data);
break;
case LibFront::EMF_REAL:
strcpy(od->data_type, "real");
((double*)dataBuffer)[0] = *((double*)data);
break;
}
od->data = dataBuffer;
od->data_length = dataBufferSize;
od->data_lengths = dataLengths;
od->nof_entries = nofEntries;
return true;
}
template <class T> bool
LibFrontReader::try_to_read(T& data)
{
if (bufferAtEnd()) {
return false;
}
push_flags();
int old_pos = readBufferPos;
bool rc = getNextNumber(data);
readBufferPos = old_pos;
pop_flags();
return rc;
}
bool
LibFrontReader::update_data_lengths(int data_count, int* data_sizes)
{
int old_nof_values = nofDataValues - data_count;
int* data_lengths = new int[nofDataValues];
int i;
for (i = 0; i < old_nof_values; i++)
// Copy old values
data_lengths[i] = dataLengths[i];
for (i = 0; i < data_count; i++)
// Add new values
data_lengths[old_nof_values + i] = data_sizes[i];
delete[] dataLengths;
dataLengths = data_lengths;
return true;
}
bool
LibFrontReader::update_variable_lengths(int var_count, int* var_sizes)
{
if (nofVariableValues == 0)
return true;
int old_nof_values = nofVariableValues - var_count;
int* var_lengths = new int[nofVariableValues];
int i;
// Copy old values
for (i = 0; i < old_nof_values; i++)
var_lengths[i] = variableLengths[i];
// Add new values
for (i = 0; i < var_count; i++)
var_lengths[old_nof_values + i] = var_sizes[i];
delete[] variableLengths;
variableLengths = var_lengths;
return true;
}
// =========================================================================
// END: LibFrontReader class implementation
// =========================================================================
syntax highlighted by Code2HTML, v. 0.9.1