Files
mars-flaim/flaim/src/frec.cpp
dsandersoremutah c55dab446f Renamed version4 to flaim and version5 to xflaim
git-svn-id: https://svn.code.sf.net/p/flaim/code/trunk@7 0109f412-320b-0410-ab79-c3e0c5ffbbe6
2006-01-27 21:06:39 +00:00

4836 lines
103 KiB
C++

//-------------------------------------------------------------------------
// Desc: Methods for the FlmRecord class
// Tabs: 3
//
// Copyright (c) 1999-2000,2002-2006 Novell, Inc. All Rights Reserved.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of version 2 of the GNU General Public
// License as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, contact Novell, Inc.
//
// To contact Novell about this file by physical or electronic mail,
// you may find current contact information at www.novell.com
//
// $Id: frec.cpp 12334 2006-01-23 12:45:35 -0700 (Mon, 23 Jan 2006) dsanders $
//-------------------------------------------------------------------------
#include "flaimsys.h"
#if defined( FLM_NLM) && !defined( __MWERKS__)
// Disable "Warning! W549: col(XX) 'sizeof' operand contains
// compiler generated information"
#pragma warning 549 9
#endif
FSTATIC RCODE importTree(
F_FileHdl * pFileHdl,
char ** pBuf,
FLMUINT uiBufSize,
F_NameTable * pNameTable,
FlmRecord * pRec);
FSTATIC RCODE importField(
FLMUINT uiLevel,
GED_STREAM * pGedStream,
F_NameTable * pNameTable,
FlmRecord * pRec);
FLMBYTE arr[ 16] =
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xC0,
0x7F, 0xFF, 0xFF, 0xE0, 0x7F, 0xFF, 0xFF, 0xE0
};
#define f_isalnum(c) \
((c) < 128 ? (( ((FLMBYTE)(arr[(c) >> 3])) << ((c) & 0x07)) & 0x80) : 0)
#define f_isdigit(c) \
((c) < 60 ? (( ((FLMBYTE)(arr[(c) >> 3])) << ((c) & 0x07)) & 0x80) : 0)
#define f_isalpha(c) \
((c) < 128 && (c) > 58 ? (( ((FLMBYTE)(arr[(c) >> 3])) << \
((c) & 0x07)) & 0x80) : 0)
/*****************************************************************************
Desc:
*****************************************************************************/
FlmRecord::FlmRecord()
{
m_pucBuffer = NULL;
m_uiBufferSize = 0;
m_uiFldTblSize = 0;
m_uiFlags = 0;
clear();
}
/*****************************************************************************
Desc:
*****************************************************************************/
FlmRecord::~FlmRecord()
{
flmAssert( m_uiFlags & RCA_OK_TO_DELETE);
if( m_pucBuffer)
{
flmAssert( *((FlmRecord **)m_pucBuffer) == this);
gv_FlmSysData.RCacheMgr.pRecBufAlloc->freeBuf(
m_uiBufferSize, &m_pucBuffer);
}
}
/*****************************************************************************
Desc: Makes a copy of self and returns pointer to the copy.
*****************************************************************************/
FlmRecord * FlmRecord::copy( void)
{
RCODE rc = FERR_OK;
FlmRecord * pNewRec = NULL;
FLMBOOL bHeapAlloc = FALSE;
#ifdef FLM_CHECK_RECORD
if( RC_BAD( rc = checkRecord()))
{
goto Exit;
}
#endif
if( (pNewRec = f_new FlmRecord) == NULL)
{
rc = RC_SET( FERR_MEM);
goto Exit;
}
if( m_uiBufferSize)
{
if( RC_BAD( rc = gv_FlmSysData.RCacheMgr.pRecBufAlloc->allocBuf(
m_uiBufferSize, &pNewRec, sizeof( FlmRecord *), &pNewRec->m_pucBuffer,
&bHeapAlloc)))
{
goto Exit;
}
f_memcpy( &pNewRec->m_pucBuffer[ sizeof( FlmRecord *)],
&m_pucBuffer[ sizeof( FlmRecord *)],
m_uiBufferSize - sizeof( FlmRecord *));
if( bHeapAlloc)
{
pNewRec->m_uiFlags |= RCA_HEAP_BUFFER;
}
}
pNewRec->m_uiBufferSize = m_uiBufferSize;
pNewRec->m_uiContainerID = m_uiContainerID;
pNewRec->m_uiRecordID = m_uiRecordID;
pNewRec->m_uiFldTblSize = m_uiFldTblSize;
pNewRec->m_uiFldTblOffset = m_uiFldTblOffset;
pNewRec->m_uiDataBufOffset = m_uiDataBufOffset;
pNewRec->m_uiFirstAvail = m_uiFirstAvail;
pNewRec->m_uiAvailFields = m_uiAvailFields;
pNewRec->m_bHolesInData = m_bHolesInData;
#ifdef FLM_CHECK_RECORD
if( RC_BAD( rc = pNewRec->checkRecord()))
{
goto Exit;
}
#endif
pNewRec->compressMemory();
#ifdef FLM_CHECK_RECORD
if( RC_BAD( rc = pNewRec->checkRecord()))
{
goto Exit;
}
#endif
Exit:
if( RC_BAD( rc) && pNewRec)
{
pNewRec->Release();
pNewRec = NULL;
}
return( pNewRec);
}
/*****************************************************************************
Desc: Return a existing record to a new state (no fields)
*****************************************************************************/
RCODE FlmRecord::clear(
FLMBOOL bReleaseMemory)
{
RCODE rc = FERR_OK;
if( isCached())
{
flmAssert( 0);
rc = RC_SET( FERR_ILLEGAL_OP);
goto Exit;
}
if( bReleaseMemory)
{
if( m_pucBuffer)
{
gv_FlmSysData.RCacheMgr.pRecBufAlloc->freeBuf(
m_uiBufferSize, &m_pucBuffer);
}
m_uiBufferSize = 0;
m_uiFldTblSize = 0;
}
m_uiFlags = 0;
m_uiContainerID = 0;
m_uiRecordID = 0;
m_uiFldTblOffset = 0;
m_uiDataBufOffset = 0;
m_uiFirstAvail = 0;
m_uiAvailFields = 0;
m_bHolesInData = FALSE;
Exit:
return( rc);
}
/*****************************************************************************
Desc: Retrieve values from a context field.
*****************************************************************************/
RCODE FlmRecord::getRecPointer(
void * pvField,
FLMUINT * puiRecPointer)
{
RCODE rc = FERR_OK;
FlmField * pField = getFieldPointer( pvField);
*puiRecPointer = 0xFFFFFFFF;
if( !pField)
{
rc = RC_SET( FERR_NOT_FOUND);
goto Exit;
}
if( isEncryptedField( pField) &&
!(getEncFlags( pField) & FLD_HAVE_DECRYPTED_DATA))
{
rc = RC_SET( FERR_ENCRYPTION_UNAVAILABLE);
goto Exit;
}
if( getFieldDataType( pField) != FLM_CONTEXT_TYPE)
{
rc = RC_SET( FERR_CONV_ILLEGAL);
goto Exit;
}
if( getFieldDataLength( pField) == 4)
{
*puiRecPointer = (FLMUINT)(FB2UD( getDataPtr( pField)));
}
else
{
flmAssert( getFieldDataLength( pField) == 0);
rc = RC_SET( FERR_NOT_FOUND);
goto Exit;
}
Exit:
return( rc);
}
/*****************************************************************************
Desc: Create a FlmBlob object
*****************************************************************************/
RCODE FlmRecord::getBlob(
void * pvField,
FlmBlob ** ppBlob)
{
RCODE rc = FERR_OK;
FlmField * pField = getFieldPointer( pvField);
FLMBYTE * pucData;
FLMUINT uiDataLen;
FlmBlobImp * pNewBlob = NULL;
*ppBlob = NULL;
if( !pField)
{
rc = RC_SET( FERR_NOT_FOUND);
goto Exit;
}
if( isEncryptedField( pField) &&
!(getEncFlags( pField) & FLD_HAVE_DECRYPTED_DATA))
{
rc = RC_SET( FERR_ENCRYPTION_UNAVAILABLE);
goto Exit;
}
if( (uiDataLen = getFieldDataLength( pField)) != 0 &&
(getFieldDataType( pField) == FLM_BLOB_TYPE))
{
if( (pNewBlob = f_new FlmBlobImp) == NULL)
{
rc = RC_SET( FERR_MEM);
goto Exit;
}
*ppBlob = pNewBlob;
if( (pucData = pNewBlob->getImportDataPtr( uiDataLen)) != NULL)
{
f_memcpy( pucData, getDataPtr( pField), uiDataLen);
}
else
{
rc = RC_SET( FERR_MEM);
goto Exit;
}
}
else
{
rc = RC_SET( FERR_NOT_FOUND);
goto Exit;
}
Exit:
return( rc);
}
/*****************************************************************************
Desc:
*****************************************************************************/
RCODE FlmRecord::setINT(
void * pvField,
FLMINT iNumber,
FLMUINT uiEncId)
{
RCODE rc = FERR_OK;
FLMBYTE * pucData;
FLMBYTE ucStorageBuf[ F_MAX_NUM_BUF + 1];
FLMUINT uiStorageLen;
FLMUINT uiEncDataLen = 0;
FLMUINT uiEncFlags = 0;
if( isReadOnly() || isCached())
{
flmAssert( 0);
rc = RC_SET( FERR_FAILURE);
goto Exit;
}
#ifdef FLM_CHECK_RECORD
if( RC_BAD( rc = checkRecord()))
{
flmAssert( 0);
goto Exit;
}
#endif
uiStorageLen = sizeof( ucStorageBuf);
if( RC_BAD( rc = FlmINT2Storage( iNumber, &uiStorageLen, ucStorageBuf)))
{
goto Exit;
}
if( uiEncId)
{
// For encrypted fields, we want to make sure we allocate
// enough space for the encrypted data too. The data does
// not get encrypted until the call to FlmRecordModify or
// FlmRecordAdd.
if( uiStorageLen % 16)
{
uiEncDataLen = uiStorageLen + (16 - (uiStorageLen % 16));
}
else
{
uiEncDataLen = uiStorageLen;
}
uiEncFlags = FLD_HAVE_DECRYPTED_DATA;
}
if( RC_BAD( rc = getNewDataPtr( getFieldPointer( pvField), FLM_NUMBER_TYPE,
uiStorageLen, uiEncDataLen, uiEncId, uiEncFlags, &pucData, NULL)))
{
goto Exit;
}
f_memcpy( pucData, ucStorageBuf, uiStorageLen);
#ifdef FLM_CHECK_RECORD
if( RC_BAD( rc = checkRecord()))
{
flmAssert( 0);
goto Exit;
}
#endif
Exit:
return( rc);
}
/*****************************************************************************
Desc:
*****************************************************************************/
RCODE FlmRecord::setUINT(
void * pvField,
FLMUINT uiNumber,
FLMUINT uiEncId)
{
RCODE rc = FERR_OK;
FLMBYTE * pucData;
FLMBYTE ucStorageBuf[ F_MAX_NUM_BUF + 1];
FLMUINT uiStorageLen;
FLMUINT uiEncDataLen = 0;
FLMUINT uiEncFlags = 0;
if( isReadOnly() || isCached())
{
flmAssert( 0);
rc = RC_SET( FERR_FAILURE);
goto Exit;
}
#ifdef FLM_CHECK_RECORD
if( RC_BAD( rc = checkRecord()))
{
flmAssert( 0);
goto Exit;
}
#endif
uiStorageLen = sizeof( ucStorageBuf);
if( RC_BAD( rc = FlmUINT2Storage( uiNumber, &uiStorageLen, ucStorageBuf)))
{
goto Exit;
}
if( uiEncId)
{
// For encrypted fields, we want to make sure we allocate
// enough space for the encrypted data too. The data does
// not get encrypted until the call to FlmRecordModify or
// FlmRecordAdd.
if( uiStorageLen % 16)
{
uiEncDataLen = uiStorageLen + (16 - (uiStorageLen % 16));
}
else
{
uiEncDataLen = uiStorageLen;
}
uiEncFlags = FLD_HAVE_DECRYPTED_DATA;
}
if( RC_BAD( rc = getNewDataPtr( getFieldPointer( pvField), FLM_NUMBER_TYPE,
uiStorageLen, uiEncDataLen, uiEncId, uiEncFlags, &pucData, NULL)))
{
goto Exit;
}
f_memcpy( pucData, ucStorageBuf, uiStorageLen);
#ifdef FLM_CHECK_RECORD
if( RC_BAD( rc = checkRecord()))
{
flmAssert( 0);
goto Exit;
}
#endif
Exit:
return( rc);
}
/*****************************************************************************
Desc:
*****************************************************************************/
RCODE FlmRecord::setRecPointer(
void * pvField,
FLMUINT uiRecPointer,
FLMUINT uiEncId)
{
RCODE rc = FERR_OK;
FLMBYTE * pucData;
FLMUINT uiEncDataLen = 0;
FLMUINT uiEncFlags = 0;
if( isReadOnly() || isCached())
{
flmAssert( 0);
rc = RC_SET( FERR_FAILURE);
goto Exit;
}
#ifdef FLM_CHECK_RECORD
if( RC_BAD( rc = checkRecord()))
{
flmAssert( 0);
goto Exit;
}
#endif
if( uiEncId)
{
// For encrypted fields, we want to make sure we allocate
// enough space for the encrypted data too. The data does
// not get encrypted until the call to FlmRecordModify or
// FlmRecordAdd.
uiEncDataLen = 16;
uiEncFlags = FLD_HAVE_DECRYPTED_DATA;
}
if( RC_BAD( rc = getNewDataPtr( getFieldPointer( pvField), FLM_CONTEXT_TYPE,
4, uiEncDataLen, uiEncId, uiEncFlags, &pucData, NULL)))
{
goto Exit;
}
UD2FBA( (FLMUINT32)uiRecPointer, pucData);
#ifdef FLM_CHECK_RECORD
if( RC_BAD( rc = checkRecord()))
{
flmAssert( 0);
goto Exit;
}
#endif
Exit:
return( rc);
}
/*****************************************************************************
Desc:
*****************************************************************************/
RCODE FlmRecord::setUnicode(
void * pvField,
const FLMUNICODE * pUnicode,
FLMUINT uiEncId)
{
RCODE rc = FERR_OK;
FLMBYTE * pucData;
FLMUINT uiBufLen;
FLMUINT uiEncDataLen = 0;
FLMUINT uiEncFlags = 0;
if( isReadOnly() || isCached())
{
flmAssert( 0);
rc = RC_SET( FERR_FAILURE);
goto Exit;
}
#ifdef FLM_CHECK_RECORD
if( RC_BAD( rc = checkRecord()))
{
flmAssert( 0);
goto Exit;
}
#endif
// A NULL or empty pUnicode string is allowed - on those
// cases just set the field type.
if( !pUnicode || *pUnicode == 0)
{
// Field may have had a value pointer that now
// needs to be set to NULL
if( RC_BAD( rc = getNewDataPtr( getFieldPointer( pvField), FLM_TEXT_TYPE,
0, 0, 0, 0, &pucData, NULL)))
{
goto Exit;
}
}
else
{
uiBufLen = FlmGetUnicodeStorageLength( pUnicode);
if( uiEncId)
{
// For encrypted fields, we want to make sure we allocate
// enough space for the encrypted data too. The data does
// not get encrypted until the call to FlmRecordModify or
// FlmRecordAdd.
if( uiBufLen % 16)
{
uiEncDataLen = uiBufLen + (16 - (uiBufLen % 16));
}
else
{
uiEncDataLen = uiBufLen;
}
uiEncFlags = FLD_HAVE_DECRYPTED_DATA;
}
if( RC_BAD( rc = getNewDataPtr( getFieldPointer( pvField), FLM_TEXT_TYPE,
uiBufLen, uiEncDataLen, uiEncId, uiEncFlags, &pucData, NULL)))
{
goto Exit;
}
if( RC_BAD( rc = FlmUnicode2Storage( pUnicode, &uiBufLen, pucData)))
{
goto Exit;
}
}
#ifdef FLM_CHECK_RECORD
if( RC_BAD( rc = checkRecord()))
{
flmAssert( 0);
goto Exit;
}
#endif
Exit:
return( rc);
}
/*****************************************************************************
Desc:
*****************************************************************************/
RCODE FlmRecord::setNative(
void * pvField,
const char * pszString,
FLMUINT uiEncId)
{
RCODE rc = FERR_OK;
FLMBYTE * pucData;
FLMUINT uiBufLen;
FLMUINT uiEncDataLen = 0;
FLMUINT uiEncFlags = 0;
if( isReadOnly() || isCached())
{
flmAssert( 0);
rc = RC_SET( FERR_FAILURE);
goto Exit;
}
#ifdef FLM_CHECK_RECORD
if( RC_BAD( rc = checkRecord()))
{
flmAssert( 0);
goto Exit;
}
#endif
if( !pszString || *pszString == 0)
{
// Field may have had a value pointer that now
// needs to be set to NULL
if( RC_BAD( rc = getNewDataPtr( getFieldPointer( pvField), FLM_TEXT_TYPE,
0, 0, 0, 0, &pucData, NULL)))
{
goto Exit;
}
}
else
{
uiBufLen = FlmGetNativeStorageLength( pszString);
if( uiEncId)
{
// For encrypted fields, we want to make sure we allocate
// enough space for the encrypted data too. The data does
// not get encrypted until the call to FlmRecordModify or
// FlmRecordAdd.
if( uiBufLen % 16)
{
uiEncDataLen = uiBufLen + (16 - (uiBufLen % 16));
}
else
{
uiEncDataLen = uiBufLen;
}
uiEncFlags = FLD_HAVE_DECRYPTED_DATA;
}
if( RC_BAD( rc = getNewDataPtr( getFieldPointer( pvField), FLM_TEXT_TYPE,
uiBufLen, uiEncDataLen, uiEncId, uiEncFlags, &pucData, NULL)))
{
goto Exit;
}
if( RC_BAD( rc = FlmNative2Storage( pszString, &uiBufLen, pucData)))
{
goto Exit;
}
}
#ifdef FLM_CHECK_RECORD
if( RC_BAD( rc = checkRecord()))
{
flmAssert( 0);
goto Exit;
}
#endif
Exit:
return( rc);
}
/*****************************************************************************
Desc:
*****************************************************************************/
RCODE FlmRecord::setBinary(
void * pvField,
const void * pvBuf,
FLMUINT uiBufLen,
FLMUINT uiEncId)
{
RCODE rc = FERR_OK;
FLMBYTE * pucData;
FLMUINT uiEncDataLen = 0;
FLMUINT uiEncFlags = 0;
if( isReadOnly() || isCached())
{
flmAssert( 0);
rc = RC_SET( FERR_FAILURE);
goto Exit;
}
#ifdef FLM_CHECK_RECORD
if( RC_BAD( rc = checkRecord()))
{
flmAssert( 0);
goto Exit;
}
#endif
if( !uiBufLen)
{
// Field may have had a value pointer that now
// needs to be set to NULL
if( RC_BAD( rc = getNewDataPtr( getFieldPointer( pvField),
FLM_BINARY_TYPE, 0, 0, 0, 0, &pucData, NULL)))
{
goto Exit;
}
}
else
{
if( uiEncId)
{
// For encrypted fields, we want to make sure we allocate
// enough space for the encrypted data too. The data does
// not get encrypted until the call to FlmRecordModify or
// FlmRecordAdd.
if( uiBufLen % 16)
{
uiEncDataLen = uiBufLen + (16 - (uiBufLen % 16));
}
else
{
uiEncDataLen = uiBufLen;
}
uiEncFlags = FLD_HAVE_DECRYPTED_DATA;
}
if( RC_BAD( rc = getNewDataPtr( getFieldPointer( pvField),
FLM_BINARY_TYPE, uiBufLen, uiEncDataLen, uiEncId, uiEncFlags,
&pucData, NULL)))
{
goto Exit;
}
f_memcpy( pucData, pvBuf, uiBufLen);
}
#ifdef FLM_CHECK_RECORD
if( RC_BAD( rc = checkRecord()))
{
flmAssert( 0);
goto Exit;
}
#endif
Exit:
return( rc);
}
/*****************************************************************************
Desc: Copies the BLOB control data into the record.
*****************************************************************************/
RCODE FlmRecord::setBlob(
void * pvField,
FlmBlob * pBlob,
FLMUINT uiEncId)
{
RCODE rc = FERR_OK;
FLMBYTE * pucData;
FLMUINT uiDataLen = ((FlmBlobImp *)pBlob)->getDataLength();
FLMUINT uiEncDataLen = 0;
FLMUINT uiEncFlags = 0;
if( isReadOnly() || isCached())
{
flmAssert( 0);
rc = RC_SET( FERR_FAILURE);
goto Exit;
}
#ifdef FLM_CHECK_RECORD
if( RC_BAD( rc = checkRecord()))
{
flmAssert( 0);
goto Exit;
}
#endif
if( !uiDataLen)
{
// Field may have had a value pointer that now
// needs to be set to NULL
if( RC_BAD( rc = getNewDataPtr( getFieldPointer( pvField), FLM_BLOB_TYPE,
0, 0, 0, 0, &pucData, NULL)))
{
goto Exit;
}
}
else
{
if( uiEncId)
{
// For encrypted fields, we want to make sure we allocate
// enough space for the encrypted data too. The data does
// not get encrypted until the call to FlmRecordModify or
// FlmRecordAdd.
if( uiDataLen % 16)
{
uiEncDataLen = uiDataLen + (16 - (uiDataLen % 16));
}
else
{
uiEncDataLen = uiDataLen;
}
uiEncFlags = FLD_HAVE_DECRYPTED_DATA;
}
if( RC_BAD( rc = getNewDataPtr( getFieldPointer( pvField),
FLM_BLOB_TYPE, uiDataLen, uiEncDataLen, uiEncId, uiEncFlags,
&pucData, NULL)))
{
goto Exit;
}
f_memcpy( pucData, ((FlmBlobImp *)pBlob)->getDataPtr(), uiDataLen);
}
#ifdef FLM_CHECK_RECORD
if( RC_BAD( rc = checkRecord()))
{
flmAssert( 0);
goto Exit;
}
#endif
Exit:
return( rc);
}
/*****************************************************************************
Desc: Create a new field at the specified position. Following the insert
the current record position will be positioned on the new field.
*****************************************************************************/
RCODE FlmRecord::insert(
void * pvField,
FLMUINT uiInsertAt,
FLMUINT uiFieldID,
FLMUINT uiDataType,
void ** ppvField)
{
RCODE rc = FERR_OK;
FlmField * pField;
FlmField * pNewField = NULL;
FlmField * pTmpField;
FLMUINT uiLevel;
if( isReadOnly() || isCached() || !uiFieldID)
{
flmAssert( 0);
rc = RC_SET( FERR_FAILURE);
goto Exit;
}
if( !pvField)
{
pField = getFirstField();
}
else
{
pField = getFieldPointer( pvField);
}
uiLevel = getFieldLevel( pField);
// User is adding first field (no fields in record)
if( !pField)
{
if( RC_BAD( rc = createField( NULL, &pNewField)))
{
goto Exit;
}
goto Exit;
}
// Perform desired insert.
switch( uiInsertAt)
{
case INSERT_PREV_SIB:
{
if( (pField = prevField( pField)) == NULL)
{
flmAssert( 0);
rc = RC_SET( FERR_ILLEGAL_OP);
goto Exit;
}
if( RC_BAD( rc = createField( pField, &pNewField)))
{
goto Exit;
}
if( RC_BAD( rc = setFieldLevel( pNewField, uiLevel)))
{
goto Exit;
}
break;
}
case INSERT_NEXT_SIB:
{
// If current field has children then we need to position to the end
// of it's sub-tree before before inserting the new next sibling.
FlmField * pSubTreeEnd = lastSubTreeField( pField);
if( RC_BAD( rc = createField(
pSubTreeEnd ? pSubTreeEnd : pField, &pNewField)))
{
goto Exit;
}
if( RC_BAD( rc = setFieldLevel( pNewField, uiLevel)))
{
goto Exit;
}
break;
}
case INSERT_FIRST_CHILD:
{
First_Child:
if( RC_BAD( rc = createField( pField, &pNewField)))
{
goto Exit;
}
if( RC_BAD( rc = setFieldLevel( pNewField, uiLevel + 1)))
{
goto Exit;
}
break;
}
case INSERT_LAST_CHILD:
{
if( (pTmpField = lastSubTreeField( pField)) != NULL)
{
if( RC_BAD( rc = createField( pTmpField, &pNewField)))
{
goto Exit;
}
if( RC_BAD( rc = setFieldLevel( pNewField, uiLevel + 1)))
{
goto Exit;
}
}
else
{
// There are no children, so add as first child
goto First_Child;
}
break;
}
default:
{
flmAssert( 0);
break;
}
}
Exit:
if( pNewField)
{
pNewField->ui16FieldID = (FLMUINT16)uiFieldID;
setFieldDataType( pNewField, uiDataType);
}
if( ppvField)
{
*ppvField = getFieldVoid( pNewField);
}
return( rc);
}
/*****************************************************************************
Desc: Returns the last field within a subtree.
*****************************************************************************/
FlmField * FlmRecord::lastSubTreeField(
FlmField * pField)
{
FlmField * pTempField = lastChildField( pField);
FlmField * pLastChild = NULL;
FLMUINT uiStartLevel = getFieldLevel( pField);
for( ; pTempField && getFieldLevel( pTempField) > uiStartLevel;
pTempField = nextField( pTempField))
{
pLastChild = pTempField;
}
#ifdef FLM_DEBUG
if( pLastChild)
{
flmAssert( pLastChild->ui16FieldID);
}
#endif
return( pLastChild);
}
/*****************************************************************************
Desc: Special level-based insert.
Note: The level must be a value between 0 - ((last field)->level + 1)
*****************************************************************************/
RCODE FlmRecord::insertLast(
FLMUINT uiLevel,
FLMUINT uiFieldID,
FLMUINT uiDataType,
void ** ppvField)
{
RCODE rc = FERR_OK;
FlmField * pField = NULL;
FlmField * pLastField;
if( isReadOnly() || isCached() || !uiFieldID)
{
flmAssert( 0);
rc = RC_SET( FERR_FAILURE);
goto Exit;
}
// Insert new field following current last field
pLastField = getLastField();
#ifdef FLM_DEBUG
if( pLastField && uiLevel > getFieldLevel( pLastField) + 1)
{
flmAssert( 0);
}
#endif
if( RC_BAD( rc = createField( pLastField, &pField)))
{
goto Exit;
}
// Set up the new field and set as the current field
pField->ui16FieldID = (FLMUINT16)uiFieldID;
setFieldDataType( pField, uiDataType);
if( RC_BAD( rc = setFieldLevel( pField, uiLevel)))
{
goto Exit;
}
if( ppvField)
{
*ppvField = getFieldVoid( pField);
}
Exit:
return( rc);
}
/*****************************************************************************
Desc: Delete a field (and it's subtree).
*****************************************************************************/
RCODE FlmRecord::remove(
FlmField * pField)
{
RCODE rc = FERR_OK;
if( isReadOnly() || isCached())
{
flmAssert( 0);
rc = RC_SET( FERR_FAILURE);
goto Exit;
}
if( !pField)
{
goto Exit;
}
if( RC_BAD( rc = removeFields( pField, lastSubTreeField( pField))))
{
goto Exit;
}
Exit:
return( rc);
}
/*****************************************************************************
Desc: Internal position to the next sibling
*****************************************************************************/
FlmField * FlmRecord::nextSiblingField(
FlmField * pField)
{
FLMUINT uiLevel = getFieldLevel( pField);
while( (pField = nextField( pField)) != NULL &&
getFieldLevel( pField) > uiLevel)
{
;
}
pField = (pField && getFieldLevel( pField) == uiLevel)
? pField
: NULL;
#ifdef FLM_DEBUG
if( pField)
{
flmAssert( pField->ui16FieldID);
}
#endif
return( pField);
}
/*****************************************************************************
Desc: Position to the prev sibling
*****************************************************************************/
void * FlmRecord::prevSibling(
void * pvField)
{
FlmField * pField = getFieldPointer( pvField);
FLMUINT uiLevel;
if( !pField)
{
return( NULL);
}
uiLevel = getFieldLevel( pField);
while( (pField = prevField( pField)) != NULL &&
getFieldLevel( pField) > uiLevel)
{
;
}
pField = (pField && getFieldLevel( pField) == uiLevel)
? pField
: NULL;
#ifdef FLM_DEBUG
if( pField)
{
flmAssert( pField->ui16FieldID);
}
#endif
return( getFieldVoid( pField));
}
/*****************************************************************************
Desc: Return the last child field
*****************************************************************************/
FlmField * FlmRecord::lastChildField(
FlmField * pField)
{
FlmField * pLastField = NULL;
if( !pField)
{
return( NULL);
}
for( pField = firstChildField( pField);
pField;
pField = nextSiblingField( pField))
{
pLastField = pField;
}
#ifdef FLM_DEBUG
if( pLastField)
{
flmAssert( pLastField->ui16FieldID);
}
#endif
return( pLastField);
}
/*****************************************************************************
Desc: Return the parent field.
*****************************************************************************/
void * FlmRecord::parent(
FlmField * pField)
{
FLMUINT uiLevel;
if( !pField)
{
return( NULL);
}
uiLevel = getFieldLevel( pField);
while( (pField = prevField( pField)) != NULL &&
getFieldLevel( pField) >= uiLevel)
{
;
}
#ifdef FLM_DEBUG
if( pField)
{
flmAssert( pField->ui16FieldID);
}
#endif
return( getFieldVoid( pField));
}
/*****************************************************************************
Desc: Set the right truncated flag.
*****************************************************************************/
void FlmRecord::setRightTruncated(
FlmField * pField,
FLMBOOL bTrueFalse)
{
flmAssert( !isCached() && !isReadOnly());
if( bTrueFalse)
{
pField->ui8TypeAndLevel |= FLD_DATA_RIGHT_TRUNCATED;
}
else
{
pField->ui8TypeAndLevel &= ~FLD_DATA_RIGHT_TRUNCATED;
}
}
/*****************************************************************************
Desc: Set the left truncated flag.
*****************************************************************************/
void FlmRecord::setLeftTruncated(
FlmField * pField,
FLMBOOL bTrueFalse)
{
flmAssert( !isCached() && !isReadOnly());
if( bTrueFalse)
{
pField->ui8TypeAndLevel |= FLD_DATA_LEFT_TRUNCATED;
}
else
{
pField->ui8TypeAndLevel &= ~FLD_DATA_LEFT_TRUNCATED;
}
}
/*****************************************************************************
Desc: Called from FLAIM's filesystem code to directly populate a record.
*****************************************************************************/
RCODE FlmRecord::allocStorageSpace(
void * pvField,
FLMUINT uiDataType,
FLMUINT uiLength,
FLMUINT uiEncLength,
FLMUINT uiEncId,
FLMUINT uiFlags,
FLMBYTE ** ppucData,
FLMBYTE ** ppucEncData)
{
return( getNewDataPtr( getFieldPointer( pvField), uiDataType,
uiLength, uiEncLength, uiEncId, uiFlags, ppucData, ppucEncData));
}
/*****************************************************************************
Desc: Gives the implementor information about how many fields and how much
data will be placed within this record.
*****************************************************************************/
RCODE FlmRecord::preallocSpace(
FLMUINT uiFieldCount,
FLMUINT uiDataSize)
{
RCODE rc = FERR_OK;
FLMUINT uiNewSize;
FlmRecord * pThis = this;
FLMBOOL bHeapAlloc = FALSE;
if( isCached() || isReadOnly())
{
flmAssert( 0);
rc = RC_SET( FERR_ILLEGAL_OP);
goto Exit;
}
flmAssert( uiFieldCount);
flmAssert( !m_uiFldTblOffset);
flmAssert( !m_uiDataBufOffset);
uiNewSize = FLM_ALIGN_SIZE +
(uiFieldCount * sizeof( FlmField)) + uiDataSize;
if( m_uiBufferSize < uiNewSize || (m_uiBufferSize - uiNewSize) >= 32)
{
if( RC_BAD( rc = gv_FlmSysData.RCacheMgr.pRecBufAlloc->reallocBuf(
m_uiBufferSize, uiNewSize, &pThis, sizeof( FlmRecord *), &m_pucBuffer,
&bHeapAlloc)))
{
goto Exit;
}
if( bHeapAlloc)
{
m_uiFlags |= RCA_HEAP_BUFFER;
}
else
{
m_uiFlags &= ~RCA_HEAP_BUFFER;
}
m_uiBufferSize = uiNewSize;
}
m_uiFldTblSize = uiFieldCount;
Exit:
return( rc);
}
/*****************************************************************************
Desc: Copies the binary data into users buffer
*****************************************************************************/
RCODE FlmRecord::getBinary(
void * pvField,
void * pvBuf,
FLMUINT * puiBufLen)
{
RCODE rc = FERR_OK;
FlmField * pField = getFieldPointer( pvField);
if( !pField)
{
rc = RC_SET( FERR_NOT_FOUND);
goto Exit;
}
if (isEncryptedField( pField) &&
!(getEncFlags( pField) & FLD_HAVE_DECRYPTED_DATA))
{
rc = RC_SET( FERR_ENCRYPTION_UNAVAILABLE);
goto Exit;
}
*puiBufLen = f_min( (*puiBufLen), getFieldDataLength( pField));
f_memcpy( pvBuf, getDataPtr( pField), *puiBufLen);
Exit:
return( rc);
}
/*****************************************************************************
Desc: Return most (if not all) unused memory back to the system. Doesn't
compress avail slots out of the field list because the application
could still have "pointers" into the list.
*****************************************************************************/
RCODE FlmRecord::compressMemory( void)
{
RCODE rc = FERR_OK;
FLMUINT uiLength;
FLMUINT uiTmp;
FLMUINT uiNewSize = 0;
FLMUINT uiNewDataSize = 0;
FLMUINT uiNewDataOffset;
FlmField * pFld;
FLMBYTE * pucNewBuf = NULL;
FLMBYTE * pucNewData;
FLMUINT uiPicketFenceSize = 0;
FlmRecord * pThis = this;
FLMBOOL bHeapAlloc = FALSE;
if( isReadOnly() || isCached())
{
flmAssert( 0);
rc = RC_SET( FERR_ILLEGAL_OP);
goto Exit;
}
if( !m_uiBufferSize ||
(!m_bHolesInData && m_uiDataBufOffset == getDataBufSize()))
{
if( m_uiFldTblOffset == m_uiFldTblSize)
{
goto Exit;
}
}
// Scan the record and determine the compressed size
pFld = getFieldPointer( root());
while( pFld)
{
uiLength = getFieldDataLength( pFld);
if (!isEncryptedField( pFld))
{
if( uiLength > 4 && uiLength < 0xFF)
{
if( getFieldDataType( pFld) == FLM_BINARY_TYPE)
{
if( (uiNewDataSize & FLM_ALLOC_ALIGN) != 0)
{
uiNewDataSize += (FLM_ALLOC_ALIGN + 1) -
(uiNewDataSize & FLM_ALLOC_ALIGN);
}
}
uiNewDataSize += uiLength;
}
else if( uiLength >= 0xFF)
{
// Add 1 to the length to allow for the flags byte which is only
// present on long fields and encrypted fields.
uiTmp = uiNewDataSize + sizeof( FLMUINT16) + 1;
if( getFieldDataType( pFld) == FLM_BINARY_TYPE)
{
if( (uiTmp & FLM_ALLOC_ALIGN) != 0)
{
uiTmp += (FLM_ALLOC_ALIGN + 1) - (uiTmp & FLM_ALLOC_ALIGN);
}
}
uiNewDataSize = uiTmp + uiLength;
}
}
else // Encrypted field
{
#ifdef FLM_PICKET_FENCE
uiPicketFenceSize = FLD_PICKET_FENCE_SIZE;
#endif
// FLM_ENC_FLD_OVERHEAD includes 1 byte for the flags
uiTmp = uiNewDataSize + FLM_ENC_FLD_OVERHEAD;
if( getFieldDataType( pFld) == FLM_BINARY_TYPE)
{
if( (uiTmp & FLM_ALLOC_ALIGN) != 0)
{
uiTmp += (FLM_ALLOC_ALIGN + 1) - (uiTmp & FLM_ALLOC_ALIGN);
}
}
uiNewDataSize = uiTmp + uiLength + getEncryptedDataLength(pFld) +
uiPicketFenceSize;
}
pFld = nextField( pFld);
}
uiNewSize = FLM_ALIGN_SIZE +
uiNewDataSize + (m_uiFldTblOffset * sizeof( FlmField));
// Re-allocate the buffer
if( RC_BAD( rc = gv_FlmSysData.RCacheMgr.pRecBufAlloc->allocBuf(
uiNewSize, &pThis, sizeof( FlmRecord *), &pucNewBuf, &bHeapAlloc)))
{
goto Exit;
}
uiNewDataOffset = 0;
pucNewData = pucNewBuf + FLM_ALIGN_SIZE + (m_uiFldTblOffset * sizeof( FlmField));
pFld = getFieldPointer( root());
while( pFld)
{
uiLength = getFieldDataLength( pFld);
if (!isEncryptedField( pFld))
{
if( uiLength > 4 && uiLength < 0xFF)
{
if( getFieldDataType( pFld) == FLM_BINARY_TYPE)
{
if( (uiNewDataOffset & FLM_ALLOC_ALIGN) != 0)
{
uiNewDataOffset += (FLM_ALLOC_ALIGN + 1) -
(uiNewDataOffset & FLM_ALLOC_ALIGN);
}
}
flmAssert( uiNewDataOffset + uiLength <= uiNewDataSize);
f_memcpy( &pucNewData[ uiNewDataOffset],
getDataPtr( pFld), uiLength);
pFld->ui32DataOffset = (FLMUINT32)uiNewDataOffset;
uiNewDataOffset += uiLength;
}
else if( uiLength >= 0xFF)
{
uiTmp = uiNewDataOffset + sizeof( FLMUINT16) + 1;
if( getFieldDataType( pFld) == FLM_BINARY_TYPE)
{
if( (uiTmp & FLM_ALLOC_ALIGN) != 0)
{
uiTmp += (FLM_ALLOC_ALIGN + 1) - (uiTmp & FLM_ALLOC_ALIGN);
}
}
flmAssert( uiTmp + uiLength <= uiNewDataSize);
pucNewData[ uiNewDataOffset] = 0; // Set the flags byte.
UW2FBA( (FLMUINT32)uiLength, &pucNewData[ uiNewDataOffset + FLD_ENC_ENCID]);
f_memcpy( &pucNewData[ uiTmp], getDataPtr( pFld), uiLength);
pFld->ui32DataOffset = (FLMUINT32)uiNewDataOffset;
uiNewDataOffset = uiTmp + uiLength;
}
}
else // Encrypted field
{
FLMUINT uiFlags;
FLMUINT uiEncId;
FLMUINT uiEncLength;
FLMUINT uiEncTmp;
#ifdef FLM_PICKET_FENCE
uiPicketFenceSize = FLD_PICKET_FENCE_SIZE;
#endif
uiFlags = getEncFlags( pFld);
uiEncId = getEncryptionID( pFld);
uiEncLength = getEncryptedDataLength( pFld);
uiTmp = uiNewDataOffset + FLM_ENC_FLD_OVERHEAD;
if( getFieldDataType( pFld) == FLM_BINARY_TYPE)
{
if( (uiTmp & FLM_ALLOC_ALIGN) != 0)
{
uiTmp += (FLM_ALLOC_ALIGN + 1) - (uiTmp & FLM_ALLOC_ALIGN);
}
}
uiEncTmp = uiTmp + uiLength + (uiPicketFenceSize / 2);
flmAssert( uiEncTmp + uiEncLength + (uiPicketFenceSize / 2) <= uiNewDataSize);
pucNewData[ uiNewDataOffset + FLD_ENC_FLAGS] = ( FLMBYTE)uiFlags;
UW2FBA( (FLMUINT32)uiEncId, &pucNewData[ uiNewDataOffset + FLD_ENC_ENCID]);
UW2FBA( (FLMUINT32)uiLength, &pucNewData[ uiNewDataOffset + FLD_ENC_DATA_LEN]);
UW2FBA( (FLMUINT32)uiEncLength, &pucNewData[ uiNewDataOffset + FLD_ENC_ENCRYPTED_DATA_LEN]);
#ifdef FLM_PICKET_FENCE
// Set the picket fence
f_sprintf( (char *)&pucNewData[ uiTmp], FLD_RAW_FENCE);
uiTmp += (FLD_PICKET_FENCE_SIZE / 2);
#endif
f_memcpy( &pucNewData[ uiTmp], getDataPtr( pFld), uiLength);
#ifdef FLM_PICKET_FENCE
// Set the picket fence
f_sprintf( (char *)&pucNewData[ uiEncTmp], FLD_ENC_FENCE);
uiEncTmp += (FLD_PICKET_FENCE_SIZE / 2);
#endif
f_memcpy( &pucNewData[ uiEncTmp], getEncryptionDataPtr( pFld), uiEncLength);
pFld->ui32DataOffset = (FLMUINT32)uiNewDataOffset;
uiNewDataOffset = uiEncTmp + uiEncLength;
}
pFld = nextField( pFld);
}
// The field list cannot be compressed because the application may
// still have "pointers" (offsets) into the table
f_memcpy( pucNewBuf, m_pucBuffer,
FLM_ALIGN_SIZE + (m_uiFldTblOffset * sizeof( FlmField)));
#ifdef FLM_DEBUG
uiTmp = (FLM_ALIGN_SIZE + uiNewDataOffset +
(sizeof( FlmField) * m_uiFldTblOffset));
flmAssert( uiTmp == uiNewSize);
#endif
// Update the member variables
gv_FlmSysData.RCacheMgr.pRecBufAlloc->freeBuf(
m_uiBufferSize, &m_pucBuffer);
m_pucBuffer = pucNewBuf;
pucNewBuf = NULL;
if( bHeapAlloc)
{
m_uiFlags |= RCA_HEAP_BUFFER;
}
else
{
m_uiFlags &= ~RCA_HEAP_BUFFER;
}
m_uiBufferSize = uiNewSize;
m_uiFldTblSize = m_uiFldTblOffset;
m_uiDataBufOffset = uiNewDataSize;
m_bHolesInData = FALSE;
Exit:
if( pucNewBuf)
{
gv_FlmSysData.RCacheMgr.pRecBufAlloc->freeBuf(
uiNewSize, &pucNewBuf);
}
return( rc);
}
/*****************************************************************************
Desc: Return most all unused memory back to the system. This should
be called by the Release method of the record object.
*****************************************************************************/
RCODE FlmRecord::compactMemory( void)
{
RCODE rc = FERR_OK;
FLMUINT uiLength;
FLMUINT uiTmp;
FLMUINT uiNewSize = 0;
FLMUINT uiNewDataSize = 0;
FLMUINT uiNewDataOffset;
FLMUINT uiFields = 0;
FLMUINT uiSlot;
FlmField * pFld;
FlmField * pNewFld;
FlmField * pNewFldTbl;
FLMBYTE * pucNewBuf = NULL;
FLMBYTE * pucNewData;
FLMUINT uiPicketFenceSize = 0;
FlmRecord * pThis = this;
FLMBOOL bHeapAlloc = FALSE;
flmAssert( isCached());
flmAssert( m_ui32RefCnt == 1);
// Temporarily increment the reference count so that we don't hit
// debug asserts while processing
m_ui32RefCnt++;
if( !m_uiBufferSize ||
(!m_bHolesInData && m_uiDataBufOffset == getDataBufSize()))
{
if( !m_uiFirstAvail && m_uiFldTblOffset == m_uiFldTblSize)
{
goto Exit;
}
}
if( isOldVersion())
{
FLMUINT uiTotalMemory = getTotalMemory();
flmAssert( gv_FlmSysData.RCacheMgr.Usage.uiOldVerBytes >= uiTotalMemory);
gv_FlmSysData.RCacheMgr.Usage.uiOldVerBytes -= uiTotalMemory;
}
// Scan the record and determine the compressed size
pFld = getFieldPointer( root());
while( pFld)
{
uiLength = getFieldDataLength( pFld);
if (!isEncryptedField(pFld))
{
if( uiLength > 4 && uiLength < 0xFF)
{
if( getFieldDataType( pFld) == FLM_BINARY_TYPE)
{
if( (uiNewDataSize & FLM_ALLOC_ALIGN) != 0)
{
uiNewDataSize += (FLM_ALLOC_ALIGN + 1) -
(uiNewDataSize & FLM_ALLOC_ALIGN);
}
}
uiNewDataSize += uiLength;
}
else if( uiLength >= 0xFF)
{
// Add one extra byte for the flags byte.
uiTmp = uiNewDataSize + sizeof( FLMUINT16) + 1;
if( getFieldDataType( pFld) == FLM_BINARY_TYPE)
{
if( (uiTmp & FLM_ALLOC_ALIGN) != 0)
{
uiTmp += (FLM_ALLOC_ALIGN + 1) - (uiTmp & FLM_ALLOC_ALIGN);
}
}
uiNewDataSize = uiTmp + uiLength;
}
}
else // Encrypted field
{
#ifdef FLM_PICKET_FENCE
uiPicketFenceSize = FLD_PICKET_FENCE_SIZE;
#endif
uiTmp = uiNewDataSize + FLM_ENC_FLD_OVERHEAD;
if( getFieldDataType( pFld) == FLM_BINARY_TYPE)
{
if( (uiTmp & FLM_ALLOC_ALIGN) != 0)
{
uiTmp += (FLM_ALLOC_ALIGN + 1) - (uiTmp & FLM_ALLOC_ALIGN);
}
}
uiNewDataSize = uiTmp + uiLength + getEncryptedDataLength(pFld) +
uiPicketFenceSize;
}
uiFields++;
pFld = nextField( pFld);
}
uiNewSize = FLM_ALIGN_SIZE +
uiNewDataSize + (uiFields * sizeof( FlmField));
flmAssert( uiNewSize <= m_uiBufferSize);
// Allocate a new buffer
if( RC_BAD( rc = gv_FlmSysData.RCacheMgr.pRecBufAlloc->allocBuf(
uiNewSize, &pThis, sizeof( FlmRecord *), &pucNewBuf, &bHeapAlloc)))
{
goto Exit;
}
pNewFldTbl = (FlmField *)(pucNewBuf + FLM_ALIGN_SIZE);
uiSlot = 0;
uiNewDataOffset = 0;
pucNewData = pucNewBuf + FLM_ALIGN_SIZE + (uiFields * sizeof( FlmField));
pFld = getFieldPointer( root());
while( pFld)
{
uiLength = getFieldDataLength( pFld);
pNewFld = &pNewFldTbl[ uiSlot];
f_memcpy( pNewFld, pFld, sizeof( FlmField));
if (!isEncryptedField(pFld))
{
if( uiLength > 4 && uiLength < 0xFF)
{
if( getFieldDataType( pFld) == FLM_BINARY_TYPE)
{
if( (uiNewDataOffset & FLM_ALLOC_ALIGN) != 0)
{
uiNewDataOffset += (FLM_ALLOC_ALIGN + 1) -
(uiNewDataOffset & FLM_ALLOC_ALIGN);
}
}
flmAssert( uiNewDataOffset + uiLength <= uiNewDataSize);
f_memcpy( &pucNewData[ uiNewDataOffset], getDataPtr( pFld), uiLength);
pNewFld->ui32DataOffset = (FLMUINT32)uiNewDataOffset;
uiNewDataOffset += uiLength;
}
else if( uiLength >= 0xFF)
{
uiTmp = uiNewDataOffset + sizeof( FLMUINT16) + 1;
if( getFieldDataType( pFld) == FLM_BINARY_TYPE)
{
if( (uiTmp & FLM_ALLOC_ALIGN) != 0)
{
uiTmp += (FLM_ALLOC_ALIGN + 1) - (uiTmp & FLM_ALLOC_ALIGN);
}
}
flmAssert( uiTmp + uiLength <= uiNewDataSize);
pucNewData[ uiNewDataOffset] = 0; // Flags
UW2FBA( (FLMUINT32)uiLength, &pucNewData[ uiNewDataOffset + FLD_ENC_ENCID]);
f_memcpy( &pucNewData[ uiTmp], getDataPtr( pFld), uiLength);
pNewFld->ui32DataOffset = (FLMUINT32)uiNewDataOffset;
uiNewDataOffset = uiTmp + uiLength;
}
}
else
{
FLMUINT uiFlags;
FLMUINT uiEncId;
FLMUINT uiEncLength;
FLMUINT uiEncTmp;
#ifdef FLM_PICKET_FENCE
uiPicketFenceSize = FLD_PICKET_FENCE_SIZE;
#endif
uiFlags = getEncFlags( pFld);
uiEncId = getEncryptionID( pFld);
uiEncLength = getEncryptedDataLength( pFld);
uiTmp = uiNewDataOffset + FLM_ENC_FLD_OVERHEAD;
if( getFieldDataType( pFld) == FLM_BINARY_TYPE)
{
if( (uiTmp & FLM_ALLOC_ALIGN) != 0)
{
uiTmp += (FLM_ALLOC_ALIGN + 1) - (uiTmp & FLM_ALLOC_ALIGN);
}
}
uiEncTmp = uiTmp + uiLength + (uiPicketFenceSize / 2);
flmAssert( uiEncTmp + uiEncLength + (uiPicketFenceSize / 2) <= uiNewDataSize);
pucNewData[ uiNewDataOffset + FLD_ENC_FLAGS] = ( FLMBYTE)uiFlags;
UW2FBA( (FLMUINT16)uiEncId, &pucNewData[ uiNewDataOffset + FLD_ENC_ENCID]);
UW2FBA( (FLMUINT16)uiLength, &pucNewData[ uiNewDataOffset + FLD_ENC_DATA_LEN]);
UW2FBA( (FLMUINT16)uiEncLength, &pucNewData[ uiNewDataOffset + FLD_ENC_ENCRYPTED_DATA_LEN]);
#ifdef FLM_PICKET_FENCE
f_sprintf( (char *)&pucNewData[ uiTmp], FLD_RAW_FENCE);
uiTmp += (FLD_PICKET_FENCE_SIZE / 2);
#endif
f_memcpy( &pucNewData[ uiTmp], getDataPtr( pFld), uiLength);
#ifdef FLM_PICKET_FENCE
f_sprintf( (char *)&pucNewData[ uiEncTmp], FLD_ENC_FENCE);
uiEncTmp += (FLD_PICKET_FENCE_SIZE / 2);
#endif
f_memcpy( &pucNewData[ uiEncTmp], getEncryptionDataPtr( pFld), uiEncLength);
pNewFld->ui32DataOffset = (FLMUINT32)uiNewDataOffset;
uiNewDataOffset = uiEncTmp + uiEncLength;
}
pFld = nextField( pFld);
pNewFld->uiPrev = (FIELDLINK)uiSlot;
if( pFld)
{
pNewFld->uiNext = (FIELDLINK)(uiSlot + 2);
}
else
{
pNewFld->uiNext = 0;
}
uiSlot++;
}
// Update the member variables
gv_FlmSysData.RCacheMgr.pRecBufAlloc->freeBuf(
m_uiBufferSize, &m_pucBuffer);
m_pucBuffer = pucNewBuf;
pucNewBuf = NULL;
if( bHeapAlloc)
{
m_uiFlags |= RCA_HEAP_BUFFER;
}
else
{
m_uiFlags &= ~RCA_HEAP_BUFFER;
}
m_uiBufferSize = uiNewSize;
m_uiFldTblOffset = uiFields;
m_uiFldTblSize = uiFields;
m_uiDataBufOffset = uiNewDataSize;
m_bHolesInData = FALSE;
m_uiAvailFields = 0;
m_uiFirstAvail = 0;
if( isOldVersion())
{
FLMUINT uiTotalMemory = getTotalMemory();
gv_FlmSysData.RCacheMgr.Usage.uiOldVerBytes += uiTotalMemory;
}
Exit:
if( pucNewBuf)
{
gv_FlmSysData.RCacheMgr.pRecBufAlloc->freeBuf(
uiNewSize, &pucNewBuf);
}
// Remove the reference count added above
m_ui32RefCnt--;
return( rc);
}
/*****************************************************************************
Desc: Create a new field after pCurField.
*****************************************************************************/
RCODE FlmRecord::createField(
FlmField * pPrevField,
FlmField ** ppNewField)
{
RCODE rc = FERR_OK;
FlmField * pNewField;
FLMUINT uiNewSize;
FlmField * pFldTbl = NULL;
void * pvPrevField;
FlmRecord * pThis = this;
FLMBOOL bHeapAlloc = FALSE;
flmAssert( !isReadOnly());
flmAssert( !isCached());
pvPrevField = getFieldVoid( pPrevField);
pPrevField = NULL;
if( m_uiFirstAvail)
{
flmAssert( m_uiAvailFields);
pNewField = &(getFieldTable()[ m_uiFirstAvail - 1]);
m_uiFirstAvail = pNewField->uiNext;
m_uiAvailFields--;
}
else
{
if( m_uiFldTblOffset == m_uiFldTblSize)
{
// Resize the buffer
if( m_uiBufferSize)
{
uiNewSize = m_uiBufferSize + (sizeof( FlmField) * 8);
}
else
{
uiNewSize = FLM_ALIGN_SIZE + (sizeof( FlmField) * 8);
}
if( RC_BAD( rc = gv_FlmSysData.RCacheMgr.pRecBufAlloc->reallocBuf(
m_uiBufferSize, uiNewSize, &pThis, sizeof( FlmRecord *),
&m_pucBuffer, &bHeapAlloc)))
{
goto Exit;
}
m_uiBufferSize = uiNewSize;
m_uiFldTblSize += 8;
if( m_uiDataBufOffset)
{
f_memmove( &(getFieldTable()[ m_uiFldTblSize]),
&(getFieldTable()[ m_uiFldTblSize - 8]),
m_uiDataBufOffset);
}
if( bHeapAlloc)
{
m_uiFlags |= RCA_HEAP_BUFFER;
}
else
{
m_uiFlags &= ~RCA_HEAP_BUFFER;
}
}
pFldTbl = getFieldTable();
pNewField = &pFldTbl[ m_uiFldTblOffset++];
}
f_memset( pNewField, 0, sizeof( FlmField));
pPrevField = getFieldPointer( pvPrevField);
if( pPrevField)
{
pNewField->ui16FieldID = 0xFFFF;
pNewField->uiPrev = (FIELDLINK)((FLMUINT)pvPrevField);
pNewField->uiNext = pPrevField->uiNext;
if( pPrevField->uiNext)
{
getFieldPointer( (void *)((FLMUINT)(pPrevField->uiNext)))->uiPrev =
(FIELDLINK)((FLMUINT)getFieldVoid( pNewField));
}
pPrevField->uiNext = (FIELDLINK)((FLMUINT)getFieldVoid( pNewField));
}
*ppNewField = pNewField;
Exit:
return( rc);
}
/*****************************************************************************
Desc: Remove a specific field, or a range of fields.
*****************************************************************************/
RCODE FlmRecord::removeFields(
FlmField * pFirstField,
FlmField * pLastField)
{
RCODE rc = FERR_OK;
FlmField * pCurField;
FLMUINT uiFieldsRemoved = 0;
flmAssert( !isReadOnly());
flmAssert( !isCached());
// Setup the common case first of removing a single field.
if( !pLastField)
{
pLastField = pFirstField;
}
// Fix up the prev and next pointers
if( pFirstField->uiPrev)
{
getFieldPointer( (void *)((FLMUINT)(pFirstField->uiPrev)))->uiNext =
pLastField->uiNext;
}
if( pLastField->uiNext)
{
getFieldPointer( (void *)((FLMUINT)(pLastField->uiNext)))->uiPrev =
pFirstField->uiPrev;
pLastField->uiNext = 0;
}
// Clear the field slots
pCurField = pFirstField;
while( pCurField)
{
pCurField->uiPrev = 0;
pCurField->ui32DataOffset = 0;
pCurField->ui16FieldID = 0;
pCurField->ui8DataLen = 0;
pCurField->ui8TypeAndLevel = 0;
pCurField = nextField( pCurField);
uiFieldsRemoved++;
}
pLastField->uiNext = m_uiFirstAvail;
m_uiFirstAvail = (FIELDLINK)((FLMUINT)getFieldVoid( pFirstField));
m_uiAvailFields += uiFieldsRemoved;
return( rc);
}
/*****************************************************************************
Desc: Returns a pointer that is of size 'uiNewLength' that the caller
can then write a fields data to. If possible the fields current
data pointer will be reused.
*****************************************************************************/
RCODE FlmRecord::getNewDataPtr(
FlmField * pField,
FLMUINT uiDataType,
FLMUINT uiNewLength,
FLMUINT uiEncNewLength,
FLMUINT uiEncId,
FLMUINT uiFlags,
FLMBYTE ** ppDataPtr,
FLMBYTE ** ppEncDataPtr)
{
RCODE rc = FERR_OK;
FLMBYTE * pucDataPtr = NULL;
FLMBYTE * pucEncDataPtr = NULL;
FLMUINT uiOldLength;
FLMUINT uiAlignment = 0;
FLMUINT uiSlot = (FLMUINT)getFieldVoid( pField);
FLMUINT uiDataBufSize;
FLMUINT uiHeader = 0;
FLMUINT uiOldHeader = 0;
FLMUINT uiAllocStart = 0;
FLMUINT uiTmp;
FLMBOOL bNewEncrypted = (uiEncId ? TRUE : FALSE);
FLMBOOL bOldEncrypted;
FLMBYTE * pucTmp;
FLMUINT uiNewSize;
FLMUINT uiPicketFenceSize = 0;
FlmRecord * pThis = this;
FLMBOOL bHeapAlloc = FALSE;
flmAssert( !isCached());
flmAssert( !isReadOnly());
#ifdef FLM_PICKET_FENCE
uiPicketFenceSize = (bNewEncrypted ? FLD_PICKET_FENCE_SIZE : 0);
#endif
// Test for an invalid encryption Id. This could be
// indicative of an uninitialized variaqble.
if (uiEncId > FLM_RESERVED_TAG_NUMS)
{
flmAssert( 0);
rc = RC_SET( FERR_BAD_ENCDEF_ID);
goto Exit;
}
// Make sure the requested size doesn't exceed the maximum
// field value size
if( uiNewLength > FLM_MAX_FIELD_VAL_SIZE ||
uiEncNewLength > FLM_MAX_FIELD_VAL_SIZE)
{
rc = RC_SET( FERR_VALUE_TOO_LARGE);
goto Exit;
}
bOldEncrypted = isEncryptedField( pField);
// If the new field is encrypted, we need to prefix the value
// with the encryption overhead.
// Otherwise, if the new length is >= 0xFF, we need to prefix the value
// with a 2-byte length
uiHeader = (bNewEncrypted ? FLM_ENC_FLD_OVERHEAD
: (uiNewLength >= 0xFF ? sizeof( FLMUINT16) + 1
: 0));
// Determine the true original data length
uiOldLength = getFieldDataLength( pField);
if( uiOldLength >= 0xFF ||
bOldEncrypted)
{
flmAssert( pField->ui8DataLen == 0xFF);
// Account for the header
uiOldHeader = (bOldEncrypted ? FLM_ENC_FLD_OVERHEAD : sizeof( FLMUINT16) + 1);
uiOldLength += uiOldHeader;
// Special work if this is a binary field
if( getFieldDataType( pField) == FLM_BINARY_TYPE)
{
// Since the value is binary, need to account for any
// alignment bytes
if( ((pField->ui32DataOffset + uiOldHeader) & FLM_ALLOC_ALIGN) != 0)
{
uiAlignment = (FLM_ALLOC_ALIGN + 1) -
((pField->ui32DataOffset + uiOldHeader) & FLM_ALLOC_ALIGN);
uiOldLength += uiAlignment;
}
if (bOldEncrypted)
{
// Add the length of the encrypted data.
uiOldLength += getEncryptedDataLength( pField);
}
}
}
#ifdef FLM_PICKET_FENCE
if (bOldEncrypted)
{
uiOldLength += FLD_PICKET_FENCE_SIZE; // Add the picket fence size
}
#endif
// If the old length is > 4 and the new length is <= 4 the value MUST
// be stored in ui32DataOffset. To be simple, this is coded for
// the four cases.
uiAlignment = 0;
if( uiOldLength <= sizeof(FLMUINT32))
{
if( uiNewLength <= sizeof(FLMUINT32))
{
if (!bNewEncrypted)
{
pField->ui32DataOffset = 0;
pucDataPtr = (FLMBYTE *)&(pField->ui32DataOffset);
pField->ui8DataLen = (FLMUINT8)uiNewLength;
}
else
{
// The new field is encrypted.
// If this is a binary field, it must start on an aligned byte.
if( uiDataType == FLM_BINARY_TYPE &&
((m_uiDataBufOffset + uiHeader) & FLM_ALLOC_ALIGN) != 0)
{
uiAlignment = (FLM_ALLOC_ALIGN + 1) -
((m_uiDataBufOffset + uiHeader) & FLM_ALLOC_ALIGN);
}
uiAllocStart = m_uiDataBufOffset;
uiDataBufSize = getDataBufSize();
if( uiNewLength + uiEncNewLength + uiAlignment +
uiHeader + m_uiDataBufOffset + uiPicketFenceSize > uiDataBufSize)
{
// Re-allocate the buffer.
uiNewSize = m_uiBufferSize +
uiHeader +
uiAlignment +
uiNewLength +
uiEncNewLength +
uiPicketFenceSize +
32;
if( RC_BAD( rc = gv_FlmSysData.RCacheMgr.pRecBufAlloc->reallocBuf(
m_uiBufferSize, uiNewSize,
&pThis, sizeof( FlmRecord *), &m_pucBuffer, &bHeapAlloc)))
{
goto Exit;
}
m_uiBufferSize = uiNewSize;
pField = &(getFieldTable()[ uiSlot - 1]);
if( bHeapAlloc)
{
m_uiFlags |= RCA_HEAP_BUFFER;
}
else
{
m_uiFlags &= ~RCA_HEAP_BUFFER;
}
}
pucDataPtr = getDataBufPtr() + uiAllocStart + uiHeader +
uiAlignment + (uiPicketFenceSize / 2);
pucEncDataPtr = pucDataPtr + uiNewLength + (uiPicketFenceSize / 2);
setEncHeader( getDataBufPtr() + uiAllocStart, uiFlags, uiEncId,
uiNewLength, uiEncNewLength);
pField->ui8DataLen = 0xFF;
pField->ui32DataOffset = (FLMUINT32)uiAllocStart;
m_uiDataBufOffset += uiHeader + uiAlignment + uiNewLength +
uiEncNewLength + uiPicketFenceSize;
}
}
else
{
// If this is a binary field, it must start on an aligned byte.
if( uiDataType == FLM_BINARY_TYPE &&
((m_uiDataBufOffset + uiHeader) & FLM_ALLOC_ALIGN) != 0)
{
uiAlignment = (FLM_ALLOC_ALIGN + 1) -
((m_uiDataBufOffset + uiHeader) & FLM_ALLOC_ALIGN);
}
uiAllocStart = m_uiDataBufOffset;
uiDataBufSize = getDataBufSize();
if( uiNewLength + uiAlignment + uiHeader + uiEncNewLength +
m_uiDataBufOffset + uiPicketFenceSize > uiDataBufSize)
{
// Re-allocate the buffer.
uiNewSize = m_uiBufferSize +
uiHeader +
uiAlignment +
uiNewLength +
uiEncNewLength +
uiPicketFenceSize +
32;
if( RC_BAD( rc = gv_FlmSysData.RCacheMgr.pRecBufAlloc->reallocBuf(
m_uiBufferSize, uiNewSize,
&pThis, sizeof( FlmRecord *), &m_pucBuffer, &bHeapAlloc)))
{
goto Exit;
}
m_uiBufferSize = uiNewSize;
pField = &(getFieldTable()[ uiSlot - 1]);
if( bHeapAlloc)
{
m_uiFlags |= RCA_HEAP_BUFFER;
}
else
{
m_uiFlags &= ~RCA_HEAP_BUFFER;
}
}
pucDataPtr = getDataBufPtr() + uiAllocStart + uiHeader +
uiAlignment + (uiPicketFenceSize / 2);
if (bNewEncrypted)
{
pucEncDataPtr = pucDataPtr + uiNewLength + (uiPicketFenceSize / 2);
}
// The presence of uiHeader indicates that the length of the new field
// is greater than 255 bytes, or it is encrypted, therefore we will
// store the actual length in the buffer.
if( uiHeader)
{
if (!bNewEncrypted)
{
pucTmp = getDataBufPtr() + uiAllocStart;
*pucTmp = 0; // Flags
pucTmp++;
UW2FBA( (FLMUINT16)uiNewLength, pucTmp);
pField->ui8DataLen = 0xFF;
pField->ui32DataOffset = (FLMUINT32)uiAllocStart;
}
else // Encrypted
{
setEncHeader( getDataBufPtr() + uiAllocStart, uiFlags,
uiEncId, uiNewLength, uiEncNewLength);
pField->ui8DataLen = 0xFF;
pField->ui32DataOffset = (FLMUINT32)uiAllocStart;
}
}
else
{
flmAssert( !bNewEncrypted);
pField->ui8DataLen = (FLMUINT8)uiNewLength;
pField->ui32DataOffset = (FLMUINT32)(uiAllocStart + uiAlignment);
}
m_uiDataBufOffset += uiHeader + uiAlignment + uiNewLength +
uiEncNewLength + uiPicketFenceSize;
}
}
else // uiOldLength > sizeof(FLMUINT32)
{
if( uiNewLength > sizeof(FLMUINT32))
{
if( uiDataType == FLM_BINARY_TYPE &&
((pField->ui32DataOffset + uiHeader) & FLM_ALLOC_ALIGN) != 0)
{
uiAlignment = (FLM_ALLOC_ALIGN + 1) -
((pField->ui32DataOffset + uiHeader) & FLM_ALLOC_ALIGN);
}
// Smaller or same size?
if( (uiTmp = (uiHeader + uiAlignment + uiNewLength +
uiEncNewLength + uiPicketFenceSize)) <= uiOldLength)
{
if( uiTmp != uiOldLength)
{
m_bHolesInData = TRUE;
}
if( uiHeader)
{
if (!bNewEncrypted)
{
pucTmp = getDataBufPtr() + pField->ui32DataOffset;
*pucTmp = 0; // Flags
pucTmp++;
UW2FBA( (FLMUINT16)uiNewLength, pucTmp);
pField->ui8DataLen = 0xFF;
}
else
{
// It's encrypted...
setEncHeader( getDataBufPtr() + pField->ui32DataOffset,
uiFlags,
uiEncId,
uiNewLength,
uiEncNewLength);
pField->ui8DataLen = 0xFF;
// No need to set the offset because we are re-using the same
// buffer space.
}
}
else
{
flmAssert( uiNewLength < 0xFF);
flmAssert( !bNewEncrypted);
pField->ui8DataLen = (FLMUINT8)uiNewLength;
}
pucDataPtr = getDataBufPtr() +
pField->ui32DataOffset + uiHeader + uiAlignment + (uiPicketFenceSize / 2);
if (bNewEncrypted)
{
pucEncDataPtr = pucDataPtr + uiNewLength + (uiPicketFenceSize / 2);
}
}
else
{
// The new value is larger than the original value.
// If this is a binary field it must start on an aligned byte.
uiAlignment = 0;
if( uiDataType == FLM_BINARY_TYPE &&
((m_uiDataBufOffset + uiHeader) & FLM_ALLOC_ALIGN) != 0)
{
uiAlignment = (FLM_ALLOC_ALIGN + 1) -
((m_uiDataBufOffset + uiHeader) & FLM_ALLOC_ALIGN);
}
uiAllocStart = m_uiDataBufOffset;
uiDataBufSize = getDataBufSize();
if( (m_uiDataBufOffset + uiHeader +
uiAlignment + uiNewLength +
uiEncNewLength + uiPicketFenceSize) > uiDataBufSize)
{
// Re-allocate the buffer.
uiNewSize = m_uiBufferSize +
uiHeader +
uiAlignment +
uiNewLength +
uiEncNewLength +
uiPicketFenceSize +
32;
if( RC_BAD( rc = gv_FlmSysData.RCacheMgr.pRecBufAlloc->reallocBuf(
m_uiBufferSize, uiNewSize,
&pThis, sizeof( FlmRecord *), &m_pucBuffer, &bHeapAlloc)))
{
goto Exit;
}
m_uiBufferSize = uiNewSize;
pField = &(getFieldTable()[ uiSlot - 1]);
if( bHeapAlloc)
{
m_uiFlags |= RCA_HEAP_BUFFER;
}
else
{
m_uiFlags &= ~RCA_HEAP_BUFFER;
}
}
pucDataPtr = getDataBufPtr() + m_uiDataBufOffset + uiHeader +
uiAlignment + (uiPicketFenceSize / 2);
if (bNewEncrypted)
{
pucEncDataPtr = pucDataPtr + uiNewLength + (uiPicketFenceSize / 2);
}
if( uiHeader)
{
if (!bNewEncrypted)
{
pucTmp = getDataBufPtr() + uiAllocStart;
*pucTmp = 0; // Flags
pucTmp++;
UW2FBA( (FLMUINT16)uiNewLength, pucTmp);
pField->ui8DataLen = 0xFF;
pField->ui32DataOffset = (FLMUINT32)uiAllocStart;
}
else
{
setEncHeader( getDataBufPtr() + uiAllocStart, uiFlags,
uiEncId, uiNewLength, uiEncNewLength);
pField->ui8DataLen = 0xFF;
pField->ui32DataOffset = (FLMUINT32)uiAllocStart;
}
}
else
{
flmAssert( uiNewLength < 0xFF);
flmAssert( !bNewEncrypted);
pField->ui32DataOffset = (FLMUINT32)(uiAllocStart + uiAlignment);
pField->ui8DataLen = (FLMUINT8)uiNewLength;
}
m_uiDataBufOffset += uiHeader + uiAlignment + uiNewLength +
uiEncNewLength + uiPicketFenceSize;
m_bHolesInData = TRUE;
}
}
else // uiNewLength <= sizeof(FLMUINT32)
{
if (!bNewEncrypted)
{
pField->ui32DataOffset = 0;
pucDataPtr = (FLMBYTE *)&(pField->ui32DataOffset);
pField->ui8DataLen = (FLMUINT8)uiNewLength;
m_bHolesInData = TRUE;
}
else
{
// The new field is encrypted.
// If this is a binary field, it must start on an aligned byte.
if( uiDataType == FLM_BINARY_TYPE &&
((pField->ui32DataOffset + uiHeader) & FLM_ALLOC_ALIGN) != 0)
{
uiAlignment = (FLM_ALLOC_ALIGN + 1) -
((pField->ui32DataOffset + uiHeader) & FLM_ALLOC_ALIGN);
}
// New field will be stored in a buffer.
// See if we can re-use the old buffer.
if( (uiTmp = (uiHeader + uiAlignment + uiNewLength +
uiEncNewLength + uiPicketFenceSize)) <= uiOldLength)
{
if( uiTmp != uiOldLength)
{
m_bHolesInData = TRUE;
}
setEncHeader( getDataBufPtr() + pField->ui32DataOffset,
uiFlags,
uiEncId,
uiNewLength,
uiEncNewLength);
pField->ui8DataLen = 0xFF;
uiAllocStart = pField->ui32DataOffset;
}
else
{
// The field position is changing, so we need to recalculate the alignment
// (if needed).
// If this is a binary field, it must start on an aligned byte.
if( uiDataType == FLM_BINARY_TYPE &&
((m_uiDataBufOffset + uiHeader) & FLM_ALLOC_ALIGN) != 0)
{
uiAlignment = (FLM_ALLOC_ALIGN + 1) -
((m_uiDataBufOffset + uiHeader) & FLM_ALLOC_ALIGN);
}
uiAllocStart = m_uiDataBufOffset;
uiDataBufSize = getDataBufSize();
if( uiNewLength + uiEncNewLength + uiAlignment +
uiHeader + m_uiDataBufOffset + uiPicketFenceSize > uiDataBufSize)
{
// Re-allocate the buffer.
uiNewSize = m_uiBufferSize +
uiHeader +
uiAlignment +
uiNewLength +
uiEncNewLength +
uiPicketFenceSize +
32;
if( RC_BAD( rc = gv_FlmSysData.RCacheMgr.pRecBufAlloc->reallocBuf(
m_uiBufferSize, uiNewSize,
&pThis, sizeof( FlmRecord *), &m_pucBuffer, &bHeapAlloc)))
{
goto Exit;
}
m_uiBufferSize = uiNewSize;
pField = &(getFieldTable()[ uiSlot - 1]);
if( bHeapAlloc)
{
m_uiFlags |= RCA_HEAP_BUFFER;
}
else
{
m_uiFlags &= ~RCA_HEAP_BUFFER;
}
}
setEncHeader( getDataBufPtr() + uiAllocStart,
uiFlags,
uiEncId,
uiNewLength,
uiEncNewLength);
pField->ui8DataLen = 0xFF;
pField->ui32DataOffset = (FLMUINT32)uiAllocStart;
m_uiDataBufOffset += uiHeader + uiAlignment + uiNewLength +
uiEncNewLength + uiPicketFenceSize;
}
pucDataPtr = getDataBufPtr() + uiAllocStart + uiHeader +
uiAlignment + (uiPicketFenceSize / 2);
pucEncDataPtr = pucDataPtr + uiNewLength + (uiPicketFenceSize / 2);
}
}
}
setFieldDataType( pField, uiDataType);
#ifdef FLM_DEBUG
f_memset( pucDataPtr, 0, uiNewLength);
f_memset( pucEncDataPtr, 0, uiEncNewLength);
#endif
if (ppDataPtr)
{
*ppDataPtr = pucDataPtr;
}
if (ppEncDataPtr)
{
*ppEncDataPtr = pucEncDataPtr;
}
#ifdef FLM_PICKET_FENCE
// Set the picket fences
if (bNewEncrypted)
{
pucDataPtr -= 4;
f_memcpy( pucDataPtr, (FLMBYTE *)FLD_RAW_FENCE,
FLD_PICKET_FENCE_SIZE / 2);
pucEncDataPtr -= 4;
f_memcpy( pucEncDataPtr, (FLMBYTE *)FLD_ENC_FENCE,
FLD_PICKET_FENCE_SIZE / 2);
}
#endif
Exit:
if( RC_BAD( rc))
{
if (ppDataPtr)
{
*ppDataPtr = NULL;
}
if (ppEncDataPtr)
{
*ppEncDataPtr = NULL;
}
}
return( rc);
}
/*****************************************************************************
Desc: Add a globally shared reference to this object.
*****************************************************************************/
FLMUINT FlmRecord::AddRef(
FLMBOOL bMutexLocked)
{
FLMUINT uiRefCnt = 0;
FLMBOOL bLockedMutex = FALSE;
#ifdef ATOMIC_INCDEC_SUPPORT
(void)bMutexLocked;
uiRefCnt = (FLMUINT)ftkAtomicIncrement( &m_ui32RefCnt);
#else
if( !bMutexLocked)
{
f_mutexLock( gv_FlmSysData.RCacheMgr.hMutex);
bLockedMutex = TRUE;
bMutexLocked = TRUE;
}
uiRefCnt = ++m_ui32RefCnt;
#endif
if( bLockedMutex)
{
f_mutexUnlock( gv_FlmSysData.RCacheMgr.hMutex);
}
flmAssert( uiRefCnt > 1);
return( uiRefCnt);
}
/*****************************************************************************
Desc: Removes a globally shared reference to this object.
*****************************************************************************/
FLMUINT FlmRecord::Release(
FLMBOOL bMutexLocked)
{
FLMUINT uiRefCnt = 0;
FLMBOOL bUnlockMutex = FALSE;
#ifdef ATOMIC_INCDEC_SUPPORT
if( isCached() && m_ui32RefCnt == 2)
{
if( !bMutexLocked)
{
f_mutexLock( gv_FlmSysData.RCacheMgr.hMutex);
bMutexLocked = TRUE;
bUnlockMutex = TRUE;
}
}
uiRefCnt = (FLMUINT)ftkAtomicDecrement( &m_ui32RefCnt);
#else
if( !bMutexLocked)
{
f_mutexLock( gv_FlmSysData.RCacheMgr.hMutex);
bMutexLocked = TRUE;
bUnlockMutex = TRUE;
}
uiRefCnt = --m_ui32RefCnt;
#endif
if( !uiRefCnt)
{
flmAssert( !isCached());
m_uiFlags |= RCA_OK_TO_DELETE;
delete this;
}
else if( bMutexLocked && uiRefCnt == 1 && isCached())
{
// If the record is still cached, and the reference count
// is 1, it is safe to compact the record's buffer
if( m_bHolesInData || getFreeMemory())
{
#ifdef FLM_CHECK_RECORD
if (RC_BAD( checkRecord()))
{
flmAssert( 0);
}
#endif
compactMemory();
#ifdef FLM_CHECK_RECORD
if (RC_BAD( checkRecord()))
{
flmAssert( 0);
}
#endif
flmAssert( !getFreeMemory());
}
}
if( bUnlockMutex)
{
f_mutexUnlock( gv_FlmSysData.RCacheMgr.hMutex);
}
return( uiRefCnt);
}
/*****************************************************************************
Desc: Return the nth occurance of the field with a matching field id.
*****************************************************************************/
void * FlmRecord::find(
void * pvField,
FLMUINT uiFieldID,
FLMUINT uiOccur,
FLMUINT uiFindOption)
{
FLMUINT uiStartLevel;
FlmField * pField = getFieldPointer( pvField);
if( !uiOccur)
{
uiOccur = 1;
}
if( !pField)
{
goto Exit;
}
uiStartLevel = getFieldLevel( pField);
do
{
if( (uiFieldID == pField->ui16FieldID) && (--uiOccur < 1))
{
return( getFieldVoid( pField));
}
} while( (pField = nextField( pField)) != NULL &&
((getFieldLevel( pField) > uiStartLevel) ||
(uiFindOption == SEARCH_FOREST &&
getFieldLevel( pField) == uiStartLevel)));
Exit:
return( NULL);
}
/*****************************************************************************
Desc: Given a null terminated field path, return the matching occurance.
*****************************************************************************/
void * FlmRecord::find(
void * pvField,
FLMUINT * puiPathArray,
FLMUINT uiOccur,
FLMUINT uiFindOption)
{
FlmField * pSaveField;
FLMUINT * path;
FLMUINT uiLevel;
FlmField * pField = getFieldPointer( pvField);
// Handle empty record
if( !pvField)
{
return( NULL);
}
if( !uiOccur)
{
uiOccur = 1;
}
uiLevel = getFieldLevel( pField);
for(;;)
{
path = puiPathArray + ( getFieldLevel( pField) - uiLevel);
pSaveField = pField;
if( *path == pField->ui16FieldID)
{
if( *(path + 1) == 0 && (--uiOccur < 1))
{
return( getFieldVoid( pField));
}
if( (pField = firstChildField( pField)) != NULL)
{
continue;
}
pField = pSaveField;
}
do
{
pField = nextField( pField);
}
while( pField != NULL && getFieldLevel( pField) > getFieldLevel( pSaveField));
if( !pField || getFieldLevel( pField) < uiLevel ||
(uiFindOption != SEARCH_FOREST && getFieldLevel( pField) == uiLevel))
{
break;
}
}
return( NULL);
}
/*****************************************************************************
Desc: Import a record from a file
*****************************************************************************/
RCODE FlmRecord::importRecord(
F_FileHdl * pFileHdl,
F_NameTable * pNameTable)
{
char ucBuffer[ 1024];
char * pucData = &ucBuffer[ 0];
flmAssert( !isCached());
flmAssert( !isReadOnly());
return( importTree( pFileHdl, &pucData,
sizeof( ucBuffer), pNameTable, this));
}
/*****************************************************************************
Desc: Import a record from a buffer
*****************************************************************************/
RCODE FlmRecord::importRecord(
const char ** ppBuffer,
FLMUINT uiBufSize,
F_NameTable * pNameTable)
{
flmAssert( !isCached());
flmAssert( !isReadOnly());
return( importTree( NULL, (char **)ppBuffer, uiBufSize, pNameTable, this));
}
/*****************************************************************************
Desc : This function parses and builds one complete GEDCOM tree from a GEDCOM
character buffer or file. The beginning level number is used only to
delimit the tree (possiblly in forest); the generated tree's level
always start at zero.
*****************************************************************************/
FSTATIC RCODE importTree(
F_FileHdl * pFileHdl,
char ** ppBuf,
FLMUINT uiBufSize,
F_NameTable * pNameTable,
FlmRecord * pRec)
{
GED_STREAM gedStream;
FLMUINT level;
FLMUINT levelBase = 0;
FLMUINT levelPrior = 0;
FLMBYTE nextChar;
FLMBOOL bFirstFieldProcessed = FALSE;
RCODE rc;
FLMUINT startPos;
gedStream.pFileHdl = pFileHdl;
gedStream.pThis = *ppBuf;
gedStream.pBuf = *ppBuf;
gedStream.uiBufSize = uiBufSize;
pRec->clear();
if( pFileHdl)
{
// Find 1st starting file position
if( RC_OK( pFileHdl->Seek( 0L, F_IO_SEEK_CUR, &gedStream.uiFilePos)))
{
gedStream.pLast = gedStream.pBuf;
gedReadChar( &gedStream, gedStream.uiFilePos);
}
else
return( RC_SET( FERR_FILE_ER));
}
else
{
gedStream.errorIO = 0;
gedStream.uiFilePos = 0;
gedStream.pLast = gedStream.pBuf + (uiBufSize - 1);
gedStream.thisC = f_toascii( *gedStream.pBuf);
}
for(;;)
{
gedSkipBlankLines( &gedStream);
startPos = gedStream.uiFilePos;
if( f_isdigit( gedStream.thisC))
{
level = 0;
do
{
level = gedStream.thisC - ASCII_ZERO + (level * 10);
nextChar = (FLMBYTE)(gedNextChar( &gedStream));
} while( f_isdigit( nextChar));
if( ! f_iswhitespace( gedStream.thisC))
{
rc = RC_SET( FERR_BAD_FIELD_LEVEL);
break;
}
if( level > GED_MAXLVLNUM)
{
rc = RC_SET( FERR_GED_MAXLVLNUM);
break;
}
if( bFirstFieldProcessed)
{
if( levelBase >= level)
{
goto successful;
}
else if( (levelPrior < level) && ((levelPrior + 1) != level))
{
rc = RC_SET( FERR_GED_SKIP_LEVEL);
break;
}
}
else
{
levelBase = level;
}
levelPrior = level;
// Process import tag and value
rc = importField( (level - levelBase), &gedStream,
pNameTable, pRec);
if( RC_OK( rc))
{
bFirstFieldProcessed = TRUE;
continue;
}
}
else if( gedStream.thisC == '\0' || gedStream.thisC == ASCII_CTRLZ)
{
if( gedStream.errorIO)
{
rc = RC_SET( FERR_FILE_ER);
}
else if( bFirstFieldProcessed)
{
successful:
if( pFileHdl == NULL)
{
*ppBuf = gedStream.pThis +
(FLMINT32)(startPos - gedStream.uiFilePos);
}
gedStream.uiFilePos = startPos;
rc = FERR_OK;
}
else
{
rc = RC_SET( FERR_END);
}
}
else
{
rc = RC_SET( FERR_BAD_FIELD_LEVEL);
}
break;
}
if( rc != FERR_OK)
{
pRec->clear();
if( pFileHdl == NULL)
{
*ppBuf = gedStream.pThis;
}
}
if( pFileHdl)
{
pFileHdl->Seek( gedStream.uiFilePos,
F_IO_SEEK_SET, &gedStream.uiFilePos);
}
return( rc);
}
/*****************************************************************************
Desc: Parse the tag, value, and length from a GEDCOM buffer, and insert it into
a FlmRecord. Continuation lines and embedded comments are also handled.
*****************************************************************************/
FSTATIC RCODE importField(
FLMUINT uiLevel,
GED_STREAM * pGedStream,
F_NameTable * pNameTable,
FlmRecord * pRec)
{
FLMUINT startPos;
RCODE rc = FERR_OK;
FLMUINT drn = 0;
FLMUINT uiTagNum;
char tagBuf[ GED_MAXTAGLEN + 1];
void * pvField;
gedSkipWhiteSpaces( pGedStream);
// Process optional xref-id
startPos = pGedStream->uiFilePos;
if( pGedStream->thisC == ASCII_AT)
{
int badDRN;
for( badDRN = 0, gedNextChar( pGedStream);
pGedStream->thisC != ASCII_AT;
gedNextChar( pGedStream))
{
FLMUINT priorDrn = drn;
if( ! badDRN)
{
if( f_isdigit( pGedStream->thisC))
{
drn = (drn * 10) + pGedStream->thisC - ASCII_ZERO;
badDRN = priorDrn != (drn / 10);
}
else
{
badDRN = 1;
}
}
}
if( badDRN)
{
drn = 0;
}
gedNextChar( pGedStream);
if( f_iswhitespace( pGedStream->thisC))
{
gedSkipWhiteSpaces( pGedStream);
}
else
{
rc = RC_SET( FERR_GED_BAD_RECID);
goto Exit;
}
}
if( drn)
{
// Record can only have one ID (DRN)
flmAssert( pRec->getID() == 0);
pRec->setID( drn);
}
// Determine the Tag Number and insert a new field
startPos = pGedStream->uiFilePos;
if( !gedCopyTag( pGedStream, tagBuf))
{
return( RC_SET( FERR_INVALID_TAG));
}
if( !pNameTable->getFromTagTypeAndName( NULL, tagBuf,
FLM_FIELD_TAG, &uiTagNum))
{
// See if tag is the reserved tag with the number following
if( tagBuf[0] == f_toascii( 'T') &&
tagBuf[1] == f_toascii( 'A') &&
tagBuf[2] == f_toascii( 'G') &&
tagBuf[3] == f_toascii( '_'))
{
uiTagNum = f_atoi( &tagBuf[ 4]);
}
else
{
return( RC_SET( FERR_NOT_FOUND));
}
}
if( RC_BAD( rc = pRec->insertLast( uiLevel, uiTagNum,
FLM_TEXT_TYPE, &pvField)))
{
goto Exit;
}
gedSkipWhiteSpaces( pGedStream);
// Alternate xref_ptr used instead of "value"
startPos = pGedStream->uiFilePos;
if( pGedStream->thisC == ASCII_AT)
{
for( drn = 0; gedNextChar( pGedStream) != ASCII_AT;)
{
FLMUINT priorDrn = drn;
if( f_isdigit( pGedStream->thisC))
{
drn = (drn * 10) + pGedStream->thisC - ASCII_ZERO;
if( priorDrn == (drn / 10))
{
continue;
}
}
rc = RC_SET( FERR_GED_BAD_VALUE);
goto Exit;
}
gedNextChar( pGedStream);
if( RC_BAD( rc = pRec->setUINT( pvField, drn)))
{
goto Exit;
}
if( gedCopyValue( pGedStream, NULL))
{
rc = RC_SET( FERR_GED_BAD_VALUE);
goto Exit;
}
}
else
{
FLMINT valLength;
FLMUINT tempPos = pGedStream->uiFilePos;
if( (valLength = gedCopyValue( pGedStream, NULL)) > 0)
{
FLMBYTE * vp;
if (RC_BAD( rc = pRec->allocStorageSpace(
pvField, FLM_TEXT_TYPE, valLength,
0, 0, 0, &vp, NULL)))
{
goto Exit;
}
gedReadChar( pGedStream, tempPos);
gedCopyValue( pGedStream, (char *)vp);
}
}
startPos = pGedStream->uiFilePos;
Exit:
gedReadChar( pGedStream, startPos);
return( rc);
}
/*****************************************************************************
Desc: Parse the tag and, if `dest' is not NULL, copy and terminating w/null
*****************************************************************************/
FLMUINT gedCopyTag(
GED_STREAM * pGedStream,
char * dest)
{
if( f_isalpha( pGedStream->thisC) || pGedStream->thisC == ASCII_UNDERSCORE )
{
int tagLen, maxTag;
for( tagLen = 0, maxTag = GED_MAXTAGLEN;
f_isalnum( pGedStream->thisC) || pGedStream->thisC == ASCII_UNDERSCORE;
gedNextChar( pGedStream))
{
tagLen++;
if( dest && maxTag)
{
*dest++ = (FLMBYTE)(pGedStream->thisC);
maxTag--;
}
}
if( dest)
{
*dest = '\0';
}
switch( pGedStream->thisC)
{
case '\0':
if( pGedStream->errorIO)
{
break;
}
case ASCII_SPACE:
case ASCII_NEWLINE:
case ASCII_CR:
case ASCII_TAB:
case ASCII_CTRLZ:
{
return( (FLMUINT) tagLen);
}
}
}
return( 0);
}
/*****************************************************************************
Desc: Parse the value and, if `dest' is not NULL, copy and terminating w/null
*****************************************************************************/
FLMINT gedCopyValue(
GED_STREAM * pGedStream,
char * dest)
{
FLMUINT OEMcount = 0;
FLMUINT valLength = 0;
FLMUINT wsCount;
FLMUINT lineLength = 0;
FLMUINT firstPos = 0;
FLMBYTE c;
for(;;)
{
gedSkipWhiteSpaces( pGedStream);
if( pGedStream->thisC == ASCII_DQUOTE)
{
gedNextChar( pGedStream);
firstPos = pGedStream->uiFilePos;
}
else
{
firstPos = 0;
}
for( lineLength = 0;;)
{
switch( pGedStream->thisC)
{
case ASCII_DQUOTE:
case ASCII_SPACE:
case ASCII_TAB:
for( wsCount = 0;;)
{
switch( gedNextChar( pGedStream))
{
case '\0':
if( pGedStream->errorIO)
{
return( 0);
}
case ASCII_NEWLINE:
case ASCII_CR:
case ASCII_CTRLZ:
goto eol;
case ASCII_SPACE:
case ASCII_TAB:
wsCount++;
continue;
default:
gedReadChar( pGedStream, pGedStream->uiFilePos - 1);
lineLength += wsCount;
goto valid;
}
}
case '\0':
if( pGedStream->errorIO)
{
return( 0);
}
case ASCII_NEWLINE:
case ASCII_CR:
case ASCII_CTRLZ:
eol: if( lineLength)
{
valLength += lineLength;
if( dest)
{
gedReadChar( pGedStream, firstPos);
while( lineLength--)
{
c = (FLMBYTE)pGedStream->thisC;
if ((c >= ASCII_SPACE) && (c < 127))
{
*dest++ = c;
}
else if (c == ASCII_TAB)
{
*dest++ = WHITE_SPACE_CODE | NATIVE_TAB;
}
else if (c == ASCII_NEWLINE)
{
*dest++ = WHITE_SPACE_CODE | NATIVE_LINEFEED;
}
else if (c == ASCII_CR)
{
*dest++ = WHITE_SPACE_CODE | HARD_RETURN;
}
else
{
*dest++ = (c >= 127)
? OEM_CODE
: UNK_EQ_1_CODE | NATIVE_TYPE;
*dest++ = c;
}
gedNextChar( pGedStream);
}
if( pGedStream->thisC == ASCII_DQUOTE)
{
gedNextChar( pGedStream);
}
}
}
break;
default:
valid:
c = (FLMBYTE)pGedStream->thisC;
if (((c < ASCII_SPACE) &&
(c != ASCII_TAB) &&
(c != ASCII_CR) &&
(c != ASCII_NEWLINE)) ||
(c >= 127))
{
OEMcount += 1;
}
if( !firstPos)
{
firstPos = pGedStream->uiFilePos;
}
lineLength++;
gedNextChar( pGedStream);
continue;
}
break;
}
gedSkipBlankLines( pGedStream);
if( pGedStream->thisC != ASCII_PLUS)
{
break;
}
gedNextChar( pGedStream);
}
return( valLength + OEMcount);
}
/*****************************************************************************
Desc: strip blank lines from buffer by repositioning pointer
*****************************************************************************/
void gedSkipBlankLines(
GED_STREAM * pGedStream)
{
for(;;)
{
gedSkipWhiteSpaces( pGedStream);
switch( pGedStream->thisC)
{
case ASCII_POUND:
for(;;)
{
switch( gedNextChar( pGedStream))
{
case ASCII_NEWLINE:
case ASCII_CR:
goto outerFor;
case '\0':
case ASCII_CTRLZ:
return;
}
}
case ASCII_NEWLINE:
case ASCII_CR:
outerFor:
gedNextChar( pGedStream);
continue;
}
return;
}
}
/*****************************************************************************
Desc: get current character then increment pointer.
buffer may be refilled if file available
*****************************************************************************/
FLMINT gedNextChar(
GED_STREAM * pGedStream)
{
pGedStream->errorIO = 0;
if( pGedStream->pThis < pGedStream->pLast)
{
pGedStream->pThis++;
goto returnC;
}
if( pGedStream->pFileHdl)
{
FLMUINT bytesRead;
RCODE rc;
rc = pGedStream->pFileHdl->Read( F_IO_CURRENT_POS,
pGedStream->uiBufSize, pGedStream->pBuf, &bytesRead);
if( rc == FERR_OK || (rc == FERR_IO_END_OF_FILE && bytesRead))
{
pGedStream->pThis = pGedStream->pBuf;
pGedStream->pLast = pGedStream->pBuf + (bytesRead - 1);
returnC:
pGedStream->uiFilePos++;
return( pGedStream->thisC = f_toascii( *pGedStream->pThis));
}
pGedStream->errorIO = rc != FERR_IO_END_OF_FILE;
}
return( pGedStream->thisC = '\0');
}
/*****************************************************************************
Desc: get an ASCII character at absolute file position and reset pointers
*****************************************************************************/
FLMINT gedReadChar(
GED_STREAM * pGedStream,
FLMUINT uiFilePos)
{
RCODE rc = FERR_OK;
pGedStream->errorIO = 0;
if( pGedStream->pFileHdl)
{
FLMUINT bytesRead;
char * pszTemp;
pszTemp = pGedStream->pThis +
(FLMINT32)(uiFilePos - pGedStream->uiFilePos);
if( pGedStream->pBuf == pGedStream->pLast ||
pszTemp > pGedStream->pLast || pszTemp < pGedStream->pBuf)
{
if( RC_OK(rc = pGedStream->pFileHdl->Seek( uiFilePos,
F_IO_SEEK_SET, &pGedStream->uiFilePos)) &&
(RC_OK( rc = pGedStream->pFileHdl->Read( F_IO_CURRENT_POS,
pGedStream->uiBufSize, pGedStream->pBuf, &bytesRead)) ||
(rc == FERR_IO_END_OF_FILE && bytesRead)))
{
pGedStream->pThis = pGedStream->pBuf;
pGedStream->pLast = pGedStream->pBuf + (bytesRead - 1);
return( pGedStream->thisC = f_toascii( *pGedStream->pThis));
}
else
{
pGedStream->errorIO = 1;
return( pGedStream->thisC = '\0');
}
}
else
{
pGedStream->uiFilePos = uiFilePos;
pGedStream->pThis = pszTemp;
return( pGedStream->thisC = f_toascii( *pszTemp));
}
}
if( (pGedStream->pBuf + uiFilePos) > pGedStream->pLast)
{
return( pGedStream->thisC = '\0');
}
pGedStream->pThis = pGedStream->pBuf + uiFilePos;
pGedStream->uiFilePos = uiFilePos;
return( pGedStream->thisC = f_toascii( *pGedStream->pThis));
}
/*****************************************************************************
Desc: Import a record from GEDCOM
*****************************************************************************/
RCODE FlmRecord::importRecord(
NODE * pNode)
{
RCODE rc = FERR_OK;
FLMBYTE * pucData;
FLMBYTE * pucEncData;
HFDB hDb;
FLMUINT uiContainerID = 0;
FLMUINT uiRecordID = 0;
void * pvField;
FlmField * pField;
FLMUINT uiDataType;
FLMUINT uiFlags;
flmAssert( pNode);
flmAssert( !isCached());
flmAssert( !isReadOnly());
clear();
// Copy any source info that is within the root node.
if( RC_OK( GedGetRecSource( pNode, &hDb, &uiContainerID, &uiRecordID)))
{
setContainerID( uiContainerID);
setID( uiRecordID);
}
while( pNode)
{
uiDataType = GedValType( pNode);
if( RC_BAD( rc = insertLast( GedNodeLevel( pNode),
GedTagNum( pNode), uiDataType, &pvField)))
{
goto Exit;
}
pField = getFieldPointer( pvField);
if( GedValLen( pNode) || GedEncLen( pNode))
{
uiFlags = pNode->ui32EncFlags;
if( RC_BAD( rc = getNewDataPtr( pField, uiDataType,
pNode->ui32Length, pNode->ui32EncLength, pNode->ui32EncId, uiFlags,
(!uiFlags || uiFlags & FLD_HAVE_DECRYPTED_DATA)
? &pucData
: NULL,
(uiFlags & FLD_HAVE_ENCRYPTED_DATA)
? &pucEncData
: NULL)))
{
goto Exit;
}
if (!uiFlags || uiFlags & FLD_HAVE_DECRYPTED_DATA)
{
f_memcpy( pucData, GedValPtr( pNode), GedValLen( pNode));
}
if ( uiFlags & FLD_HAVE_ENCRYPTED_DATA)
{
f_memcpy( pucEncData, GedEncPtr( pNode), GedEncLen( pNode));
}
}
// Copy any of the value flags that this node may have
if( GedIsRightTruncated( pNode))
{
setRightTruncated( pField, TRUE);
}
if( GedIsLeftTruncated( pNode))
{
setLeftTruncated( pField, TRUE);
}
pNode = GedNodeNext( pNode);
if( pNode && GedNodeLevel( pNode) == 0)
{
break;
}
}
Exit:
return( rc);
}
/*****************************************************************************
Desc: Export the record to GEDCOM
*****************************************************************************/
RCODE FlmRecord::exportRecord(
HFDB hDb,
POOL * pPool,
NODE ** ppRoot)
{
RCODE rc = FERR_OK;
FLMBYTE * pucData;
FLMBYTE * pucEncData = NULL;
FLMBYTE * exPtr;
FlmField * pField = getFieldPointer(root());
NODE * pPrevNode = NULL;
NODE * pNode = NULL;
FLMUINT uiLevelBase = getFieldLevel( pField);
FLMUINT uiEncLength = 0;
flmAssert( ppRoot != NULL);
flmAssert( pPool != NULL);
*ppRoot = NULL;
while( pField)
{
if( *ppRoot)
{
if( (pNode = GedNodeMake( pPool,
pField->ui16FieldID, &rc)) == NULL)
{
goto Exit;
}
}
else
{
// Create root source node
if( RC_BAD( rc = gedCreateSourceNode( pPool, pField->ui16FieldID,
hDb, getContainerID(), getID(), &pNode)))
{
goto Exit;
}
}
// Link in new node
if( pPrevNode)
{
pPrevNode->next = pNode;
}
else
{
*ppRoot = pNode;
}
pNode->prior = pPrevNode;
GedNodeLevelSet( pNode, (getFieldLevel( pField) - uiLevelBase));
pPrevNode = pNode;
if (isEncryptedField(pField))
{
uiEncLength = getEncryptedDataLength( pField);
pucData = (FLMBYTE *)GedAllocSpace( pPool,
pNode,
getFieldDataType( pField),
getFieldDataLength( pField),
getEncryptionID( pField),
uiEncLength);
pucEncData = (FLMBYTE *)GedEncPtr( pNode);
if( !pucData && uiEncLength)
{
rc = RC_SET( FERR_MEM);
goto Exit;
}
}
else
{
pucData = (FLMBYTE *)GedAllocSpace( pPool, pNode,
getFieldDataType( pField), getFieldDataLength( pField));
if( !pucData && getFieldDataLength( pField))
{
rc = RC_SET( FERR_MEM);
goto Exit;
}
}
// Directly copy over the NODE value pucData.
if( getFieldDataLength( pField))
{
if( (exPtr = getDataPtr( pField)) == NULL)
{
rc = RC_SET( FERR_MEM);
goto Exit;
}
f_memcpy( pucData, exPtr, getFieldDataLength( pField));
if (pNode->ui32EncId)
{
flmAssert( pNode->ui32EncFlags & FLD_HAVE_DECRYPTED_DATA);
}
}
if (pNode->ui32EncId)
{
if ((exPtr = getEncryptionDataPtr( pField)) == NULL)
{
rc = RC_SET( FERR_MEM);
goto Exit;
}
flmAssert( uiEncLength);
flmAssert( pNode->ui32EncFlags & FLD_HAVE_ENCRYPTED_DATA);
f_memcpy( pucEncData, exPtr, uiEncLength);
}
// Copy any of the value flags that this node may have
if( isRightTruncated( pField))
{
GedSetRightTruncated( pNode);
}
if( isLeftTruncated( pField))
{
GedSetLeftTruncated( pNode);
}
pField = nextField( pField);
}
Exit:
return( rc);
}
/*****************************************************************************
Desc:
*****************************************************************************/
void * FlmRecord::getFieldVoid(
FlmField * pField)
{
FLMUINT uiSlot;
if( !pField)
{
return( NULL);
}
if( !m_uiFldTblOffset ||
pField > &(getFieldTable()[ m_uiFldTblOffset - 1]))
{
flmAssert( 0);
return( NULL);
}
uiSlot = (pField - getFieldTable()) + 1;
return( (void *)uiSlot);
}
/*****************************************************************************
Desc:
*****************************************************************************/
FlmField * FlmRecord::getFieldPointer(
void * pvField)
{
FLMUINT uiSlot = (FLMUINT)pvField;
FlmField * pField = NULL;
if( !uiSlot)
{
goto Exit;
}
if( uiSlot > m_uiFldTblOffset)
{
flmAssert( 0);
goto Exit;
}
pField = &(getFieldTable()[ uiSlot - 1]);
flmAssert( pField->ui16FieldID);
Exit:
return( pField);
}
/*****************************************************************************
Desc:
*****************************************************************************/
FLMBYTE * FlmRecord::getDataPtr(
FlmField * pField)
{
if (!isEncryptedField(pField))
{
if( !pField->ui8DataLen)
{
return( NULL);
}
else if( pField->ui8DataLen <= 4)
{
return( (FLMBYTE *)&(pField->ui32DataOffset));
}
else if( pField->ui8DataLen < 0xFF)
{
return( getDataBufPtr() + pField->ui32DataOffset);
}
else
{
FLMUINT uiOffset = pField->ui32DataOffset + sizeof( FLMUINT16) + 1;
if( getFieldDataType( pField) == FLM_BINARY_TYPE)
{
if( (uiOffset & FLM_ALLOC_ALIGN) != 0)
{
uiOffset += (FLM_ALLOC_ALIGN + 1) - (uiOffset & FLM_ALLOC_ALIGN);
}
}
return( getDataBufPtr() + uiOffset);
}
}
else
{
FLMUINT uiOffset = pField->ui32DataOffset + FLM_ENC_FLD_OVERHEAD;
FLMUINT uiPicketFenceSize = 0;
#ifdef FLM_PICKET_FENCE
uiPicketFenceSize = FLD_PICKET_FENCE_SIZE / 2;
#endif
if( getFieldDataType( pField) == FLM_BINARY_TYPE)
{
if( (uiOffset & FLM_ALLOC_ALIGN) != 0)
{
uiOffset += (FLM_ALLOC_ALIGN + 1) - (uiOffset & FLM_ALLOC_ALIGN);
}
}
return ( getDataBufPtr() + uiOffset + uiPicketFenceSize);
}
}
/*****************************************************************************
Desc: Get the pointer to the encrypted data.
*****************************************************************************/
FLMBYTE * FlmRecord::getEncryptionDataPtr(
FlmField * pField)
{
FLMBYTE * pucTmp = NULL;
FLMUINT uiOffset;
FLMUINT uiPicketFenceSize = 0;
// We assume that this field is encrypted. If it isn't,
// then we will return NULL.
if (!isEncryptedField(pField))
{
flmAssert( 0);
goto Exit;
}
#ifdef FLM_PICKET_FENCE
uiPicketFenceSize = FLD_PICKET_FENCE_SIZE;
#endif
uiOffset = pField->ui32DataOffset + FLM_ENC_FLD_OVERHEAD;
if( getFieldDataType( pField) == FLM_BINARY_TYPE)
{
if( (uiOffset & FLM_ALLOC_ALIGN) != 0)
{
uiOffset += (FLM_ALLOC_ALIGN + 1) - (uiOffset & FLM_ALLOC_ALIGN);
}
}
pucTmp = getDataBufPtr() + uiOffset + getFieldDataLength( pField) +
uiPicketFenceSize;
Exit:
return pucTmp;
}
/*****************************************************************************
Desc:
*****************************************************************************/
FlmField * FlmRecord::getFirstField( void)
{
if( !m_uiFldTblOffset)
{
return( NULL);
}
flmAssert( (getFieldTable()[ 0]).ui16FieldID);
return( &(getFieldTable()[ 0]));
}
/*****************************************************************************
Desc:
*****************************************************************************/
FlmField * FlmRecord::getLastField( void)
{
FLMUINT uiLoop;
FlmField * pField = NULL;
if( !m_uiFldTblOffset)
{
goto Exit;
}
for( uiLoop = m_uiFldTblOffset; uiLoop; uiLoop--)
{
pField = &(getFieldTable()[ uiLoop - 1]);
if( pField->ui16FieldID)
{
break;
}
}
Exit:
return( pField);
}
/*****************************************************************************
Desc:
*****************************************************************************/
FlmField * FlmRecord::prevField(
FlmField * pField)
{
if( !pField)
{
return( NULL);
}
return( getFieldPointer( (void *)((FLMUINT)(pField->uiPrev))));
}
/*****************************************************************************
Desc:
*****************************************************************************/
FlmField * FlmRecord::nextField(
FlmField * pField)
{
if( !pField)
{
return( NULL);
}
return( getFieldPointer( (void *)((FLMUINT)(pField->uiNext))));
}
/*****************************************************************************
Desc:
*****************************************************************************/
FLMUINT FlmRecord::getTotalMemory( void)
{
return( gv_FlmSysData.RCacheMgr.pRecBufAlloc->getTrueSize(
m_uiBufferSize, m_pucBuffer) + sizeof( FlmRecord));
}
/*****************************************************************************
Desc:
*****************************************************************************/
RCODE FlmRecord::setFieldLevel(
FlmField * pField,
FLMUINT uiLevel)
{
flmAssert( !isCached());
flmAssert( !isReadOnly());
if( uiLevel > 7)
{
flmAssert( 0);
return( RC_SET( FERR_BAD_FIELD_LEVEL));
}
pField->ui8TypeAndLevel &= 0x1F;
pField->ui8TypeAndLevel |= (((FLMUINT8)uiLevel) << 5);
return( FERR_OK);
}
/*****************************************************************************
Desc:
*****************************************************************************/
FLMUINT FlmRecord::getFieldDataLength(
FlmField * pField)
{
FLMBYTE * pucLength;
FLMUINT uiDataLen = 0;
flmAssert( pField);
if( pField->ui8DataLen != 0xFF)
{
uiDataLen = pField->ui8DataLen;
goto Exit;
}
pucLength = getDataBufPtr() + pField->ui32DataOffset + 1;
if (isEncryptedField( pField))
{
pucLength += 2;
}
uiDataLen = FB2UW( pucLength);
Exit:
return uiDataLen;
}
/*****************************************************************************
Desc:
*****************************************************************************/
void FlmRecord::setFieldDataType(
FlmField * pField,
FLMUINT uiDataType)
{
flmAssert( !isCached());
flmAssert( !isReadOnly());
pField->ui8TypeAndLevel &= 0xF8;
if( uiDataType <= 3)
{
pField->ui8TypeAndLevel |= (FLMUINT8)uiDataType;
}
else
{
flmAssert( uiDataType == FLM_BLOB_TYPE);
pField->ui8TypeAndLevel |= (FLMUINT8)FLD_BLOB_TYPE;
}
}
/*****************************************************************************
Desc: Function to determine if the field is encrypted.
*****************************************************************************/
FLMBOOL FlmRecord::isEncryptedField(
FlmField * pField
)
{
FLMBOOL bResult = FALSE;
FLMUINT uiFlags;
FLMBYTE * pucBuffer;
if (!pField)
{
goto Exit;
}
if (pField->ui8DataLen == 0xFF)
{
pucBuffer = getDataBufPtr() + pField->ui32DataOffset;
uiFlags = pucBuffer[ FLD_ENC_FLAGS];
if (uiFlags && uiFlags <= 0x03)
{
bResult = TRUE;
}
}
Exit:
return bResult;
}
/*****************************************************************************
Desc: Function to get the length of the encrypted data.
*****************************************************************************/
FLMUINT FlmRecord::getEncryptedDataLength(
FlmField * pField
)
{
FLMBYTE * pucBuffer = NULL;
FLMUINT uiEncDataLength = 0;
// Make sure this is an encrypted field.
if (!isEncryptedField(pField))
{
flmAssert( 0);
goto Exit;
}
pucBuffer = getDataBufPtr() + pField->ui32DataOffset;
uiEncDataLength = FB2UW( &pucBuffer[ FLD_ENC_ENCRYPTED_DATA_LEN]);
Exit:
return uiEncDataLength;
}
/*****************************************************************************
Desc: Function to get the DRN of the encryption definition record in the
dictionary.
*****************************************************************************/
FLMUINT FlmRecord::getEncryptionID(
FlmField * pField
)
{
FLMBYTE * pucBuffer = NULL;
FLMUINT uiEncId = 0;
if (!isEncryptedField( pField))
{
flmAssert( 0);
goto Exit;
}
pucBuffer = getDataBufPtr() + pField->ui32DataOffset;
uiEncId = FB2UW( &pucBuffer[ FLD_ENC_ENCID]);
Exit:
return uiEncId;
}
/*****************************************************************************
Desc:
*****************************************************************************/
FLMUINT FlmRecord::getEncFlags(
FlmField * pField
)
{
FLMBYTE * pucBuffer;
if (!isEncryptedField( pField))
{
flmAssert( 0);
return( 0);
}
pucBuffer = getDataBufPtr() + pField->ui32DataOffset;
return( (FLMUINT)pucBuffer[ FLD_ENC_FLAGS]);
}
/*****************************************************************************
Desc:
*****************************************************************************/
void FlmRecord::setEncFlags(
FlmField * pField,
FLMUINT uiFlags
)
{
FLMBYTE * pucBuffer;
if (!isEncryptedField( pField))
{
flmAssert( 0);
return;
}
pucBuffer = getDataBufPtr() + pField->ui32DataOffset;
pucBuffer[ FLD_ENC_FLAGS] = (FLMBYTE)uiFlags;
}
/*****************************************************************************
Desc:
*****************************************************************************/
RCODE FlmRecord::getINT(
void * pvField,
FLMINT * piNumber)
{
RCODE rc = FERR_OK;
FLMBOOL bEncrypted;
FlmField * pField = getFieldPointer( pvField);
if (!pField)
{
rc = RC_SET( FERR_NOT_FOUND);
goto Exit;
}
bEncrypted = isEncryptedField( pField);
if (!bEncrypted ||
(getEncFlags( pField) & FLD_HAVE_DECRYPTED_DATA))
{
rc = FlmStorage2INT( getFieldDataType( pField),
getFieldDataLength( pField),
(const FLMBYTE *)getDataPtr( pField),
piNumber);
}
else if (bEncrypted &&
!(getEncFlags( pField) & FLD_HAVE_DECRYPTED_DATA))
{
rc = RC_SET( FERR_ENCRYPTION_UNAVAILABLE);
goto Exit;
}
else
{
rc = RC_SET( FERR_NOT_FOUND);
goto Exit;
}
Exit:
return( rc);
}
/*****************************************************************************
Desc:
*****************************************************************************/
RCODE FlmRecord::getUINT(
void * pvField,
FLMUINT * puiNumber)
{
RCODE rc = FERR_OK;
FLMBOOL bEncrypted;
FlmField * pField = getFieldPointer( pvField);
if (!pField)
{
rc = RC_SET( FERR_NOT_FOUND);
goto Exit;
}
bEncrypted = isEncryptedField( pField);
if (!bEncrypted ||
(getEncFlags( pField) & FLD_HAVE_DECRYPTED_DATA))
{
rc = FlmStorage2UINT( getFieldDataType( pField),
getFieldDataLength( pField),
(const FLMBYTE *)getDataPtr( pField),
puiNumber);
}
else if (bEncrypted &&
!(getEncFlags( pField) & FLD_HAVE_DECRYPTED_DATA))
{
rc = RC_SET( FERR_ENCRYPTION_UNAVAILABLE);
goto Exit;
}
else
{
rc = RC_SET( FERR_NOT_FOUND);
goto Exit;
}
Exit:
return( rc);
}
/*****************************************************************************
Desc:
*****************************************************************************/
RCODE FlmRecord::getUINT32(
void * pvField,
FLMUINT32 * pui32Number)
{
RCODE rc = FERR_OK;
FLMBOOL bEncrypted;
FlmField * pField = getFieldPointer( pvField);
if (!pField)
{
rc = RC_SET( FERR_NOT_FOUND);
goto Exit;
}
bEncrypted = isEncryptedField( pField);
if (!bEncrypted ||
(getEncFlags( pField) & FLD_HAVE_DECRYPTED_DATA))
{
rc = FlmStorage2UINT32( getFieldDataType( pField),
getFieldDataLength( pField),
(const FLMBYTE *)getDataPtr( pField),
pui32Number);
}
else if (bEncrypted &&
!(getEncFlags( pField) & FLD_HAVE_DECRYPTED_DATA))
{
rc = RC_SET( FERR_ENCRYPTION_UNAVAILABLE);
goto Exit;
}
else
{
rc = RC_SET( FERR_NOT_FOUND);
goto Exit;
}
Exit:
return( rc);
}
/*****************************************************************************
Desc:
*****************************************************************************/
RCODE FlmRecord::getUnicode(
void * pvField,
FLMUNICODE * pUnicode,
FLMUINT * puiBufLen)
{
RCODE rc = FERR_OK;
FLMBOOL bEncrypted;
FlmField * pField = getFieldPointer( pvField);
if (!pField)
{
rc = RC_SET( FERR_NOT_FOUND);
goto Exit;
}
bEncrypted = isEncryptedField( pField);
if (!bEncrypted ||
(getEncFlags( pField) & FLD_HAVE_DECRYPTED_DATA))
{
rc = FlmStorage2Unicode( getFieldDataType( pField),
getFieldDataLength( pField),
(const FLMBYTE *)getDataPtr( pField),
puiBufLen,
pUnicode);
}
else if (bEncrypted &&
!(getEncFlags( pField) & FLD_HAVE_DECRYPTED_DATA))
{
rc = RC_SET( FERR_ENCRYPTION_UNAVAILABLE);
goto Exit;
}
else
{
rc = RC_SET( FERR_NOT_FOUND);
goto Exit;
}
Exit:
return( rc);
}
/*****************************************************************************
Desc:
*****************************************************************************/
RCODE FlmRecord::getNative(
void * pvField,
char * pszString,
FLMUINT * puiBufLen)
{
RCODE rc = FERR_OK;
FLMBOOL bEncrypted;
FlmField * pField = getFieldPointer( pvField);
if (!pField)
{
rc = RC_SET( FERR_NOT_FOUND);
goto Exit;
}
bEncrypted = isEncryptedField( pField);
if (!bEncrypted ||
(getEncFlags( pField) & FLD_HAVE_DECRYPTED_DATA))
{
rc = FlmStorage2Native( getFieldDataType( pField),
getFieldDataLength( pField),
(const FLMBYTE *)getDataPtr( pField),
puiBufLen,
pszString);
}
else if (bEncrypted &&
!(getEncFlags( pField) & FLD_HAVE_DECRYPTED_DATA))
{
rc = RC_SET( FERR_ENCRYPTION_UNAVAILABLE);
goto Exit;
}
else
{
rc = RC_SET( FERR_NOT_FOUND);
goto Exit;
}
Exit:
return( rc);
}
/*****************************************************************************
Desc: Set the header fields in an encrypted field.
*****************************************************************************/
void FlmRecord::setEncHeader(
FLMBYTE * pBuffer,
FLMUINT uiFlags,
FLMUINT uiEncId,
FLMUINT uiNewLength,
FLMUINT uiEncNewLength)
{
*pBuffer = (FLMBYTE)uiFlags;
pBuffer++;
UW2FBA( uiEncId, pBuffer);
pBuffer += 2;
UW2FBA( uiNewLength, pBuffer);
pBuffer += 2;
UW2FBA( uiEncNewLength, pBuffer);
}
/*****************************************************************************
Desc:
*****************************************************************************/
void * FlmRecord::locateFieldByPosition(
FLMUINT uiPosition)
{
FlmField * pField = getFieldPointer( root());
FLMUINT uiLoop;
flmAssert( pField);
for (uiLoop = 1; pField && uiLoop < uiPosition; uiLoop++)
{
pField = nextField( pField);
}
return (getFieldVoid( pField));
}
#undef new
#undef delete
/****************************************************************************
Desc:
****************************************************************************/
void * FlmRecord::operator new(
FLMSIZET uiSize)
#ifndef FLM_NLM
throw()
#endif
{
F_UNREFERENCED_PARM( uiSize);
flmAssert( gv_FlmSysData.RCacheMgr.pRecAlloc->getCellSize() >= uiSize);
return( gv_FlmSysData.RCacheMgr.pRecAlloc->allocCell());
}
/****************************************************************************
Desc:
****************************************************************************/
void * FlmRecord::operator new[]( FLMSIZET)
#ifndef FLM_NLM
throw()
#endif
{
flmAssert( 0);
return( NULL);
}
/****************************************************************************
Desc:
****************************************************************************/
#ifdef FLM_DEBUG
void * FlmRecord::operator new(
FLMSIZET uiSize,
const char *,
int)
#ifndef FLM_NLM
throw()
#endif
{
flmAssert( gv_FlmSysData.RCacheMgr.pRecAlloc->getCellSize() >= uiSize);
return( gv_FlmSysData.RCacheMgr.pRecAlloc->allocCell());
}
#endif
/****************************************************************************
Desc:
****************************************************************************/
#ifdef FLM_DEBUG
void * FlmRecord::operator new[](
FLMSIZET, // uiSize,
const char *, // pszFile,
int) // iLine)
#ifndef FLM_NLM
throw()
#endif
{
flmAssert( 0);
return( NULL);
}
#endif
/****************************************************************************
Desc:
****************************************************************************/
void FlmRecord::operator delete(
void * ptr)
{
if( !ptr)
{
return;
}
flmAssert( ((FlmRecord *)ptr)->m_ui32RefCnt == 0);
gv_FlmSysData.RCacheMgr.pRecAlloc->freeCell( ptr);
}
/****************************************************************************
Desc:
****************************************************************************/
void FlmRecord::operator delete[](
void * // ptr)
)
{
flmAssert( 0);
}
/****************************************************************************
Desc:
****************************************************************************/
#if defined( FLM_DEBUG) && !defined( __WATCOMC__)
void FlmRecord::operator delete(
void * ptr,
const char *, // file
int // line
)
{
if( !ptr)
{
return;
}
flmAssert( ((FlmRecord *)ptr)->m_ui32RefCnt == 0);
gv_FlmSysData.RCacheMgr.pRecAlloc->freeCell( ptr);
}
#endif
/****************************************************************************
Desc:
****************************************************************************/
#if defined( FLM_DEBUG) && !defined( __WATCOMC__)
void FlmRecord::operator delete[](
void *, // ptr,
const char *, // file
int // line
)
{
flmAssert( 0);
}
#endif
/*****************************************************************************
Desc: Verify the structural integrity of the FlmRecord
*****************************************************************************/
RCODE FlmRecord::checkRecord()
{
RCODE rc = FERR_OK;
FlmField * pFld;
// Check each field to make sure it is acceptable.
pFld = getFieldPointer( root());
while( pFld)
{
if (RC_BAD( rc = checkField( pFld)))
{
flmAssert( 0);
goto Exit;
}
pFld = nextField( pFld);
}
Exit:
return( rc);
}
/******************************************************************************
Desc: Verify the structure and content of the FlmField
******************************************************************************/
RCODE FlmRecord::checkField(
FlmField * pFld)
{
RCODE rc = FERR_OK;
FLMBYTE * pucFldBuffer;
FLMUINT16 ui16DataLen;
FLMUINT16 ui16EncDataLen;
FLMUINT uiAlignment = 0;
FLMBYTE * pucDataFence = NULL;
FLMBYTE * pucEncFence = NULL;
FLMUNICODE * pUnicode = NULL;
FLMUINT uiBufLen;
FLMUINT uiEncID;
FLMUINT uiSlot = (FLMUINT)getFieldVoid( pFld);
// Determine if the field may be encrypted. Fields >= 255 and
// encrypted fields have their actual length stored in the buffer.
if ( pFld->ui8DataLen < 0xFF)
{
goto Exit;
}
// Get the buffer pointer and test it to make sure the structure is okay.
pucFldBuffer = getDataBufPtr() + pFld->ui32DataOffset;
// Test for encryption. If the field is not encrypted, we won't do any check
// right now.
if (*pucFldBuffer == 0)
{
goto Exit;
}
// If we have any other value now besides 1, 2 or 3, we have some corruption!
flmAssert( *pucFldBuffer <= 3);
// Make sure we have an encryption ID and that it appears to be within range
// at least.
uiEncID = FB2UW( &pucFldBuffer[ FLD_ENC_ENCID]);
if (!uiEncID)
{
flmAssert( 0);
rc = RC_SET( FERR_FAILURE);
goto Exit;
}
if (uiEncID > FLM_RESERVED_TAG_NUMS)
{
flmAssert( 0);
rc = RC_SET( FERR_BAD_ENCDEF_ID);
goto Exit;
}
ui16DataLen = FB2UW( &pucFldBuffer[ FLD_ENC_DATA_LEN]);
if (!ui16DataLen)
{
flmAssert( 0);
rc = RC_SET( FERR_FAILURE);
goto Exit;
}
ui16EncDataLen = FB2UW( &pucFldBuffer[ FLD_ENC_ENCRYPTED_DATA_LEN]);
if (!ui16EncDataLen)
{
flmAssert( 0);
rc = RC_SET( FERR_FAILURE);
goto Exit;
}
// Adjust for alignment issues of binary fields.
if( getFieldDataType( pFld) == FLM_BINARY_TYPE)
{
// Since the value is binary, need to account for any
// alignment bytes
if( ((pFld->ui32DataOffset + FLM_ENC_FLD_OVERHEAD) & FLM_ALLOC_ALIGN) != 0)
{
uiAlignment = (FLM_ALLOC_ALIGN + 1) -
((pFld->ui32DataOffset + FLM_ENC_FLD_OVERHEAD) & FLM_ALLOC_ALIGN);
}
}
#ifdef FLM_PICKET_FENCE
// Verify the picket fences.
pucDataFence = pucFldBuffer + FLM_ENC_FLD_OVERHEAD + uiAlignment;
pucEncFence = pucDataFence + ui16DataLen + 4;
if ( f_memcmp( pucDataFence, FLD_RAW_FENCE, FLD_PICKET_FENCE_SIZE / 2))
{
flmAssert( 0);
rc = RC_SET( FERR_FAILURE);
goto Exit;
}
if ( f_memcmp( pucEncFence, FLD_ENC_FENCE, FLD_PICKET_FENCE_SIZE / 2))
{
flmAssert( 0);
rc = RC_SET( FERR_FAILURE);
goto Exit;
}
#else
F_UNREFERENCED_PARM( pucDataFence);
F_UNREFERENCED_PARM( pucEncFence);
#endif
// Verify the raw data if it is a text type.
if( getFieldDataType( pFld) == FLM_TEXT_TYPE)
{
// Let's try to get this as unicode.
// Allocate a temporary buffer.
uiBufLen = (ui16DataLen * 2) + 2;
if (RC_BAD( rc = f_alloc( uiBufLen, &pUnicode)))
{
goto Exit;
}
if (RC_BAD( rc = getUnicode( (void *)uiSlot,
pUnicode,
&uiBufLen)))
{
if (rc == FERR_ENCRYPTION_UNAVAILABLE)
{
rc = FERR_OK;
}
else
{
goto Exit;
}
}
f_free( &pUnicode);
pUnicode = NULL;
}
else if ( getFieldDataType( pFld) == FLM_NUMBER_TYPE)
{
FLMUINT uiTemp;
if ( RC_BAD( rc = getUINT( (void *)uiSlot, &uiTemp)))
{
if ( rc == FERR_ENCRYPTION_UNAVAILABLE)
{
rc = FERR_OK;
}
else
{
flmAssert(0);
goto Exit;
}
}
}
Exit:
if (pUnicode)
{
f_free( &pUnicode);
}
return( rc);
}