You are here: Elements > Decoder Data Objects > A Simple Example

A Simple Example

Let us examine a real use of a data object. This example is the code behind the StorePersistentField and PersistentField methods. These methods are generic inter-frame data methods that allow a decoder writer to save a field value from frame to frame.

DECODER_STATIC __Persist__

// Declare the class just like in C++

private:

__int64 m_i64Value;

int m_iSize;

bool m_bIsSet;

public:

void Set(__int64 i64Value, int iSize)

{

m_i64Value = i64Value;

m_iSize = iSize;

m_bIsSet = true;

};

 

bool Get(__int64& i64FieldValue, int& iSize) const

{

// be sure the object is initialized

ASSERT((m_bIsSet == false) || (m_bIsSet == true));

i64FieldValue = m_i64Value;

iSize = m_iSize;

return m_bIsSet;

};

void Clear()

{

_Reset();

}

 

@CTOR

// Nothing has to be initialized here, so this section can be

// omitted. This is for initializing one-time items. The RESET

// section will be called right after the initialization.

 

@DTOR

// This is for freeing memory that we've allocated. In this case,

// there is nothing to free, so this section can be omitted.

 

@PUT_DATA_INTO_A_BYTE_ARRAY

// If the data needs to be remembered for new frames, then we

// need a way to save and restore it to the FRM file. This

// section saves the class as a BYTE array that can be streamed

// to the FRM file. It is important to keep the size of the array

// to the smallest needed, to keep the size of the FRM file down.

//

// If this section is omitted, then the RESET section will be

// called at the beginning of each frame.

//

// abStatic is to be filled in

if (m_bIsSet)

{

int iSize = (m_iSize+7)/8 + 1;

abStatic.SetSize(iSize);

BYTE* pb = abStatic.GetData();

*pb++ = (BYTE)m_iSize;

memcpy(pb, (BYTE*)&m_i64Value, iSize-1);

}

else

abStatic.RemoveAll();

@GET_DATA_FROM_A_BYTE_ARRAY

// This is the complement of the above section. It takes the BYTE

// stream and turns it back into the class data.

//

//abStatic contains the static

m_bIsSet = true;

const BYTE* pb = abStatic.GetData();

m_iSize = *pb++;

m_i64Value = 0;

int iSize = (m_iSize+7)/8 + 1;

memcpy((BYTE*)&m_i64Value, pb, iSize-1);

@RESET

// This is called right after the object is constructed, and

// through various other events. It should set the object to a

// known state.

m_i64Value = -1;

m_iSize = 0;

m_bIsSet = false;

@END_STATIC

Here is the method that uses this Decoder Data Object:

RETRIEVING_DATA

METHOD __StorePersistentField__ USES_STATIC __Persist__

/*

Saves the value of the current field in the data object

specified. The item after the method name must be the name of

the data object in which the field is to be stored.

Data is retrieved using the __PersistentField__ method.

*/

CODE

pStatic->Set(i64CurrentField, isizbitCurrentField);

ENDCODE

RETRIEVING_DATA

METHOD __PersistentField__ USES_STATIC __Persist__

/*

Retrieves a field stored previously by a __StorePersistentField__ method.

When using this method, the first item after the method name

must be the name of the data object in which the field

was stored.

*/

CODE

if (!pStatic->Get(i64FieldValue, iFieldSize))

throw CFdFieldException("Data not present (The field that the data comes from was not encountered.)");

ENDCODE

In one decoder, declare a field like this --

FIELD code (Fixed 1) RETRIEVE (StorePersistentField KeepThisCode) (Decimal) "Code"

In another decoder, or in a different path in the same decoder, declare a field

like this --

FIELD retrieved_code (Fixed 0 bits) RETRIEVE (PersistentField KeepThisCode) (Hex) "Retrieved Code"