在处理某种消息报文时, 我们会时常对报文内容进行分析, 下面的类对象提供了一种简单方式, 使得我们能够从烦人的报文细节解脱出来. 下面这段为C/C++头文件内容:
#ifndef __WC_NDCDDCPROTOCOLASSISTANT__H_
#define __WC_NDCDDCPROTOCOLASSISTANT__H_
#include "stdafx.h"
const char
CONST_PROT_MSG_FIELD_SEPARATER = '\x1C',
CONST_PROT_MSG_GROUP_SEPARATER = '\x1D';
////////////////////////////////////////////////////////
class TMessageGroupItem
{
public:
TMessageGroupItem (LPCSTR lpGroupContent, UINT uiItemIndex);
virtual ~TMessageGroupItem ();
public:
LPCSTR GetGroupValue ();
UINT Index ();
private:
UINT m_uiIndex;
CString m_strGroupContent;
};
class TMessageFieldItem
{
public:
TMessageFieldItem (LPCSTR lpFieldContent, UINT uiItemIndex);
~TMessageFieldItem ();
public:
bool Initialize ();
TMessageGroupItem * GetFirstGroup ();
TMessageGroupItem * GetPrevGroup ();
TMessageGroupItem * GetNextGroup ();
TMessageGroupItem * GetLastGroup ();
UINT GetGroupCount ();
BOOL IsEmpty () {return m_lstGroupItems.IsEmpty();}
bool IsEnd ();
LPCSTR GetFieldValue ();
UINT Index () {return m_uiIndex;}
private:
POSITION m_GroupPosition;
CList <TMessageGroupItem *, TMessageGroupItem *> m_lstGroupItems;
UINT m_uiIndex;
CString m_strFieldContent;
CString m_strSimpleFieldValue;
};
class TCustomProtocolAssistant
{
public:
TCustomProtocolAssistant (LPCSTR lpMessageContent);
~TCustomProtocolAssistant ();
public:
bool Initialize ();
TMessageFieldItem * GetFirstField ();
TMessageFieldItem * GetPrevField ();
TMessageFieldItem * GetNextField ();
TMessageFieldItem * GetLastField ();
UINT GetFieldCount ();
BOOL IsEmpty () {return m_lstFieldItems.IsEmpty();}
bool IsEnd ();
private:
POSITION m_FieldPosition;
CList <TMessageFieldItem *, TMessageFieldItem *> m_lstFieldItems;
CString m_strMsgContent;
};
////////////////////////////////////////////////////////////////////////
class TCustomProtocolInterpreterComponent
{
public:
TCustomProtocolInterpreterComponent (){}
~TCustomProtocolInterpreterComponent (){}
public:
bool Interpret (LPSTR lpDestBuf, UINT uiDestBufSize, LPCSTR lpFrom);
protected:
virtual void OnMessageFieldItemEvent (UINT uiFieldIndex, LPCSTR lpFieldValue,
CString &strNewData, BOOL &bAppendNewData);
virtual void OnMessageGroupItemEvent (UINT uiFieldIndex, UINT uiGroupIndex,
LPCSTR lpGroupValue, CString &strNewData, BOOL &bAppendNewData);
private:
CString m_strNewMessage;
};
class TSampleInterpreter: public TCustomProtocolInterpreterComponent
{
public:
TSampleInterpreter (): TCustomProtocolInterpreterComponent() {}
virtual ~TSampleInterpreter () {}
protected:
void OnMessageFieldItemEvent (UINT uiFieldIndex, LPCSTR lpFieldValue,
CString &strNewData, BOOL &bAppendNewData);
void OnMessageGroupItemEvent (UINT uiFieldIndex, UINT uiGroupIndex,
LPCSTR lpGroupValue, CString &strNewData, BOOL &bAppendNewData);
};
#endif
// end of header file
接着是CPP的内容,
#include "stdafx.h"
#include "ProtocolAssistant.h"
// TMessageGroupItem class
TMessageGroupItem::TMessageGroupItem (LPCSTR lpGroupContent, UINT uiItemIndex)
: m_uiIndex (uiItemIndex), m_strGroupContent (lpGroupContent)
{
}
TMessageGroupItem::~TMessageGroupItem ()
{
}
LPCSTR TMessageGroupItem::GetGroupValue ()
{
return (LPCTSTR) m_strGroupContent;
}
UINT TMessageGroupItem::Index ()
{
return m_uiIndex;
}
// TMessageFieldItem class
TMessageFieldItem::TMessageFieldItem (LPCSTR lpFieldContent, UINT uiItemIndex)
: m_strFieldContent (lpFieldContent), m_uiIndex(uiItemIndex),
m_GroupPosition (NULL)
{
}
TMessageFieldItem::~TMessageFieldItem ()
{
m_lstGroupItems.RemoveAll();
}
bool TMessageFieldItem::Initialize ()
{
m_lstGroupItems.RemoveAll();
m_strSimpleFieldValue = "";
if (m_strFieldContent.IsEmpty())
return false;
LPSTR lpThisGroup = NULL, lpNextGroup = NULL;
LPCSTR lpBeginPtr = (LPCTSTR) m_strFieldContent;
lpThisGroup = strchr (lpBeginPtr, CONST_PROT_MSG_GROUP_SEPARATER);
if (!lpThisGroup)
{
// not found any group in this field!
m_strSimpleFieldValue = m_strFieldContent;
return true;
}
CString strSimpleFieldContent (lpBeginPtr, lpThisGroup - lpBeginPtr);
m_strSimpleFieldValue = strSimpleFieldContent;
// skip the group separater
lpThisGroup++;
UINT uiItemIndex = 1;
for (;;)
{
TMessageGroupItem *pNewGroupItem = NULL;
lpNextGroup = strchr (lpThisGroup, CONST_PROT_MSG_GROUP_SEPARATER);
if (!lpNextGroup)
{
pNewGroupItem = new TMessageGroupItem (lpThisGroup, uiItemIndex++);
m_lstGroupItems.AddTail (pNewGroupItem);
break;
}
CString strGroupContent (lpThisGroup, lpNextGroup - lpThisGroup);
pNewGroupItem = new TMessageGroupItem ((LPCTSTR) strGroupContent, uiItemIndex++);
m_lstGroupItems.AddTail (pNewGroupItem);
lpThisGroup = ++lpNextGroup;
} // end for
return true;
}
TMessageGroupItem * TMessageFieldItem::GetFirstGroup ()
{
if (m_lstGroupItems.IsEmpty())
return NULL;
m_GroupPosition = m_lstGroupItems.GetHeadPosition();
if (!m_GroupPosition)
return NULL;
return m_lstGroupItems.GetNext (m_GroupPosition);
}
TMessageGroupItem * TMessageFieldItem::GetPrevGroup ()
{
if (m_lstGroupItems.IsEmpty() || !m_GroupPosition)
return NULL;
return m_lstGroupItems.GetPrev (m_GroupPosition);
}
TMessageGroupItem * TMessageFieldItem::GetNextGroup ()
{
if (m_lstGroupItems.IsEmpty() || !m_GroupPosition)
return NULL;
return m_lstGroupItems.GetNext (m_GroupPosition);
}
TMessageGroupItem * TMessageFieldItem::GetLastGroup ()
{
if (m_lstGroupItems.IsEmpty())
return NULL;
m_GroupPosition = m_lstGroupItems.GetTailPosition ();
if (!m_GroupPosition)
return NULL;
return m_lstGroupItems.GetPrev (m_GroupPosition);
}
UINT TMessageFieldItem::GetGroupCount ()
{
return (UINT) m_lstGroupItems.GetCount();
}
bool TMessageFieldItem::IsEnd ()
{
return m_GroupPosition == m_lstGroupItems.GetTailPosition ();
}
LPCSTR TMessageFieldItem::GetFieldValue ()
{
LPCSTR lpFieldHeadPtr = (LPCTSTR) m_strFieldContent;
LPCSTR lpFirstGroupFound = strchr (lpFieldHeadPtr, CONST_PROT_MSG_GROUP_SEPARATER);
if (!lpFirstGroupFound)
m_strSimpleFieldValue = m_strFieldContent;
else
{
CString strSimpleFieldVal (lpFieldHeadPtr, lpFirstGroupFound - lpFieldHeadPtr);
m_strSimpleFieldValue = strSimpleFieldVal;
}
return (LPCTSTR) m_strSimpleFieldValue;
}
// TCustomProtocolAssistant class
TCustomProtocolAssistant::TCustomProtocolAssistant (LPCSTR lpMessageContent)
: m_strMsgContent (lpMessageContent), m_FieldPosition (NULL)
{
}
TCustomProtocolAssistant::~TCustomProtocolAssistant ()
{
m_lstFieldItems.RemoveAll();
}
bool TCustomProtocolAssistant::Initialize ()
{
if (m_strMsgContent.IsEmpty())
return false;
LPSTR lpThisField = NULL, lpNextField = NULL;
lpThisField = (LPSTR)(LPCTSTR) m_strMsgContent;
UINT uiItemIndex = 1;
for (;;)
{
TMessageFieldItem *pNewFieldItem = NULL;
lpNextField = strchr (lpThisField, CONST_PROT_MSG_FIELD_SEPARATER);
if (!lpNextField)
{
pNewFieldItem = new TMessageFieldItem (lpThisField, uiItemIndex++);
pNewFieldItem->Initialize ();
m_lstFieldItems.AddTail (pNewFieldItem);
break;
}
CString strFieldContent (lpThisField, lpNextField - lpThisField);
pNewFieldItem = new TMessageFieldItem ((LPCTSTR) strFieldContent, uiItemIndex++);
pNewFieldItem->Initialize();
m_lstFieldItems.AddTail (pNewFieldItem);
lpThisField = ++lpNextField;
} // end for
return true;
}
TMessageFieldItem * TCustomProtocolAssistant::GetFirstField ()
{
if (m_lstFieldItems.IsEmpty())
return NULL;
m_FieldPosition = m_lstFieldItems.GetHeadPosition();
if (!m_FieldPosition)
return NULL;
return m_lstFieldItems.GetNext (m_FieldPosition);
}
TMessageFieldItem * TCustomProtocolAssistant::GetPrevField ()
{
if (m_lstFieldItems.IsEmpty() || !m_FieldPosition)
return NULL;
return m_lstFieldItems.GetPrev (m_FieldPosition);
}
TMessageFieldItem * TCustomProtocolAssistant::GetNextField ()
{
if (m_lstFieldItems.IsEmpty() || !m_FieldPosition)
return NULL;
return m_lstFieldItems.GetNext (m_FieldPosition);
}
TMessageFieldItem * TCustomProtocolAssistant::GetLastField ()
{
if (m_lstFieldItems.IsEmpty())
return NULL;
m_FieldPosition = m_lstFieldItems.GetTailPosition();
if (!m_FieldPosition)
return NULL;
return m_lstFieldItems.GetPrev (m_FieldPosition);
}
UINT TCustomProtocolAssistant::GetFieldCount ()
{
return (UINT) m_lstFieldItems.GetCount();
}
bool TCustomProtocolAssistant::IsEnd ()
{
return m_FieldPosition == m_lstFieldItems.GetTailPosition ();
}
// TCustomProtocolInterpreterComponent class
// Description: Responsible for interpretting the message through
// iterating all of messsage fields.
// Parameters:
// [in/out] lpDestBuf: specifies the pointer to destination;
// [in] uiDestBufSize: specifies the size of destination in bytes;
// [in] lpFrom: specifies the pointer to source buffer;
// Return Value:
// returns TRUE if succeed, otherwise FALSE.
// Remark:
// This function will copy the created new data into the destination,
// actually those work about interpretting are finished by the following
// two event functions in which user can re-constitute or handle data
// retrieved.
//
bool TCustomProtocolInterpreterComponent::Interpret (LPSTR lpDestBuf,
UINT uiDestBufSize, LPCSTR lpFrom)
{
if (!lpDestBuf || 0 == uiDestBufSize || !lpFrom)
return false;
TCustomProtocolAssistant AMsgIterater (lpFrom);
if (!AMsgIterater.Initialize ())
return false;
TMessageFieldItem * ACurrentField = AMsgIterater.GetFirstField ();
// Determine whether the cursor of iterater reached the tail.
for (UINT ix = 0; ix < AMsgIterater.GetFieldCount(); ix++)
{
// Event for processing the values of message fields
CString strNewData;
BOOL bAppendNewData = true;
OnMessageFieldItemEvent (ACurrentField->Index (), ACurrentField->GetFieldValue (),
strNewData, bAppendNewData);
if (bAppendNewData)
m_strNewMessage += strNewData;
else
m_strNewMessage = strNewData;
if (!ACurrentField->IsEmpty ())
{
TMessageGroupItem * ACurrentGroup = ACurrentField->GetFirstGroup ();
for (UINT iy = 0; iy < ACurrentField->GetGroupCount(); iy++)
{
// Event for processing the valus of message groups
strNewData = "";
bAppendNewData = true;
OnMessageGroupItemEvent (ACurrentField->Index (), ACurrentGroup->Index (),
ACurrentGroup->GetGroupValue (), strNewData, bAppendNewData);
if (bAppendNewData)
m_strNewMessage += strNewData;
else
m_strNewMessage = strNewData;
ACurrentGroup = ACurrentField->GetNextGroup ();
}
} // end if
ACurrentField = AMsgIterater.GetNextField ();
} // end for
return (!strncpy (lpDestBuf, (LPCTSTR) m_strNewMessage, uiDestBufSize-1))
? false : true;
}
// Description: It can process each one of fields retrieved, or
// re-constitute new data.
// Parameters:
// [in] uiFieldIndex: the 1-based index of currently selected field
// from source message;
// [in] lpFieldValue: the value-string of currently selected field
// from source message;
// [in/out] strNewData: new data needed to reconstitute. If strNewData changed
// as interpretting process, it'll update the output result directly;
// [in] bAppendNewData: specifies the kind of updating the output result.
// If it was set to true, new data would be appended to the tail of
// output result; otherwise the output result would be overwritten;
// Default is set to true;
// Return Value: None.
// Remark:
void TCustomProtocolInterpreterComponent::OnMessageFieldItemEvent (UINT uiFieldIndex,
LPCSTR lpFieldValue, CString &strNewData, BOOL &bAppendNewData)
{
}
// Description: It can process each one group of fields retrieved, or
// re-constitute new data.
// Parameters:
// [in] uiFieldIndex: the 1-based index of currently selected field
// from source message;
// [in] uiGroupIndex: the 1-based index of currently selected group
// in somewhat field;
// [in] lpGroupValue: the value-string of currently selected group;
// [in/out] strNewData: refer to OnMessageFieldItemEvent() event;
// [in] bAppendNewData: refer to OnMessageFieldItemEvent() event;
// Return Value: None.
// Remark:
void TCustomProtocolInterpreterComponent::OnMessageGroupItemEvent (UINT uiFieldIndex,
UINT uiGroupIndex, LPCSTR lpGroupValue, CString &strNewData, BOOL &bAppendNewData)
{
}
//////////////////////////////////////////////////////////////////////////
//
// TSampleInterpreter class
//
void TSampleInterpreter::OnMessageFieldItemEvent (UINT uiFieldIndex,
LPCSTR lpFieldValue, CString &strNewData, BOOL &bAppendNewData)
{
switch (uiFieldIndex)
{
case 1:
case 2:
case 3:
case 4:
case 6:
case 7:
case 8:
case 9:
case 10:
case 11:
case 12:
case 13:
case 14:
strNewData.Format ("%s%c", lpFieldValue, CONST_PROT_MSG_FIELD_SEPARATER);
break;
case 5:
{
CString strHiBills (lpFieldValue, 2);
int nHiBillsDispensed = atoi ((LPCTSTR) strHiBills);
CString strLoBills (lpFieldValue + 2, 2);
int nLoBillsDispensed = atoi ((LPCTSTR) strLoBills);
strNewData.Format ("%02d", nHiBillsDispensed + nLoBillsDispensed);
}
break;
default:
break;
} // end switch
}
void TSampleInterpreter::OnMessageGroupItemEvent (UINT uiFieldIndex,
UINT uiGroupIndex, LPCSTR lpGroupValue, CString &strNewData, BOOL &bAppendNewData)
{
// cout << uiFieldIndex << "." << uiGroupIndex << " GroupVal=" << lpGroupValue << endl;
}
// end of file