Files
mars-flaim/flaim/src/fcs_dis.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

1423 lines
24 KiB
C++

//-------------------------------------------------------------------------
// Desc: Data input stream class.
// Tabs: 3
//
// Copyright (c) 1998-2001,2003-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: fcs_dis.cpp 12329 2006-01-20 17:49:30 -0700 (Fri, 20 Jan 2006) ahodgkinson $
//-------------------------------------------------------------------------
#include "flaimsys.h"
/****************************************************************************
Desc:
****************************************************************************/
FCS_DIS::FCS_DIS( void)
{
m_pIStream = NULL;
m_uiBOffset = m_uiBDataSize = 0;
m_bSetupCalled = FALSE;
}
/****************************************************************************
Desc:
****************************************************************************/
FCS_DIS::~FCS_DIS( void)
{
if( m_bSetupCalled)
{
(void)close();
}
}
/****************************************************************************
Desc:
****************************************************************************/
RCODE FCS_DIS::setup(
FCS_ISTM * pIStream)
{
m_pIStream = pIStream;
m_bSetupCalled = TRUE;
return( FERR_OK);
}
/****************************************************************************
Desc:
****************************************************************************/
RCODE FCS_DIS::readByte(
FLMBYTE * pValue)
{
return( read( pValue, 1, NULL));
}
/****************************************************************************
Desc:
****************************************************************************/
RCODE FCS_DIS::readShort(
FLMINT16 * pValue)
{
FLMUINT16 ui16Value;
RCODE rc;
// Read the data.
if( RC_OK( rc = read( (FLMBYTE *)pValue, 2, NULL)))
{
ui16Value = byteToInt( (FLMBYTE *)pValue);
*pValue = *((FLMINT16 *)&ui16Value);
}
return( rc);
}
/****************************************************************************
Desc:
****************************************************************************/
RCODE FCS_DIS::readUShort(
FLMUINT16 * pValue)
{
RCODE rc;
// Read the data.
if( RC_OK( rc = read( (FLMBYTE *)pValue, 2, NULL)))
{
*pValue = byteToInt( (FLMBYTE *)pValue);
}
return( rc);
}
/****************************************************************************
Desc:
****************************************************************************/
RCODE FCS_DIS::readInt(
FLMINT32 * pValue)
{
FLMUINT32 ui32Value;
RCODE rc;
// Read the data.
if( RC_OK( rc = read( (FLMBYTE *)pValue, 4, NULL)))
{
ui32Value = byteToLong( (FLMBYTE *)pValue);
*pValue = *((FLMINT32 *)&ui32Value);
}
return( rc);
}
/****************************************************************************
Desc:
****************************************************************************/
RCODE FCS_DIS::readUInt(
FLMUINT32 * pValue)
{
RCODE rc;
// Read the data.
if( RC_OK( rc = read( (FLMBYTE *)pValue, 4, NULL)))
{
*pValue = byteToLong( (FLMBYTE *)pValue);
}
return( rc);
}
/****************************************************************************
Desc:
****************************************************************************/
RCODE FCS_DIS::readInt64(
FLMINT64 * pValue)
{
FLMUINT64 ui64Value;
RCODE rc;
// Read the data.
if( RC_OK( rc = read( (FLMBYTE *)pValue, 8, NULL)))
{
ui64Value = byteToLong64( (FLMBYTE *)pValue);
*pValue = *((FLMINT64 *)&ui64Value);
}
return( rc);
}
/****************************************************************************
Desc:
****************************************************************************/
RCODE FCS_DIS::readUInt64(
FLMUINT64 * pValue)
{
RCODE rc;
// Read the data.
if( RC_OK( rc = read( (FLMBYTE *)pValue, 8, NULL)))
{
*pValue = byteToLong64( (FLMBYTE *)pValue);
}
return( rc);
}
/****************************************************************************
Desc:
****************************************************************************/
RCODE FCS_DIS::skip(
FLMUINT uiBytesToSkip)
{
return( read( NULL, uiBytesToSkip, NULL));
}
/****************************************************************************
Desc: Flushes any pending data and closes the DIS
****************************************************************************/
RCODE FCS_DIS::close( void)
{
RCODE rc = FERR_OK;
/*
Verify that Setup has been called.
*/
flmAssert( m_bSetupCalled == TRUE);
/*
Terminate and flush.
*/
if( RC_BAD( rc = endMessage()))
{
goto Exit;
}
/*
Reset the member variables.
*/
m_pIStream = NULL;
Exit:
return( rc);
}
/****************************************************************************
Desc: Returns the state of the stream (open == TRUE, closed == FALSE)
****************************************************************************/
FLMBOOL FCS_DIS::isOpen( void)
{
/*
Verify that Setup has been called.
*/
flmAssert( m_bSetupCalled == TRUE);
if( m_pIStream && m_pIStream->isOpen())
{
return( TRUE);
}
return( FALSE);
}
/****************************************************************************
Desc: Flushes and terminates the current parent stream message
****************************************************************************/
RCODE FCS_DIS::endMessage( void)
{
RCODE rc = FERR_OK;
/*
Verify that Setup has been called.
*/
flmAssert( m_bSetupCalled == TRUE);
if( !m_pIStream)
{
rc = RC_SET( FERR_FAILURE);
goto Exit;
}
/*
Flush any pending data.
*/
if( RC_BAD( rc = flush()))
{
goto Exit;
}
/*
Terminate the message.
*/
if( RC_BAD( rc = m_pIStream->endMessage()))
{
goto Exit;
}
Exit:
return( rc);
}
/****************************************************************************
Desc: Flushes any pending data
****************************************************************************/
RCODE FCS_DIS::flush( void)
{
RCODE rc = FERR_OK;
/*
Verify that Setup has been called.
*/
flmAssert( m_bSetupCalled == TRUE);
if( !m_pIStream)
{
rc = RC_SET( FERR_FAILURE);
goto Exit;
}
/*
Flush the passed-in input stream.
*/
if( RC_BAD( rc = m_pIStream->flush()))
{
goto Exit;
}
Exit:
return( rc);
}
/****************************************************************************
Desc: Reads the specified number of bytes.
****************************************************************************/
RCODE FCS_DIS::read(
FLMBYTE * pucData,
FLMUINT uiLength,
FLMUINT * puiBytesRead)
{
FLMUINT uiCopySize;
FLMUINT uiReadLen;
FLMBYTE * pucPos = NULL;
RCODE rc = FERR_OK;
/*
Verify that Setup has been called.
*/
flmAssert( m_bSetupCalled == TRUE);
if( !m_pIStream)
{
rc = RC_SET( FERR_FAILURE);
goto Exit;
}
if( puiBytesRead)
{
*puiBytesRead = uiLength;
}
pucPos = pucData;
while( uiLength)
{
if( m_uiBOffset == m_uiBDataSize)
{
m_uiBOffset = m_uiBDataSize = 0;
if( RC_BAD( rc = m_pIStream->read( m_pucBuffer,
FCS_DIS_BUFFER_SIZE, &uiReadLen)))
{
if( uiReadLen)
{
rc = FERR_OK;
}
else
{
goto Exit;
}
}
m_uiBDataSize = uiReadLen;
}
uiCopySize = m_uiBDataSize - m_uiBOffset;
if( uiLength < uiCopySize)
{
uiCopySize = uiLength;
}
if( pucPos)
{
#if defined( FLM_NLM) || defined( FLM_WIN)
if( uiCopySize == 1)
{
*pucPos = m_pucBuffer[ m_uiBOffset];
}
else if( uiLength == 2)
{
*(FLMUINT16 *)pucPos = *((FLMUINT16 *)&m_pucBuffer[ m_uiBOffset]);
}
else if( uiLength == 4)
{
*(FLMUINT32 *)pucPos = *((FLMUINT32 *)&m_pucBuffer[ m_uiBOffset]);
}
else
{
f_memcpy( pucPos, &(m_pucBuffer[ m_uiBOffset]), uiCopySize);
}
#else
f_memcpy( pucPos, &(m_pucBuffer[ m_uiBOffset]), uiCopySize);
#endif
pucPos += uiCopySize;
}
m_uiBOffset += uiCopySize;
uiLength -= uiCopySize;
}
Exit:
if( RC_OK( rc) && uiLength)
{
/*
Unable to satisfy the read request.
*/
rc = RC_SET( FERR_EOF_HIT);
}
if( puiBytesRead)
{
(*puiBytesRead) -= uiLength;
}
return( rc);
}
/****************************************************************************
Desc: Reads a binary token from the stream. The token is tagged with a
length.
****************************************************************************/
RCODE FCS_DIS::readBinary(
POOL * pPool,
FLMBYTE ** ppValue,
FLMUINT * puiDataSize)
{
FLMUINT16 ui16DataSize;
RCODE rc = FERR_OK;
if( RC_BAD( rc = readUShort( &ui16DataSize)))
{
goto Exit;
}
if( pPool)
{
/*
If the data size is non-zero, allocate a buffer and
read the entire binary value.
*/
if( ui16DataSize)
{
if( (*ppValue = (FLMBYTE *)GedPoolAlloc( pPool, ui16DataSize)) == NULL)
{
rc = RC_SET( FERR_MEM);
goto Exit;
}
if( RC_BAD( rc = read( *ppValue, ui16DataSize, NULL)))
{
goto Exit;
}
}
else
{
*ppValue = NULL;
}
}
else
{
/*
The application is not interested in the value. Just skip the
to the end of the value.
*/
if( RC_BAD( rc = skip( ui16DataSize)))
{
goto Exit;
}
}
Exit:
if( puiDataSize)
{
*puiDataSize = ui16DataSize;
}
return( rc);
}
/****************************************************************************
Desc: Reads a large binary token from the stream. The token is tagged with a
length.
****************************************************************************/
RCODE FCS_DIS::readLargeBinary(
POOL * pPool,
FLMBYTE ** ppValue,
FLMUINT * puiDataSize)
{
FLMUINT32 ui32DataSize;
RCODE rc = FERR_OK;
if( RC_BAD( rc = readUInt( &ui32DataSize)))
{
goto Exit;
}
if( pPool)
{
/*
If the data size is non-zero, allocate a buffer and
read the entire binary value.
*/
if( ui32DataSize)
{
if( (*ppValue = (FLMBYTE *)GedPoolAlloc( pPool, ui32DataSize)) == NULL)
{
rc = RC_SET( FERR_MEM);
goto Exit;
}
if( RC_BAD( rc = read( *ppValue, ui32DataSize, NULL)))
{
goto Exit;
}
}
else
{
*ppValue = NULL;
}
}
else
{
/*
The application is not interested in the value. Just skip the
to the end of the value.
*/
if( RC_BAD( rc = skip( ui32DataSize)))
{
goto Exit;
}
}
Exit:
if( puiDataSize)
{
*puiDataSize = (FLMUINT)ui32DataSize;
}
return( rc);
}
/****************************************************************************
Desc: Reads a UTF-8 string from the stream.
****************************************************************************/
RCODE FCS_DIS::readUTF(
POOL * pPool,
FLMUNICODE ** ppValue)
{
FLMBYTE ucByte1;
FLMBYTE ucByte2;
FLMBYTE ucByte3;
FLMBYTE ucLoByte;
FLMBYTE ucHiByte;
FLMUINT16 ui16UTFLen;
FLMUINT uiOffset = 0;
RCODE rc = FERR_OK;
/*
Read the data.
*/
if( RC_BAD( rc = readUShort( &ui16UTFLen)))
{
goto Exit;
}
/*
Check the size of the UTF string. FLAIM does not support
strings that are larger than 32K characters.
*/
if( ui16UTFLen >= 32767)
{
rc = RC_SET( FERR_MEM);
goto Exit;
}
/*
Allocate space for the string.
*/
if( pPool)
{
*ppValue = (FLMUNICODE *)GedPoolAlloc( pPool,
(FLMUINT)((FLMUINT)sizeof( FLMUNICODE) * (FLMUINT)(ui16UTFLen + 1)));
}
else if( ppValue)
{
*ppValue = NULL;
}
while( ui16UTFLen)
{
/*
Read and decode the bytes.
*/
if( RC_BAD( rc = read( &ucByte1, 1, NULL)))
{
goto Exit;
}
if( (ucByte1 & 0xC0) != 0xC0)
{
ucHiByte = 0;
ucLoByte = ucByte1;
}
else
{
if( RC_BAD( rc = read( &ucByte2, 1, NULL)))
{
goto Exit;
}
if( (ucByte1 & 0xE0) == 0xE0)
{
if( RC_BAD( rc = read( &ucByte3, 1, NULL)))
{
goto Exit;
}
ucHiByte =
(FLMBYTE)(((ucByte1 & 0x0F) << 4) | ((ucByte2 & 0x3C) >> 2));
ucLoByte = (FLMBYTE)(((ucByte2 & 0x03) << 6) | (ucByte3 & 0x3F));
}
else
{
ucHiByte = (FLMBYTE)(((ucByte1 & 0x1C) >> 2));
ucLoByte = (FLMBYTE)(((ucByte1 & 0x03) << 6) | (ucByte2 & 0x3F));
}
}
if( pPool)
{
(*ppValue)[ uiOffset] =
(FLMUNICODE)(((((FLMUNICODE)(ucHiByte)) << 8) |
((FLMUNICODE)(ucLoByte))));
}
uiOffset++;
ui16UTFLen--;
}
if( pPool)
{
(*ppValue)[ uiOffset] = 0;
}
Exit:
return( rc);
}
/****************************************************************************
Desc: Reads an Hierarchical Tagged Data record from the stream.
****************************************************************************/
RCODE FCS_DIS::readHTD(
POOL * pPool,
FLMUINT uiContainer,
FLMUINT uiDrn,
NODE ** ppNode,
FlmRecord ** ppRecord)
{
FLMBYTE ucType;
FLMBYTE ucLevel = 0;
FLMBYTE ucPrevLevel = 0;
FLMBYTE ucDescriptor;
FLMBYTE ucFlags;
FLMUINT16 ui16Tag;
FLMBOOL bHasValue;
FLMBOOL bChild;
FLMBOOL bSibling;
FLMBOOL bLeftTruncated;
FLMBOOL bRightTruncated;
NODE * pRoot = NULL;
NODE * pNode = NULL;
NODE * pPrevNode = NULL;
void * pField = NULL;
void * pvMark = NULL;
RCODE rc = FERR_OK;
if( pPool)
{
pvMark = GedPoolMark( pPool);
}
for( ;;)
{
/*
Reset variables.
*/
bChild = FALSE;
bSibling = FALSE;
/*
Read the attribute's tag number.
*/
if( RC_BAD( rc = readUShort( &ui16Tag)))
{
goto Exit;
}
/*
A tag number of 0 indicates that the end of the HTD data
stream has been reached.
*/
if( !ui16Tag)
{
break;
}
/*
Read the attribute's descriptor.
*/
if( RC_BAD(rc = read( &ucDescriptor, 1, NULL)))
{
goto Exit;
}
/*
Set the flag indicating whether or not the
attribute has a value.
*/
bHasValue = (FLMBOOL)((ucDescriptor & HTD_HAS_VALUE_FLAG)
? (FLMBOOL)TRUE
: (FLMBOOL)FALSE);
/*
Set the value type.
*/
ucType = (FLMBYTE)((ucDescriptor & HTD_VALUE_TYPE_MASK));
/*
Get the attribute's level.
*/
switch( (ucDescriptor & HTD_LEVEL_MASK) >> HTD_LEVEL_POS)
{
case HTD_LEVEL_SIBLING:
{
bSibling = TRUE;
ucLevel = ucPrevLevel;
break;
}
case HTD_LEVEL_CHILD:
{
if( ucLevel < 0xFF)
{
bChild = TRUE;
ucLevel = (FLMBYTE)(ucPrevLevel + 1);
}
else
{
rc = RC_SET( FERR_BAD_FIELD_LEVEL);
goto Exit;
}
break;
}
case HTD_LEVEL_BACK:
{
if( ucLevel > 0)
{
ucLevel = (FLMBYTE)(ucPrevLevel - 1);
}
else
{
rc = RC_SET( FERR_BAD_FIELD_LEVEL);
goto Exit;
}
break;
}
case HTD_LEVEL_BACK_X:
{
FLMBYTE ucLevelsBack;
if( RC_BAD(rc = read( &ucLevelsBack, 1, NULL)))
{
goto Exit;
}
if( ucPrevLevel >= ucLevelsBack)
{
ucLevel = (FLMBYTE)(ucPrevLevel - ucLevelsBack);
}
else
{
rc = RC_SET( FERR_BAD_FIELD_LEVEL);
goto Exit;
}
break;
}
}
/*
Allocate the record object
*/
if( ppRecord && ucLevel == 0)
{
if( *ppRecord)
{
if( (*ppRecord)->isReadOnly() ||
(*ppRecord)->getRefCount() > 1)
{
(*ppRecord)->Release();
if( (*ppRecord = f_new FlmRecord) == NULL)
{
rc = RC_SET( FERR_MEM);
goto Exit;
}
}
else
{
// Reuse the existing FlmRecord object.
(*ppRecord)->clear();
}
}
else
{
if( (*ppRecord = f_new FlmRecord) == NULL)
{
rc = RC_SET( FERR_MEM);
goto Exit;
}
}
(*ppRecord)->setContainerID( uiContainer);
(*ppRecord)->setID( uiDrn);
}
/*
Allocate the attribute.
*/
if( pPool && ppNode)
{
pNode = GedNodeMake( pPool, ui16Tag, &rc);
if( RC_BAD( rc))
{
goto Exit;
}
}
bLeftTruncated = FALSE;
bRightTruncated = FALSE;
/*
Read the attribute's value.
*/
switch( ucType)
{
case HTD_TYPE_UNICODE:
{
FLMUNICODE * pUTF;
if( pNode)
{
GedValTypeSet( pNode, FLM_TEXT_TYPE);
}
if( ppRecord)
{
if( RC_BAD( rc = (*ppRecord)->insertLast( ucLevel,
ui16Tag, FLM_TEXT_TYPE, &pField)))
{
goto Exit;
}
}
if( !bHasValue)
{
break;
}
/*
Read UNICODE text in UTF-8 format.
*/
if( pPool)
{
if( RC_BAD( rc = readUTF( pPool, &pUTF)))
{
goto Exit;
}
if( pNode)
{
if( RC_BAD( rc = GedPutUNICODE( pPool, pNode, pUTF)))
{
goto Exit;
}
}
if( ppRecord)
{
if( RC_BAD( rc = (*ppRecord)->setUnicode( pField, pUTF)))
{
goto Exit;
}
}
}
else
{
if( RC_BAD( rc = readUTF( NULL, NULL)))
{
goto Exit;
}
}
break;
}
case HTD_TYPE_UINT:
{
FLMUINT32 ui32Value;
if( pNode)
{
GedValTypeSet( pNode, FLM_NUMBER_TYPE);
}
if( ppRecord)
{
if( RC_BAD( rc = (*ppRecord)->insertLast( ucLevel,
ui16Tag, FLM_NUMBER_TYPE, &pField)))
{
goto Exit;
}
}
if( !bHasValue)
{
break;
}
/*
Read an unsigned 32-bit integer.
*/
if( RC_BAD( rc = readUInt( &ui32Value)))
{
goto Exit;
}
if( pNode)
{
if( RC_BAD( rc = GedPutUINT( pPool, pNode, ui32Value)))
{
goto Exit;
}
}
if( ppRecord)
{
if( RC_BAD( rc = (*ppRecord)->setUINT( pField, ui32Value)))
{
goto Exit;
}
}
break;
}
case HTD_TYPE_INT:
{
FLMINT32 i32Value;
if( pNode)
{
GedValTypeSet( pNode, FLM_NUMBER_TYPE);
}
if( ppRecord)
{
if( RC_BAD( rc = (*ppRecord)->insertLast( ucLevel,
ui16Tag, FLM_NUMBER_TYPE, &pField)))
{
goto Exit;
}
}
if( !bHasValue)
{
break;
}
/*
Read a signed 32-bit integer.
*/
if( RC_BAD( rc = readInt( &i32Value)))
{
goto Exit;
}
if( pNode)
{
if( RC_BAD( rc = GedPutINT( pPool, pNode, i32Value)))
{
goto Exit;
}
}
if( ppRecord)
{
if( RC_BAD( rc = (*ppRecord)->setINT( pField, i32Value)))
{
goto Exit;
}
}
break;
}
case HTD_TYPE_CONTEXT:
{
FLMUINT32 ui32Value;
if( pNode)
{
GedValTypeSet( pNode, FLM_CONTEXT_TYPE);
}
if( ppRecord)
{
if( RC_BAD( rc = (*ppRecord)->insertLast( ucLevel,
ui16Tag, FLM_CONTEXT_TYPE, &pField)))
{
goto Exit;
}
}
if( !bHasValue)
{
break;
}
/*
Read an unsigned 32-bit integer.
*/
if( RC_BAD( rc = readUInt( &ui32Value)))
{
goto Exit;
}
if( pNode)
{
if( RC_BAD( rc = GedPutRecPtr( pPool, pNode, ui32Value)))
{
goto Exit;
}
}
if( ppRecord)
{
if( RC_BAD( rc = (*ppRecord)->setRecPointer( pField, ui32Value)))
{
goto Exit;
}
}
break;
}
case HTD_TYPE_BINARY:
{
FLMUINT16 ui16DataSize;
FLMBYTE * pucData = NULL;
if( pNode)
{
GedValTypeSet( pNode, FLM_BINARY_TYPE);
}
if( ppRecord)
{
if( RC_BAD( rc = (*ppRecord)->insertLast( ucLevel,
ui16Tag, FLM_BINARY_TYPE, &pField)))
{
goto Exit;
}
}
if( !bHasValue)
{
break;
}
/*
Read a binary data stream.
*/
if( RC_BAD( rc = readUShort( &ui16DataSize)))
{
goto Exit;
}
if( pPool)
{
if( pNode)
{
if( (pucData = (FLMBYTE *)GedAllocSpace( pPool, pNode,
FLM_BINARY_TYPE, ui16DataSize)) == NULL)
{
rc = RC_SET( FERR_MEM);
goto Exit;
}
}
else if( ppRecord)
{
if( RC_BAD(rc = (*ppRecord)->allocStorageSpace( pField,
FLM_BINARY_TYPE, ui16DataSize, 0, 0, 0, &pucData, NULL)))
{
goto Exit;
}
}
if( RC_BAD( rc = read( pucData, ui16DataSize, NULL)))
{
goto Exit;
}
if( pNode)
{
if( ppRecord)
{
if( RC_BAD( rc = (*ppRecord)->setBinary( pField, pucData, ui16DataSize)))
{
goto Exit;
}
}
}
}
else
{
if( RC_BAD( rc = skip( ui16DataSize)))
{
goto Exit;
}
}
break;
}
case HTD_TYPE_DATE:
{
rc = RC_SET( FERR_NOT_IMPLEMENTED);
goto Exit;
}
case HTD_TYPE_GEDCOM:
{
FLMBYTE ucGedType;
FLMUINT16 ui16DataSize;
FLMBYTE * pucData = NULL;
/*
Read the GEDCOM data type and flags
*/
if( RC_BAD( rc = read( &ucGedType, 1, NULL)))
{
goto Exit;
}
ucFlags = ucGedType & 0xF0;
ucGedType &= 0x0F;
if( ucFlags & 0x10)
{
bLeftTruncated = TRUE;
}
if( ucFlags & 0x20)
{
bRightTruncated = TRUE;
}
if( ucGedType != FLM_TEXT_TYPE &&
ucGedType != FLM_NUMBER_TYPE &&
ucGedType != FLM_BINARY_TYPE &&
ucGedType != FLM_BLOB_TYPE &&
ucGedType != FLM_CONTEXT_TYPE)
{
rc = RC_SET( FERR_NOT_IMPLEMENTED);
goto Exit;
}
if( pNode)
{
GedValTypeSet( pNode, ucGedType);
if( bLeftTruncated)
{
GedSetLeftTruncated( pNode);
}
if( bRightTruncated)
{
GedSetRightTruncated( pNode);
}
}
if( ppRecord)
{
if( RC_BAD( rc = (*ppRecord)->insertLast( ucLevel,
ui16Tag, ucGedType, &pField)))
{
goto Exit;
}
if( bLeftTruncated)
{
(*ppRecord)->setLeftTruncated( pField, TRUE);
}
if( bRightTruncated)
{
(*ppRecord)->setRightTruncated( pField, TRUE);
}
}
if( !bHasValue)
{
break;
}
/*
Read the data size.
*/
if( RC_BAD( rc = readUShort( &ui16DataSize)))
{
goto Exit;
}
/*
Read the data value.
*/
if( pPool)
{
if( pNode)
{
if( (pucData = (FLMBYTE *)GedAllocSpace( pPool, pNode,
ucGedType, ui16DataSize)) == NULL)
{
rc = RC_SET( FERR_MEM);
goto Exit;
}
}
else if( ppRecord)
{
if (RC_BAD( rc = (*ppRecord)->allocStorageSpace( pField,
ucGedType, ui16DataSize, 0, 0, 0, &pucData, NULL)))
{
goto Exit;
}
}
if( RC_BAD( rc = read( pucData, ui16DataSize, NULL)))
{
goto Exit;
}
if( pNode)
{
if( ppRecord)
{
if( RC_BAD( rc = (*ppRecord)->setBinary( pField, pucData, ui16DataSize)))
{
goto Exit;
}
}
}
}
else
{
if( RC_BAD( rc = skip( ui16DataSize)))
{
goto Exit;
}
}
break;
}
default:
{
rc = RC_SET( FERR_NOT_IMPLEMENTED);
goto Exit;
}
}
/*
Set the truncation flags
*/
if( ucType != HTD_TYPE_GEDCOM)
{
if( pNode)
{
if( bLeftTruncated)
{
GedSetLeftTruncated( pNode);
}
if( bRightTruncated)
{
GedSetRightTruncated( pNode);
}
}
else if( pField)
{
if( bLeftTruncated)
{
(*ppRecord)->setLeftTruncated( pField, TRUE);
}
if( bRightTruncated)
{
(*ppRecord)->setRightTruncated( pField, TRUE);
}
}
}
/*
Graft the attribute into the tree.
*/
if( pNode)
{
if( pRoot == NULL)
{
pRoot = pNode;
}
else
{
if( bSibling)
{
pPrevNode->next = pNode;
pNode->prior = pPrevNode;
GedNodeLevelSet( pNode, GedNodeLevel( pPrevNode));
}
else if( bChild)
{
pPrevNode->next = pNode;
pNode->prior = pPrevNode;
GedNodeLevelSet( pNode, GedNodeLevel( pPrevNode) + 1);
}
else
{
pPrevNode->next = pNode;
pNode->prior = pPrevNode;
GedNodeLevelSet( pNode, ucLevel);
}
}
}
ucPrevLevel = ucLevel;
pPrevNode = pNode;
/*
Reset the pool if a GEDCOM record is not
going to be returned.
*/
if( pPool && !ppNode)
{
GedPoolReset( pPool, pvMark);
}
}
Exit:
if( RC_OK( rc))
{
if( ppNode)
{
*ppNode = pRoot;
}
}
else
{
if( ppRecord && *ppRecord)
{
(*ppRecord)->Release();
}
}
if( pPool && !ppNode)
{
GedPoolReset( pPool, pvMark);
}
return( rc);
}