998 lines
26 KiB
C++
Executable File
998 lines
26 KiB
C++
Executable File
/*===========================================================================
|
|
FILE:
|
|
ProtocolEntityNav.cpp
|
|
|
|
DESCRIPTION:
|
|
Implementation of cProtocolEntityNav
|
|
|
|
PUBLIC CLASSES AND METHODS:
|
|
cProtocolEntityNav
|
|
This calss serves as a base for all class that need to
|
|
'navigate' a protocol entity database description. It is
|
|
necessary in order to seperate the structural aspects
|
|
from parsing/packing details
|
|
|
|
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 "ProtocolEntityNav.h"
|
|
#include "BitParser.h"
|
|
#include "CoreUtilities.h"
|
|
#include "DB2NavTree.h"
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Definitions
|
|
//---------------------------------------------------------------------------
|
|
|
|
// Field seperator string
|
|
LPCSTR PE_NAV_FIELD_SEP = ".";
|
|
|
|
/*=========================================================================*/
|
|
// cProtocolEntityNav Methods
|
|
/*=========================================================================*/
|
|
|
|
/*===========================================================================
|
|
METHOD:
|
|
cProtocolEntityNav (Public Method)
|
|
|
|
DESCRIPTION:
|
|
Constructor
|
|
|
|
PARAMETERS:
|
|
db [ I ] - Database to use
|
|
bSummaryOnly [ I ] - Only navigate if a format specifier exists?
|
|
|
|
RETURN VALUE:
|
|
None
|
|
===========================================================================*/
|
|
cProtocolEntityNav::cProtocolEntityNav( const cCoreDatabase & db )
|
|
: mDB( db ),
|
|
mbFieldNames( true ),
|
|
mConditions( db.GetOptionalMods() ),
|
|
mExpressions( db.GetExpressionMods() ),
|
|
mArrays1( db.GetArray1Mods() ),
|
|
mArrays2( db.GetArray2Mods() )
|
|
{
|
|
// Nothing to do
|
|
}
|
|
|
|
/*===========================================================================
|
|
METHOD:
|
|
~cProtocolEntityNav (Public Method)
|
|
|
|
DESCRIPTION:
|
|
Destructor
|
|
|
|
RETURN VALUE:
|
|
None
|
|
===========================================================================*/
|
|
cProtocolEntityNav::~cProtocolEntityNav()
|
|
{
|
|
// Nothing to do
|
|
}
|
|
|
|
/*===========================================================================
|
|
METHOD:
|
|
EvaluateCondition (Internal Method)
|
|
|
|
DESCRIPTION:
|
|
Evaluate the given condition
|
|
|
|
PARAMETERS:
|
|
pCondition [ I ] - Condition to evaluate
|
|
bResult [ O ] - Result of evaluating the condition (true/false)
|
|
|
|
RETURN VALUE:
|
|
bool :
|
|
true - We were able to evaluate the condition
|
|
false - Unable to evaluate condition
|
|
===========================================================================*/
|
|
bool cProtocolEntityNav::EvaluateCondition(
|
|
LPCSTR pCondition,
|
|
bool & bResult )
|
|
{
|
|
// Assume error
|
|
bool bRC = false;
|
|
|
|
tDB2OptionalModMap::const_iterator pIter;
|
|
pIter = mConditions.find( pCondition );
|
|
|
|
if (pIter != mConditions.end())
|
|
{
|
|
const sDB2SimpleCondition & con = pIter->second;
|
|
|
|
// Grab the value for the given field ID
|
|
LONGLONG valA = 0;
|
|
bRC = GetLastValue( con.mID, valA );
|
|
|
|
// Field to field?
|
|
LONGLONG valB = con.mValue;
|
|
if (con.mbF2F == true)
|
|
{
|
|
// Yes, grab value of the second field
|
|
bRC &= GetLastValue( (ULONG)con.mValue, valB );
|
|
}
|
|
|
|
if (bRC == true)
|
|
{
|
|
bResult = sDB2Fragment::EvaluateCondition( valA,
|
|
con.mOperator,
|
|
valB );
|
|
}
|
|
else
|
|
{
|
|
// We could not find the field used in the condition, this
|
|
// can either be because of a bad entity (which is ruled
|
|
// out prior to reaching this point) or the existence of
|
|
// the field itself is based on another condition. The
|
|
// former should not happen and the later is not an error
|
|
bResult = false;
|
|
bRC = true;
|
|
}
|
|
}
|
|
|
|
return bRC;
|
|
}
|
|
|
|
/*===========================================================================
|
|
METHOD:
|
|
GetArrayBounds (Internal Method)
|
|
|
|
DESCRIPTION:
|
|
Get the array bounds described by the fragment descriptor
|
|
|
|
PARAMETERS:
|
|
frag [ I ] - Fragment descriptor
|
|
arraySz [ O ] - Size of array
|
|
arrayAdj [ O ] - Adjust for array indices
|
|
|
|
RETURN VALUE:
|
|
bool
|
|
===========================================================================*/
|
|
bool cProtocolEntityNav::GetArrayBounds(
|
|
const sDB2Fragment & frag,
|
|
LONGLONG & arraySz,
|
|
LONGLONG & arrayAdj )
|
|
{
|
|
// Assume failure
|
|
bool bRC = false;
|
|
|
|
// Figure out the array size/adjust
|
|
arraySz = 0;
|
|
arrayAdj = 0;
|
|
|
|
switch (frag.mModifierType)
|
|
{
|
|
case eDB2_MOD_CONSTANT_ARRAY:
|
|
{
|
|
tDB2Array1ModMap::const_iterator pIter;
|
|
pIter = mArrays1.find( frag.mpModifierValue );
|
|
|
|
if (pIter != mArrays1.end())
|
|
{
|
|
arraySz = (LONGLONG)pIter->second;
|
|
bRC = true;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case eDB2_MOD_VARIABLE_ARRAY:
|
|
{
|
|
tDB2Array1ModMap::const_iterator pIter;
|
|
pIter = mArrays1.find( frag.mpModifierValue );
|
|
|
|
if (pIter != mArrays1.end())
|
|
{
|
|
ULONG id = pIter->second;
|
|
|
|
// Now find last occurence of this field ID and grab the value
|
|
bRC = GetLastValue( id, arraySz );
|
|
if (bRC == true)
|
|
{
|
|
// It makes no sense to have a negative sized array
|
|
if (arraySz < 0)
|
|
{
|
|
bRC = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case eDB2_MOD_VARIABLE_ARRAY2:
|
|
{
|
|
tDB2Array2ModMap::const_iterator pIter;
|
|
pIter = mArrays2.find( frag.mpModifierValue );
|
|
|
|
if (pIter != mArrays2.end())
|
|
{
|
|
ULONG sID = pIter->second.first;
|
|
ULONG eID = pIter->second.second;
|
|
|
|
LONGLONG s;
|
|
LONGLONG e;
|
|
|
|
// Now find last occurence of these field IDs and
|
|
// grab the values
|
|
bRC = GetLastValue( sID, s );
|
|
bRC &= GetLastValue( eID, e );
|
|
if (bRC == true)
|
|
{
|
|
// It makes no sense to have an negative sized array
|
|
if (e < s)
|
|
{
|
|
bRC = false;
|
|
}
|
|
else
|
|
{
|
|
arrayAdj = s;
|
|
arraySz = (e - s) + 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case eDB2_MOD_VARIABLE_ARRAY3:
|
|
{
|
|
tDB2ExpressionModMap::const_iterator pIter;
|
|
pIter = mExpressions.find( frag.mpModifierValue );
|
|
|
|
if (pIter != mExpressions.end())
|
|
{
|
|
const sDB2SimpleExpression & expr = pIter->second;
|
|
|
|
// Grab the value for the given field ID
|
|
LONGLONG valA = 0;
|
|
bRC = GetLastValue( expr.mID, valA );
|
|
|
|
// Field to field?
|
|
LONGLONG valB = expr.mValue;
|
|
if (expr.mbF2F == true)
|
|
{
|
|
// Yes, grab value of the second field
|
|
bRC &= GetLastValue( (ULONG)expr.mValue, valB );
|
|
}
|
|
|
|
if (bRC == true)
|
|
{
|
|
bRC = sDB2Fragment::EvaluateExpression( valA,
|
|
expr.mOperator,
|
|
valB,
|
|
arraySz );
|
|
|
|
// It makes no sense to have a negative sized array
|
|
if (bRC == true && arraySz < 0)
|
|
{
|
|
bRC = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
return bRC;
|
|
}
|
|
|
|
/*===========================================================================
|
|
METHOD:
|
|
ModifyStringLength (Internal Method)
|
|
|
|
DESCRIPTION:
|
|
Modify string length based on existing field value, at the end
|
|
of this function the field size will be the string length in bits
|
|
|
|
PARAMETERS:
|
|
frag [ I ] - Fragment descriptor
|
|
field [ O ] - Field to modify
|
|
|
|
RETURN VALUE:
|
|
bool
|
|
===========================================================================*/
|
|
bool cProtocolEntityNav::ModifyStringLength(
|
|
const sDB2Fragment & frag,
|
|
sDB2Field & field )
|
|
{
|
|
// Assume failure
|
|
bool bRC = false;
|
|
|
|
if (field.mType != eDB2_FIELD_STD)
|
|
{
|
|
// Why are we here?
|
|
ASSERT( 0 );
|
|
return false;
|
|
}
|
|
|
|
if ( (field.mTypeVal != (ULONG)eDB2_FIELD_STDTYPE_STRING_A)
|
|
&& (field.mTypeVal != (ULONG)eDB2_FIELD_STDTYPE_STRING_U)
|
|
&& (field.mTypeVal != (ULONG)eDB2_FIELD_STDTYPE_STRING_U8) )
|
|
{
|
|
// Why are we here?
|
|
ASSERT( 0 );
|
|
return false;
|
|
}
|
|
|
|
if ( (frag.mModifierType == eDB2_MOD_VARIABLE_STRING3)
|
|
&& (field.mTypeVal == (ULONG)eDB2_FIELD_STDTYPE_STRING_U8) )
|
|
{
|
|
// We can't have the size specified in characters when the
|
|
// size of the character itself is variable length
|
|
ASSERT( 0 );
|
|
return false;
|
|
}
|
|
|
|
tDB2Array1ModMap::const_iterator pIter;
|
|
pIter = mArrays1.find( frag.mpModifierValue );
|
|
if (pIter == mArrays1.end())
|
|
{
|
|
// Unable to obtain string length
|
|
return bRC;
|
|
}
|
|
|
|
ULONG id = pIter->second;
|
|
|
|
// Now find last occurence of this field ID and grab the value
|
|
LONGLONG strSz;
|
|
bRC = GetLastValue( id, strSz );
|
|
if (bRC == false || strSz < 0)
|
|
{
|
|
// Unable to obtain size or invalid size
|
|
bRC = false;
|
|
return bRC;
|
|
}
|
|
|
|
// Compute character size
|
|
ULONG charSz = BITS_PER_BYTE;
|
|
if (field.mTypeVal == (ULONG)eDB2_FIELD_STDTYPE_STRING_U)
|
|
{
|
|
charSz *= 2;
|
|
}
|
|
|
|
if (frag.mModifierType == eDB2_MOD_VARIABLE_STRING2)
|
|
{
|
|
strSz *= BITS_PER_BYTE;
|
|
}
|
|
else if (frag.mModifierType == eDB2_MOD_VARIABLE_STRING3)
|
|
{
|
|
strSz *= charSz;
|
|
}
|
|
|
|
if (strSz > ULONG_MAX)
|
|
{
|
|
// String length far too large
|
|
bRC = false;
|
|
return bRC;
|
|
}
|
|
|
|
if (strSz != 0)
|
|
{
|
|
if (strSz < charSz || (strSz % charSz) != 0)
|
|
{
|
|
// String length not a proper multiple of character size
|
|
bRC = false;
|
|
return bRC;
|
|
}
|
|
}
|
|
|
|
field.mSize = (ULONG)strSz;
|
|
return bRC;
|
|
}
|
|
|
|
/*===========================================================================
|
|
METHOD:
|
|
ProcessEntity (Internal Method)
|
|
|
|
DESCRIPTION:
|
|
Process a protocol entity
|
|
|
|
PARAMETERS:
|
|
key [ I ] - Key into the protocol entity table
|
|
|
|
RETURN VALUE:
|
|
bool
|
|
===========================================================================*/
|
|
bool cProtocolEntityNav::ProcessEntity( const std::vector <ULONG> & key )
|
|
{
|
|
// Assume failure
|
|
bool bRC = false;
|
|
|
|
// Look up entity definition
|
|
const cDB2NavTree * pNavTree = mDB.GetEntityNavTree( key );
|
|
|
|
// Did we find it?
|
|
if (pNavTree == 0)
|
|
{
|
|
return bRC;
|
|
}
|
|
|
|
// Is it valid?
|
|
mEntity = pNavTree->GetEntity();
|
|
if (mEntity.IsValid() == false)
|
|
{
|
|
// No definition in database
|
|
return bRC;
|
|
}
|
|
|
|
// Check if we should continue
|
|
if (ContinueNavigation() == false)
|
|
{
|
|
// Success!
|
|
bRC = true;
|
|
return bRC;
|
|
}
|
|
|
|
// A structure to navigate?
|
|
if (mEntity.mStructID == -1)
|
|
{
|
|
// Success!
|
|
bRC = true;
|
|
return bRC;
|
|
}
|
|
|
|
// Grab navigation fragments
|
|
const std::list <sDB2NavFragment *> & frags = pNavTree->GetFragments();
|
|
|
|
// Nothing to navigate?
|
|
if (frags.size() == 0)
|
|
{
|
|
ASSERT( 0 );
|
|
return bRC;
|
|
}
|
|
|
|
// No name?
|
|
if (mEntity.mpName == 0 || mEntity.mpName[0] == 0)
|
|
{
|
|
ASSERT( 0 );
|
|
return bRC;
|
|
}
|
|
|
|
// Grab tracked fields
|
|
mTrackedFields = pNavTree->GetTrackedFields();
|
|
|
|
std::string preamble = "";
|
|
|
|
// Process the initial structure
|
|
EnterStruct( mEntity.mpName, -1 );
|
|
bRC = ProcessStruct( frags.front(), preamble, -1 );
|
|
ExitStruct( mEntity.mpName, -1 );
|
|
|
|
return bRC;
|
|
}
|
|
|
|
/*===========================================================================
|
|
METHOD:
|
|
ProcessStruct (Internal Method)
|
|
|
|
DESCRIPTION:
|
|
Process a structure described by the given initial fragment
|
|
|
|
PARAMETERS:
|
|
pFrag [ I ] - First fragment in structure
|
|
preamable [ I ] - String to prepend to any field/struct names
|
|
arrayIndex [ I ] - Array index (-1 = not part of an array)
|
|
|
|
RETURN VALUE:
|
|
bool
|
|
===========================================================================*/
|
|
bool cProtocolEntityNav::ProcessStruct(
|
|
const sDB2NavFragment * pFrag,
|
|
const std::string & preamble,
|
|
LONGLONG /* arrayIndex */ )
|
|
{
|
|
// Assume success
|
|
bool bRC = true;
|
|
|
|
ULONG structSz = 0;
|
|
ULONG structOffset = GetOffset();
|
|
|
|
// Grab current navigation order
|
|
bool bOldLSB = GetLSBMode();
|
|
bool bNewLSB = bOldLSB;
|
|
|
|
// Check for directives
|
|
if (pFrag != 0)
|
|
{
|
|
bool bDirective = false;
|
|
|
|
const sDB2Fragment & frag = *pFrag->mpFragment;
|
|
if (frag.mFragmentType == eDB2_FRAGMENT_MSB_2_LSB)
|
|
{
|
|
bDirective = true;
|
|
if (bOldLSB == true)
|
|
{
|
|
bNewLSB = false;
|
|
bRC = SetLSBMode( bNewLSB );
|
|
}
|
|
}
|
|
|
|
if (frag.mFragmentType == eDB2_FRAGMENT_LSB_2_MSB)
|
|
{
|
|
bDirective = true;
|
|
if (bOldLSB == false)
|
|
{
|
|
bNewLSB = true;
|
|
bRC = SetLSBMode( bNewLSB );
|
|
}
|
|
}
|
|
|
|
if (bDirective == true)
|
|
{
|
|
// We process directives here so move on to the next fragment
|
|
// upon success
|
|
if (bRC == true)
|
|
{
|
|
pFrag = pFrag->mpNextFragment;
|
|
}
|
|
else
|
|
{
|
|
pFrag = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Process each fragment in the structure
|
|
while (pFrag != 0)
|
|
{
|
|
bRC = ProcessFragment( pFrag, structOffset, structSz, preamble );
|
|
if (bRC == true)
|
|
{
|
|
pFrag = pFrag->mpNextFragment;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Restore navigation order
|
|
if (bRC == true && bOldLSB != bNewLSB)
|
|
{
|
|
bRC = SetLSBMode( bOldLSB );
|
|
}
|
|
|
|
return bRC;
|
|
}
|
|
|
|
/*===========================================================================
|
|
METHOD:
|
|
ProcessFragment (Internal Method)
|
|
|
|
DESCRIPTION:
|
|
Process the given fragment
|
|
|
|
PARAMETERS:
|
|
pFrag [ I ] - Fragment to be processed
|
|
structOffset [ I ] - Offset (from start of payload) of enclosing struct
|
|
structSize [ I ] - Current size of enclosing struct
|
|
preamble [ I ] - String to prepend to any field/struct names
|
|
|
|
RETURN VALUE:
|
|
bool
|
|
===========================================================================*/
|
|
bool cProtocolEntityNav::ProcessFragment(
|
|
const sDB2NavFragment * pFrag,
|
|
ULONG structOffset,
|
|
ULONG & structSize,
|
|
const std::string & preamble )
|
|
{
|
|
// Assume failure
|
|
bool bRC = false;
|
|
if (pFrag == 0 || pFrag->mpFragment == 0)
|
|
{
|
|
return bRC;
|
|
}
|
|
|
|
// Grab database fragment
|
|
const sDB2Fragment & frag = *pFrag->mpFragment;
|
|
|
|
// Is this fragment optional?
|
|
if (frag.mModifierType == eDB2_MOD_OPTIONAL)
|
|
{
|
|
bool bParse = false;
|
|
bool bOK = EvaluateCondition( frag.mpModifierValue, bParse );
|
|
if (bOK == false)
|
|
{
|
|
// Error evaluating the condition
|
|
bRC = false;
|
|
return bRC;
|
|
}
|
|
|
|
if (bParse == false)
|
|
{
|
|
// Condition not satisfied, nothing to parse
|
|
bRC = true;
|
|
return bRC;
|
|
}
|
|
}
|
|
|
|
// Is this an array?
|
|
LONGLONG arraySz = -1;
|
|
LONGLONG arrayAdj = 0;
|
|
bool bArray = ModifiedToArray( frag.mModifierType );
|
|
if (bArray == true)
|
|
{
|
|
bool bOK = GetArrayBounds( frag, arraySz, arrayAdj );
|
|
if (bOK == false)
|
|
{
|
|
// Error obtaining array dimensions
|
|
bRC = false;
|
|
return bRC;
|
|
}
|
|
else if (arraySz == 0)
|
|
{
|
|
// No array to process
|
|
bRC = true;
|
|
return bRC;
|
|
}
|
|
}
|
|
|
|
// Set base name
|
|
std::string baseName = "";
|
|
if (mbFieldNames == true)
|
|
{
|
|
baseName = preamble;
|
|
|
|
// Add in fragment name?
|
|
if (frag.mpName != EMPTY_STRING)
|
|
{
|
|
if (baseName.size() > 0)
|
|
{
|
|
baseName += PE_NAV_FIELD_SEP;
|
|
}
|
|
|
|
// Yes, add to the preamble
|
|
baseName += frag.mpName;
|
|
}
|
|
}
|
|
|
|
// Is this fragment offset?
|
|
if (frag.mFragmentOffset != -1)
|
|
{
|
|
// Yes, add in offset to structure offset and save
|
|
ULONG newOffset = frag.mFragmentOffset + structOffset;
|
|
SetOffset( newOffset );
|
|
}
|
|
|
|
// What type of fragment is this?
|
|
switch (frag.mFragmentType)
|
|
{
|
|
case eDB2_FRAGMENT_FIELD:
|
|
{
|
|
const sDB2Field * pField = pFrag->mpField;
|
|
if (pField != 0)
|
|
{
|
|
if (mbFieldNames == true)
|
|
{
|
|
if (baseName.size() > 0)
|
|
{
|
|
baseName += PE_NAV_FIELD_SEP;
|
|
}
|
|
|
|
// Add in field name
|
|
baseName += pField->mpName;
|
|
}
|
|
|
|
// Variable string?
|
|
sDB2Field modField;
|
|
if ( (frag.mModifierType == eDB2_MOD_VARIABLE_STRING1)
|
|
|| (frag.mModifierType == eDB2_MOD_VARIABLE_STRING2)
|
|
|| (frag.mModifierType == eDB2_MOD_VARIABLE_STRING3) )
|
|
{
|
|
modField = *pField;
|
|
bRC = ModifyStringLength( frag, modField );
|
|
if (bRC == false)
|
|
{
|
|
// Unable to obtain string length
|
|
return bRC;
|
|
}
|
|
|
|
if (modField.mSize == 0)
|
|
{
|
|
// String has no length - treat like an optional fragment
|
|
bRC = true;
|
|
return bRC;
|
|
}
|
|
|
|
pField = &modField;
|
|
}
|
|
|
|
// Handle an array?
|
|
if (bArray == true)
|
|
{
|
|
EnterArray( frag, arraySz );
|
|
|
|
if (mbFieldNames == true)
|
|
{
|
|
ULONG baseLen = baseName.size();
|
|
|
|
std::string fieldName;
|
|
fieldName.reserve( baseLen + 16 );
|
|
fieldName = baseName;
|
|
|
|
CHAR arraySpec[32];
|
|
|
|
for (LONGLONG i = 0; i < arraySz; i++)
|
|
{
|
|
snprintf( arraySpec, 31, "[%lld]", i + arrayAdj );
|
|
fieldName += arraySpec;
|
|
|
|
bRC = ProcessField( pField, fieldName, i );
|
|
if (bRC == false)
|
|
{
|
|
break;
|
|
}
|
|
|
|
// Remove the array specifier for the next pass
|
|
fieldName.resize( baseLen );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (LONGLONG i = 0; i < arraySz; i++)
|
|
{
|
|
bRC = ProcessField( pField, baseName, i );
|
|
if (bRC == false)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
ExitArray( frag, arraySz );
|
|
}
|
|
else
|
|
{
|
|
bRC = ProcessField( pField, baseName );
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case eDB2_FRAGMENT_STRUCT:
|
|
{
|
|
if (pFrag->mpLinkFragment != 0)
|
|
{
|
|
// Handle an array?
|
|
if (bArray == true)
|
|
{
|
|
EnterArray( frag, arraySz );
|
|
|
|
if (mbFieldNames == true)
|
|
{
|
|
ULONG baseLen = baseName.size();
|
|
|
|
std::string structName;
|
|
structName.reserve( baseLen + 16 );
|
|
structName = baseName;
|
|
|
|
CHAR arraySpec[32];
|
|
|
|
for (LONGLONG i = 0; i < arraySz; i++)
|
|
{
|
|
snprintf( arraySpec, 31, "[%lld]", i + arrayAdj );
|
|
structName += arraySpec;
|
|
|
|
EnterStruct( frag.mpName, i );
|
|
|
|
bRC = ProcessStruct( pFrag->mpLinkFragment,
|
|
structName,
|
|
i );
|
|
|
|
ExitStruct( frag.mpName, i );
|
|
|
|
if (bRC == false)
|
|
{
|
|
break;
|
|
}
|
|
|
|
// Remove the array specifier for the next pass
|
|
structName.resize( baseLen );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
for (LONGLONG i = 0; i < arraySz; i++)
|
|
{
|
|
EnterStruct( frag.mpName, i );
|
|
|
|
bRC = ProcessStruct( pFrag->mpLinkFragment,
|
|
baseName,
|
|
i );
|
|
|
|
ExitStruct( frag.mpName, i );
|
|
|
|
if (bRC == false)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
ExitArray( frag, arraySz );
|
|
}
|
|
else
|
|
{
|
|
EnterStruct( frag.mpName, -1 );
|
|
bRC = ProcessStruct( pFrag->mpLinkFragment, baseName );
|
|
ExitStruct( frag.mpName, -1 );
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case eDB2_FRAGMENT_CONSTANT_PAD:
|
|
{
|
|
// Is the structure is smaller than the specified
|
|
// value that we are to pad out to?
|
|
ULONG totalSz = frag.mFragmentValue;
|
|
if (totalSz >= structSize)
|
|
{
|
|
ULONG newOffset = structOffset + totalSz;
|
|
SetOffset( newOffset );
|
|
}
|
|
|
|
// Succcess!
|
|
bRC = true;
|
|
}
|
|
break;
|
|
|
|
case eDB2_FRAGMENT_VARIABLE_PAD_BITS:
|
|
case eDB2_FRAGMENT_VARIABLE_PAD_BYTES:
|
|
{
|
|
// Find last occurence of this field ID and grab the value
|
|
LONGLONG totalSz = 0;
|
|
bRC = GetLastValue( frag.mFragmentValue, totalSz );
|
|
if (bRC == true)
|
|
{
|
|
// Convert to bits?
|
|
if (frag.mFragmentType == eDB2_FRAGMENT_VARIABLE_PAD_BYTES)
|
|
{
|
|
totalSz *= BITS_PER_BYTE;
|
|
}
|
|
|
|
// Is the structure is smaller than the specified
|
|
// value that we are to pad out to?
|
|
if ((ULONG)totalSz >= structSize)
|
|
{
|
|
ULONG newOffset = structOffset + (ULONG)totalSz;
|
|
SetOffset( newOffset );
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case eDB2_FRAGMENT_FULL_BYTE_PAD:
|
|
{
|
|
ULONG totalSz = structSize;
|
|
while ((totalSz % BITS_PER_BYTE) != 0)
|
|
{
|
|
totalSz++;
|
|
}
|
|
|
|
if (totalSz > structSize)
|
|
{
|
|
ULONG newOffset = structOffset + totalSz;
|
|
SetOffset( newOffset );
|
|
}
|
|
|
|
// Succcess!
|
|
bRC = true;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
bRC = false;
|
|
break;
|
|
}
|
|
|
|
// Adjust struct size?
|
|
if (bRC == true)
|
|
{
|
|
ULONG newOffset = GetOffset();
|
|
if (newOffset > structOffset)
|
|
{
|
|
ULONG newSz = newOffset - structOffset;
|
|
if (newSz > structSize)
|
|
{
|
|
structSize = newSz;
|
|
}
|
|
}
|
|
}
|
|
|
|
return bRC;
|
|
}
|
|
|
|
/*===========================================================================
|
|
METHOD:
|
|
GetPartialFieldName (Public Method)
|
|
|
|
DESCRIPTION:
|
|
Return the fully qualified field name given the partial name
|
|
|
|
PARAMETERS:
|
|
partialName [ I ] - Partial field name
|
|
|
|
RETURN VALUE:
|
|
std::string
|
|
===========================================================================*/
|
|
std::string cProtocolEntityNav::GetFullFieldName(
|
|
const std::string & partialName ) const
|
|
{
|
|
std::string retStr = EMPTY_STRING;
|
|
|
|
if (mEntity.mpName != 0 && mEntity.mpName != EMPTY_STRING)
|
|
{
|
|
retStr = mEntity.mpName;
|
|
retStr += PE_NAV_FIELD_SEP;
|
|
retStr += partialName;
|
|
}
|
|
|
|
return retStr;
|
|
}
|
|
|
|
/*===========================================================================
|
|
METHOD:
|
|
GetPartialFieldName (Public Method)
|
|
|
|
DESCRIPTION:
|
|
Return the partial field name given the fully qualified name
|
|
|
|
PARAMETERS:
|
|
fieldNameFQ [ I ] - Fully qualified name
|
|
|
|
RETURN VALUE:
|
|
std::string
|
|
===========================================================================*/
|
|
std::string cProtocolEntityNav::GetPartialFieldName(
|
|
const std::string & fieldNameFQ ) const
|
|
{
|
|
std::string retStr = EMPTY_STRING;
|
|
|
|
if (mEntity.mpName != 0 && mEntity.mpName != EMPTY_STRING)
|
|
{
|
|
int idx = fieldNameFQ.find( mEntity.mpName, 0 );
|
|
if (idx == 0)
|
|
{
|
|
idx = fieldNameFQ.find( PE_NAV_FIELD_SEP );
|
|
if (idx != -1)
|
|
{
|
|
retStr = fieldNameFQ.substr( idx - 1 );
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
return retStr;
|
|
}
|