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
This commit is contained in:
571
flaim/src/gdmisc.cpp
Normal file
571
flaim/src/gdmisc.cpp
Normal file
@@ -0,0 +1,571 @@
|
||||
//-------------------------------------------------------------------------
|
||||
// Desc: Miscellaneous GEDCOM routines.
|
||||
// Tabs: 3
|
||||
//
|
||||
// Copyright (c) 1992,1994-2000,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: gdmisc.cpp 12329 2006-01-20 17:49:30 -0700 (Fri, 20 Jan 2006) ahodgkinson $
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
#include "flaimsys.h"
|
||||
|
||||
/* Offset from the end of the node to each record source element */
|
||||
#define NODE_DRN_POS 0
|
||||
#define NODE_CONTAINER_POS (NODE_DRN_POS + sizeof( FLMUINT))
|
||||
#define NODE_DB_POS (NODE_CONTAINER_POS + sizeof( FLMUINT))
|
||||
|
||||
/*API~*********************************************************************
|
||||
Name : GedNodeCreate
|
||||
Area : GEDCOM
|
||||
Desc : Allocates space for a new GEDCOM node. Returns a pointer to the
|
||||
node or NULL if an allocation error occurs.
|
||||
Notes:
|
||||
****************************************************************************/
|
||||
NODE * GedNodeCreate(
|
||||
POOL * pPool,
|
||||
FLMUINT tagNum,
|
||||
FLMUINT id,
|
||||
RCODE * rc)
|
||||
{
|
||||
NODE * nd;
|
||||
|
||||
if( (nd = (NODE *)GedPoolAlloc( pPool,
|
||||
( sizeof(NODE) + (id ? sizeof(id) : 0)))) == NULL)
|
||||
{
|
||||
*rc = RC_SET( FERR_MEM);
|
||||
}
|
||||
else
|
||||
{
|
||||
f_memset( nd, '\0', sizeof( NODE));
|
||||
|
||||
GedValTypeSet( nd, FLM_CONTEXT_TYPE);
|
||||
GedTagNumSet( nd, tagNum);
|
||||
|
||||
if( id)
|
||||
{
|
||||
FLMBYTE * ptr;
|
||||
GedValTypeSetFlag( nd, HAS_REC_ID); /* Must set the ID before getting ptr */
|
||||
ptr = ((FLMBYTE *) nd) + sizeof(NODE); /* If we call GedIdPtr */
|
||||
*((FLMUINT *)(ptr + NODE_DRN_POS)) = id;
|
||||
}
|
||||
*rc = FERR_OK;
|
||||
}
|
||||
|
||||
return( nd);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Desc: This routine allocates space in a GEDCOM node for a value. If the
|
||||
node already has the required space, nothing is done. Otherwise,
|
||||
it calls the PoolAlloc routine to get the needed memory. This
|
||||
routine also sets the value length and type information.
|
||||
Note: On FLM_TEXT_TYPE data type one extra byte will be allocated.
|
||||
This byte will be used for a NULL character.
|
||||
NOTE: WARNING - If there is a length then the ptr value may be reused.
|
||||
This could cause problems with reusing GEDCOM memory and using
|
||||
the pool marker.
|
||||
****************************************************************************/
|
||||
void * GedAllocSpace(
|
||||
POOL * pPool,
|
||||
NODE * node,
|
||||
FLMUINT valType,
|
||||
FLMUINT size,
|
||||
FLMUINT uiEncId,
|
||||
FLMUINT uiEncSize)
|
||||
{
|
||||
FLMBYTE * rPtr; /* Return Pointer */
|
||||
FLMUINT uiAllocSize = size;
|
||||
|
||||
if( valType == FLM_TEXT_TYPE)
|
||||
uiAllocSize++;
|
||||
|
||||
if( uiAllocSize <= sizeof( void *))
|
||||
{
|
||||
/* If the size is less than sizeof (void *), we use the space right */
|
||||
/* inside value pointer itself. */
|
||||
|
||||
rPtr = (FLMBYTE *) &node->value;
|
||||
}
|
||||
|
||||
/* BUG 10/1/96: Don't use wAllocSize here */
|
||||
|
||||
else if( size <= GedValLen( node))
|
||||
{
|
||||
/* If there is already allocated space, just re-use it */
|
||||
|
||||
rPtr = (FLMBYTE *)GedValPtr( node);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
/* At this point, we know we have to allocate space elsewhere.
|
||||
** NOTE: If we are unable to allocate the space required, DO
|
||||
** NOT modify the node -- return NULL immediately.
|
||||
*/
|
||||
|
||||
if( (node->value = rPtr =
|
||||
(FLMBYTE *) GedPoolAlloc( pPool, uiAllocSize)) == NULL)
|
||||
{
|
||||
/* VISIT: 10/1/96: Comment above does not agree with this code. */
|
||||
|
||||
node->ui32Length = 0;
|
||||
node->value = NULL;
|
||||
return( NULL);
|
||||
}
|
||||
}
|
||||
if( valType == FLM_TEXT_TYPE)
|
||||
rPtr[ size] = '\0';
|
||||
|
||||
/* Now set the size and the data type */
|
||||
|
||||
node->ui32Length = (FLMUINT32)size;
|
||||
GedSetType( node, valType);
|
||||
|
||||
// If passed-in enc id is zero, use the node's enc id.
|
||||
|
||||
if (!uiEncId)
|
||||
{
|
||||
flmAssert( !uiEncSize);
|
||||
if (size)
|
||||
{
|
||||
uiEncId = node->ui32EncId;
|
||||
uiEncSize = size + (16 - (size % 16));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
// We only should have an encryption ID if size is non-zero.
|
||||
// If size is non-zero, encryption size must also be non-zero.
|
||||
|
||||
flmAssert( size);
|
||||
flmAssert( uiEncSize);
|
||||
}
|
||||
|
||||
if (uiEncId)
|
||||
{
|
||||
if( uiEncSize > GedEncLen( node))
|
||||
{
|
||||
if( (node->pucEncValue =
|
||||
(FLMBYTE *) GedPoolAlloc( pPool, uiEncSize)) == NULL)
|
||||
{
|
||||
node->ui32EncLength = 0;
|
||||
node->pucEncValue = NULL;
|
||||
return( NULL);
|
||||
}
|
||||
}
|
||||
node->ui32EncFlags = FLD_HAVE_DECRYPTED_DATA | FLD_HAVE_ENCRYPTED_DATA;
|
||||
node->ui32EncId = (FLMUINT32)uiEncId;
|
||||
node->ui32EncLength = (FLMUINT32)uiEncSize;
|
||||
}
|
||||
|
||||
|
||||
return( rPtr);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Desc: return pointer to value. The value may be store in the node if it's
|
||||
small enough in size to fit in the void * value pointer slot.
|
||||
****************************************************************************/
|
||||
void * GedValPtr(
|
||||
NODE * nd)
|
||||
{
|
||||
return(
|
||||
nd && nd->ui32Length
|
||||
? GedValType( nd) == FLM_TEXT_TYPE
|
||||
? nd->ui32Length < sizeof( void *)
|
||||
? (void *) &nd->value
|
||||
: (void *) nd->value
|
||||
: nd->ui32Length > sizeof( void *) /* non-text (no null terminator) */
|
||||
? (void *) nd->value /* value seperate from node */
|
||||
: (void *) &nd->value /* value in node's valuePtr space */
|
||||
: (void *)NULL /* no node or value */
|
||||
);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Desc: return pointer to encryption value.
|
||||
****************************************************************************/
|
||||
void * GedEncPtr(
|
||||
NODE * nd)
|
||||
{
|
||||
return(
|
||||
nd && nd->ui32EncLength
|
||||
? (void *)nd->pucEncValue
|
||||
: (void *)NULL /* no node or encrypted value */
|
||||
);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Desc: Allows the user to set the ID (record number, or sub-record number)
|
||||
for the supplied field.
|
||||
****************************************************************************/
|
||||
RCODE GedPutRecId(
|
||||
POOL * pPool,
|
||||
NODE ** ppNd,
|
||||
FLMUINT uiId)
|
||||
{
|
||||
NODE * pNewNd;
|
||||
NODE * pOldNd = *ppNd;
|
||||
FLMBYTE * ptr;
|
||||
|
||||
if( (pNewNd = (NODE *)GedPoolAlloc(pPool,
|
||||
sizeof( NODE) + sizeof( uiId))) == NULL)
|
||||
{
|
||||
*ppNd = NULL;
|
||||
return( RC_SET( FERR_MEM));
|
||||
}
|
||||
|
||||
// Copy the contents of the existing node
|
||||
|
||||
pNewNd->prior = pOldNd->prior;
|
||||
pNewNd->next = pOldNd->next;
|
||||
pNewNd->value = pOldNd->value;
|
||||
pNewNd->ui32Length = pOldNd->ui32Length;
|
||||
pNewNd->ui32EncId = pOldNd->ui32EncId;
|
||||
pNewNd->ui32EncLength = pOldNd->ui32EncLength;
|
||||
pNewNd->ui32EncFlags = pOldNd->ui32EncFlags;
|
||||
pNewNd->pucEncValue = pOldNd->pucEncValue;
|
||||
GedTagNumSet( pNewNd, GedTagNum( pOldNd));
|
||||
GedNodeLevelSet( pNewNd, GedNodeLevel( pOldNd));
|
||||
GedNodeTypeSet( pNewNd, (GedNodeType( pOldNd) | HAS_REC_ID));
|
||||
|
||||
// Link in new node to parent and children/siblings
|
||||
|
||||
if( pNewNd->prior)
|
||||
{
|
||||
pNewNd->prior->next = pNewNd;
|
||||
}
|
||||
|
||||
if( pNewNd->next)
|
||||
{
|
||||
pNewNd->next->prior = pNewNd;
|
||||
}
|
||||
|
||||
// Set the Ids value
|
||||
ptr = (FLMBYTE *)GedIdPtr( pNewNd );
|
||||
*((FLMUINT *)(ptr + NODE_DRN_POS)) = uiId;
|
||||
*ppNd = pNewNd;
|
||||
|
||||
return( FERR_OK);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Desc: Will set the source information in a GEDCOM node.
|
||||
****************************************************************************/
|
||||
void gedSetRecSource(
|
||||
NODE * pNode,
|
||||
HFDB hDb,
|
||||
FLMUINT uiContainer,
|
||||
FLMUINT uiDrn )
|
||||
{
|
||||
FLMBYTE * pucPtr;
|
||||
|
||||
pucPtr = ((FLMBYTE *) pNode) + sizeof( NODE); /* Set pucPtr to end of node */
|
||||
if( uiDrn)
|
||||
{
|
||||
GedValTypeSetFlag( pNode, HAS_REC_ID);
|
||||
*((FLMUINT *)(pucPtr + NODE_DRN_POS)) = uiDrn;
|
||||
}
|
||||
if( uiContainer)
|
||||
{
|
||||
GedValTypeSetFlag( pNode, HAS_REC_SOURCE);
|
||||
*((FLMUINT *)(pucPtr + NODE_CONTAINER_POS)) = uiContainer;
|
||||
}
|
||||
if( hDb)
|
||||
{
|
||||
GedValTypeSetFlag( pNode, HAS_REC_SOURCE);
|
||||
*((HFDB *)(pucPtr + NODE_DB_POS)) = hDb;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Desc: Will create a GEDCOM node that contains a FLAIM Database's HFDB,
|
||||
store number, container number, and record id (DRN).
|
||||
****************************************************************************/
|
||||
RCODE gedCreateSourceNode(
|
||||
POOL * pPool, /* Users allocation pool */
|
||||
FLMUINT uiFieldNum, /* Tag Number */
|
||||
HFDB hDb, /* FLAIM Database that record came from */
|
||||
FLMUINT uiContainer, /* Container record came from */
|
||||
FLMUINT uiRecId, /* Record id (DRN) */
|
||||
NODE ** ppNode) /* [out] newly created gedcom source node */
|
||||
{
|
||||
NODE * nd;
|
||||
RCODE rc = FERR_OK;
|
||||
|
||||
*ppNode = nd = (NODE *)GedPoolCalloc( pPool,
|
||||
( sizeof( NODE)
|
||||
+ sizeof( FLMUINT) /* Record Id (DRN) */
|
||||
+ sizeof( FLMUINT) /* Container Number */
|
||||
+ sizeof( HFDB))); /* Database handle */
|
||||
if( nd != NULL)
|
||||
{
|
||||
GedValTypeSet( nd, FLM_CONTEXT_TYPE);
|
||||
GedTagNumSet( nd, uiFieldNum);
|
||||
gedSetRecSource( nd, hDb, uiContainer, uiRecId);
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = RC_SET( FERR_MEM);
|
||||
}
|
||||
|
||||
return( rc);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Desc: Returns the FLAIM database source that this GEDCOM record is from.
|
||||
Remarks: The root node of each GEDCOM record returned from FLAIM will contain
|
||||
information about where the record came from. This information is
|
||||
known as its source information and includes:
|
||||
Memory Handle to FLAIM Database (HFDB)
|
||||
Store Number
|
||||
Container Number
|
||||
Record Id (DRN)
|
||||
|
||||
Note: Some GEDCOM Nodes may only contain the Record Id, in those cases
|
||||
calls to GedGetRecSource will return a NULL for the HFDB and 0's for
|
||||
the Store and Container number (meaning the record has not been
|
||||
assigned to a FLAIM database yet).
|
||||
****************************************************************************/
|
||||
RCODE GedGetRecSource(
|
||||
NODE * pNode, /* GEDCOM node to return FLAIM database source
|
||||
information. */
|
||||
HFDB * phDb, /* [out] FLAIM Database that this record came from.
|
||||
NOTE: This value is only valid while the
|
||||
database is actually open, and has no persistent
|
||||
capabilities. */
|
||||
FLMUINT * puiContainer,/* [out] Database Container that this record is from.*/
|
||||
FLMUINT * puiRecId) /* [out] Database Record Id (DRN) that has been
|
||||
assigned to this record. This is unique only
|
||||
within a database's container. */
|
||||
{
|
||||
RCODE rc = FERR_OK;
|
||||
FLMBYTE * ptr = ((FLMBYTE *) pNode) + sizeof( NODE); /* Set ptr to end of node */
|
||||
|
||||
if( GedNodeType( pNode) & HAS_REC_SOURCE)
|
||||
{
|
||||
if( phDb)
|
||||
{
|
||||
*phDb = *((HFDB *)(ptr + NODE_DB_POS));
|
||||
}
|
||||
|
||||
if( puiContainer)
|
||||
{
|
||||
*puiContainer = *((FLMUINT *)(ptr + NODE_CONTAINER_POS));
|
||||
}
|
||||
|
||||
if( puiRecId)
|
||||
{
|
||||
*puiRecId = *((FLMUINT *)( ptr + NODE_DRN_POS));
|
||||
}
|
||||
}
|
||||
else if( GedNodeType( pNode) & HAS_REC_ID)
|
||||
{
|
||||
if( phDb)
|
||||
{
|
||||
*phDb = NULL;
|
||||
}
|
||||
|
||||
if( puiContainer)
|
||||
{
|
||||
*puiContainer = 0;
|
||||
}
|
||||
|
||||
if( puiRecId)
|
||||
{
|
||||
*puiRecId = *((FLMUINT *)( ptr + NODE_DRN_POS));
|
||||
}
|
||||
}
|
||||
else
|
||||
{ /* The record contains no record source, because the user may ignore
|
||||
the return code lets make sure everything is set to null/0. */
|
||||
|
||||
if( phDb)
|
||||
{
|
||||
*phDb = NULL;
|
||||
}
|
||||
|
||||
if( puiContainer)
|
||||
{
|
||||
*puiContainer = 0;
|
||||
}
|
||||
|
||||
if( puiRecId)
|
||||
{
|
||||
*puiRecId = 0;
|
||||
}
|
||||
|
||||
rc = RC_SET( FERR_NOT_FOUND);
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
Exit:
|
||||
return( rc);
|
||||
}
|
||||
|
||||
|
||||
/*API~*********************************************************************
|
||||
Desc: Places the suppolied DRN into a context type node.
|
||||
*END************************************************************************/
|
||||
RCODE GedPutRecPtr(
|
||||
POOL * pPool,
|
||||
NODE * nd,
|
||||
FLMUINT drn,
|
||||
FLMUINT uiEncId,
|
||||
FLMUINT uiEncSize)
|
||||
{
|
||||
void * ptr;
|
||||
RCODE rc = FERR_OK;
|
||||
|
||||
/* Check for a null node being passed in */
|
||||
|
||||
if( nd == NULL)
|
||||
{
|
||||
rc = RC_SET( FERR_CONV_NULL_DEST);
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
if( (ptr = GedAllocSpace( pPool, nd, FLM_CONTEXT_TYPE,
|
||||
sizeof(FLMUINT32), uiEncId, uiEncSize)) == NULL)
|
||||
{
|
||||
rc = RC_SET( FERR_MEM);
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
UD2FBA( (FLMUINT32) drn, ptr);
|
||||
|
||||
if (nd->ui32EncId)
|
||||
{
|
||||
nd->ui32EncFlags = FLD_HAVE_DECRYPTED_DATA;
|
||||
}
|
||||
|
||||
Exit:
|
||||
return( rc);
|
||||
}
|
||||
|
||||
/*API~*********************************************************************
|
||||
Name : GedGetRecPtr
|
||||
Area : GEDCOM
|
||||
Desc : Obtain the DRN (database record number) from a GEDCOM context type
|
||||
node. No conversion from other data types will be performed.
|
||||
*END************************************************************************/
|
||||
RCODE // FERR_CONV_ILLEGAL - the input node (nd) is not a context type.
|
||||
// FERR_CONV_NULL_SRC - The input node (nd) is NULL.
|
||||
GedGetRecPtr(
|
||||
NODE * nd,
|
||||
// [IN] Input GEDCOM node.
|
||||
FLMUINT * drnRV
|
||||
// [OUT] Returns the DRN value on SUCCESS.
|
||||
)
|
||||
{
|
||||
RCODE rc = FERR_OK;
|
||||
|
||||
*drnRV = (FLMUINT) 0xFFFFFFFF; /* value for "no value" */
|
||||
|
||||
if( nd == NULL) /* Make sure we have a valid node */
|
||||
{
|
||||
rc = RC_SET( FERR_CONV_NULL_SRC);
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
if (nd->ui32EncId)
|
||||
{
|
||||
if (!(nd->ui32EncFlags & FLD_HAVE_DECRYPTED_DATA))
|
||||
{
|
||||
rc = RC_SET( FERR_FLD_NOT_DECRYPTED);
|
||||
goto Exit;
|
||||
}
|
||||
}
|
||||
|
||||
if( GedValType(nd) != FLM_CONTEXT_TYPE)
|
||||
{
|
||||
rc = RC_SET( FERR_CONV_ILLEGAL); /* DIN's doesn't convert */
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
if( GedValLen( nd) == sizeof( FLMUINT32))
|
||||
{
|
||||
*drnRV = (FLMUINT)(FB2UD((FLMBYTE *) GedValPtr( nd)));
|
||||
}
|
||||
|
||||
Exit:
|
||||
return( rc);
|
||||
}
|
||||
|
||||
|
||||
/*API~*********************************************************************
|
||||
Name : GedWalk
|
||||
Area : GEDCOM
|
||||
Desc : Traverses a tree or forest of GEDCOM tress. For each GEDCOM node
|
||||
that is visited, a user specified callback function is called.
|
||||
|
||||
The passed-in function needs to accept the following parameters:
|
||||
FLMUINT level; * current relative level of this node *
|
||||
NODE * node; * pointer to current node *
|
||||
void * arg; * user's passed-thru parameter *
|
||||
This passed-in function is repeatedly called until its return code is
|
||||
not SUCCESS, the tree/forest is completely processed, or the count
|
||||
expires.
|
||||
|
||||
Notes:This function can be extremely useful in many contexts.
|
||||
*END************************************************************************/
|
||||
RCODE GedWalk(
|
||||
FLMUINT treeCnt,
|
||||
// [IN] treeCnt is the number of sibling trees to process.
|
||||
// Pass in GED_TREE to walk through the input node and all
|
||||
// of its children. Pass in GED_FOREST to walk through the input
|
||||
// node and all of its siblings as well as all children. A number
|
||||
// may also be specified to limit the number of trees that are
|
||||
// walked through. GED_TREE has a value of one.
|
||||
NODE * node,
|
||||
// [IN] Pointer to the first node of a GEDCOM tree or forest.
|
||||
GEDWALK_FUNC_p func,
|
||||
// [IN] User specified callback function called on every GEDCOM
|
||||
// node that is visited.
|
||||
void * arg)
|
||||
// [IN] Argument used as an argument for the callback function func().
|
||||
{
|
||||
RCODE rc;
|
||||
|
||||
if( node) /* non-null tree */
|
||||
{
|
||||
FLMUINT baseLevel = GedNodeLevel( node);/* save to know when sub-tree's done */
|
||||
do
|
||||
{
|
||||
rc = /* save return code for test & exit */
|
||||
(*func)( /* passed-in function pointer */
|
||||
(GedNodeLevel( node) - baseLevel),/* node's relative level number */
|
||||
node, arg);
|
||||
}while(
|
||||
RC_OK( rc) && /* stop if( *func) != SUCCESS */
|
||||
(node = node->next) != NULL && /* stop if end of tree/forest */
|
||||
(
|
||||
GedNodeLevel( node) > baseLevel || /* continue while in sub-tree */
|
||||
(
|
||||
GedNodeLevel( node) == baseLevel &&/* if sibling, decrement treeCnt */
|
||||
--treeCnt /* continue if treeCnt != 0 */
|
||||
)
|
||||
) /* else, stop if no sibling trees */
|
||||
);
|
||||
}
|
||||
else
|
||||
rc = FERR_OK; /* null tree always SUCCESS */
|
||||
|
||||
return( rc);
|
||||
}
|
||||
Reference in New Issue
Block a user