#include <windows.h>
#include <ddeml.h>
#include <malloc.h> //fuer _memmax()
#include <string.h> //fuer memmove()
#include <stdlib.h> //fuer atof()
#define DLLMEX
#include "header\mex.h"
#include "header\fastdde.h"
#include "header\testargs.h" //fuer ErrorBeep()
#pragma hdrstop
/////////////////////////////////////////////////////////////////////////////////////////////////////
void GetMatrixSize( char huge* hDataString, DWORD* DataSize, int* rows, int* columns )
{
DWORD i = 0;
*rows = 0; //Initialwerte
*columns = 1; //Initialwerte
while ( hDataString[i++] && i < *DataSize )
{
if ( hDataString[i] == '\t' && *rows == 0 ) //Tabulatoren nur in der 1. Zeile der Matrix erfassen
(*columns)++; //und Anzahl der Spalten ermitteln
if ( hDataString[i] == '\r' ) //wenn Zeilenende, dann eine Zeile mehr
(*rows)++;
}
if (*rows == 0 && i > 1) (*rows)++; //mindestens eine Zeile, sonst leere Matrix
*DataSize = i; //tatsaechliche Groesse bis zur abschliessenden Null
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
BOOL Str2Double( double huge* dest, DWORD MatrixSize, char huge* hDataString, DWORD DataSize )
{
DWORD i,k,m;
i = k = m = 0;
BOOL result = TRUE;
char huge* pNextString = hDataString;
char strBuffer[100]; //es werden bis zu 100 Stellen (max. Wert fuer atof) fuer eine Zahl kopiert
while ( i < MatrixSize )
{
//Beginn der naechsten Zahl suchen
while ( m++ < DataSize )
{
if ( *pNextString == '\0' || *pNextString == '\t' )
{
pNextString++;
break;
}
if ( *pNextString == '\r' )
{
pNextString += 2;
m++;
break;
}
pNextString++;
}
if ( *hDataString == '\0' ) //wenn Daten fehlen
return FALSE;
if ( *hDataString == '\t' || *hDataString == '\r' )
{
dest[i] = 0;
result = FALSE;
}
else
{
//lokale Kopie, wegen atof() -huge-Zeigerproblem
hmemcpy( (char huge*) strBuffer, (char huge*) hDataString, min(sizeof(strBuffer), m - k) );
dest[i] = atof( strBuffer );
}
k = m;
hDataString = pNextString;
i++;
}
if (!result)
mexPrintf( "??? Possible empty element(s) of source matrix.\r\n" );
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
void Transpose( double huge* dest, double huge* src, UINT rows, UINT cols )
{
double huge* help;
// *** Matrix transponieren
if (cols < rows)
{ //Spalten-Schleife aussen
for ( UINT i = 0; i < cols; i++ )
{
help = src + (DWORD)i;
for ( UINT k = 0; k < rows; k++ )
{
hmemcpy( dest, help, sizeof(double) );
dest++;
help += (DWORD)cols;
}
}
} else { //Zeilen-Schleife aussen
for ( UINT k = 0; k < rows; k++ )
{
help = dest + (DWORD)k;
for ( UINT i = 0; i < cols; i++ )
{
hmemcpy( help, src, sizeof(double) );
src++;
help += (DWORD)rows;
}
}
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
void HandleDdeError(UINT DdeError)
{
static char szErr[31] = "??? DDEML: ";
static char *DdeE[] = {
"AdvAckTimeout" ,
"Busy" ,
"DataAckTimeout" ,
"Dll_Not_Initialized" ,
"Dll_Usage" ,
"ExecAckTimeout" ,
"InvalidParameter" ,
"Low Memory warning" ,
"Memory_Error" ,
"NotProcessed" ,
"No_Conv_Established" ,
"PokeAckTimeout" ,
"PostMsg_Failed" ,
"Reentrancy" ,
"Server_Died" ,
"Sys_Error" ,
"UnadvAckTimeout" ,
"Unfound_Queue_ID" ,
};
if (!DdeError) {
strcpy(&szErr[4], "0");
} else if (DdeError > DMLERR_LAST || DdeError < DMLERR_FIRST) {
strcpy(&szErr[4], "Unknown DDEML Error");
} else {
strcpy(&szErr[4], DdeE[DdeError - DMLERR_FIRST]);
}
strcat(szErr,".\r\n");
mexPrintf(szErr);
ErrorBeep();
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
BOOL CFTextStringReq( HDDEDATA hData, Matrix** DestMatrix )
{
DWORD DataSize, StringLen = 0;
char huge* hDataString = (char huge*)DdeAccessData( hData, &DataSize );
size_t LocalMax = _memmax();
//Stringlaenge bestimmen
char huge* hDataString_end = hDataString;
while ( *(hDataString_end++) != '\0' && StringLen++ < DataSize);
if (StringLen > LocalMax-1) //besser: heapSize malloc
{
mexPrintf( "??? Possible data lost. More then 64 KByte text.\r\n" );
ErrorBeep();
StringLen = LocalMax-1;
}
//Speicher reservieren, um String lokal umzukopieren
//HLOCAL hLocalString = LocalAlloc( LPTR, (UINT)((hDataString_end - hDataString) +1) );
HLOCAL hLocalString = LocalAlloc( LPTR, (UINT)(StringLen+1) );
if ( !hLocalString )
{
DdeUnaccessData( hData );
mexPrintf( "??? Memory allocation error.\r\n" );
ErrorBeep();
return TRUE;
}
char* szString = (char*) LocalLock( hLocalString );
//kopieren
//hmemcpy( (char huge*) szString, (char huge*) hDataString, hDataString_end - hDataString );
hmemcpy( (char huge*) szString, (char huge*) hDataString, StringLen+1 );
*DestMatrix = mxCreateString( szString ); //arbeitet nicht mit huge-Speicher!
//Speicher freigeben
LocalUnlock( hLocalString );
LocalFree( hLocalString );
DdeUnaccessData( hData );
return FALSE;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
BOOL CFTextRequest( HDDEDATA hData, Matrix** DestMatrix )
{
HGLOBAL hGlobal;
int rows, columns;
DWORD DataSize;
char huge* hDataString = (char huge*)DdeAccessData( hData, &DataSize);
//GetMatrixSize( hDataString, &rows, &columns );
GetMatrixSize( hDataString, &DataSize, &rows, &columns );
DWORD matrixSize = (DWORD)rows * (DWORD)columns;
//Speicher reservieren
hGlobal = GlobalAlloc( GPTR, matrixSize * sizeof(double) );
if ( !hGlobal )
{
DdeUnaccessData( hData );
mexPrintf( "??? Memory allocation error.\r\n" );
ErrorBeep();
return TRUE;
}
double huge* dest = (double huge*) GlobalLock( hGlobal ); //Speicherbereich mit double-Werten
if ( Str2Double( dest, matrixSize, hDataString, DataSize ) ) //Konvertierung string -> double
{
//Matrix erzeugen
if ((*DestMatrix = mxCreateFull( rows, columns, REAL )) )
{
double huge* src = dest; //die zu double konvertierten strings sind jetzt source
dest = (double huge*)mxGetPr( *DestMatrix );
//Matrix transponieren
Transpose( dest, src, rows, columns ); //ddelib.c
}
else
{
mexPrintf( "??? Memory allocation error.\r\n" );
ErrorBeep();
}
}
GlobalUnlock( hGlobal );
GlobalFree( hGlobal );
DdeUnaccessData( hData );
return FALSE;
}
///////////////////////////////////////////////////////DDE-Excel Format
BOOL FastDDEReq( HDDEDATA hData, Matrix** DestMatrix )
{
DWORD DataSize;
TableHeader TabHeader;
char huge* hDataBlock = (char huge*) DdeAccessData( hData, &DataSize );
//tdtTable-Header lesen
hmemcpy( &TabHeader, hDataBlock, sizeof(TabHeader) );
//Matrix erzeugen
if ( !(*DestMatrix = mxCreateFull( (int)TabHeader.rows, (int)TabHeader.columns, REAL )) )
{
DdeUnaccessData( hData );
mexPrintf( "??? Memory allocation error.\r\n" );
ErrorBeep();
return TRUE;
}
WORD i=0; WORD j, k=0;
char huge* src = hDataBlock + sizeof(TabHeader);
char huge* dest = (char huge*)mxGetPr( *DestMatrix );
char huge* help = dest;
DWORD SourceBytes = sizeof(TabHeader);
DWORD BytesMoved = 0;
DWORD Size = (DWORD)TabHeader.rows * TabHeader.columns * sizeof(double);
BOOL result = TRUE;
FloatHeader FtHeader;
while ( BytesMoved < Size )
{
SourceBytes += sizeof(FtHeader);
if ( SourceBytes > DataSize )
{
result = FALSE;
break;
}
//tdtFloat-Header kopieren
hmemcpy( (char*)&FtHeader, (char huge*)src, sizeof(FtHeader) );
src += sizeof(FtHeader);
SourceBytes += FtHeader.cbFloat;
if ( FtHeader.Float != tdtFloat || SourceBytes > DataSize)
{
result = FALSE;
break;
}
//Double-Daten kopieren
if (TabHeader.columns == 1 || TabHeader.rows == 1) //Reihenfolge bleibt
{
hmemcpy( (char huge*)help, (char huge*)src, FtHeader.cbFloat);
src += FtHeader.cbFloat;
help += FtHeader.cbFloat;
}
else //Transponieren
{
j = FtHeader.cbFloat;
while ( k < TabHeader.rows )
{
while ( i < TabHeader.columns )
{
if ( j < sizeof(double) )
break;
hmemcpy( help, src, sizeof(double) );
j -= sizeof(double);
src += sizeof(double);
help += TabHeader.rows * sizeof(double);
i++;
}
if ( i < TabHeader.columns )
break;
i = 0;
k++;
help = dest + (DWORD)k * sizeof(double); //huge-Adresse!
}
}
BytesMoved += FtHeader.cbFloat;
}
DdeUnaccessData( hData );
if (result)
return FALSE;
else
{
mexPrintf( "??? Error. Invalid binary data.\r\n" );
ErrorBeep();
return TRUE;
}
}
void Go2Next( char huge*huge* );
/////////////////////////////////////////////////////////////////////////////////////////////////////
BOOL Old_Str2Double( double huge* dest, char huge* hDataString )
{
DWORD i = 0;
char strBuffer[60]; //es werden 60 Stellen (willkuerlicher Wert) fuer eine Zahl kopiert
//das Feststellen der tatsaechlichen Laenge dauert zu lange
while ( *hDataString != '\0' )
{
if ( *hDataString == '\t' || *hDataString == '\r' )
{
mexPrintf( "Matrix not actualized. Possible empty element of source matrix.\r\n" );
return FALSE;
}
else
{
hmemcpy( (char huge*) strBuffer, (char huge*) hDataString, sizeof(strBuffer) ); //lokale Kopie, wegen
dest[i] = atof( strBuffer ); //atof() -huge-Zeigerproblem
}
Go2Next( &hDataString );
i++;
}
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
_inline void Go2Next( char huge* huge* hDataString )
{
do
{
switch ( **hDataString )
{
case '\t': (*hDataString)++;
return;
case '\r': (*hDataString) += 2;
return;
}
}
while ( (*hDataString)++ );
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
BOOL RemoveHeader( TableHeader* TabHeader, BYTE huge* src )
{
//Groesse der Matrix in bytes
DWORD Size = (DWORD)TabHeader->rows * (DWORD)TabHeader->columns * sizeof(double);
DWORD BytesMoved = (DWORD)0;
BOOL result = TRUE;
BYTE huge* dest = src;
FloatHeader FtHeader;
while ( BytesMoved < Size )
{
hmemcpy( (char*)&FtHeader, (char huge*)src, sizeof(FtHeader) );
src += sizeof(FtHeader);
if ( FtHeader.Float != tdtFloat )
{
result = FALSE;
break;
}
memmove( (char*)dest, (char*)src, FtHeader.cbFloat);
src += FtHeader.cbFloat;
dest += FtHeader.cbFloat;
BytesMoved += FtHeader.cbFloat;
}
return result;
}
Vorgefundene Kodierung: ASCII (7 bit) | 2
|