/**************************************************************************
 * Source Id :
 *
 * $Id: marshal.cpp,v 1.3 2001/04/20 10:15:01 georgetasker Exp $
 *-------------------------------------------------------------------------
 * Project Notes :
 *
 *  Diamond Base
 *  ============
 *      A solid database implementation, spurred on by the continuing
 *  Metal (Lead) Base saga.
 *
 *  Project Team :
 *        A. Davison
 *        K. Lentin
 *        D. Platt
 *
 *	Project Commenced : 05-02-1993
 *
 *-------------------------------------------------------------------------
 *  Module Notes :
 *
 *    Marshaling of relations for transport over client/server
 *
 *
 *  Original Author : daz/kev
 *
 **************************************************************************/

// FOR NOW::
// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"

#ifdef __BORLANDC__
    #pragma hdrstop
#endif

//
// Record marshaling.
//

#include <diamond/object.h>

//
// marshalRecord:
//
// Given an object, tell us how much space is required to marshal it and
// also fill in a buffer of that size with the marshaled record.
//

//
// These could conceivably be members of the DIA_object class actually, in
// which case you would drop the theObj parameter.  If you go that way,
// mail me the new versions of the file.
//

size_t
marshalSpaceRequired(const DIA_object *theObj)
{
	//
	// Easiest if we put the length of the various strings up front
	// and put the actual string data at the end.
	// NB Length of string and memServer offset both should be encoded.
	//

	int32 sz = 2 * sizeof(int32) * theObj->numStrings() + theObj->getDataLength();
	const _db_strStruct* ss = theObj->getArray();
	for (int i=0; i < theObj->numStrings(); i++)
	{
		sz += ss[i].theString->storage();
	}
	return sz;
}


void
marshalObject(const DIA_object *theObj,char *data)
{
	//
	// For each string (assume receiver knows #strings) put the length
	// and offset into int32 pairs at the start of the data
	//
	int i;

	const _db_strStruct* ss = theObj->getArray();
	int32* dataAsLongs = (int32*)data;
	for (i=0; i < theObj->numStrings(); i++)
	{
		dataAsLongs[2*i] = ss[i].theString->storage();
		dataAsLongs[2*i+1] = *ss[i].theLong;
	}

	//
	// Copy the actual object into the data buffer now
	//
	char* start = data + 2 * sizeof(int32) * theObj->numStrings();
	copyMem((void*)*theObj , (void*)start, theObj->getDataLength());

	//
	// For each string, append the contents of the dbString/dbData to
	// the data buffer
	//
	start += theObj->getDataLength();
	for (i=0; i < theObj->numStrings(); i++)
	{
		copyMem((char*)(*ss[i].theString), start, dataAsLongs[2*i]);
		start += dataAsLongs[2*i];
	}

}

void
unmarshalObject(DIA_object *theObj,const char *data)
{
	//
	// Reverse of marshalObject
	//
	
	int i;

	//
	// Extract the lengths and offsets of any dbStrings/dbData
	//
	const _db_strStruct* ss = theObj->getArray();
	int32* dataAsLongs = (int32*)data;
	for (i=0; i < theObj->numStrings(); i++)
	{
		ss[i].theString->setSize(dataAsLongs[2*i]);
		*ss[i].theLong = dataAsLongs[2*i+1];
	}

	//
	// Extract the contents of the object
	//
	const char* start = data + 2 * sizeof(int32) * theObj->numStrings();
	copyMem( (void*)start, (void *)*theObj, theObj->getDataLength());

	//
	// Extract the contents of the actual strings/dbData
	//
	start += theObj->getDataLength();
	for (i=0; i < theObj->numStrings(); i++)
	{
		copyMem(start, (char*)(*ss[i].theString), dataAsLongs[2*i]);
		start += dataAsLongs[2*i];
	}
}
