📄 dl_iso8583_fields.c
字号:
/******************************************************************************/
/* */
/* Copyright (C) 2005-2007 Oscar Sanderson */
/* */
/* This software is provided 'as-is', without any express or implied */
/* warranty. In no event will the author(s) be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* */
/* 2. Altered source versions must be plainly marked as such, and must not be */
/* misrepresented as being the original software. */
/* */
/* 3. This notice may not be removed or altered from any source distribution. */
/* */
/******************************************************************************/
/* */
/* ISO8583 field packers / unpackers */
/* */
/******************************************************************************/
#include "dl_iso8583_fields.h"
/******************************************************************************/
//
// FIELD HANDLER PROTOTYPES
//
DL_ERR _pack_iso_ASCHEX ( DL_UINT16 iField,
const DL_ISO8583_MSG *iMsg,
const DL_ISO8583_FIELD_DEF *iFieldDefPtr,
DL_UINT8 **ioPtr );
// unpacks ISO Numeric (bcd format)
// NB if iSize is odd then we have a padding char on left
// (but don't include when unpacking)
DL_ERR _unpack_iso_ASCHEX ( DL_UINT16 iField,
DL_ISO8583_MSG *ioMsg,
const DL_ISO8583_FIELD_DEF *iFieldDefPtr,
DL_UINT8 **ioPtr );
DL_ERR _pack_iso_ASCII ( DL_UINT16 iField,
const DL_ISO8583_MSG *iMsg,
const DL_ISO8583_FIELD_DEF *iFieldDefPtr,
DL_UINT8 **ioPtr );
DL_ERR _unpack_iso_ASCII ( DL_UINT16 iField,
DL_ISO8583_MSG *ioMsg,
const DL_ISO8583_FIELD_DEF *iFieldDefPtr,
DL_UINT8 **ioPtr );
DL_ERR _pack_iso_BINARY ( DL_UINT16 iField,
const DL_ISO8583_MSG *iMsg,
const DL_ISO8583_FIELD_DEF *iFieldDefPtr,
DL_UINT8 **ioPtr );
DL_ERR _unpack_iso_BINARY ( DL_UINT16 iField,
DL_ISO8583_MSG *ioMsg,
const DL_ISO8583_FIELD_DEF *iFieldDefPtr,
DL_UINT8 **ioPtr );
DL_ERR _pack_iso_BITMAP ( DL_UINT16 iField,
const DL_ISO8583_MSG *iMsg,
const DL_ISO8583_FIELD_DEF *iFieldDefPtr,
DL_UINT8 **ioPtr );
DL_ERR _unpack_iso_BITMAP ( DL_UINT16 iField,
DL_ISO8583_MSG *ioMsg,
const DL_ISO8583_FIELD_DEF *iFieldDefPtr,
DL_UINT8 **ioPtr );
/******************************************************************************/
//
// LENGTH HANDLER PROTOTYPES
//
// outputs the variable length element
// iVarLenType - e.g. kDL_ISO8583_LLVAR
static DL_ERR VarLen_Put ( DL_UINT8 iVarLenType,
DL_UINT32 iActLen,
DL_UINT32 *ioReqLen,
DL_UINT8 **ioPtr );
// determines variable length element
static DL_ERR VarLen_Get ( const DL_UINT8 **ioPtr,
DL_UINT8 iVarLenDigits,
DL_UINT16 iMaxValue,
DL_UINT16 *oLen );
/******************************************************************************/
//
// TYPES
//
struct DL_ISO8583_TYPE_S
{
DL_ERR (*unpackFunc)(DL_UINT16,DL_ISO8583_MSG*,const DL_ISO8583_FIELD_DEF*,DL_UINT8**);
DL_ERR (*packFunc )(DL_UINT16,const DL_ISO8583_MSG*,const DL_ISO8583_FIELD_DEF*,DL_UINT8**);
};
typedef struct DL_ISO8583_TYPE_S DL_ISO8583_TYPE;
/******************************************************************************/
//
// VARIABLES
//
static DL_ISO8583_TYPE fieldTypeArr[] = {
/* ISO_N */ {_unpack_iso_ASCHEX,_pack_iso_ASCHEX},
/* ISO_NS */ {_unpack_iso_BINARY,_pack_iso_BINARY},
/* ISO_XN */ {_unpack_iso_ASCHEX,_pack_iso_ASCHEX},
/* ISO_A */ {_unpack_iso_ASCII ,_pack_iso_ASCII },
/* ISO_AN */ {_unpack_iso_ASCII ,_pack_iso_ASCII },
/* ISO_ANS */ {_unpack_iso_ASCII ,_pack_iso_ASCII },
/* ISO_ANSB */ {_unpack_iso_ASCII ,_pack_iso_ASCII },
/* ISO_ANP */ {_unpack_iso_ASCII ,_pack_iso_ASCII },
/* ISO_B */ {_unpack_iso_BINARY,_pack_iso_BINARY},
/* ISO_Z */ {_unpack_iso_BINARY,_pack_iso_BINARY},
/* ISO_BMAP */ {_unpack_iso_BITMAP,_pack_iso_BITMAP} };
/******************************************************************************/
//
// MACROS
//
// gets the field type details
#define GetFieldType(fieldType)\
(&fieldTypeArr[fieldType])
/******************************************************************************/
DL_ERR _DL_ISO8583_FIELD_Pack ( DL_UINT16 iField,
const DL_ISO8583_MSG *iMsg,
const DL_ISO8583_HANDLER *iHandler,
DL_UINT8 **ioPtr )
{
DL_ERR err = kDL_ERR_NONE;
DL_ISO8583_FIELD_DEF *fieldDefPtr = DL_ISO8583_GetFieldDef(iField,iHandler);
DL_ISO8583_TYPE *fieldTypePtr = GetFieldType(fieldDefPtr->fieldType);
err = fieldTypePtr->packFunc(iField,iMsg,fieldDefPtr,ioPtr);
return err;
}
/******************************************************************************/
DL_ERR _DL_ISO8583_FIELD_Unpack ( DL_UINT16 iField,
DL_ISO8583_MSG *ioMsg,
const DL_ISO8583_HANDLER *iHandler,
DL_UINT8 **ioPtr )
{
DL_ERR err = kDL_ERR_NONE;
DL_ISO8583_FIELD_DEF *fieldDefPtr = DL_ISO8583_GetFieldDef(iField,iHandler);
DL_ISO8583_TYPE *fieldTypePtr = GetFieldType(fieldDefPtr->fieldType);
err = fieldTypePtr->unpackFunc(iField,ioMsg,fieldDefPtr,ioPtr);
return err;
}
/******************************************************************************/
DL_ERR _pack_iso_ASCHEX ( DL_UINT16 iField,
const DL_ISO8583_MSG *iMsg,
const DL_ISO8583_FIELD_DEF *iFieldDefPtr,
DL_UINT8 **ioPtr )
{
DL_ERR err = kDL_ERR_NONE;
DL_UINT8 *tmpPtr = *ioPtr;
DL_ISO8583_MSG_FIELD *fieldPtr = ((DL_ISO8583_MSG*)iMsg)->field + iField;
DL_UINT32 actLen = fieldPtr->len;
DL_UINT8 *dataPtr = fieldPtr->ptr;
DL_UINT32 reqLen = iFieldDefPtr->len;
DL_UINT32 wholeActBytes = 0;
DL_UINT32 wholeReqBytes = 0;
DL_UINT32 i;
/* variable length handling */
err = VarLen_Put(iFieldDefPtr->varLen,actLen,&reqLen,&tmpPtr);
if ( !err )
{
if ( actLen > reqLen ) /* too long */
{
err = kDL_ERR_OTHER;
}
else
{
/* determine numbers of bytes for required / actual lengths */
/* NB 'required bytes' are rounded up, 'actual' are rounded down */
wholeActBytes = actLen / 2;
wholeReqBytes = (reqLen + 1) / 2;
/* output left padding (00h) bytes - where required */
/* NB less one if the actual length has an odd number of digits */
i = wholeReqBytes - wholeActBytes;
if ( actLen % 2 )
i--;
DL_MEM_memset(tmpPtr,0,i);
tmpPtr += i;
/* handle partial digit - if required */
if ( actLen % 2 ) /* have partial digit */
{
*tmpPtr++ = (DL_UINT8)DL_ASCHEX_2_NIBBLE(dataPtr[0]);
dataPtr++;
}
/* handle complete digit pairs */
for ( i=0 ; i<wholeActBytes ; i++,dataPtr+=2 )
{
*tmpPtr++ = (DL_UINT8)((DL_ASCHEX_2_NIBBLE(dataPtr[0]) << 4) |
DL_ASCHEX_2_NIBBLE(dataPtr[1]) );
} /* end-for */
}
}
*ioPtr = tmpPtr;
return err;
}
/******************************************************************************/
// unpacks ISO Numeric (bcd format)
// NB if iSize is odd then we have a padding char on left
// (but don't include when unpacking)
// NB doesn't remove any leading padding (0 nibbles)
DL_ERR _unpack_iso_ASCHEX ( DL_UINT16 iField,
DL_ISO8583_MSG *ioMsg,
const DL_ISO8583_FIELD_DEF *iFieldDefPtr,
DL_UINT8 **ioPtr )
{
DL_ERR err = kDL_ERR_NONE;
DL_UINT8 *tmpPtr = *ioPtr;
DL_UINT16 size = 0;
DL_UINT8 *tmpDataPtr = NULL;
/* variable length handling */
err = VarLen_Get(&tmpPtr,iFieldDefPtr->varLen,iFieldDefPtr->len,&size);
/* allocate field */
if ( !err )
err = _DL_ISO8583_MSG_AllocField(iField,size,ioMsg,&tmpDataPtr);
if ( !err )
{
DL_UINT8 ch;
/* if size is 'odd' then ignore the leading nibble, as this is a pad character */
if ( size % 2 ) /* odd */
{
ch = *tmpPtr & 0x0f;
*tmpDataPtr++ = DL_NIBBLE_2_ASCHEX(ch);
tmpPtr++;
size -= 1;
}
size /= 2;
while ( size-- > 0 )
{
ch = (*tmpPtr >> 4) & 0xf;
*tmpDataPtr++ = DL_NIBBLE_2_ASCHEX(ch);
ch = *tmpPtr & 0xf;
*tmpDataPtr++ = DL_NIBBLE_2_ASCHEX(ch);
tmpPtr++;
}
*tmpDataPtr = kDL_ASCII_NULL; /* null terminate */
}
*ioPtr = tmpPtr;
return err;
}
/******************************************************************************/
DL_ERR _pack_iso_ASCII ( DL_UINT16 iField,
const DL_ISO8583_MSG *iMsg,
const DL_ISO8583_FIELD_DEF *iFieldDefPtr,
DL_UINT8 **ioPtr )
{
DL_ERR err = kDL_ERR_NONE;
DL_UINT8 *tmpPtr = *ioPtr;
DL_ISO8583_MSG_FIELD *fieldPtr = ((DL_ISO8583_MSG*)iMsg)->field + iField;
DL_UINT32 actLen = fieldPtr->len;
DL_UINT8 *dataPtr = fieldPtr->ptr;
DL_UINT32 reqLen = iFieldDefPtr->len;
/* variable length handling */
err = VarLen_Put(iFieldDefPtr->varLen,actLen,&reqLen,&tmpPtr);
if ( !err )
{
if ( actLen > reqLen ) /* too long */
{
err = kDL_ERR_OTHER;
}
else if ( actLen == reqLen ) /* exact size */
{
/* copy up to 'required' amount */
DL_MEM_memcpy(tmpPtr,dataPtr,reqLen);
tmpPtr += reqLen;
}
else /* shorter - so need to right pad (space) */
{
/* copy what data we have (actual length) */
DL_MEM_memcpy(tmpPtr,dataPtr,actLen);
/* right pad as required */
DL_MEM_memset(tmpPtr+actLen,(int)kDL_ASCII_SP,reqLen-actLen);
tmpPtr += reqLen;
}
}
*ioPtr = tmpPtr;
return err;
}
/******************************************************************************/
// NB doesn't remove any trailing padding (spaces)
DL_ERR _unpack_iso_ASCII ( DL_UINT16 iField,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -