1119 lines
32 KiB
C++
Executable File
1119 lines
32 KiB
C++
Executable File
/*===========================================================================
|
|
FILE:
|
|
DataParser.cpp
|
|
|
|
DESCRIPTION:
|
|
Implementation of sParsedField and cDataParser
|
|
|
|
PUBLIC CLASSES AND METHODS:
|
|
sParsedField
|
|
Structure to represent a single parsed field (field ID, offset,
|
|
size, value, name, etc.)
|
|
|
|
cDataParser
|
|
Class to parse a buffer into bit/byte specified fields accordinging
|
|
to a database description, uses cProtocolEntityNav to navigate the DB
|
|
definition
|
|
|
|
Copyright (c) 2011, Code Aurora Forum. All rights reserved.
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
modification, are permitted provided that the following conditions are met:
|
|
* Redistributions of source code must retain the above copyright
|
|
notice, this list of conditions and the following disclaimer.
|
|
* Redistributions in binary form must reproduce the above copyright
|
|
notice, this list of conditions and the following disclaimer in the
|
|
documentation and/or other materials provided with the distribution.
|
|
* Neither the name of Code Aurora Forum nor
|
|
the names of its contributors may be used to endorse or promote
|
|
products derived from this software without specific prior written
|
|
permission.
|
|
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
POSSIBILITY OF SUCH DAMAGE.
|
|
===========================================================================*/
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Include Files
|
|
//---------------------------------------------------------------------------
|
|
#include "StdAfx.h"
|
|
#include "DataParser.h"
|
|
|
|
#include "CoreDatabase.h"
|
|
#include "DB2Utilities.h"
|
|
|
|
#include <climits>
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Definitions
|
|
//---------------------------------------------------------------------------
|
|
|
|
/*=========================================================================*/
|
|
// sParsedField Methods
|
|
/*=========================================================================*/
|
|
|
|
/*===========================================================================
|
|
METHOD:
|
|
sParsedField (Public Method)
|
|
|
|
DESCRIPTION:
|
|
Construct a parsed field by setting the values and extracting
|
|
the data according to the definition
|
|
|
|
PARAMETERS:
|
|
db [ I ] - Database to use
|
|
field [ I ] - Field description (from database)
|
|
name [ I ] - Desired field name
|
|
bp [I/O] - Bit parser to use
|
|
bGenStrings [ I ] - Generate field value strings?
|
|
|
|
NOTE: 'bGenStrings' does not apply to fields that are string types?
|
|
|
|
RETURN VALUE:
|
|
None
|
|
===========================================================================*/
|
|
sParsedField::sParsedField(
|
|
const cCoreDatabase & db,
|
|
const sDB2Field * pField,
|
|
const std::string & name,
|
|
cBitParser & bp,
|
|
bool bGenStrings )
|
|
: mField(),
|
|
mOffset( bp.GetNumBitsParsed() ),
|
|
mValueString( "" ),
|
|
mName( name ),
|
|
mbValid( false )
|
|
{
|
|
// Clear value
|
|
memset( (PVOID)&mValue, 0, (SIZE_T)sizeof( mValue ) );
|
|
|
|
// Assume failure
|
|
bool bOK = false;
|
|
if (pField == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
mField = *pField;
|
|
|
|
char tempValueString[128];
|
|
memset( &tempValueString[0], 0, 128 );
|
|
|
|
// What type is this field?
|
|
switch (mField.mType)
|
|
{
|
|
case eDB2_FIELD_STD:
|
|
{
|
|
// Standard field, what kind?
|
|
eDB2StdFieldType ft = (eDB2StdFieldType)mField.mTypeVal;
|
|
switch (ft)
|
|
{
|
|
// Field is a boolean (0/1, false/true)/8-bit unsigned integer
|
|
case eDB2_FIELD_STDTYPE_BOOL:
|
|
case eDB2_FIELD_STDTYPE_UINT8:
|
|
{
|
|
// We store as a UCHAR
|
|
UCHAR val;
|
|
DWORD rc = bp.Get( mField.mSize, val );
|
|
if (rc == NO_ERROR)
|
|
{
|
|
// Constrain boolean values?
|
|
if (ft == eDB2_FIELD_STDTYPE_BOOL && val > 1)
|
|
{
|
|
val = 1;
|
|
}
|
|
|
|
// Success!
|
|
mValue.mU8 = val;
|
|
bOK = true;
|
|
|
|
if (bGenStrings == true)
|
|
{
|
|
if (mField.mbHex == true)
|
|
{
|
|
snprintf( &tempValueString[0], 0, "0x%02X", (UINT)mValue.mU8 );
|
|
}
|
|
else
|
|
{
|
|
snprintf( &tempValueString[0], 0, "%u", (UINT)mValue.mU8 );
|
|
}
|
|
mValueString = &tempValueString[0];
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
// Field is 8-bit signed integer
|
|
case eDB2_FIELD_STDTYPE_INT8:
|
|
{
|
|
// We store as a CHAR
|
|
CHAR val;
|
|
DWORD rc = bp.Get( mField.mSize, val );
|
|
if (rc == NO_ERROR)
|
|
{
|
|
// Success!
|
|
mValue.mS8 = val;
|
|
bOK = true;
|
|
|
|
if (bGenStrings == true)
|
|
{
|
|
if (mField.mbHex == true)
|
|
{
|
|
snprintf( &tempValueString[0], 0, "0x%02X", (UINT)mValue.mU8 );
|
|
}
|
|
else
|
|
{
|
|
snprintf( &tempValueString[0], 0, "%d", (INT)mValue.mS8 );
|
|
}
|
|
mValueString = &tempValueString[0];
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
// Field is 16-bit signed integer
|
|
case eDB2_FIELD_STDTYPE_INT16:
|
|
{
|
|
// We store as a SHORT
|
|
SHORT val;
|
|
DWORD rc = bp.Get( mField.mSize, val );
|
|
if (rc == NO_ERROR)
|
|
{
|
|
// Success!
|
|
mValue.mS16 = val;
|
|
bOK = true;
|
|
|
|
if (bGenStrings == true)
|
|
{
|
|
if (mField.mbHex == true)
|
|
{
|
|
snprintf( &tempValueString[0], 0, "0x%04hX", mValue.mU16 );
|
|
}
|
|
else
|
|
{
|
|
snprintf( &tempValueString[0], 0, "%hd", mValue.mS16 );
|
|
}
|
|
mValueString = &tempValueString[0];
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
// Field is 16-bit unsigned integer
|
|
case eDB2_FIELD_STDTYPE_UINT16:
|
|
{
|
|
// We store as a USHORT
|
|
USHORT val;
|
|
DWORD rc = bp.Get( mField.mSize, val );
|
|
if (rc == NO_ERROR)
|
|
{
|
|
// Success!
|
|
mValue.mU16 = val;
|
|
bOK = true;
|
|
|
|
if (bGenStrings == true)
|
|
{
|
|
if (mField.mbHex == true)
|
|
{
|
|
snprintf( &tempValueString[0], 0, "0x%04hX", mValue.mU16 );
|
|
}
|
|
else
|
|
{
|
|
snprintf( &tempValueString[0], 0, "%hu", mValue.mU16 );
|
|
}
|
|
mValueString = &tempValueString[0];
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
// Field is 32-bit signed integer
|
|
case eDB2_FIELD_STDTYPE_INT32:
|
|
{
|
|
// We store as a LONG
|
|
LONG val;
|
|
DWORD rc = bp.Get( mField.mSize, val );
|
|
if (rc == NO_ERROR)
|
|
{
|
|
// Success!
|
|
mValue.mS32 = val;
|
|
bOK = true;
|
|
|
|
if (bGenStrings == true)
|
|
{
|
|
if (mField.mbHex == true)
|
|
{
|
|
snprintf( &tempValueString[0], 0, "0x%08lX", mValue.mU32 );
|
|
}
|
|
else
|
|
{
|
|
snprintf( &tempValueString[0], 0, "%ld", mValue.mS32 );
|
|
}
|
|
mValueString = &tempValueString[0];
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
// Field is 32-bit unsigned integer
|
|
case eDB2_FIELD_STDTYPE_UINT32:
|
|
{
|
|
// We store as a ULONG
|
|
ULONG val;
|
|
DWORD rc = bp.Get( mField.mSize, val );
|
|
if (rc == NO_ERROR)
|
|
{
|
|
// Success!
|
|
mValue.mU32 = val;
|
|
bOK = true;
|
|
|
|
if (bGenStrings == true)
|
|
{
|
|
if (mField.mbHex == true)
|
|
{
|
|
snprintf( &tempValueString[0], 0, "0x%08lX", mValue.mU32 );
|
|
}
|
|
else
|
|
{
|
|
snprintf( &tempValueString[0], 0, "%lu", mValue.mU32 );
|
|
}
|
|
mValueString = &tempValueString[0];
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
// Field is 64-bit signed integer
|
|
case eDB2_FIELD_STDTYPE_INT64:
|
|
{
|
|
// We store as a LONGLONG
|
|
LONGLONG val;
|
|
DWORD rc = bp.Get( mField.mSize, val );
|
|
if (rc == NO_ERROR)
|
|
{
|
|
// Success!
|
|
mValue.mS64 = val;
|
|
bOK = true;
|
|
|
|
if (bGenStrings == true)
|
|
{
|
|
if (mField.mbHex == true)
|
|
{
|
|
snprintf( &tempValueString[0], 0, "0x%016llX", mValue.mU64 );
|
|
}
|
|
else
|
|
{
|
|
snprintf( &tempValueString[0], 0, "%lld", mValue.mS64 );
|
|
}
|
|
mValueString = &tempValueString[0];
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
// Field is 64-bit unsigned integer
|
|
case eDB2_FIELD_STDTYPE_UINT64:
|
|
{
|
|
// We store as a ULONGLONG
|
|
ULONGLONG val;
|
|
DWORD rc = bp.Get( mField.mSize, val );
|
|
if (rc == NO_ERROR)
|
|
{
|
|
// Success!
|
|
mValue.mU64 = val;
|
|
bOK = true;
|
|
|
|
if (bGenStrings == true)
|
|
{
|
|
if (mField.mbHex == true)
|
|
{
|
|
snprintf( &tempValueString[0], 0, "0x%016llX", mValue.mU64 );
|
|
}
|
|
else
|
|
{
|
|
snprintf( &tempValueString[0], 0, "%llu", mValue.mU64 );
|
|
}
|
|
mValueString = &tempValueString[0];
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
// ANSI/UNICODE fixed length string
|
|
case eDB2_FIELD_STDTYPE_STRING_A:
|
|
case eDB2_FIELD_STDTYPE_STRING_U:
|
|
{
|
|
// Compute the number of characters
|
|
ULONG numChars = mField.mSize / BITS_PER_BYTE;
|
|
|
|
// Parse out the string
|
|
bOK = ParseString( numChars, bp );
|
|
}
|
|
break;
|
|
|
|
// ANSI NULL terminated string
|
|
case eDB2_FIELD_STDTYPE_STRING_ANT:
|
|
{
|
|
// Figure out the length of the string
|
|
ULONG numChars = 0;
|
|
|
|
// Temporarily assume success
|
|
bOK = true;
|
|
|
|
ULONG tmpOffset = bp.GetNumBitsParsed();
|
|
|
|
CHAR val = 1;
|
|
while (val != 0)
|
|
{
|
|
DWORD rc = bp.Get( BITS_PER_BYTE, val );
|
|
if (rc == NO_ERROR)
|
|
{
|
|
numChars++;
|
|
}
|
|
else
|
|
{
|
|
val = 0;
|
|
}
|
|
}
|
|
|
|
// Now actually parse/load the string
|
|
if (bOK == true)
|
|
{
|
|
bp.SetOffset( tmpOffset );
|
|
bOK = ParseString( numChars, bp );
|
|
}
|
|
}
|
|
break;
|
|
|
|
// UNICODE NULL terminated string
|
|
case eDB2_FIELD_STDTYPE_STRING_UNT:
|
|
{
|
|
// Figure out the length of the string
|
|
ULONG numChars = 0;
|
|
|
|
// Temporarily assume success
|
|
bOK = true;
|
|
|
|
ULONG tmpOffset = bp.GetNumBitsParsed();
|
|
|
|
USHORT val = 1;
|
|
while (val != 0)
|
|
{
|
|
DWORD rc = bp.Get( BITS_PER_BYTE, val );
|
|
if (rc == NO_ERROR)
|
|
{
|
|
numChars++;
|
|
}
|
|
else
|
|
{
|
|
val = 0;
|
|
}
|
|
}
|
|
|
|
// Now actually parse/load the string
|
|
if (bOK == true)
|
|
{
|
|
bp.SetOffset( tmpOffset );
|
|
bOK = ParseString( numChars, bp );
|
|
}
|
|
}
|
|
break;
|
|
|
|
case eDB2_FIELD_STDTYPE_STRING_U8:
|
|
case eDB2_FIELD_STDTYPE_STRING_U8NT:
|
|
// Unsupported in the Linux adaptation
|
|
bOK = false;
|
|
break;
|
|
|
|
// Field is 32-bit floating point value
|
|
case eDB2_FIELD_STDTYPE_FLOAT32:
|
|
{
|
|
// We store as a ULONG
|
|
ULONG val;
|
|
DWORD rc = bp.Get( mField.mSize, val );
|
|
if (rc == NO_ERROR)
|
|
{
|
|
FLOAT * pFloat = (FLOAT *)&val;
|
|
|
|
// Success!
|
|
mValue.mFP32 = *pFloat;
|
|
bOK = true;
|
|
|
|
if (bGenStrings == true)
|
|
{
|
|
if (mField.mbHex == true)
|
|
{
|
|
snprintf( &tempValueString[0], 0, "0x%04lX", mValue.mU32 );
|
|
}
|
|
else
|
|
{
|
|
snprintf( &tempValueString[0], 0, "%f", mValue.mFP32 );
|
|
}
|
|
mValueString = &tempValueString[0];
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
// Field is 64-bit floating point value
|
|
case eDB2_FIELD_STDTYPE_FLOAT64:
|
|
{
|
|
// We store as a ULONGLONG
|
|
ULONGLONG val;
|
|
DWORD rc = bp.Get( mField.mSize, val );
|
|
if (rc == NO_ERROR)
|
|
{
|
|
DOUBLE * pFloat = (DOUBLE *)&val;
|
|
|
|
// Success!
|
|
mValue.mFP64 = *pFloat;
|
|
bOK = true;
|
|
|
|
if (bGenStrings == true)
|
|
{
|
|
if (mField.mbHex == true)
|
|
{
|
|
snprintf( &tempValueString[0], 0, "0x%08llX", mValue.mU64 );
|
|
}
|
|
else
|
|
{
|
|
snprintf( &tempValueString[0], 0, "%f", mValue.mFP64 );
|
|
}
|
|
mValueString = &tempValueString[0];
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
|
|
// Unsigend enum value
|
|
case eDB2_FIELD_ENUM_UNSIGNED:
|
|
{
|
|
// We store as a ULONG
|
|
ULONG val;
|
|
DWORD rc = bp.Get( mField.mSize, val );
|
|
if (rc == NO_ERROR)
|
|
{
|
|
// Success!
|
|
mValue.mU32 = val;
|
|
bOK = true;
|
|
|
|
// Grab the enum ID
|
|
ULONG id = pField->mTypeVal;
|
|
|
|
// Map to a string?
|
|
if (bGenStrings == true)
|
|
{
|
|
mValueString = db.MapEnumToString( id,
|
|
(int)mValue.mU32,
|
|
true,
|
|
mField.mbHex );
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
// Signed enum value
|
|
case eDB2_FIELD_ENUM_SIGNED:
|
|
{
|
|
// We store as a LONG
|
|
LONG val;
|
|
DWORD rc = bp.Get( mField.mSize, val );
|
|
if (rc == NO_ERROR)
|
|
{
|
|
// Success!
|
|
mValue.mS32 = val;
|
|
bOK = true;
|
|
|
|
// Grab the enum ID
|
|
ULONG id = pField->mTypeVal;
|
|
|
|
// Map to a string?
|
|
if (bGenStrings == true)
|
|
{
|
|
mValueString = db.MapEnumToString( id,
|
|
(int)mValue.mS32,
|
|
true,
|
|
mField.mbHex );
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
mbValid = bOK;
|
|
}
|
|
|
|
/*===========================================================================
|
|
METHOD:
|
|
ParseString (Public Method)
|
|
|
|
DESCRIPTION:
|
|
Convert the field value to a string
|
|
|
|
PARAMETERS:
|
|
numChars [ I ] - Number of characters to parse/load
|
|
bp [I/O] - Bit parser to use
|
|
|
|
RETURN VALUE:
|
|
bool
|
|
===========================================================================*/
|
|
bool sParsedField::ParseString(
|
|
ULONG numChars,
|
|
cBitParser & bp )
|
|
{
|
|
// Validate size (including null char)
|
|
if (MAX_SHARED_BUFFER_SIZE < numChars + 1)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// Assume success
|
|
bool bRC = true;
|
|
|
|
// Store current offset so we can update field length
|
|
ULONG curOffset = bp.GetNumBitsParsed();
|
|
|
|
// Load each byte of the string individually
|
|
BYTE buf[MAX_SHARED_BUFFER_SIZE];
|
|
for (ULONG c = 0; c < numChars; c++)
|
|
{
|
|
BYTE val = 0;
|
|
DWORD rc = bp.Get( BITS_PER_BYTE, val );
|
|
if (rc == NO_ERROR)
|
|
{
|
|
buf[c] = val;
|
|
}
|
|
else
|
|
{
|
|
bRC = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (bRC == true)
|
|
{
|
|
// Write zeros to the rest of the buffer
|
|
ULONG size = numChars;
|
|
ULONG end = numChars + 1;
|
|
for (ULONG current = size; current < end; current++)
|
|
{
|
|
buf[current] = 0;
|
|
}
|
|
|
|
mValueString = (LPCSTR)&buf[0];
|
|
|
|
mValue.mpAStr = (LPCSTR)mValueString.c_str();
|
|
|
|
// Update field size
|
|
mField.mSize = bp.GetNumBitsParsed() - curOffset;
|
|
}
|
|
|
|
return bRC;
|
|
}
|
|
|
|
/*=========================================================================*/
|
|
// cParsedFieldNavigator Methods
|
|
/*=========================================================================*/
|
|
|
|
/*===========================================================================
|
|
METHOD:
|
|
GetFieldIndex (Public Method)
|
|
|
|
DESCRIPTION:
|
|
Get index of the (first) field that matches the given field ID
|
|
|
|
PARAMETERS:
|
|
fieldID [ I ] - Field ID to look for
|
|
bLoop [ I ] - Loop around end of field list?
|
|
|
|
RETURN VALUE:
|
|
ULONG - Index of the field (0xFFFFFFFF upon failure)
|
|
===========================================================================*/
|
|
ULONG cParsedFieldNavigator::GetFieldIndex(
|
|
ULONG fieldID,
|
|
bool bLoop ) const
|
|
{
|
|
ULONG id = ULONG_MAX;
|
|
ULONG count = (ULONG)mFields.size();
|
|
|
|
// Start from last field ID?
|
|
ULONG fp = 0;
|
|
ULONG fi = 0;
|
|
if (mLastIDIndex < count)
|
|
{
|
|
fi = mLastIDIndex;
|
|
}
|
|
else if (mLastIDIndex != ULONG_MAX && bLoop == false)
|
|
{
|
|
// Beyond end of fields with no looping
|
|
mLastIDIndex = id;
|
|
return id;
|
|
}
|
|
|
|
for (fp = 0; fp < count; fp++)
|
|
{
|
|
if (mFields[fi].mField.mID == fieldID)
|
|
{
|
|
id = fi;
|
|
break;
|
|
}
|
|
|
|
fi++;
|
|
if (fi == count)
|
|
{
|
|
if (bLoop == true)
|
|
{
|
|
fi = 0;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Update last ID accordingly (0xFFFFFFFF upon failure), and return
|
|
mLastIDIndex = id;
|
|
if (mLastIDIndex != ULONG_MAX)
|
|
{
|
|
mLastIDIndex++;
|
|
if (mLastIDIndex == count)
|
|
{
|
|
mLastIDIndex = 0;
|
|
}
|
|
}
|
|
|
|
return id;
|
|
}
|
|
|
|
/*=========================================================================*/
|
|
// cDataParser Methods
|
|
/*=========================================================================*/
|
|
|
|
/*===========================================================================
|
|
METHOD:
|
|
cDataParser (Public Method)
|
|
|
|
DESCRIPTION:
|
|
Constructor (protocol buffer, entity key, and payload)
|
|
|
|
PARAMETERS:
|
|
db [ I ] - Database to use
|
|
buffer [ I ] - The protocol buffer being parsed
|
|
key [ I ] - Protocol entity key
|
|
pData [ I ] - Payload from above protocol buffer
|
|
dataLen [ I ] - Size of above payload
|
|
|
|
RETURN VALUE:
|
|
None
|
|
===========================================================================*/
|
|
cDataParser::cDataParser(
|
|
const cCoreDatabase & db,
|
|
const sProtocolBuffer & buffer,
|
|
const std::vector <ULONG> & key,
|
|
const BYTE * pData,
|
|
ULONG dataLen )
|
|
: cProtocolEntityNav( db ),
|
|
mBuffer( buffer.GetSharedBuffer() ),
|
|
mbFieldStrings( true ),
|
|
mbParsed( false )
|
|
{
|
|
// We must have a valid protocol buffer
|
|
if (mBuffer.IsValid() == false)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// We need something to parse
|
|
if (pData == 0 || dataLen == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Key has to be proper
|
|
if (key.size() < 1)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Key needs to match protocol
|
|
eProtocolType pt = (eProtocolType)mBuffer.GetType();
|
|
eDB2EntityType et = (eDB2EntityType)key[0];
|
|
|
|
if (pt == ePROTOCOL_DIAG_RX || pt == ePROTOCOL_DIAG_TX)
|
|
{
|
|
if (IsDiagEntityType( et ) == false)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
else if (IsQMIProtocol( pt ) == true)
|
|
{
|
|
if (IsQMIEntityType( et ) == false)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Pass data to the bit parser
|
|
mKey = key;
|
|
mBitsy.SetData( pData, dataLen * BITS_PER_BYTE );
|
|
}
|
|
|
|
/*===========================================================================
|
|
METHOD:
|
|
~cDataParser (Public Method)
|
|
|
|
DESCRIPTION:
|
|
Destructor
|
|
|
|
RETURN VALUE:
|
|
None
|
|
===========================================================================*/
|
|
cDataParser::~cDataParser()
|
|
{
|
|
// Ask bit parser to release data
|
|
mBitsy.ReleaseData();
|
|
|
|
// Empty fields
|
|
mFields.clear();
|
|
}
|
|
|
|
/*===========================================================================
|
|
METHOD:
|
|
Parse (Public Method)
|
|
|
|
DESCRIPTION:
|
|
Parse the data to a list of fields/summary text
|
|
|
|
PARAMETERS:
|
|
bFieldStrings [ I ] - Generate string representations of field values?
|
|
bFieldNames [ I ] - Generate (partial) field names?
|
|
|
|
RETURN VALUE:
|
|
bool
|
|
===========================================================================*/
|
|
bool cDataParser::Parse(
|
|
bool bFieldStrings,
|
|
bool bFieldNames )
|
|
{
|
|
// Store parsing options
|
|
mbFieldStrings = bFieldStrings;
|
|
mbFieldNames = bFieldNames;
|
|
|
|
if (mbParsed == false)
|
|
{
|
|
// Allocate space for 1024 fields up front in order to increase
|
|
// performance when parsing and accessing parsed fields
|
|
mFields.reserve( 1024 );
|
|
|
|
// Process (parse) the protocol entity
|
|
mbParsed = ProcessEntity( mKey );
|
|
}
|
|
|
|
return mbParsed;
|
|
}
|
|
|
|
|
|
/*===========================================================================
|
|
METHOD:
|
|
GetLastValue (Internal Method)
|
|
|
|
DESCRIPTION:
|
|
Working from the back of the current field list find and return the
|
|
value for the specified field ID as a LONGLONG (field type must be
|
|
able to fit in a LONGLONG for a value to be returned)
|
|
|
|
PARAMETERS:
|
|
fieldID [ I ] - Field ID we are looking for
|
|
val [ O ] - The value
|
|
|
|
RETURN VALUE:
|
|
bool
|
|
===========================================================================*/
|
|
bool cDataParser::GetLastValue(
|
|
ULONG fieldID,
|
|
LONGLONG & val )
|
|
{
|
|
// Assume failure
|
|
bool bRC = false;
|
|
|
|
// Use field value tracking information
|
|
std::map <ULONG, std::pair <bool, LONGLONG> >::iterator pTF;
|
|
pTF = mTrackedFields.find( fieldID );
|
|
if (pTF != mTrackedFields.end() && pTF->second.first == true)
|
|
{
|
|
val = pTF->second.second;
|
|
bRC = true;
|
|
}
|
|
|
|
return bRC;
|
|
}
|
|
|
|
/*===========================================================================
|
|
METHOD:
|
|
ContinueNavigation (Internal Method)
|
|
|
|
DESCRIPTION:
|
|
Continue navigation now that entity has been set?
|
|
|
|
RETURN VALUE:
|
|
bool
|
|
===========================================================================*/
|
|
bool cDataParser::ContinueNavigation()
|
|
{
|
|
// Proceed to parse?
|
|
bool bParse = true;
|
|
|
|
// Is there actually something to process?
|
|
if (mBitsy.GetNumBitsLeft() == 0)
|
|
{
|
|
bParse = false;
|
|
}
|
|
|
|
return bParse;
|
|
}
|
|
|
|
/*===========================================================================
|
|
METHOD:
|
|
ProcessField (Internal Method)
|
|
|
|
DESCRIPTION:
|
|
Process the given field by parsing the value
|
|
|
|
PARAMETERS:
|
|
pField [ I ] - The field being processed
|
|
fieldName [ I ] - Field name (partial)
|
|
arrayIndex [ I ] - Not used
|
|
|
|
RETURN VALUE:
|
|
bool
|
|
===========================================================================*/
|
|
bool cDataParser::ProcessField(
|
|
const sDB2Field * pField,
|
|
const std::string & fieldName,
|
|
LONGLONG /* arrayIndex */ )
|
|
{
|
|
// Assume failure
|
|
bool bRC = false;
|
|
if (pField == 0)
|
|
{
|
|
return bRC;
|
|
}
|
|
|
|
// We must have a name
|
|
sParsedField theField( mDB,
|
|
pField,
|
|
fieldName,
|
|
mBitsy,
|
|
mbFieldStrings );
|
|
|
|
// Did that result in a valid field?
|
|
if (theField.IsValid() == true)
|
|
{
|
|
// Add field
|
|
mFields.push_back( theField );
|
|
bRC = true;
|
|
|
|
// Are we tracking the value of this field?
|
|
std::map <ULONG, std::pair <bool, LONGLONG> >::iterator pTF;
|
|
pTF = mTrackedFields.find( pField->mID );
|
|
if (pTF != mTrackedFields.end())
|
|
{
|
|
std::pair <bool, LONGLONG> & entry = pTF->second;
|
|
|
|
// What type is this field?
|
|
switch (pField->mType)
|
|
{
|
|
case eDB2_FIELD_STD:
|
|
{
|
|
// Standard field, what kind?
|
|
eDB2StdFieldType ft = (eDB2StdFieldType)pField->mTypeVal;
|
|
switch (ft)
|
|
{
|
|
// Field is a boolean (0/1, false/true)/8-bit unsigned
|
|
case eDB2_FIELD_STDTYPE_BOOL:
|
|
case eDB2_FIELD_STDTYPE_UINT8:
|
|
{
|
|
// Treat as UCHAR
|
|
entry.second = (LONGLONG)theField.mValue.mU8;
|
|
entry.first = true;
|
|
}
|
|
break;
|
|
|
|
// Field is 8-bit signed integer
|
|
case eDB2_FIELD_STDTYPE_INT8:
|
|
{
|
|
// Treat as CHAR
|
|
entry.second = (LONGLONG)theField.mValue.mS8;
|
|
entry.first = true;
|
|
}
|
|
break;
|
|
|
|
// Field is 16-bit signed integer
|
|
case eDB2_FIELD_STDTYPE_INT16:
|
|
{
|
|
// Treat as SHORT
|
|
entry.second = (LONGLONG)theField.mValue.mS16;
|
|
entry.first = true;
|
|
}
|
|
break;
|
|
|
|
// Field is 16-bit unsigned integer
|
|
case eDB2_FIELD_STDTYPE_UINT16:
|
|
{
|
|
// Treat as USHORT
|
|
entry.second = (LONGLONG)theField.mValue.mU16;
|
|
entry.first = true;
|
|
}
|
|
break;
|
|
|
|
// Field is 32-bit signed integer
|
|
case eDB2_FIELD_STDTYPE_INT32:
|
|
{
|
|
// Treat as LONG
|
|
entry.second = (LONGLONG)theField.mValue.mS32;
|
|
entry.first = true;
|
|
}
|
|
break;
|
|
|
|
// Field is 32-bit unsigned integer
|
|
case eDB2_FIELD_STDTYPE_UINT32:
|
|
{
|
|
// Treat as ULONG
|
|
entry.second = (LONGLONG)theField.mValue.mU32;
|
|
entry.first = true;
|
|
}
|
|
break;
|
|
|
|
// Field is 64-bit signed integer
|
|
case eDB2_FIELD_STDTYPE_INT64:
|
|
{
|
|
// Treat as LONGLONG
|
|
entry.second = (LONGLONG)theField.mValue.mS64;
|
|
entry.first = true;
|
|
}
|
|
break;
|
|
|
|
// Field is 64-bit unsigned integer
|
|
case eDB2_FIELD_STDTYPE_UINT64:
|
|
{
|
|
// Treat as ULONGLONG
|
|
if (theField.mValue.mU64 <= LLONG_MAX)
|
|
{
|
|
entry.second = (LONGLONG)theField.mValue.mU64;
|
|
entry.first = true;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case eDB2_FIELD_ENUM_UNSIGNED:
|
|
{
|
|
// Treat as ULONG
|
|
entry.second = (LONGLONG)theField.mValue.mU32;
|
|
entry.first = true;
|
|
}
|
|
break;
|
|
|
|
case eDB2_FIELD_ENUM_SIGNED:
|
|
{
|
|
// Treat as LONG
|
|
entry.second = (LONGLONG)theField.mValue.mS32;
|
|
entry.first = true;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return bRC;
|
|
}
|
|
|
|
/*===========================================================================
|
|
METHOD:
|
|
HandleSpecialCases (Internal Method)
|
|
|
|
DESCRIPTION:
|
|
Handle special case processing for summary text generation
|
|
|
|
NOTE: This should only be added to as a last resort
|
|
|
|
PARAMETERS:
|
|
args [I/O] - Current argument list/updated 'special' argument list
|
|
fs [I/O] - Current format specifier/updated 'special' format
|
|
specifier
|
|
|
|
RETURN VALUE:
|
|
None
|
|
===========================================================================*/
|
|
void cDataParser::HandleSpecialCases(
|
|
std::string & args,
|
|
std::string & fs )
|
|
{
|
|
std::vector <ULONG> key = mEntity.GetKey();
|
|
if (key.size() == 2 && key[0] == (ULONG)eDB2_ET_DIAG_EVENT)
|
|
{
|
|
ULONG id = key[1];
|
|
|
|
mBitsy.SetOffset( 0 );
|
|
ULONG lenInBits = mBitsy.GetNumBitsLeft();
|
|
|
|
switch (id)
|
|
{
|
|
case 276:
|
|
if (lenInBits == 16)
|
|
{
|
|
// Old style idle handoff event, remap summary
|
|
args = "idle_handoff";
|
|
fs = "idle_handoff=%u";
|
|
}
|
|
break;
|
|
|
|
case 277:
|
|
if (lenInBits == 16)
|
|
{
|
|
// Old style access handoff event, remap summary
|
|
args = "ms_access_handoff";
|
|
fs = "ms_access_handoff=%u";
|
|
}
|
|
break;
|
|
|
|
case 278:
|
|
if (lenInBits == 16)
|
|
{
|
|
// Old style access probe handoff event, remap summary
|
|
args = "ms_access_probe_handoff";
|
|
fs = "ms_access_probe_handoff=%u";
|
|
}
|
|
break;
|
|
|
|
case 639:
|
|
if (lenInBits == 16)
|
|
{
|
|
// Old style access entry handoff event, remap summary
|
|
args = "ms_access_handoff";
|
|
fs = "ms_access_handoff=%u";
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|