Files
mars-flaim/ftk/src/ftkntab.cpp
ahodgkinson eb0f9e82cc Updates, etc.
git-svn-id: https://svn.code.sf.net/p/flaim/code/trunk@357 0109f412-320b-0410-ab79-c3e0c5ffbbe6
2006-04-27 15:59:33 +00:00

1959 lines
43 KiB
C++

//------------------------------------------------------------------------------
// Desc: Class for managing a name table.
//
// Tabs: 3
//
// Copyright (c) 1992, 1994-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: fntable.cpp 3114 2006-01-19 13:22:45 -0700 (Thu, 19 Jan 2006) dsanders $
//------------------------------------------------------------------------------
#include "ftksys.h"
#define MAX_ELEMENTS_TO_LOAD 0xFFFF
#define MAX_ATTRIBUTES_TO_LOAD 0xFFFF
typedef struct
{
FLMUINT uiType;
FLMUNICODE * puzTagName;
FLMUINT uiTagNum;
FLMUINT uiDataType;
FLMUNICODE * puzNamespace;
} FLM_TAG_INFO;
typedef FLMINT (* TAG_COMPARE_FUNC)(
FLM_TAG_INFO * pTagInfo1,
FLM_TAG_INFO * pTagInfo2);
FSTATIC FLMINT tagNameCompare(
const FLMUNICODE * puzName1,
const char * pszName1,
const FLMUNICODE * puzName2);
FSTATIC FLMINT compareTagTypeAndName(
FLM_TAG_INFO * pTagInfo1,
FLM_TAG_INFO * pTagInfo2);
FSTATIC FLMINT compareTagTypeAndNum(
FLM_TAG_INFO * pTagInfo1,
FLM_TAG_INFO * pTagInfo2);
FSTATIC void sortTagTbl(
FLM_TAG_INFO ** ppTagInfoTbl,
FLMUINT uiLowerBounds,
FLMUINT uiUpperBounds,
TAG_COMPARE_FUNC fnTagCompare);
/****************************************************************************
Desc: Class for name/number lookup.
****************************************************************************/
class F_NameTable : public IF_NameTable, public F_Base
{
public:
F_NameTable();
virtual ~F_NameTable();
RCODE FLMAPI setupNameTable( void);
void FLMAPI clearTable(
FLMUINT uiPoolBlkSize);
RCODE FLMAPI getNextTagTypeAndNumOrder(
FLMUINT uiType,
FLMUINT * puiNextPos,
FLMUNICODE * puzTagName = NULL,
char * pszTagName = NULL,
FLMUINT uiNameBufSize = 0,
FLMUINT * puiTagNum = NULL,
FLMUINT * puiDataType = NULL,
FLMUNICODE * puzNamespace = NULL,
FLMUINT uiNamespaceBufSize = 0,
FLMBOOL bTruncatedNamesOk = TRUE);
RCODE FLMAPI getNextTagTypeAndNameOrder(
FLMUINT uiType,
FLMUINT * puiNextPos,
FLMUNICODE * puzTagName = NULL,
char * pszTagName = NULL,
FLMUINT uiNameBufSize = 0,
FLMUINT * puiTagNum = NULL,
FLMUINT * puiDataType = NULL,
FLMUNICODE * puzNamespace = NULL,
FLMUINT uiNamespaceBufSize = 0,
FLMBOOL bTruncatedNamesOk = TRUE);
RCODE FLMAPI getFromTagTypeAndName(
FLMUINT uiType,
const FLMUNICODE * puzTagName,
const char * pszTagName,
FLMBOOL bMatchNamespace,
const FLMUNICODE * puzNamespace = NULL,
FLMUINT * puiTagNum = NULL,
FLMUINT * puiDataType = NULL);
RCODE FLMAPI getFromTagTypeAndNum(
FLMUINT uiType,
FLMUINT uiTagNum,
FLMUNICODE * puzTagName = NULL,
char * pszTagName = NULL,
FLMUINT * puiNameBufSize = NULL,
FLMUINT * puiDataType = NULL,
FLMUNICODE * puzNamespace = NULL,
char * pszNamespace = NULL,
FLMUINT * puiNamespaceBufSize = NULL,
FLMBOOL bTruncatedNamesOk = TRUE);
RCODE FLMAPI addTag(
FLMUINT uiType,
FLMUNICODE * puzTagName,
const char * pszTagName,
FLMUINT uiTagNum,
FLMUINT uiDataType = 0,
FLMUNICODE * puzNamespace = NULL,
FLMBOOL bCheckDuplicates = TRUE);
void FLMAPI removeTag(
FLMUINT uiType,
FLMUINT uiTagNum);
RCODE FLMAPI cloneNameTable(
IF_NameTable * pSrcNameTable);
RCODE FLMAPI importFromNameTable(
IF_NameTable * pSrcNameTable);
FLMINT FLMAPI AddRef( void);
FLMINT FLMAPI Release( void);
private:
void sortTags( void);
RCODE allocTag(
FLMUINT uiType,
FLMUNICODE * puzTagName,
const char * pszTagName,
FLMUINT uiTagNum,
FLMUINT uiDataType,
FLMUNICODE * puzNamespace,
FLM_TAG_INFO ** ppTagInfo);
RCODE reallocSortTables(
FLMUINT uiNewTblSize);
RCODE copyTagName(
FLMUNICODE * puzDestTagName,
char * pszDestTagName,
FLMUINT * puiDestBufSize,
FLMUNICODE * puzSrcTagName,
FLMBOOL bTruncatedNamesOk);
FLM_TAG_INFO * findTagByTypeAndNum(
FLMUINT uiType,
FLMUINT uiTagNum,
FLMUINT * puiInsertPos = NULL);
FLM_TAG_INFO * findTagByTypeAndName(
FLMUINT uiType,
const FLMUNICODE * puzTagName,
const char * pszTagName,
FLMBOOL bMatchNamespace,
const FLMUNICODE * puzNamespace,
FLMBOOL * pbAmbiguous,
FLMUINT * puiInsertPos = NULL);
RCODE insertTagInTables(
FLM_TAG_INFO * pTagInfo,
FLMUINT uiTagTypeAndNameTblInsertPos,
FLMUINT uiTagTypeAndNumTblInsertPos);
FLMUNICODE * findNamespace(
FLMUNICODE * puzNamespace,
FLMUINT * puiInsertPos);
RCODE insertNamespace(
FLMUNICODE * puzNamespace,
FLMUINT uiInsertPos);
IF_Pool * m_pPool;
FLMUINT m_uiMemoryAllocated;
FLM_TAG_INFO ** m_ppSortedByTagTypeAndName;
FLM_TAG_INFO ** m_ppSortedByTagTypeAndNum;
FLMUINT m_uiTblSize;
FLMUINT m_uiNumTags;
FLMBOOL m_bTablesSorted;
FLMUNICODE ** m_ppuzNamespaces;
FLMUINT m_uiNamespaceTblSize;
FLMUINT m_uiNumNamespaces;
F_MUTEX m_hRefMutex;
};
/****************************************************************************
Desc:
****************************************************************************/
F_NameTable::F_NameTable()
{
m_pPool = NULL;
m_uiMemoryAllocated = 0;
m_ppSortedByTagTypeAndName = NULL;
m_ppSortedByTagTypeAndNum = NULL;
m_uiTblSize = 0;
m_uiNumTags = 0;
m_bTablesSorted = FALSE;
m_ppuzNamespaces = NULL;
m_uiNamespaceTblSize = 0;
m_uiNumNamespaces = 0;
m_hRefMutex = F_MUTEX_NULL;
}
/****************************************************************************
Desc:
****************************************************************************/
F_NameTable::~F_NameTable()
{
clearTable( 0);
if( m_pPool)
{
m_pPool->Release();
}
if( m_hRefMutex)
{
f_mutexDestroy( &m_hRefMutex);
}
}
/****************************************************************************
Desc: Setup name table. This routine should be called immediately after
the object is allocated.
****************************************************************************/
RCODE FLMAPI F_NameTable::setupNameTable( void)
{
RCODE rc = NE_FLM_OK;
if( RC_BAD( rc = FlmAllocPool( &m_pPool)))
{
goto Exit;
}
m_pPool->poolInit( 1024);
Exit:
return( rc);
}
/****************************************************************************
Desc: Free everything in the table
****************************************************************************/
void FLMAPI F_NameTable::clearTable(
FLMUINT uiPoolBlkSize)
{
m_pPool->poolFree();
if (uiPoolBlkSize)
{
m_pPool->poolInit( uiPoolBlkSize);
}
m_uiMemoryAllocated = 0;
// NOTE: Only one allocation is used for m_ppSortedByTagTypeAndName and
// m_ppSortedByTagTypeAndNum - there is no
// need to free m_ppSortedByTagTypeAndNum
if (m_ppSortedByTagTypeAndName)
{
f_free( &m_ppSortedByTagTypeAndName);
m_ppSortedByTagTypeAndNum = NULL;
m_uiTblSize = 0;
m_uiNumTags = 0;
}
if (m_ppuzNamespaces)
{
f_free( &m_ppuzNamespaces);
m_ppuzNamespaces = NULL;
m_uiNamespaceTblSize = 0;
m_uiNumNamespaces = 0;
}
m_bTablesSorted = FALSE;
}
/****************************************************************************
Desc: Compare two tag names. Name1 can be NATIVE or UNICODE. If a non-NULL
UNICODE string is passed, it will be used. Otherwise, the NATIVE
string will be used.
Note: Comparison is case sensitive. Either or both names may be NULL.
Empty strings and NULL pointers are considered to be equal.
****************************************************************************/
FSTATIC FLMINT tagNameCompare(
const FLMUNICODE * puzName1, // If NULL, use pszName1 for comparison
const char * pszName1,
const FLMUNICODE * puzName2)
{
FLMUNICODE uzChar1;
FLMUNICODE uzChar2;
FLMUNICODE uzLowerChar1;
FLMUNICODE uzLowerChar2;
if (puzName1)
{
if (!puzName2)
{
if (*puzName1)
{
return( 1);
}
else
{
return( 0);
}
}
for (;;)
{
uzChar1 = *puzName1;
uzChar2 = *puzName2;
if (!uzChar1)
{
if (!uzChar2)
{
return( 0);
}
else
{
return( -1);
}
}
else if (!uzChar2)
{
return( 1);
}
else if (uzChar1 != uzChar2)
{
Test_Case:
uzLowerChar1 = f_unitolower( uzChar1);
uzLowerChar2 = f_unitolower( uzChar2);
if (uzLowerChar1 < uzLowerChar2)
{
return( -1);
}
else if (uzLowerChar1 > uzLowerChar2)
{
return( 1);
}
else if (uzLowerChar1 != uzChar1)
{
// Char1 is uppercase, char2 is lowercase
// Uppercase sorts before lowercase
return( -1);
}
else
{
// Char1 is lowercase, char2 is uppercase
// Lowercase sorts after uppercase
return( 1);
}
}
puzName1++;
puzName2++;
}
}
else if (pszName1)
{
if (!puzName2)
{
if (*pszName1)
{
return( 1);
}
else
{
return( 0);
}
}
for (;;)
{
uzChar1 = (FLMUNICODE)*pszName1;
uzChar2 = *puzName2;
if (!uzChar1)
{
if (!uzChar2)
{
return( 0);
}
else
{
return( -1);
}
}
else if (!uzChar2)
{
return( 1);
}
else if (uzChar1 != uzChar2)
{
goto Test_Case;
}
pszName1++;
puzName2++;
}
}
else if (puzName2)
{
// Both name1's are NULL.
if (*puzName2)
{
return( -1);
}
else
{
return( 0);
}
}
else
{
// Both name1 and name2 are NULL.
return( 0);
}
}
/****************************************************************************
Desc: Lookup a tag by type and tag number.
****************************************************************************/
FLM_TAG_INFO * F_NameTable::findTagByTypeAndNum(
FLMUINT uiType,
FLMUINT uiTagNum,
FLMUINT * puiInsertPos)
{
FLM_TAG_INFO * pTagInfo = NULL;
FLMUINT uiTblSize;
FLMUINT uiLow;
FLMUINT uiMid;
FLMUINT uiHigh;
FLMUINT uiTblTagNum;
FLMUINT uiTblType;
if (!m_bTablesSorted)
{
sortTags();
}
// Do binary search in the table
if ((uiTblSize = m_uiNumTags) == 0)
{
if (puiInsertPos)
{
*puiInsertPos = 0;
}
goto Exit;
}
uiHigh = --uiTblSize;
uiLow = 0;
for (;;)
{
uiMid = (uiLow + uiHigh) / 2;
uiTblType = m_ppSortedByTagTypeAndNum [uiMid]->uiType;
uiTblTagNum = m_ppSortedByTagTypeAndNum [uiMid]->uiTagNum;
if (uiTblType == uiType && uiTagNum == uiTblTagNum)
{
// Found Match
pTagInfo = m_ppSortedByTagTypeAndNum [uiMid];
if (puiInsertPos)
{
*puiInsertPos = uiMid;
}
goto Exit;
}
// Check if we are done
if (uiLow >= uiHigh)
{
// Done, item not found
if (puiInsertPos)
{
*puiInsertPos = (uiType < uiTblType ||
(uiType == uiTblType && uiTagNum < uiTblTagNum))
? uiMid
: uiMid + 1;
}
goto Exit;
}
if (uiType < uiTblType ||
(uiType == uiTblType && uiTagNum < uiTblTagNum))
{
if (uiMid == 0)
{
if (puiInsertPos)
{
*puiInsertPos = 0;
}
goto Exit;
}
uiHigh = uiMid - 1;
}
else
{
if (uiMid == uiTblSize)
{
if (puiInsertPos)
{
*puiInsertPos = uiMid + 1;
}
goto Exit;
}
uiLow = uiMid + 1;
}
}
Exit:
return( pTagInfo);
}
/****************************************************************************
Desc: Lookup a tag by tag type and tag name. Tag name is passed in as a
UNICODE string or a NATIVE string. If a non-NULL UNICODE string is
passed in, it will be used. Otherwise, the NATIVE string will be used.
****************************************************************************/
FLM_TAG_INFO * F_NameTable::findTagByTypeAndName(
FLMUINT uiType,
const FLMUNICODE * puzTagName,
const char * pszTagName,
FLMBOOL bMatchNamespace,
const FLMUNICODE * puzNamespace,
FLMBOOL * pbAmbiguous,
FLMUINT * puiInsertPos)
{
FLM_TAG_INFO * pTagInfo = NULL;
FLMUINT uiTblType;
FLMUINT uiTblSize;
FLMUINT uiLow;
FLMUINT uiMid;
FLMUINT uiHigh;
FLMINT iCmp;
if (!m_bTablesSorted)
{
sortTags();
}
// Do binary search in the table
*pbAmbiguous = FALSE;
if ((uiTblSize = m_uiNumTags) == 0)
{
if (puiInsertPos)
{
*puiInsertPos = 0;
}
goto Exit;
}
uiHigh = --uiTblSize;
uiLow = 0;
for (;;)
{
uiMid = (uiLow + uiHigh) / 2;
uiTblType = m_ppSortedByTagTypeAndName [uiMid]->uiType;
if (uiType < uiTblType)
{
iCmp = -1;
}
else if (uiType > uiTblType)
{
iCmp = 1;
}
else if ((iCmp = tagNameCompare( puzTagName, pszTagName,
m_ppSortedByTagTypeAndName [uiMid]->puzTagName)) == 0)
{
if (!bMatchNamespace)
{
// Better not be trying to insert a new one in this case!
flmAssert( puiInsertPos == NULL);
if ((uiMid &&
tagNameCompare( puzTagName, pszTagName,
m_ppSortedByTagTypeAndName [uiMid-1]->puzTagName) == 0) ||
(uiMid < m_uiNumTags - 1 &&
tagNameCompare( puzTagName, pszTagName,
m_ppSortedByTagTypeAndName [uiMid+1]->puzTagName) == 0))
{
*pbAmbiguous = TRUE;
}
}
else
{
iCmp = tagNameCompare( puzNamespace, NULL,
m_ppSortedByTagTypeAndName [uiMid]->puzNamespace);
}
if (iCmp == 0)
{
// Found Match
pTagInfo = m_ppSortedByTagTypeAndName [uiMid];
if (puiInsertPos)
{
*puiInsertPos = uiMid;
}
goto Exit;
}
}
// Check if we are done
if (uiLow >= uiHigh)
{
// Done, item not found
if (puiInsertPos)
{
*puiInsertPos = (iCmp < 0)
? uiMid
: uiMid + 1;
}
goto Exit;
}
if (iCmp < 0)
{
if (uiMid == 0)
{
if (puiInsertPos)
{
*puiInsertPos = 0;
}
goto Exit;
}
uiHigh = uiMid - 1;
}
else
{
if (uiMid == uiTblSize)
{
if (puiInsertPos)
{
*puiInsertPos = uiMid + 1;
}
goto Exit;
}
uiLow = uiMid + 1;
}
}
Exit:
return( pTagInfo);
}
/****************************************************************************
Desc: Copy a tag name to a UNICODE or NATIVE buffer. Truncate if necessary.
If a non-NULL UNICODE string is passed in, it will be populated.
Otherwise, the NATIVE string will be populated.
****************************************************************************/
RCODE F_NameTable::copyTagName(
FLMUNICODE * puzDestTagName,
char * pszDestTagName,
FLMUINT * puiDestBufSize, // Bytes, must be enough for null terminator
FLMUNICODE * puzSrcTagName, // May be NULL
FLMBOOL bTruncatedNamesOk)
{
RCODE rc = NE_FLM_OK;
FLMUINT uiDestCharCnt = *puiDestBufSize;
FLMUINT uiCharCnt;
if (puzDestTagName)
{
// Decrement name buffer size by sizeof( FLMUNICODE) to allow for a
// terminating NULL character. uiDestChars better be at least big
// enough for a null terminating character.
flmAssert( uiDestCharCnt >= sizeof( FLMUNICODE));
uiDestCharCnt /= sizeof( FLMUNICODE);
uiDestCharCnt--;
if (puzSrcTagName)
{
// Copy the name to the UNICODE buffer.
uiCharCnt = 0;
while (uiCharCnt < uiDestCharCnt && *puzSrcTagName)
{
*puzDestTagName++ = *puzSrcTagName;
uiCharCnt++;
puzSrcTagName++;
}
*puzDestTagName = 0;
*puiDestBufSize = uiCharCnt;
if (!bTruncatedNamesOk && *puzSrcTagName)
{
rc = RC_SET( NE_FLM_CONV_DEST_OVERFLOW);
goto Exit;
}
}
else
{
*puzDestTagName = 0;
*puiDestBufSize = 0;
}
}
else
{
// Decrement name buffer size by one to allow for a terminating
// 0 character. uiDestCharCnt better be at list big
// enough for a 0 terminating character.
flmAssert( uiDestCharCnt);
uiDestCharCnt--;
if (puzSrcTagName)
{
// Copy the name to the NATIVE buffer. Non-Ascii UNICODE characters
// will cause NE_FLM_CONV_ILLEGAL to be returned.
uiCharCnt = 0;
while (uiCharCnt < uiDestCharCnt && *puzSrcTagName)
{
if (*puzSrcTagName <= 0xFF)
{
*pszDestTagName++ =
(char)f_tonative( (FLMBYTE)*puzSrcTagName);
uiCharCnt++;
puzSrcTagName++;
}
else
{
rc = RC_SET( NE_FLM_CONV_ILLEGAL);
goto Exit;
}
}
*pszDestTagName = 0;
*puiDestBufSize = uiCharCnt;
if (!bTruncatedNamesOk && *puzSrcTagName)
{
rc = RC_SET( NE_FLM_CONV_DEST_OVERFLOW);
goto Exit;
}
}
else
{
*pszDestTagName = 0;
*puiDestBufSize = 0;
}
}
Exit:
return( rc);
}
/***************************************************************************
Desc: Swap two entries in tag info table during sort.
*****************************************************************************/
FINLINE void tagInfoSwap(
FLM_TAG_INFO * * ppTagInfoTbl,
FLMUINT uiPos1,
FLMUINT uiPos2
)
{
FLM_TAG_INFO * pTmpTagInfo = ppTagInfoTbl [uiPos1];
ppTagInfoTbl [uiPos1] = ppTagInfoTbl [uiPos2];
ppTagInfoTbl [uiPos2] = pTmpTagInfo;
}
/***************************************************************************
Desc: Comparison function for sorting by tag type and name.
****************************************************************************/
FSTATIC FLMINT compareTagTypeAndName(
FLM_TAG_INFO * pTagInfo1,
FLM_TAG_INFO * pTagInfo2)
{
FLMINT iCmp;
if (pTagInfo1->uiType < pTagInfo2->uiType)
{
return( -1);
}
else if (pTagInfo1->uiType > pTagInfo2->uiType)
{
return( 1);
}
else if ((iCmp = tagNameCompare( pTagInfo1->puzTagName, NULL,
pTagInfo2->puzTagName)) != 0)
{
return( iCmp);
}
else
{
return( tagNameCompare( pTagInfo1->puzNamespace, NULL,
pTagInfo2->puzNamespace));
}
}
/***************************************************************************
Desc: Comparison function for sorting by tag type and number.
****************************************************************************/
FSTATIC FLMINT compareTagTypeAndNum(
FLM_TAG_INFO * pTagInfo1,
FLM_TAG_INFO * pTagInfo2
)
{
if (pTagInfo1->uiType < pTagInfo2->uiType)
{
return( -1);
}
else if (pTagInfo1->uiType > pTagInfo2->uiType)
{
return( 1);
}
else if (pTagInfo1->uiTagNum < pTagInfo2->uiTagNum)
{
return( -1);
}
else if (pTagInfo1->uiTagNum > pTagInfo2->uiTagNum)
{
return( 1);
}
else
{
return( 0);
}
}
/***************************************************************************
Desc: Sort an array of SCACHE pointers by their block address.
****************************************************************************/
FSTATIC void sortTagTbl(
FLM_TAG_INFO * * ppTagInfoTbl,
FLMUINT uiLowerBounds,
FLMUINT uiUpperBounds,
TAG_COMPARE_FUNC fnTagCompare)
{
FLMUINT uiLBPos;
FLMUINT uiUBPos;
FLMUINT uiMIDPos;
FLMUINT uiLeftItems;
FLMUINT uiRightItems;
FLM_TAG_INFO * pCurTagInfo;
FLMINT iCompare;
Iterate_Larger_Half:
uiUBPos = uiUpperBounds;
uiLBPos = uiLowerBounds;
uiMIDPos = (uiUpperBounds + uiLowerBounds + 1) / 2;
pCurTagInfo = ppTagInfoTbl [uiMIDPos ];
for (;;)
{
while (uiLBPos == uiMIDPos || // Don't compare with target
((iCompare =
fnTagCompare( ppTagInfoTbl [uiLBPos], pCurTagInfo)) < 0))
{
if (uiLBPos >= uiUpperBounds)
{
break;
}
uiLBPos++;
}
while (uiUBPos == uiMIDPos || // Don't compare with target
(((iCompare =
fnTagCompare( pCurTagInfo, ppTagInfoTbl [uiUBPos])) < 0)))
{
if (!uiUBPos)
{
break;
}
uiUBPos--;
}
if (uiLBPos < uiUBPos ) // Interchange and continue loop.
{
// Exchange [uiLBPos] with [uiUBPos].
tagInfoSwap( ppTagInfoTbl, uiLBPos, uiUBPos);
uiLBPos++; // Scan from left to right.
uiUBPos--; // Scan from right to left.
}
else // Past each other - done
{
break;
}
}
// Check for swap( LB, MID ) - cases 3 and 4
if( uiLBPos < uiMIDPos )
{
// Exchange [uiLBPos] with [uiMIDPos]
tagInfoSwap( ppTagInfoTbl, uiMIDPos, uiLBPos);
uiMIDPos = uiLBPos;
}
else if( uiMIDPos < uiUBPos )
{
// Exchange [uUBPos] with [uiMIDPos]
tagInfoSwap( ppTagInfoTbl, uiMIDPos, uiUBPos);
uiMIDPos = uiUBPos;
}
// Check the left piece.
uiLeftItems = (uiLowerBounds + 1 < uiMIDPos )
? uiMIDPos - uiLowerBounds // 2 or more
: 0;
uiRightItems = (uiMIDPos + 1 < uiUpperBounds )
? uiUpperBounds - uiMIDPos // 2 or more
: 0;
if( uiLeftItems < uiRightItems )
{
// Recurse on the LEFT side and goto the top on the RIGHT side.
if (uiLeftItems )
{
sortTagTbl( ppTagInfoTbl, uiLowerBounds, uiMIDPos - 1, fnTagCompare);
}
uiLowerBounds = uiMIDPos + 1;
goto Iterate_Larger_Half;
}
else if (uiLeftItems ) // Compute a truth table to figure out this check.
{
// Recurse on the RIGHT side and goto the top for the LEFT side.
if (uiRightItems )
{
sortTagTbl( ppTagInfoTbl, uiMIDPos + 1, uiUpperBounds, fnTagCompare);
}
uiUpperBounds = uiMIDPos - 1;
goto Iterate_Larger_Half;
}
}
/****************************************************************************
Desc: Lookup a namespace - so we can reuse the memory.
****************************************************************************/
FLMUNICODE * F_NameTable::findNamespace(
FLMUNICODE * puzNamespace,
FLMUINT * puiInsertPos)
{
FLMUNICODE * puzFoundNamespace = NULL;
FLMUINT uiTblSize;
FLMUINT uiLow;
FLMUINT uiMid;
FLMUINT uiHigh;
FLMINT iCmp;
// Do binary search in the table
if ((uiTblSize = m_uiNumNamespaces) == 0)
{
if (puiInsertPos)
{
*puiInsertPos = 0;
}
goto Exit;
}
uiHigh = --uiTblSize;
uiLow = 0;
for (;;)
{
uiMid = (uiLow + uiHigh) / 2;
if ((iCmp = tagNameCompare( puzNamespace, NULL,
m_ppuzNamespaces [uiMid])) == 0)
{
// Found Match
puzFoundNamespace = m_ppuzNamespaces [uiMid];
if (puiInsertPos)
{
*puiInsertPos = uiMid;
}
goto Exit;
}
// Check if we are done
if (uiLow >= uiHigh)
{
// Done, item not found
if (puiInsertPos)
{
*puiInsertPos = (iCmp < 0)
? uiMid
: uiMid + 1;
}
goto Exit;
}
if (iCmp < 0)
{
if (uiMid == 0)
{
if (puiInsertPos)
{
*puiInsertPos = 0;
}
goto Exit;
}
uiHigh = uiMid - 1;
}
else
{
if (uiMid == uiTblSize)
{
if (puiInsertPos)
{
*puiInsertPos = uiMid + 1;
}
goto Exit;
}
uiLow = uiMid + 1;
}
}
Exit:
return( puzFoundNamespace);
}
/****************************************************************************
Desc: Insert a tag info structure into the sorted tables at the specified
positions.
****************************************************************************/
RCODE F_NameTable::insertNamespace(
FLMUNICODE * puzNamespace,
FLMUINT uiInsertPos)
{
RCODE rc = NE_FLM_OK;
FLMUINT uiLoop;
// See if we need to resize the table. Add 32 each time. There
// should not be that many different namespaces.
if (m_uiNumNamespaces == m_uiNamespaceTblSize)
{
FLMUINT uiNewSize = m_uiNamespaceTblSize + 32;
FLMUNICODE ** ppNewTbl;
if( RC_BAD( rc = f_alloc( sizeof( FLMUNICODE *) * uiNewSize, &ppNewTbl)))
{
goto Exit;
}
// Copy the old tables into the new.
if (m_uiNumNamespaces)
{
f_memcpy( ppNewTbl, m_ppuzNamespaces,
sizeof( FLMUNICODE *) * m_uiNumNamespaces);
f_free( &m_ppuzNamespaces);
}
m_ppuzNamespaces = ppNewTbl;
m_uiNamespaceTblSize = uiNewSize;
}
// Insert the new namespace into the table.
uiLoop = m_uiNumNamespaces;
while (uiLoop > uiInsertPos)
{
m_ppuzNamespaces [uiLoop] = m_ppuzNamespaces [uiLoop - 1];
uiLoop--;
}
m_ppuzNamespaces [uiInsertPos] = puzNamespace;
// Increment the total number of namespaces
m_uiNumNamespaces++;
Exit:
return( rc);
}
/****************************************************************************
Desc: Allocate a new tag info structure and set it up.
****************************************************************************/
RCODE F_NameTable::allocTag(
FLMUINT uiType,
FLMUNICODE * puzTagName,
const char * pszTagName,
FLMUINT uiTagNum,
FLMUINT uiDataType,
FLMUNICODE * puzNamespace,
FLM_TAG_INFO ** ppTagInfo)
{
RCODE rc = NE_FLM_OK;
void * pvMark;
FLMUINT uiSaveMemoryAllocated;
FLM_TAG_INFO * pTagInfo;
FLMUINT uiNameSize;
FLMUNICODE * puzTmp;
FLMUNICODE * puzTblNamespace;
FLMUINT uiNamespaceInsertPos;
// Create a new tag info structure.
pvMark = m_pPool->poolMark();
uiSaveMemoryAllocated = m_uiMemoryAllocated;
if (RC_BAD( rc = m_pPool->poolCalloc( sizeof( FLM_TAG_INFO),
(void **)&pTagInfo)))
{
goto Exit;
}
m_uiMemoryAllocated += sizeof( FLM_TAG_INFO);
// Allocate the space for the tag name.
if (puzTagName)
{
uiNameSize = (f_unilen( puzTagName) + 1) * sizeof( FLMUNICODE);
if (RC_BAD( rc = m_pPool->poolAlloc( uiNameSize,
(void **)&pTagInfo->puzTagName)))
{
goto Exit;
}
m_uiMemoryAllocated += uiNameSize;
f_memcpy( pTagInfo->puzTagName, puzTagName, uiNameSize);
}
else
{
uiNameSize = (f_strlen( pszTagName) + 1) * sizeof( FLMUNICODE);
if (RC_BAD( rc = m_pPool->poolAlloc( uiNameSize,
(void **)&pTagInfo->puzTagName)))
{
goto Exit;
}
m_uiMemoryAllocated += uiNameSize;
puzTmp = pTagInfo->puzTagName;
while (*pszTagName)
{
*puzTmp++ = (FLMUNICODE)*pszTagName;
pszTagName++;
}
*puzTmp = 0;
}
pTagInfo->uiType = uiType;
pTagInfo->uiTagNum = uiTagNum;
pTagInfo->uiDataType = uiDataType;
if (puzNamespace && *puzNamespace)
{
// See if we have already allocated the namespace. If so, just
// point to it. Otherwise, allocate it and add it to the
// namespace table and then point to it.
if ((puzTblNamespace = findNamespace( puzNamespace,
&uiNamespaceInsertPos)) == NULL)
{
uiNameSize = (f_unilen( puzNamespace) + 1) * sizeof( FLMUNICODE);
if (RC_BAD( rc = m_pPool->poolAlloc( uiNameSize,
(void **)&puzTblNamespace)))
{
goto Exit;
}
m_uiMemoryAllocated += uiNameSize;
f_memcpy( puzTblNamespace, puzNamespace, uiNameSize);
if (RC_BAD( rc = insertNamespace( puzTblNamespace,
uiNamespaceInsertPos)))
{
goto Exit;
}
// Need to re-mark the pool after this point, because
// we can now not afford to lose the namespace that was
// allocated if the pool is reset at Exit due to a later
// error.
pvMark = m_pPool->poolMark();
uiSaveMemoryAllocated = m_uiMemoryAllocated;
}
pTagInfo->puzNamespace = puzTblNamespace;
}
Exit:
if (RC_BAD( rc))
{
m_pPool->poolReset( pvMark);
m_uiMemoryAllocated = uiSaveMemoryAllocated;
pTagInfo = NULL;
}
*ppTagInfo = pTagInfo;
return( rc);
}
/****************************************************************************
Desc: Allocate the sort tables.
****************************************************************************/
RCODE F_NameTable::reallocSortTables(
FLMUINT uiNewTblSize)
{
RCODE rc = NE_FLM_OK;
FLM_TAG_INFO ** ppNewTbl;
if( RC_BAD( f_alloc(
sizeof( FLM_TAG_INFO *) * uiNewTblSize * 2, &ppNewTbl)))
{
goto Exit;
}
// Copy the old tables into the new.
if (m_uiNumTags)
{
f_memcpy( ppNewTbl, m_ppSortedByTagTypeAndName,
sizeof( FLM_TAG_INFO *) * m_uiNumTags);
f_memcpy( &ppNewTbl [uiNewTblSize],
m_ppSortedByTagTypeAndNum,
sizeof( FLM_TAG_INFO *) * m_uiNumTags);
f_free( &m_ppSortedByTagTypeAndName);
}
m_ppSortedByTagTypeAndName = ppNewTbl;
m_ppSortedByTagTypeAndNum = &ppNewTbl [uiNewTblSize];
m_uiTblSize = uiNewTblSize;
Exit:
return( rc);
}
/****************************************************************************
Desc: Get a tag name, number, etc. using type + tag number ordering.
Tag name is returned as a UNICODE string or NATIVE string. If a
non-NULL UNICODE string is passed in, it will be used.
Otherwise, the NATIVE string will be used.
****************************************************************************/
RCODE FLMAPI F_NameTable::getNextTagTypeAndNumOrder(
FLMUINT uiType,
FLMUINT * puiNextPos,
FLMUNICODE * puzTagName, // May be NULL
char * pszTagName, // May be NULL
FLMUINT uiNameBufSize,
FLMUINT * puiTagNum, // May be NULL
FLMUINT * puiDataType, // May be NULL
FLMUNICODE * puzNamespace, // May be NULL
FLMUINT uiNamespaceBufSize,
FLMBOOL bTruncatedNamesOk)
{
RCODE rc = NE_FLM_OK;
FLM_TAG_INFO * pTagInfo = NULL;
FLMBOOL bFound = FALSE;
if (!m_bTablesSorted)
{
sortTags();
}
while (*puiNextPos < m_uiNumTags)
{
pTagInfo = m_ppSortedByTagTypeAndNum [*puiNextPos];
if (pTagInfo->uiType == uiType)
{
bFound = TRUE;
if (puiTagNum)
{
*puiTagNum = pTagInfo->uiTagNum;
}
if( puzTagName || pszTagName)
{
if (RC_BAD( rc = copyTagName( puzTagName, pszTagName,
&uiNameBufSize,
pTagInfo->puzTagName, bTruncatedNamesOk)))
{
goto Exit;
}
}
if (puiDataType)
{
*puiDataType = pTagInfo->uiDataType;
}
if (puzNamespace)
{
if (RC_BAD( rc = copyTagName( puzNamespace, NULL,
&uiNamespaceBufSize,
pTagInfo->puzNamespace,
bTruncatedNamesOk)))
{
goto Exit;
}
}
// Returned *puiNextPos should be the next one to retrieve.
(*puiNextPos)++;
break;
}
else if (pTagInfo->uiType > uiType)
{
break;
}
else
{
(*puiNextPos)++;
}
}
if (!bFound)
{
rc = RC_SET( NE_FLM_EOF_HIT);
goto Exit;
}
Exit:
return( rc);
}
/****************************************************************************
Desc: Get a tag name, number, etc. using type + tag name ordering.
Tag name is returned as a UNICODE string or NATIVE string. If a
non-NULL UNICODE string is passed in, it will be used.
Otherwise, the NATIVE string will be used.
****************************************************************************/
RCODE FLMAPI F_NameTable::getNextTagTypeAndNameOrder(
FLMUINT uiType,
FLMUINT * puiNextPos,
FLMUNICODE * puzTagName, // May be NULL
char * pszTagName, // May be NULL
FLMUINT uiNameBufSize,
FLMUINT * puiTagNum, // May be NULL
FLMUINT * puiDataType, // May be NULL
FLMUNICODE * puzNamespace, // May be NULL
FLMUINT uiNamespaceBufSize,
FLMBOOL bTruncatedNamesOk)
{
RCODE rc = NE_FLM_OK;
FLM_TAG_INFO * pTagInfo = NULL;
FLMBOOL bFound = FALSE;
if (!m_bTablesSorted)
{
sortTags();
}
while (*puiNextPos < m_uiNumTags)
{
pTagInfo = m_ppSortedByTagTypeAndName [*puiNextPos];
if (pTagInfo->uiType == uiType)
{
bFound = TRUE;
if (puiTagNum)
{
*puiTagNum = pTagInfo->uiTagNum;
}
if (puzTagName || pszTagName)
{
if (RC_BAD( rc = copyTagName( puzTagName, pszTagName,
&uiNameBufSize, pTagInfo->puzTagName,
bTruncatedNamesOk)))
{
goto Exit;
}
}
if (puiDataType)
{
*puiDataType = pTagInfo->uiDataType;
}
if (puzNamespace)
{
if (RC_BAD( rc = copyTagName( puzNamespace, NULL,
&uiNamespaceBufSize,
pTagInfo->puzNamespace,
bTruncatedNamesOk)))
{
goto Exit;
}
}
// Returned *puiNextPos should be the next one to retrieve.
(*puiNextPos)++;
break;
}
else if (pTagInfo->uiType > uiType)
{
break;
}
else
{
(*puiNextPos)++;
}
}
if (!bFound)
{
rc = RC_SET( NE_FLM_EOF_HIT);
goto Exit;
}
Exit:
return( rc);
}
/****************************************************************************
Desc: Get a tag name from its tag type and number. Tag name is returned as a
UNICODE string or NATIVE string. If a non-NULL UNICODE string is passed
in, it will be used. Otherwise, the NATIVE string will be used.
****************************************************************************/
RCODE FLMAPI F_NameTable::getFromTagTypeAndNum(
FLMUINT uiType,
FLMUINT uiTagNum,
FLMUNICODE * puzTagName, // May be NULL
char * pszTagName, // May be NULL
FLMUINT * puiNameBufSize, // May be NULL, returns # characters
FLMUINT * puiDataType, // May be NULL
FLMUNICODE * puzNamespace, // May be NULL
char * pszNamespace, // May be NULL
FLMUINT * puiNamespaceBufSize, // May be NULL, returns # characters
FLMBOOL bTruncatedNamesOk)
{
RCODE rc = NE_FLM_OK;
FLM_TAG_INFO * pTagInfo;
FLMUNICODE * puzTmpNamespace = NULL;
FLMUNICODE * puzTmpName = NULL;
if ((pTagInfo = findTagByTypeAndNum( uiType, uiTagNum)) != NULL)
{
if( puzTagName || pszTagName)
{
if (RC_BAD( rc = copyTagName( puzTagName, pszTagName,
puiNameBufSize,
pTagInfo->puzTagName, bTruncatedNamesOk)))
{
goto Exit;
}
}
else if (puiNameBufSize)
{
*puiNameBufSize = f_unilen( pTagInfo->puzTagName);
}
if (puiDataType)
{
*puiDataType = pTagInfo->uiDataType;
}
if (puzNamespace || pszNamespace)
{
if (RC_BAD( rc = copyTagName( puzNamespace, pszNamespace,
puiNamespaceBufSize,
pTagInfo->puzNamespace,
bTruncatedNamesOk)))
{
goto Exit;
}
}
else if (puiNamespaceBufSize)
{
*puiNamespaceBufSize = f_unilen( pTagInfo->puzNamespace);
}
}
else
{
rc = RC_SET( NE_FLM_NOT_FOUND);
goto Exit;
}
Exit:
if (puzTmpName)
{
f_free( &puzTmpName);
}
if (puzTmpNamespace)
{
f_free( &puzTmpNamespace);
}
return( rc);
}
/****************************************************************************
Desc: Get a tag number from its tag name and type. Tag name is passed
in as a UNICODE or NATIVE string. If a non-NULL UNICODE string is
passed in, it will be used. Otherwise, the NATIVE string will
be used.
****************************************************************************/
RCODE FLMAPI F_NameTable::getFromTagTypeAndName(
FLMUINT uiType,
const FLMUNICODE * puzTagName,
const char * pszTagName,
FLMBOOL bMatchNamespace,
const FLMUNICODE * puzNamespace,
FLMUINT * puiTagNum, // May be NULL
FLMUINT * puiDataType) // May be NULL
{
RCODE rc = NE_FLM_OK;
FLM_TAG_INFO * pTagInfo;
FLMBOOL bAmbiguous;
if ((pTagInfo = findTagByTypeAndName( uiType,
puzTagName, pszTagName, bMatchNamespace,
puzNamespace,
&bAmbiguous)) != NULL)
{
if (puiTagNum)
{
*puiTagNum = pTagInfo->uiTagNum;
}
if (puiDataType)
{
*puiDataType = pTagInfo->uiDataType;
}
if (bAmbiguous)
{
rc = RC_SET( NE_FLM_MULTIPLE_MATCHES);
goto Exit;
}
}
else
{
rc = RC_SET( NE_FLM_NOT_FOUND);
goto Exit;
}
Exit:
return( rc);
}
/****************************************************************************
Desc: Insert a tag info structure into the sorted tables at the specified
positions.
****************************************************************************/
RCODE F_NameTable::insertTagInTables(
FLM_TAG_INFO * pTagInfo,
FLMUINT uiTagTypeAndNameTblInsertPos,
FLMUINT uiTagTypeAndNumTblInsertPos)
{
RCODE rc = NE_FLM_OK;
FLMUINT uiLoop;
// See if we need to resize the tables. Start at 256. Double each
// time up to 2048. Then just add 2048 at a time.
if (m_uiNumTags == m_uiTblSize)
{
FLMUINT uiNewSize;
if (!m_uiTblSize)
{
uiNewSize = 256;
}
else if (m_uiTblSize < 2048)
{
uiNewSize = m_uiTblSize * 2;
}
else
{
uiNewSize = m_uiTblSize + 2048;
}
if (RC_BAD( rc = reallocSortTables( uiNewSize)))
{
goto Exit;
}
}
// Insert into the sorted-by-tag-type-and-name table
uiLoop = m_uiNumTags;
while (uiLoop > uiTagTypeAndNameTblInsertPos)
{
m_ppSortedByTagTypeAndName [uiLoop] =
m_ppSortedByTagTypeAndName [uiLoop - 1];
uiLoop--;
}
m_ppSortedByTagTypeAndName [uiTagTypeAndNameTblInsertPos] = pTagInfo;
// Insert into the sorted-by-tag-type-and-num table
uiLoop = m_uiNumTags;
while (uiLoop > uiTagTypeAndNumTblInsertPos)
{
m_ppSortedByTagTypeAndNum [uiLoop] =
m_ppSortedByTagTypeAndNum [uiLoop - 1];
uiLoop--;
}
m_ppSortedByTagTypeAndNum [uiTagTypeAndNumTblInsertPos] = pTagInfo;
// Increment the total number of tags
m_uiNumTags++;
Exit:
return( rc);
}
/****************************************************************************
Desc: Add a tag to the table. Tag name is passed in as a UNICODE string or
NATIVE string. If a non-NULL UNICODE string is passed in, it will
be used. Otherwise, the NATIVE string will be used.
****************************************************************************/
RCODE FLMAPI F_NameTable::addTag(
FLMUINT uiType,
FLMUNICODE * puzTagName,
const char * pszTagName,
FLMUINT uiTagNum,
FLMUINT uiDataType,
FLMUNICODE * puzNamespace,
FLMBOOL bCheckDuplicates)
{
RCODE rc = NE_FLM_OK;
FLMUINT uiTagTypeAndNameTblInsertPos;
FLMUINT uiTagTypeAndNumTblInsertPos;
FLM_TAG_INFO * pTagInfo;
FLMBOOL bAmbiguous;
// Must have a non-NULL tag name. Use UNICODE string if it is
// non-NULL. Otherwise, use NATIVE string.
if (puzTagName && *puzTagName)
{
pszTagName = NULL;
}
else if (pszTagName && *pszTagName)
{
puzTagName = NULL;
}
else
{
rc = RC_SET_AND_ASSERT( NE_FLM_INVALID_PARM);
goto Exit;
}
// Tag number of zero not allowed.
if (!uiTagNum)
{
rc = RC_SET_AND_ASSERT( NE_FLM_INVALID_PARM);
goto Exit;
}
// Tables must be sorted in order for this to work
if (bCheckDuplicates)
{
// Make sure that the tag type + name is not already used.
if (findTagByTypeAndName( uiType, puzTagName, pszTagName,
TRUE, puzNamespace,
&bAmbiguous, &uiTagTypeAndNameTblInsertPos))
{
rc = RC_SET( NE_FLM_EXISTS);
goto Exit;
}
// Make sure that the tag type + number is not already used.
if (findTagByTypeAndNum( uiType, uiTagNum,
&uiTagTypeAndNumTblInsertPos))
{
rc = RC_SET( NE_FLM_EXISTS);
goto Exit;
}
}
else
{
uiTagTypeAndNameTblInsertPos = uiTagTypeAndNumTblInsertPos = m_uiNumTags;
m_bTablesSorted = FALSE;
}
// Create a new tag info structure.
if (RC_BAD( rc = allocTag( uiType, puzTagName, pszTagName, uiTagNum,
uiDataType, puzNamespace, &pTagInfo)))
{
goto Exit;
}
// Insert the tag structure into the appropriate places in the
// sorted tables.
if (RC_BAD( rc = insertTagInTables( pTagInfo,
uiTagTypeAndNameTblInsertPos,
uiTagTypeAndNumTblInsertPos)))
{
goto Exit;
}
Exit:
return( rc);
}
/****************************************************************************
Desc: Sort the tag tables according to their respective criteria.
****************************************************************************/
void F_NameTable::sortTags( void)
{
if (!m_bTablesSorted && m_uiNumTags > 1)
{
sortTagTbl( m_ppSortedByTagTypeAndName, 0, m_uiNumTags - 1,
compareTagTypeAndName);
sortTagTbl( m_ppSortedByTagTypeAndNum, 0, m_uiNumTags - 1,
compareTagTypeAndNum);
}
m_bTablesSorted = TRUE;
}
/****************************************************************************
Desc: Remove a tag from the table
****************************************************************************/
void FLMAPI F_NameTable::removeTag(
FLMUINT uiType,
FLMUINT uiTagNum)
{
FLM_TAG_INFO * pTagInfo;
FLMUINT uiTagTypeAndNameTblPos;
FLMUINT uiTagTypeAndNumTblPos;
FLMBOOL bAmbiguous;
FLMBOOL bMatchNamespace;
FLMUNICODE * puzNamespace;
if ((pTagInfo = findTagByTypeAndNum( uiType, uiTagNum,
&uiTagTypeAndNumTblPos)) != NULL)
{
puzNamespace = pTagInfo->puzNamespace;
bMatchNamespace = TRUE;
if (findTagByTypeAndName( uiType, pTagInfo->puzTagName,
NULL, bMatchNamespace,
puzNamespace, &bAmbiguous,
&uiTagTypeAndNameTblPos) == NULL)
{
// It should have been in the name table too!
flmAssert( 0);
}
// Shift everything in the sorted number table that is above
// the found position down one.
if (uiTagTypeAndNumTblPos < m_uiNumTags - 1)
{
f_memmove( &m_ppSortedByTagTypeAndNum [uiTagTypeAndNumTblPos],
&m_ppSortedByTagTypeAndNum [uiTagTypeAndNumTblPos + 1],
sizeof( FLM_TAG_INFO *) *
(m_uiNumTags - 1 - uiTagTypeAndNumTblPos));
}
// Shift everything in the sorted name table that is above
// the found position down one.
if (uiTagTypeAndNameTblPos < m_uiNumTags - 1)
{
f_memmove( &m_ppSortedByTagTypeAndName [uiTagTypeAndNameTblPos],
&m_ppSortedByTagTypeAndName [uiTagTypeAndNameTblPos + 1],
sizeof( FLM_TAG_INFO *) *
(m_uiNumTags - 1 - uiTagTypeAndNameTblPos));
}
m_uiNumTags--;
}
}
/****************************************************************************
Desc: Clone a name table from another one
****************************************************************************/
#if 0
RCODE FLMAPI F_NameTable::cloneNameTable(
IF_NameTable * pSrcNameTable)
{
RCODE rc = NE_FLM_OK;
FLMUINT uiLoop;
FLM_TAG_INFO * pTagInfo;
FLMUINT uiPoolBlkSize;
// Set the pool size to be as optimal as possible.
uiPoolBlkSize = pSrcNameTable->m_uiMemoryAllocated / 8;
if (uiPoolBlkSize < 1024)
{
uiPoolBlkSize = 1024;
}
else if (uiPoolBlkSize > 65536)
{
uiPoolBlkSize = 65536;
}
clearTable( uiPoolBlkSize);
// Pre-allocate exactly enough table space
if (RC_BAD( rc = reallocSortTables( pSrcNameTable->m_uiNumTags)))
{
goto Exit;
}
// Add all of the tags
for (uiLoop = 0; uiLoop < pSrcNameTable->m_uiNumTags; uiLoop++)
{
pTagInfo = pSrcNameTable->m_ppSortedByTagTypeAndNum [uiLoop];
if (RC_BAD( rc = addTag( pTagInfo->uiType, pTagInfo->puzTagName, NULL,
pTagInfo->uiTagNum,
pTagInfo->uiDataType,
pTagInfo->puzNamespace, FALSE)))
{
goto Exit;
}
}
sortTags();
Exit:
return( rc);
}
#endif
/****************************************************************************
Desc: Copy a name table from another one. This differs from cloneNameTable
in that it doesn't clear the name table, it just copies the names.
Thus, the destination name table may already have names in it, and the
names from the source table will just be added.
****************************************************************************/
#if 0
RCODE FLMAPI F_NameTable::importFromNameTable(
IF_NameTable * pSrcNameTable)
{
RCODE rc = NE_FLM_OK;
FLMUINT uiLoop;
FLM_TAG_INFO * pTagInfo;
// Pre-allocate exactly enough table space
if (RC_BAD( rc = reallocSortTables( m_uiNumTags +
pSrcNameTable->m_uiNumTags)))
{
goto Exit;
}
// Add all of the tags from the source table
for (uiLoop = 0; uiLoop < pSrcNameTable->m_uiNumTags; uiLoop++)
{
pTagInfo = pSrcNameTable->m_ppSortedByTagTypeAndNum [uiLoop];
if (RC_BAD( rc = addTag( pTagInfo->uiType, pTagInfo->puzTagName, NULL,
pTagInfo->uiTagNum,
pTagInfo->uiDataType,
pTagInfo->puzNamespace, FALSE)))
{
if (rc != NE_FLM_EXISTS)
{
goto Exit;
}
else
{
rc = NE_FLM_OK;
}
}
}
sortTags();
Exit:
return( rc);
}
#endif
/****************************************************************************
Desc: Increment use count on this object.
****************************************************************************/
FLMINT FLMAPI F_NameTable::AddRef( void)
{
return( f_atomicInc( &m_refCnt));
}
/****************************************************************************
Desc: Decrement the use count and delete if use count goes to zero.
****************************************************************************/
FLMINT FLMAPI F_NameTable::Release( void)
{
FLMINT iRefCnt;
if ((iRefCnt = f_atomicDec( &m_refCnt)) == 0)
{
delete this;
}
return( iRefCnt);
}