git-svn-id: https://svn.code.sf.net/p/flaim/code/trunk@7 0109f412-320b-0410-ab79-c3e0c5ffbbe6
899 lines
17 KiB
C++
899 lines
17 KiB
C++
//-------------------------------------------------------------------------
|
|
// Desc: Data output stream class.
|
|
// Tabs: 3
|
|
//
|
|
// Copyright (c) 1998-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_dos.cpp 12329 2006-01-20 17:49:30 -0700 (Fri, 20 Jan 2006) ahodgkinson $
|
|
//-------------------------------------------------------------------------
|
|
|
|
#include "flaimsys.h"
|
|
|
|
/****************************************************************************
|
|
Desc:
|
|
****************************************************************************/
|
|
FCS_DOS::FCS_DOS( void)
|
|
{
|
|
m_pOStream = NULL;
|
|
m_uiBOffset = 0;
|
|
GedPoolInit( &m_tmpPool, 512);
|
|
m_bSetupCalled = FALSE;
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
Desc:
|
|
****************************************************************************/
|
|
FCS_DOS::~FCS_DOS( void)
|
|
{
|
|
if( m_bSetupCalled)
|
|
{
|
|
(void)close();
|
|
}
|
|
GedPoolFree( &m_tmpPool);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Writes a specified number of bytes from a buffer to the output
|
|
stream.
|
|
****************************************************************************/
|
|
RCODE FCS_DOS::write(
|
|
FLMBYTE * pucData,
|
|
FLMUINT uiLength)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
|
|
/*
|
|
Verify that setup has been called.
|
|
*/
|
|
|
|
flmAssert( m_bSetupCalled == TRUE);
|
|
|
|
/*
|
|
Write the data.
|
|
*/
|
|
|
|
Retry_Write:
|
|
|
|
if( FCS_DOS_BUFFER_SIZE - m_uiBOffset >= uiLength)
|
|
{
|
|
#if defined( FLM_NLM) || defined( FLM_WIN)
|
|
if( uiLength == 1)
|
|
{
|
|
m_pucBuffer[ m_uiBOffset] = *pucData;
|
|
m_uiBOffset++;
|
|
}
|
|
else if( uiLength == 2)
|
|
{
|
|
*(FLMUINT16 *)&(m_pucBuffer[ m_uiBOffset]) = *((FLMUINT16 *)pucData);
|
|
m_uiBOffset += 2;
|
|
}
|
|
else if( uiLength == 4)
|
|
{
|
|
*(FLMUINT32 *)&(m_pucBuffer[ m_uiBOffset]) = *((FLMUINT32 *)pucData);
|
|
m_uiBOffset += 4;
|
|
}
|
|
else
|
|
{
|
|
f_memcpy( &(m_pucBuffer[ m_uiBOffset]), pucData, uiLength);
|
|
m_uiBOffset += uiLength;
|
|
}
|
|
#else
|
|
f_memcpy( &(m_pucBuffer[ m_uiBOffset]), pucData, uiLength);
|
|
m_uiBOffset += uiLength;
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
if( m_uiBOffset > 0)
|
|
{
|
|
if( RC_BAD( rc = flush()))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
if( uiLength <= FCS_DOS_BUFFER_SIZE)
|
|
{
|
|
goto Retry_Write;
|
|
}
|
|
|
|
if( RC_BAD( rc = m_pOStream->write( pucData, uiLength)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
Exit:
|
|
|
|
return( rc);
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
Desc: Writes a UNICODE string to the stream in the UTF-8 format.
|
|
****************************************************************************/
|
|
RCODE FCS_DOS::writeUTF(
|
|
FLMUNICODE * puzValue)
|
|
{
|
|
FLMUINT uiUTFLen;
|
|
FLMUNICODE * puzTmp;
|
|
RCODE rc = FERR_OK;
|
|
|
|
/*
|
|
Verify that setup has been called.
|
|
*/
|
|
|
|
flmAssert( m_bSetupCalled == TRUE);
|
|
|
|
/*
|
|
Verify pValue is valid.
|
|
*/
|
|
|
|
flmAssert( puzValue != NULL);
|
|
|
|
/*
|
|
Determine the size of the string.
|
|
*/
|
|
|
|
uiUTFLen = 0;
|
|
puzTmp = puzValue;
|
|
while( *puzTmp)
|
|
{
|
|
uiUTFLen++;
|
|
puzTmp++;
|
|
}
|
|
|
|
if( RC_BAD( rc = writeUShort( (FLMUINT16)uiUTFLen)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
puzTmp = puzValue;
|
|
while( *puzTmp)
|
|
{
|
|
if( *puzTmp <= 0x007F)
|
|
{
|
|
if( RC_BAD( rc = writeByte( (FLMBYTE)(*puzTmp))))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
else if( *puzTmp >= 0x0080 && *puzTmp <= 0x07FF)
|
|
{
|
|
if( RC_BAD( rc = writeUShort((FLMUINT16)
|
|
((((FLMUINT16)(0xC0 | (FLMBYTE)((*puzTmp & 0x07C0) >> 6))) << 8) |
|
|
(FLMUINT16)(0x80 | (FLMBYTE)(*puzTmp & 0x003F))))))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if( RC_BAD( rc = writeUShort((FLMUINT16)
|
|
((((FLMUINT16)(0xE0 | (FLMBYTE)((*puzTmp & 0xF000) >> 12))) << 8) |
|
|
(FLMUINT16)(0x80 | (FLMBYTE)((*puzTmp & 0x0FC0) >> 6))))))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if( RC_BAD( rc = writeByte( (0x80 | (FLMBYTE)(*puzTmp & 0x003F)))))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
puzTmp++;
|
|
}
|
|
|
|
Exit:
|
|
|
|
return( rc);
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
Desc: Writes a binary token (including length) to the stream.
|
|
****************************************************************************/
|
|
RCODE FCS_DOS::writeBinary(
|
|
FLMBYTE * pucValue,
|
|
FLMUINT uiSize)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
|
|
flmAssert( uiSize <= 0x0000FFFF);
|
|
|
|
if( RC_BAD( rc = writeUShort( (FLMUINT16)uiSize)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if( uiSize)
|
|
{
|
|
if( RC_BAD( rc = write( pucValue, uiSize)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
Exit:
|
|
|
|
return( rc);
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
Desc: Writes a large binary token (including length) to the stream.
|
|
****************************************************************************/
|
|
RCODE FCS_DOS::writeLargeBinary(
|
|
FLMBYTE * pucValue,
|
|
FLMUINT uiSize)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
|
|
if( RC_BAD( rc = writeUInt32( (FLMUINT32)uiSize)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if( uiSize)
|
|
{
|
|
if( RC_BAD( rc = write( pucValue, uiSize)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
Exit:
|
|
|
|
return( rc);
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
Desc: Writes a Hierarchical Tagged Data record to the stream.
|
|
****************************************************************************/
|
|
RCODE FCS_DOS::writeHTD(
|
|
NODE * pHTD,
|
|
FlmRecord * pRecord,
|
|
FLMBOOL bSendForest,
|
|
FLMBOOL bSendAsGedcom)
|
|
{
|
|
FLMUINT uiPrevLevel = 0;
|
|
FLMUINT uiLevelsBack = 0;
|
|
FLMUINT uiDescriptor = 0;
|
|
FLMUINT uiCurLevel = 0;
|
|
FLMUINT uiCurValType = 0;
|
|
FLMUINT uiCurDataLen = 0;
|
|
FLMBOOL bLeftTruncated;
|
|
FLMBOOL bRightTruncated;
|
|
FLMBYTE * pucCurData = NULL;
|
|
FLMBYTE pucTmpBuf[ 32];
|
|
void * pvMark = GedPoolMark( &m_tmpPool);
|
|
NODE * pCurNode = NULL;
|
|
void * pCurField = NULL;
|
|
RCODE rc = FERR_OK;
|
|
|
|
/*
|
|
Verify that setup has been called.
|
|
*/
|
|
|
|
flmAssert( m_bSetupCalled == TRUE);
|
|
|
|
/*
|
|
Set the current node or field
|
|
*/
|
|
|
|
if( pHTD)
|
|
{
|
|
pCurNode = pHTD;
|
|
}
|
|
else
|
|
{
|
|
pCurField = pRecord->root();
|
|
}
|
|
|
|
while( pCurNode || pCurField)
|
|
{
|
|
/*
|
|
See if we are done sending the tree/forest.
|
|
*/
|
|
|
|
if( pCurNode)
|
|
{
|
|
if( !bSendForest && (pCurNode != pHTD) &&
|
|
(GedNodeLevel( pCurNode) == GedNodeLevel( pHTD)))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*
|
|
Output the attribute's tag number.
|
|
*/
|
|
|
|
if( pCurNode)
|
|
{
|
|
intToByte( (FLMUINT16)GedTagNum( pCurNode), pucTmpBuf);
|
|
}
|
|
else if( pCurField)
|
|
{
|
|
intToByte( (FLMUINT16)pRecord->getFieldID( pCurField), pucTmpBuf);
|
|
}
|
|
|
|
if( RC_BAD( rc = write( pucTmpBuf, 2)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
/*
|
|
Setup the attribute's descriptor.
|
|
*/
|
|
|
|
uiDescriptor = 0;
|
|
uiLevelsBack = 0;
|
|
|
|
if( pCurNode)
|
|
{
|
|
uiCurLevel = GedNodeLevel( pCurNode);
|
|
}
|
|
else
|
|
{
|
|
uiCurLevel = pRecord->getLevel( pCurField);
|
|
}
|
|
|
|
if( uiCurLevel == uiPrevLevel)
|
|
{
|
|
(void)(uiDescriptor |= (HTD_LEVEL_SIBLING << HTD_LEVEL_POS));
|
|
}
|
|
else if( uiCurLevel == uiPrevLevel + 1)
|
|
{
|
|
uiDescriptor |= (HTD_LEVEL_CHILD << HTD_LEVEL_POS);
|
|
}
|
|
else if( uiCurLevel == uiPrevLevel - 1)
|
|
{
|
|
uiDescriptor |= (HTD_LEVEL_BACK << HTD_LEVEL_POS);
|
|
}
|
|
else if( uiCurLevel < uiPrevLevel)
|
|
{
|
|
uiDescriptor |= (HTD_LEVEL_BACK_X << HTD_LEVEL_POS);
|
|
uiLevelsBack = uiPrevLevel - uiCurLevel;
|
|
}
|
|
else
|
|
{
|
|
flmAssert( 0);
|
|
rc = RC_SET( FERR_FAILURE);
|
|
goto Exit;
|
|
}
|
|
|
|
if( pCurNode)
|
|
{
|
|
uiCurDataLen = GedValLen( pCurNode);
|
|
uiCurValType = GedValType( pCurNode) & 0x0F;
|
|
bLeftTruncated = GedIsLeftTruncated( pCurNode);
|
|
bRightTruncated = GedIsRightTruncated( pCurNode);
|
|
pucCurData = (FLMBYTE *)GedValPtr( pCurNode);
|
|
}
|
|
else
|
|
{
|
|
uiCurDataLen = pRecord->getDataLength( pCurField);
|
|
uiCurValType = (FLMUINT)pRecord->getDataType( pCurField);
|
|
bLeftTruncated = pRecord->isLeftTruncated( pCurField);
|
|
bRightTruncated = pRecord->isRightTruncated( pCurField);
|
|
pucCurData = (FLMBYTE *)(pRecord->getDataPtr( pCurField));
|
|
}
|
|
|
|
if( uiCurDataLen)
|
|
{
|
|
uiDescriptor |= HTD_HAS_VALUE_FLAG;
|
|
}
|
|
|
|
if( bSendAsGedcom)
|
|
{
|
|
uiDescriptor |= HTD_TYPE_GEDCOM;
|
|
}
|
|
else
|
|
{
|
|
switch( uiCurValType)
|
|
{
|
|
case FLM_TEXT_TYPE:
|
|
{
|
|
uiDescriptor |= HTD_TYPE_UNICODE;
|
|
break;
|
|
}
|
|
|
|
case FLM_NUMBER_TYPE:
|
|
{
|
|
/*
|
|
To save conversion time, cheat to determine if
|
|
the number is negative.
|
|
*/
|
|
|
|
if( ((*pucCurData & 0xF0) == 0xB0))
|
|
{
|
|
uiDescriptor |= HTD_TYPE_INT;
|
|
}
|
|
else
|
|
{
|
|
uiDescriptor |= HTD_TYPE_UINT;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FLM_CONTEXT_TYPE:
|
|
{
|
|
uiDescriptor |= HTD_TYPE_CONTEXT;
|
|
break;
|
|
}
|
|
|
|
case FLM_BINARY_TYPE:
|
|
{
|
|
uiDescriptor |= HTD_TYPE_BINARY;
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
rc = RC_SET( FERR_NOT_IMPLEMENTED);
|
|
goto Exit;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
Output the attribute's descriptor.
|
|
*/
|
|
|
|
pucTmpBuf[ 0] = (FLMBYTE)uiDescriptor;
|
|
if( RC_BAD( rc = write( pucTmpBuf, 1)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
/*
|
|
Output the "levels back" value (if available).
|
|
*/
|
|
|
|
if( uiLevelsBack)
|
|
{
|
|
flmAssert( uiLevelsBack <= 0xFF);
|
|
pucTmpBuf[ 0] = (FLMBYTE)uiLevelsBack;
|
|
if( RC_BAD( rc = write( pucTmpBuf, 1)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
/*
|
|
Output the attribute's value.
|
|
*/
|
|
|
|
if( bSendAsGedcom)
|
|
{
|
|
/*
|
|
Output the GEDCOM data type and flags
|
|
*/
|
|
|
|
pucTmpBuf[ 0] = (FLMBYTE)uiCurValType;
|
|
if( bLeftTruncated)
|
|
{
|
|
pucTmpBuf[ 0] |= 0x10;
|
|
}
|
|
|
|
if( bRightTruncated)
|
|
{
|
|
pucTmpBuf[ 0] |= 0x20;
|
|
}
|
|
|
|
if( RC_BAD( rc = write( pucTmpBuf, 1)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if( uiCurDataLen)
|
|
{
|
|
/*
|
|
Output the data size.
|
|
*/
|
|
flmAssert( uiCurDataLen <= 0x0000FFFF);
|
|
|
|
intToByte( (FLMUINT16)uiCurDataLen, pucTmpBuf);
|
|
if( RC_BAD( rc = write( pucTmpBuf, 2)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
/*
|
|
Send the data.
|
|
*/
|
|
|
|
if( RC_BAD( rc = write( pucCurData, uiCurDataLen)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
Send the value.
|
|
*/
|
|
|
|
switch( uiCurValType)
|
|
{
|
|
case FLM_TEXT_TYPE:
|
|
{
|
|
/*
|
|
Extract the value.
|
|
*/
|
|
|
|
if( uiCurDataLen)
|
|
{
|
|
FLMUINT uiBufSize;
|
|
FLMUNICODE * puzValue;
|
|
|
|
/*
|
|
Reset the temporary pool.
|
|
*/
|
|
|
|
GedPoolReset( &m_tmpPool, pvMark);
|
|
if( uiCurDataLen <= 32751)
|
|
{
|
|
/*
|
|
Allocate a buffer that is twice the size of the
|
|
attribute's value length. This is necessary because the
|
|
UNICODE conversion will may double the size of the
|
|
attribute's value. A "safety" zone of 32 bytes is added
|
|
to the buffer size to allow for strings that may require
|
|
more than 2x the attribute's size and to account for
|
|
null-termination bytes.
|
|
*/
|
|
|
|
uiBufSize = (2 * uiCurDataLen) + 32;
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
Allocate a full 64K.
|
|
*/
|
|
|
|
uiBufSize = 65535;
|
|
}
|
|
|
|
if( (puzValue = (FLMUNICODE *)GedPoolAlloc( &m_tmpPool,
|
|
uiBufSize)) == NULL)
|
|
{
|
|
rc = RC_SET( FERR_MEM);
|
|
goto Exit;
|
|
}
|
|
|
|
/*
|
|
Extract UNICODE from the attribute.
|
|
*/
|
|
|
|
if( (pCurNode && RC_BAD( rc = GedGetUNICODE( pCurNode, puzValue, &uiBufSize))) ||
|
|
(pCurField && RC_BAD( rc = pRecord->getUnicode( pCurField, puzValue, &uiBufSize))))
|
|
{
|
|
if( rc == FERR_CONV_DEST_OVERFLOW)
|
|
{
|
|
/*
|
|
Since we did not correctly guess the buffer size,
|
|
try again. This time, take the slow (but safe)
|
|
approach of calculating the size of the UNICODE string.
|
|
*/
|
|
|
|
if( (pCurNode && RC_BAD( rc = GedGetUNICODE( pCurNode, NULL, &uiBufSize))) ||
|
|
(pCurField && RC_BAD( rc = pRecord->getUnicodeLength( pCurField, &uiBufSize))))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
/*
|
|
Add two bytes to account for null-termination.
|
|
*/
|
|
|
|
uiBufSize += 2;
|
|
|
|
/*
|
|
Reset the pool to clear the prior allocation.
|
|
*/
|
|
|
|
GedPoolReset( &m_tmpPool, pvMark);
|
|
|
|
/*
|
|
Allocate the new buffer.
|
|
*/
|
|
|
|
if( (puzValue = (FLMUNICODE *)GedPoolAlloc( &m_tmpPool,
|
|
uiBufSize)) == NULL)
|
|
{
|
|
rc = RC_SET( FERR_MEM);
|
|
goto Exit;
|
|
}
|
|
|
|
/*
|
|
Extract the UNICODE string.
|
|
*/
|
|
|
|
if( (pCurNode && RC_BAD( rc = GedGetUNICODE(
|
|
pCurNode, puzValue, &uiBufSize))) ||
|
|
(pCurField && RC_BAD( rc = pRecord->getUnicode(
|
|
pCurField, puzValue, &uiBufSize))))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
/*
|
|
Write the attribute's value.
|
|
*/
|
|
|
|
if( RC_BAD( rc = writeUTF( puzValue)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case FLM_NUMBER_TYPE:
|
|
{
|
|
if( uiCurDataLen)
|
|
{
|
|
if( uiDescriptor & HTD_TYPE_INT)
|
|
{
|
|
/*
|
|
Since the number is negative, extract and send it
|
|
as a signed 32-bit value.
|
|
*/
|
|
|
|
FLMINT iValue;
|
|
|
|
if( (pCurNode && RC_BAD( rc = GedGetINT( pCurNode, &iValue))) ||
|
|
(pCurField && RC_BAD( rc = pRecord->getINT( pCurField, &iValue))))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
/*
|
|
Write the value.
|
|
*/
|
|
|
|
if( RC_BAD( rc = writeInt32( (FLMINT32)iValue)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
The number is non-negative
|
|
*/
|
|
|
|
FLMUINT uiValue;
|
|
|
|
if( (pCurNode && RC_BAD( rc = GedGetUINT( pCurNode, &uiValue))) ||
|
|
(pCurField && RC_BAD( rc = pRecord->getUINT( pCurField, &uiValue))))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
/*
|
|
Write the value.
|
|
*/
|
|
|
|
if( RC_BAD( rc = writeUInt32( (FLMUINT32)uiValue)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FLM_CONTEXT_TYPE:
|
|
{
|
|
/*
|
|
Extract the value.
|
|
*/
|
|
|
|
if( uiCurDataLen)
|
|
{
|
|
/*
|
|
The context node has a DRN value associated with
|
|
it. Send the value as an unsigned 32-bit number.
|
|
*/
|
|
|
|
FLMUINT uiDrn;
|
|
|
|
if( (pCurNode && RC_BAD( rc = GedGetRecPtr( pCurNode, &uiDrn))) ||
|
|
(pCurField && RC_BAD( rc = pRecord->getUINT( pCurField, &uiDrn))))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if( RC_BAD( rc = writeUInt32( (FLMUINT32)uiDrn)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FLM_BINARY_TYPE:
|
|
{
|
|
/*
|
|
Extract the value.
|
|
*/
|
|
|
|
if( uiCurDataLen)
|
|
{
|
|
if( RC_BAD( rc = writeUShort( (FLMUINT16)uiCurDataLen)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if( RC_BAD( rc = write( pucCurData, uiCurDataLen)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
rc = RC_SET( FERR_NOT_IMPLEMENTED);
|
|
goto Exit;
|
|
}
|
|
}
|
|
}
|
|
|
|
uiPrevLevel = uiCurLevel;
|
|
if( pCurNode)
|
|
{
|
|
pCurNode = GedNodeNext( pCurNode);
|
|
}
|
|
else
|
|
{
|
|
pCurField = pRecord->next( pCurField);
|
|
}
|
|
}
|
|
|
|
/*
|
|
Write a zero tag to indicate the end of the transmission.
|
|
*/
|
|
|
|
if( RC_BAD( rc = writeUShort( 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
Exit:
|
|
|
|
GedPoolReset( &m_tmpPool, pvMark);
|
|
return( rc);
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
Desc: Flushes any pending data and closes the stream.
|
|
****************************************************************************/
|
|
RCODE FCS_DOS::close( void)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
|
|
/*
|
|
Verify that setup has been called.
|
|
*/
|
|
|
|
flmAssert( m_bSetupCalled == TRUE);
|
|
|
|
/*
|
|
Flush and terminate any pending message.
|
|
*/
|
|
|
|
if( RC_BAD( rc = endMessage()))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
|
|
Exit:
|
|
|
|
return( rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Flushes pending data.
|
|
****************************************************************************/
|
|
RCODE FCS_DOS::flush( void)
|
|
{
|
|
/*
|
|
Verify that setup has been called.
|
|
*/
|
|
|
|
flmAssert( m_bSetupCalled == TRUE);
|
|
|
|
/*
|
|
Flush the output buffer.
|
|
*/
|
|
|
|
if( m_uiBOffset > 0)
|
|
{
|
|
m_pOStream->write( m_pucBuffer, m_uiBOffset);
|
|
m_uiBOffset = 0;
|
|
}
|
|
|
|
/*
|
|
Flush the parent stream.
|
|
*/
|
|
|
|
return( m_pOStream->flush());
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
Desc: Flushes and terminates the current parent stream message
|
|
****************************************************************************/
|
|
RCODE FCS_DOS::endMessage( void)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
|
|
/*
|
|
Verify that Setup has been called.
|
|
*/
|
|
|
|
flmAssert( m_bSetupCalled == TRUE);
|
|
|
|
if( !m_pOStream)
|
|
{
|
|
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_pOStream->endMessage()))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
Exit:
|
|
|
|
return( rc);
|
|
}
|