On Sat, 10 Apr 2021 10:51:18 -0700, John Speth <
john...@yahoo.com>
wrote:
While I agree with Don and Hans-Bernhard re: maintainability, I did
something similar in one of my projects.
In my case, I was translating messages between machine format (C
structs) and readable text format (to be sent via TCP or logged to a
file, depending).
I used a table-driven solution shown below. Note this is just one
example - there were hundreds of such message structures in the
application, and keeping everything consistent was a chore. The C
structs were used by many tasks, but only one needed to translate
them.
YMMV,
George
*****************************************
typedef struct
{
DWORD jobId;
float position; /* position for _first_ exposure
*/
int slices;
long H1exposureTime; /* ms total */
long H2exposureTime; /* ms total for all - this may be
a guesstimate */
int H2s; /* number of H2s */
char* magazineId;
RECTANGLE border; /* image border */
char* patientName;
char* printDate;
}
MSG_JOB_PARAMETERS;
*****************************************
typedef struct
{
BOOLEAN use;
char* text;
t_Parameter type;
int offset;
}
MESSAGE_FORMAT;
static MESSAGE_FORMAT JobParametersFormat[] =
{
{ 1, "[EXPJ]" , PARAM_NONE , 0 },
{ 1, "%JobId=" , PARAM_INTEGER, offsetof(
MSG_JOB_PARAMETERS, jobId ) },
{ 1, "%StartPosition=" , PARAM_FLOAT , offsetof(
MSG_JOB_PARAMETERS, position ) },
{ 1, "%NumberOfSlabs=" , PARAM_INTEGER, offsetof(
MSG_JOB_PARAMETERS, slices ) },
{ 1, "%TotalH1ExposeTime=" , PARAM_INTEGER, offsetof(
MSG_JOB_PARAMETERS, H1exposureTime ) },
{ 1, "%NumberOfH2s=" , PARAM_INTEGER, offsetof(
MSG_JOB_PARAMETERS, H2s ) },
{ 1, "%TotalH2ExposeTimeGuess=", PARAM_INTEGER, offsetof(
MSG_JOB_PARAMETERS, H2exposureTime ) },
{ 1, "%MagazineId=" , PARAM_STRING , offsetof(
MSG_JOB_PARAMETERS, magazineId ) },
{ 1, "%HotspotX1=" , PARAM_INTEGER, offsetof(
MSG_JOB_PARAMETERS, border.left ) },
{ 1, "%HotspotY1=" , PARAM_INTEGER, offsetof(
MSG_JOB_PARAMETERS, border.top ) },
{ 1, "%HotspotX2=" , PARAM_INTEGER, offsetof(
MSG_JOB_PARAMETERS, border.right ) },
{ 1, "%HotspotY2=" , PARAM_INTEGER, offsetof(
MSG_JOB_PARAMETERS, border.bottom ) },
{ 1, "%PatientName=" , PARAM_STRING , offsetof(
MSG_JOB_PARAMETERS, patientName ) },
{ 1, "%PrintDateTime=" , PARAM_STRING , offsetof(
MSG_JOB_PARAMETERS, printDate ) },
{ 1, "[]" , PARAM_NONE , 0 },
{ 0, NULL , PARAM_NONE , 0 }
};
static BOOLEAN
LM_Encode( LM_ConnectionInfo* connection, BYTE* msg, MESSAGE_FORMAT*
format )
{
char buffer[64];
int retcode;
int index;
int length;
int i;
int* iptr;
float* fptr;
char** sptr;
retcode = LM_OK;
index = 0;
for ( i = 0; format->use == TRUE; ++i )
{
if ( i == 1)
{
length = sprintf( buffer, "%%ConnectionId=%d\r\n",
connection->socketId );
}
else
{
iptr = (int*) (msg + format->offset);
fptr = (float*) (msg + format->offset);
sptr = (char**) (msg + format->offset);
switch ( format->type )
{
case PARAM_NONE : length = sprintf( buffer, "%s\r\n"
, format->text ); break;
case PARAM_INTEGER: length = sprintf( buffer,
"%s%d\r\n", format->text, *iptr ); break;
case PARAM_FLOAT : length = sprintf( buffer,
"%s%f\r\n", format->text, *fptr ); break;
case PARAM_STRING : length = sprintf( buffer,
"%s%s\r\n", format->text, *sptr ? *sptr : "" ); break;
}
format++;
}
if ((index + length) < connection->sendLimit)
{
strcpy( &connection->sendBuffer[index], buffer );
index += length;
}
else
{
retcode = LM_BAD_MESSAGE_SIZE;
break;
}
}
return ( retcode );
}