| /*=========================================================================== |
| 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; |
| } |
| } |
| } |