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

2567 lines
60 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 "flaimsys.h"
#define MAX_ELEMENTS_TO_LOAD 0xFFFF
#define MAX_ATTRIBUTES_TO_LOAD 0xFFFF
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 RCODE findTagName(
F_Db * pDb,
FLMUINT uiType,
const FLMUNICODE * puzTagName,
const char * pszTagName,
F_DataVector * pSrchKey,
FLMUINT * puiDictNum,
FLMUINT64 * pui64DocumentID);
FLMUNICODE gv_uzXFLAIMNamespace[] = // http://www.novell.com/XMLDatabase/Schema
{ 'h','t','t','p',':','/','/','w','w','w','.','n','o','v','e','l','l','.','c','o','m','/',
'X','M','L','D','a','t','a','b','a','s','e','/','S','c','h','e','m','a', 0};
RESERVED_TAG_NAME FlmReservedElementTags[] =
{
{ELM_ELEMENT_TAG_NAME, ELM_ELEMENT_TAG, XFLM_NODATA_TYPE, gv_uzXFLAIMNamespace},
{ELM_ATTRIBUTE_TAG_NAME, ELM_ATTRIBUTE_TAG, XFLM_NODATA_TYPE, gv_uzXFLAIMNamespace},
{ELM_INDEX_TAG_NAME, ELM_INDEX_TAG, XFLM_NODATA_TYPE, gv_uzXFLAIMNamespace},
{ELM_ELEMENT_COMPONENT_TAG_NAME, ELM_ELEMENT_COMPONENT_TAG, XFLM_NODATA_TYPE, gv_uzXFLAIMNamespace},
{ELM_ATTRIBUTE_COMPONENT_TAG_NAME, ELM_ATTRIBUTE_COMPONENT_TAG, XFLM_NODATA_TYPE, gv_uzXFLAIMNamespace},
{ELM_COLLECTION_TAG_NAME, ELM_COLLECTION_TAG, XFLM_NODATA_TYPE, gv_uzXFLAIMNamespace},
{ELM_PREFIX_TAG_NAME, ELM_PREFIX_TAG, XFLM_NODATA_TYPE, gv_uzXFLAIMNamespace},
{ELM_NEXT_DICT_NUMS_TAG_NAME, ELM_NEXT_DICT_NUMS_TAG, XFLM_NODATA_TYPE, gv_uzXFLAIMNamespace},
{ELM_DOCUMENT_TITLE_TAG_NAME, ELM_DOCUMENT_TITLE_TAG, XFLM_TEXT_TYPE, gv_uzXFLAIMNamespace},
{ELM_INVALID_TAG_NAME, ELM_INVALID_TAG, XFLM_NODATA_TYPE, gv_uzXFLAIMNamespace},
{ELM_QUARANTINED_TAG_NAME, ELM_QUARANTINED_TAG, XFLM_TEXT_TYPE, gv_uzXFLAIMNamespace},
{ELM_ALL_TAG_NAME, ELM_ALL_TAG, XFLM_NODATA_TYPE, gv_uzXFLAIMNamespace},
{ELM_ANNOTATION_TAG_NAME, ELM_ANNOTATION_TAG, XFLM_NODATA_TYPE, gv_uzXFLAIMNamespace},
{ELM_ANY_TAG_NAME, ELM_ANY_TAG, XFLM_NODATA_TYPE, gv_uzXFLAIMNamespace},
{ELM_ATTRIBUTE_GROUP_TAG_NAME, ELM_ATTRIBUTE_GROUP_TAG, XFLM_NODATA_TYPE, gv_uzXFLAIMNamespace},
{ELM_CHOICE_TAG_NAME, ELM_CHOICE_TAG, XFLM_NODATA_TYPE, gv_uzXFLAIMNamespace},
{ELM_COMPLEX_CONTENT_TAG_NAME, ELM_COMPLEX_CONTENT_TAG, XFLM_NODATA_TYPE, gv_uzXFLAIMNamespace},
{ELM_COMPLEX_TYPE_TAG_NAME, ELM_COMPLEX_TYPE_TAG, XFLM_NODATA_TYPE, gv_uzXFLAIMNamespace},
{ELM_DOCUMENTATION_TAG_NAME, ELM_DOCUMENTATION_TAG, XFLM_NODATA_TYPE, gv_uzXFLAIMNamespace},
{ELM_ENUMERATION_TAG_NAME, ELM_ENUMERATION_TAG, XFLM_NODATA_TYPE, gv_uzXFLAIMNamespace},
{ELM_EXTENSION_TAG_NAME, ELM_EXTENSION_TAG, XFLM_NODATA_TYPE, gv_uzXFLAIMNamespace},
{ELM_DELETE_TAG_NAME, ELM_DELETE_TAG, XFLM_TEXT_TYPE, gv_uzXFLAIMNamespace},
{ELM_BLOCK_CHAIN_TAG_NAME, ELM_BLOCK_CHAIN_TAG, XFLM_TEXT_TYPE, gv_uzXFLAIMNamespace},
{ELM_ENCDEF_TAG_NAME, ELM_ENCDEF_TAG, XFLM_TEXT_TYPE, gv_uzXFLAIMNamespace},
{ELM_SWEEP_TAG_NAME, ELM_SWEEP_TAG, XFLM_TEXT_TYPE, gv_uzXFLAIMNamespace},
{NULL, 0, 0, NULL}
};
RESERVED_TAG_NAME FlmReservedAttributeTags[] =
{
{ATTR_DICT_NUMBER_TAG_NAME, ATTR_DICT_NUMBER_TAG, XFLM_NUMBER_TYPE, gv_uzXFLAIMNamespace},
{ATTR_COLLECTION_NUMBER_TAG_NAME, ATTR_COLLECTION_NUMBER_TAG, XFLM_NUMBER_TYPE, gv_uzXFLAIMNamespace},
{ATTR_COLLECTION_NAME_TAG_NAME, ATTR_COLLECTION_NAME_TAG, XFLM_TEXT_TYPE, gv_uzXFLAIMNamespace},
{ATTR_NAME_TAG_NAME, ATTR_NAME_TAG, XFLM_TEXT_TYPE, gv_uzXFLAIMNamespace},
{ATTR_TARGET_NAMESPACE_TAG_NAME, ATTR_TARGET_NAMESPACE_TAG, XFLM_TEXT_TYPE, gv_uzXFLAIMNamespace},
{ATTR_TYPE_TAG_NAME, ATTR_TYPE_TAG, XFLM_TEXT_TYPE, gv_uzXFLAIMNamespace},
{ATTR_STATE_TAG_NAME, ATTR_STATE_TAG, XFLM_TEXT_TYPE, gv_uzXFLAIMNamespace},
{ATTR_LANGUAGE_TAG_NAME, ATTR_LANGUAGE_TAG, XFLM_TEXT_TYPE, gv_uzXFLAIMNamespace},
{ATTR_INDEX_OPTIONS_TAG_NAME, ATTR_INDEX_OPTIONS_TAG, XFLM_TEXT_TYPE, gv_uzXFLAIMNamespace},
{ATTR_INDEX_ON_TAG_NAME, ATTR_INDEX_ON_TAG, XFLM_TEXT_TYPE, gv_uzXFLAIMNamespace},
{ATTR_REQUIRED_TAG_NAME, ATTR_REQUIRED_TAG, XFLM_TEXT_TYPE, gv_uzXFLAIMNamespace},
{ATTR_LIMIT_TAG_NAME, ATTR_LIMIT_TAG, XFLM_NUMBER_TYPE, gv_uzXFLAIMNamespace},
{ATTR_COMPARE_RULES_TAG_NAME, ATTR_COMPARE_RULES_TAG, XFLM_TEXT_TYPE, gv_uzXFLAIMNamespace},
{ATTR_KEY_COMPONENT_TAG_NAME, ATTR_KEY_COMPONENT_TAG, XFLM_NUMBER_TYPE, gv_uzXFLAIMNamespace},
{ATTR_DATA_COMPONENT_TAG_NAME, ATTR_DATA_COMPONENT_TAG, XFLM_NUMBER_TYPE, gv_uzXFLAIMNamespace},
{ATTR_LAST_DOC_INDEXED_TAG_NAME, ATTR_LAST_DOC_INDEXED_TAG, XFLM_NUMBER_TYPE, gv_uzXFLAIMNamespace},
{ATTR_NEXT_ELEMENT_NUM_TAG_NAME, ATTR_NEXT_ELEMENT_NUM_TAG, XFLM_NUMBER_TYPE, gv_uzXFLAIMNamespace},
{ATTR_NEXT_ATTRIBUTE_NUM_TAG_NAME, ATTR_NEXT_ATTRIBUTE_NUM_TAG, XFLM_NUMBER_TYPE, gv_uzXFLAIMNamespace},
{ATTR_NEXT_INDEX_NUM_TAG_NAME, ATTR_NEXT_INDEX_NUM_TAG, XFLM_NUMBER_TYPE, gv_uzXFLAIMNamespace},
{ATTR_NEXT_COLLECTION_NUM_TAG_NAME, ATTR_NEXT_COLLECTION_NUM_TAG, XFLM_NUMBER_TYPE, gv_uzXFLAIMNamespace},
{ATTR_NEXT_PREFIX_NUM_TAG_NAME, ATTR_NEXT_PREFIX_NUM_TAG, XFLM_NUMBER_TYPE, gv_uzXFLAIMNamespace},
{ATTR_SOURCE_TAG_NAME, ATTR_SOURCE_TAG, XFLM_TEXT_TYPE, gv_uzXFLAIMNamespace},
{ATTR_STATE_CHANGE_COUNT_TAG_NAME, ATTR_STATE_CHANGE_COUNT_TAG, XFLM_NUMBER_TYPE, gv_uzXFLAIMNamespace},
{ATTR_XMLNS_TAG_NAME, ATTR_XMLNS_TAG, XFLM_TEXT_TYPE, NULL},
{ATTR_ABSTRACT_TAG_NAME, ATTR_ABSTRACT_TAG, XFLM_TEXT_TYPE, gv_uzXFLAIMNamespace},
{ATTR_BASE_TAG_NAME, ATTR_BASE_TAG, XFLM_TEXT_TYPE, gv_uzXFLAIMNamespace},
{ATTR_BLOCK_TAG_NAME, ATTR_BLOCK_TAG, XFLM_TEXT_TYPE, gv_uzXFLAIMNamespace},
{ATTR_DEFAULT_TAG_NAME, ATTR_DEFAULT_TAG, XFLM_TEXT_TYPE, gv_uzXFLAIMNamespace},
{ATTR_FINAL_TAG_NAME, ATTR_FINAL_TAG, XFLM_TEXT_TYPE, gv_uzXFLAIMNamespace},
{ATTR_FIXED_TAG_NAME, ATTR_FIXED_TAG, XFLM_TEXT_TYPE, gv_uzXFLAIMNamespace},
{ATTR_ITEM_TYPE_TAG_NAME, ATTR_ITEM_TYPE_TAG, XFLM_TEXT_TYPE, gv_uzXFLAIMNamespace},
{ATTR_MEMBER_TYPES_TAG_NAME, ATTR_MEMBER_TYPES_TAG, XFLM_TEXT_TYPE, gv_uzXFLAIMNamespace},
{ATTR_MIXED_TAG_NAME, ATTR_MIXED_TAG, XFLM_TEXT_TYPE, gv_uzXFLAIMNamespace},
{ATTR_NILLABLE_TAG_NAME, ATTR_NILLABLE_TAG, XFLM_TEXT_TYPE, gv_uzXFLAIMNamespace},
{ATTR_REF_TAG_NAME, ATTR_REF_TAG, XFLM_TEXT_TYPE, gv_uzXFLAIMNamespace},
{ATTR_USE_TAG_NAME, ATTR_USE_TAG, XFLM_TEXT_TYPE, gv_uzXFLAIMNamespace},
{ATTR_VALUE_TAG_NAME, ATTR_VALUE_TAG, XFLM_TEXT_TYPE, gv_uzXFLAIMNamespace},
{ATTR_ADDRESS_TAG_NAME, ATTR_ADDRESS_TAG, XFLM_TEXT_TYPE, gv_uzXFLAIMNamespace},
{ATTR_XMLNS_XFLAIM_TAG_NAME, ATTR_XMLNS_XFLAIM_TAG, XFLM_TEXT_TYPE, NULL},
{ATTR_ENCRYPTION_KEY_TAG_NAME, ATTR_ENCRYPTION_KEY_TAG, XFLM_BINARY_TYPE, gv_uzXFLAIMNamespace},
{ATTR_TRANSACTION_TAG_NAME, ATTR_TRANSACTION_TAG, XFLM_NUMBER_TYPE, gv_uzXFLAIMNamespace},
{ATTR_NEXT_ENCDEF_NUM_TAG_NAME, ATTR_NEXT_ENCDEF_NUM_TAG, XFLM_NUMBER_TYPE, gv_uzXFLAIMNamespace},
{ATTR_ENCRYPTION_ID_TAG_NAME, ATTR_ENCRYPTION_ID_TAG, XFLM_NUMBER_TYPE, gv_uzXFLAIMNamespace},
{ATTR_ENCRYPTION_KEY_SIZE_TAG_NAME, ATTR_ENCRYPTION_KEY_SIZE_TAG, XFLM_NUMBER_TYPE, gv_uzXFLAIMNamespace},
{ATTR_UNIQUE_SUB_ELEMENTS_TAG_NAME, ATTR_UNIQUE_SUB_ELEMENTS_TAG, XFLM_TEXT_TYPE, gv_uzXFLAIMNamespace},
{NULL, 0, 0, NULL}
};
FSTATIC void sortTagTbl(
FLM_TAG_INFO * * ppTagInfoTbl,
FLMUINT uiLowerBounds,
FLMUINT uiUpperBounds,
TAG_COMPARE_FUNC fnTagCompare);
/****************************************************************************
Desc: Constructor
****************************************************************************/
F_NameTable::F_NameTable()
{
m_pool.poolInit( 1024);
m_uiMemoryAllocated = 0;
m_ppSortedByTagTypeAndName = NULL;
m_ppSortedByTagTypeAndNum = NULL;
m_uiTblSize = 0;
m_uiNumTags = 0;
m_bTablesSorted = FALSE;
// The m_bLoadedAllElements will be set to FALSE if we call addTag and
// there is no more room for elements. Same for m_bLoadedAllAttributes
// with respect to attributes.
m_bLoadedAllElements = TRUE;
m_bLoadedAllAttributes = TRUE;
m_uiNumElementsLoaded = 0;
m_uiNumAttributesLoaded = 0;
m_ppuzNamespaces = NULL;
m_uiNamespaceTblSize = 0;
m_uiNumNamespaces = 0;
}
/****************************************************************************
Desc: Destructor
****************************************************************************/
F_NameTable::~F_NameTable()
{
clearTable( 0);
}
/****************************************************************************
Desc: Setup name table. This routine should be called immediately after
the object is allocated.
****************************************************************************/
RCODE F_NameTable::setupNameTable( void)
{
return( NE_XFLM_OK);
}
/****************************************************************************
Desc: Free everything in the table
****************************************************************************/
void F_NameTable::clearTable(
FLMUINT uiPoolBlkSize)
{
m_pool.poolFree();
if (uiPoolBlkSize)
{
m_pool.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;
m_bLoadedAllElements = TRUE;
m_bLoadedAllAttributes = TRUE;
m_uiNumElementsLoaded = 0;
m_uiNumAttributesLoaded = 0;
}
/****************************************************************************
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)
{
// Elements and attributes need to also compare namespace
if (uiType == ELM_ELEMENT_TAG || uiType == ELM_ATTRIBUTE_TAG)
{
// If the bMatchNamespace flag is FALSE, only search on
// name. If there are multiple elements or attributes
// with the same name, return an ambiguous flag.
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_XFLM_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_XFLM_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_XFLM_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_XFLM_CONV_ILLEGAL);
goto Exit;
}
}
*pszDestTagName = 0;
*puiDestBufSize = uiCharCnt;
if (!bTruncatedNamesOk && *puzSrcTagName)
{
rc = RC_SET( NE_XFLM_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 if (pTagInfo1->uiType == ELM_ELEMENT_TAG ||
pTagInfo1->uiType == ELM_ATTRIBUTE_TAG)
{
return( tagNameCompare( pTagInfo1->puzNamespace, NULL,
pTagInfo2->puzNamespace));
}
else
{
return( 0);
}
}
/***************************************************************************
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_XFLM_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_XFLM_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_pool.poolMark();
uiSaveMemoryAllocated = m_uiMemoryAllocated;
if (RC_BAD( rc = m_pool.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_pool.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_pool.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;
// If this is an element or attribute, set namespace and data type
if (uiType == ELM_ELEMENT_TAG || uiType == ELM_ATTRIBUTE_TAG)
{
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_pool.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_pool.poolMark();
uiSaveMemoryAllocated = m_uiMemoryAllocated;
}
pTagInfo->puzNamespace = puzTblNamespace;
}
}
Exit:
if (RC_BAD( rc))
{
m_pool.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_XFLM_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: Add the reserved dictionary tags to the name table.
****************************************************************************/
RCODE F_NameTable::addReservedDictTags( void)
{
RCODE rc = NE_XFLM_OK;
FLMUINT uiLoop;
for (uiLoop = 0; FlmReservedElementTags [uiLoop].pszTagName; uiLoop++)
{
if (RC_BAD( rc = addTag( ELM_ELEMENT_TAG, NULL,
FlmReservedElementTags [uiLoop].pszTagName,
FlmReservedElementTags [uiLoop].uiTagNum,
FlmReservedElementTags [uiLoop].uiDataType,
FlmReservedElementTags [uiLoop].puzNamespace, FALSE, FALSE)))
{
goto Exit;
}
}
for (uiLoop = 0; FlmReservedAttributeTags [uiLoop].pszTagName; uiLoop++)
{
if (RC_BAD( rc = addTag( ELM_ATTRIBUTE_TAG, NULL,
FlmReservedAttributeTags [uiLoop].pszTagName,
FlmReservedAttributeTags [uiLoop].uiTagNum,
FlmReservedAttributeTags [uiLoop].uiDataType,
FlmReservedAttributeTags [uiLoop].puzNamespace, FALSE, FALSE)))
{
goto Exit;
}
}
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 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_XFLM_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 (uiType == ELM_ELEMENT_TAG || uiType == ELM_ATTRIBUTE_TAG)
{
if (puiDataType)
{
*puiDataType = pTagInfo->uiDataType;
}
if (puzNamespace)
{
if (RC_BAD( rc = copyTagName( puzNamespace, NULL,
&uiNamespaceBufSize,
pTagInfo->puzNamespace,
bTruncatedNamesOk)))
{
goto Exit;
}
}
}
else
{
flmAssert( !puiDataType && !puzNamespace);
}
// 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_XFLM_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 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_XFLM_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 (uiType == ELM_ELEMENT_TAG || uiType == ELM_ATTRIBUTE_TAG)
{
if (puiDataType)
{
*puiDataType = pTagInfo->uiDataType;
}
if (puzNamespace)
{
if (RC_BAD( rc = copyTagName( puzNamespace, NULL,
&uiNamespaceBufSize,
pTagInfo->puzNamespace,
bTruncatedNamesOk)))
{
goto Exit;
}
}
}
else
{
flmAssert( !puiDataType && !puzNamespace);
}
// 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_XFLM_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 F_NameTable::getFromTagTypeAndNum(
F_Db * pDb,
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_XFLM_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 (uiType == ELM_ELEMENT_TAG || uiType == ELM_ATTRIBUTE_TAG)
{
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
{
flmAssert( !puiDataType && !puzNamespace && !pszNamespace);
}
}
else
{
// If we do not have all of the tags cached, and this tag number is
// outside the range of tag numbers we read in, read the database
// definition document to get the information.
if (pDb &&
((uiType == ELM_ELEMENT_TAG && !m_bLoadedAllElements) ||
(uiType == ELM_ATTRIBUTE_TAG && !m_bLoadedAllAttributes)))
{
F_DataVector searchKey;
F_DataVector foundKey;
F_AttrElmInfo defInfo;
// Need to lookup the document's ID, using the tag number
if (RC_BAD( rc = searchKey.setUINT( 0, uiType)))
{
goto Exit;
}
if (RC_BAD( rc = searchKey.setUINT( 1, uiTagNum)))
{
goto Exit;
}
if (RC_BAD( rc = pDb->keyRetrieve( XFLM_DICT_NUMBER_INDEX,
&searchKey, XFLM_EXACT, &foundKey)))
{
goto Exit;
}
if (RC_BAD( rc = pDb->getElmAttrInfo( uiType,
foundKey.getDocumentID(), &defInfo, TRUE, FALSE)))
{
goto Exit;
}
if( RC_BAD( rc = defInfo.m_pNameAttr->getUnicode(
pDb, &puzTmpName)))
{
goto Exit;
}
if( defInfo.m_pTargetNamespaceAttr)
{
if( RC_BAD( rc = defInfo.m_pTargetNamespaceAttr->getUnicode(
pDb, &puzTmpNamespace)))
{
goto Exit;
}
}
if( puiDataType)
{
*puiDataType = defInfo.m_uiDataType;
}
if (puzTagName || pszTagName)
{
if (RC_BAD( rc = copyTagName( puzTagName, pszTagName,
puiNameBufSize,
puzTmpName, bTruncatedNamesOk)))
{
goto Exit;
}
}
else if (puiNameBufSize)
{
*puiNameBufSize = f_unilen( puzTmpName);
}
if (puzNamespace || pszNamespace)
{
if (RC_BAD( rc = copyTagName( puzNamespace, pszNamespace,
puiNamespaceBufSize, puzTmpNamespace,
bTruncatedNamesOk)))
{
goto Exit;
}
}
else if (puiNamespaceBufSize)
{
*puiNamespaceBufSize = f_unilen( puzTmpNamespace);
}
}
else
{
rc = RC_SET( NE_XFLM_NOT_FOUND);
goto Exit;
}
}
Exit:
if (puzTmpName)
{
f_free( &puzTmpName);
}
if (puzTmpNamespace)
{
f_free( &puzTmpNamespace);
}
return( rc);
}
/****************************************************************************
Desc: Find a name of a particular type and determine if it is ambiguous.
****************************************************************************/
FSTATIC RCODE findTagName(
F_Db * pDb,
FLMUINT uiType,
const FLMUNICODE * puzTagName,
const char * pszTagName,
F_DataVector * pSrchKey,
FLMUINT * puiDictNum,
FLMUINT64 * pui64DocumentID)
{
RCODE rc = NE_XFLM_OK;
F_DataVector foundKey;
F_DataVector foundKey2;
FLMUINT uiFoundType;
FLMUNICODE * puzTmpName = NULL;
// Node type and namespace are unknown, find the first name
// that matches.
if (RC_BAD( rc = pDb->keyRetrieve( XFLM_DICT_NAME_INDEX,
pSrchKey, XFLM_INCL, &foundKey)))
{
if (rc == NE_XFLM_EOF_HIT)
{
rc = RC_SET( NE_XFLM_NOT_FOUND);
}
goto Exit;
}
if (RC_BAD( rc = foundKey.getUINT( 0, &uiFoundType)))
{
goto Exit;
}
// Make sure we are still on the right kind of definition.
if (uiFoundType != uiType)
{
rc = RC_SET( NE_XFLM_NOT_FOUND);
goto Exit;
}
// Verify that we landed on a key that has the name we
// were searching for. Name is in component [1] of the key.
if (RC_BAD( rc = foundKey.getUnicode( 1, &puzTmpName)))
{
goto Exit;
}
if (tagNameCompare( puzTagName, pszTagName, puzTmpName) != 0)
{
rc = RC_SET( NE_XFLM_NOT_FOUND);
goto Exit;
}
// Get the document ID
*pui64DocumentID = foundKey.getDocumentID();
// Get the dictionary number from the data part of the key
if (RC_BAD( rc = foundKey.getUINT( 3, puiDictNum)))
{
goto Exit;
}
// Determine if there is more than one of that key.
if (RC_BAD( rc = pDb->keyRetrieve( XFLM_DICT_NAME_INDEX, &foundKey,
XFLM_EXCL | XFLM_MATCH_IDS, &foundKey2)))
{
if (rc == NE_XFLM_EOF_HIT)
{
rc = NE_XFLM_OK;
}
else
{
goto Exit;
}
}
else
{
if (RC_BAD( rc = foundKey2.getUINT( 0, &uiFoundType)))
{
if (rc == NE_XFLM_NOT_FOUND)
{
rc = NE_XFLM_OK;
}
goto Exit;
}
// Make sure we are still on the right kind of definition.
if (uiFoundType != uiType)
{
goto Exit; // will return NE_XFLM_OK
}
// Verify that we landed on a key that has a different name than we
// were searching for. Name is in component [1] of the key.
if (RC_BAD( rc = foundKey2.getUnicode( 1, &puzTmpName)))
{
if (rc == NE_XFLM_NOT_FOUND)
{
rc = NE_XFLM_OK;
}
goto Exit;
}
if (tagNameCompare( puzTagName, pszTagName, puzTmpName) != 0)
{
goto Exit; // will return NE_XFLM_OK
}
rc = RC_SET( NE_XFLM_MULTIPLE_MATCHES);
goto Exit;
}
Exit:
if (puzTmpName)
{
f_free( &puzTmpName);
}
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 F_NameTable::getFromTagTypeAndName(
F_Db * pDb,
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_XFLM_OK;
FLM_TAG_INFO * pTagInfo;
FLMUINT uiDictNum;
FLMBOOL bAmbiguous;
FLMUINT uiTmpDictNum;
FLMUINT64 ui64DocumentID;
F_DataVector searchKey;
F_DataVector foundKey;
if ((pTagInfo = findTagByTypeAndName( uiType,
puzTagName, pszTagName, bMatchNamespace,
puzNamespace,
&bAmbiguous)) != NULL)
{
if (puiTagNum)
{
*puiTagNum = pTagInfo->uiTagNum;
}
if (puiDataType)
{
*puiDataType = (FLMUINT)(uiType == ELM_ELEMENT_TAG ||
uiType == ELM_ATTRIBUTE_TAG
? pTagInfo->uiDataType
: 0);
}
if (bAmbiguous)
{
rc = RC_SET( NE_XFLM_MULTIPLE_MATCHES);
goto Exit;
}
else if (pDb && !bMatchNamespace &&
((uiType == ELM_ELEMENT_TAG && !m_bLoadedAllElements) ||
(uiType == ELM_ATTRIBUTE_TAG && !m_bLoadedAllAttributes)))
{
// Must see if it is ambiguous - create a search key
if (RC_BAD( rc = searchKey.setUINT( 0, uiType)))
{
goto Exit;
}
// Put name into the key.
if (puzTagName)
{
if (RC_BAD( rc = searchKey.setUnicode( 1, puzTagName)))
{
goto Exit;
}
}
else
{
if (RC_BAD( rc = searchKey.setUTF8( 1, (FLMBYTE *)pszTagName)))
{
goto Exit;
}
}
if (RC_BAD( rc = findTagName( pDb, uiType, puzTagName, pszTagName,
&searchKey, &uiTmpDictNum, &ui64DocumentID)))
{
// Better be found at this point because it was in the
// name table! Error may be NE_XFLM_MULTIPLE_MATCHES.
flmAssert( rc != NE_XFLM_NOT_FOUND);
goto Exit;
}
// What we found in the index better match what we found in
// the table!
flmAssert( uiTmpDictNum == *puiTagNum);
}
}
else
{
// If we do not have all of the tags cached, and we did not read in
// all of the elements or attributes, read the dictionary name index
// to see if we can find this tag name. NOTE that if bMatchNamespace ==
// FALSE we will simply find the first tag name that
// matches and not worry about matching the namespace.
if (pDb &&
((uiType == ELM_ELEMENT_TAG && !m_bLoadedAllElements) ||
(uiType == ELM_ATTRIBUTE_TAG && !m_bLoadedAllAttributes)))
{
F_AttrElmInfo defInfo;
// Create a search key
if (RC_BAD( rc = searchKey.setUINT( 0, uiType)))
{
goto Exit;
}
if (puzTagName)
{
if (RC_BAD( rc = searchKey.setUnicode( 1, puzTagName)))
{
goto Exit;
}
}
else
{
if (RC_BAD( rc = searchKey.setUTF8( 1, (FLMBYTE *)pszTagName)))
{
goto Exit;
}
}
if (!bMatchNamespace)
{
if (RC_BAD( rc = findTagName( pDb, uiType, puzTagName, pszTagName,
&searchKey, &uiDictNum, &ui64DocumentID)))
{
goto Exit;
}
}
else
{
// Add the namespace as a child node.
if (puzNamespace)
{
if (RC_BAD( rc = searchKey.setUnicode( 2, puzNamespace)))
{
goto Exit;
}
}
// Search for this exact key.
if (RC_BAD( rc = pDb->keyRetrieve( XFLM_DICT_NAME_INDEX,
&searchKey, XFLM_EXACT, &foundKey)))
{
goto Exit;
}
ui64DocumentID = foundKey.getDocumentID();
// Data component [0]'s value will be the dictionary number
if (RC_BAD( rc = foundKey.getUINT( 3, &uiDictNum)))
{
if (rc == NE_XFLM_NOT_FOUND)
{
flmAssert( 0);
uiDictNum = 0;
rc = NE_XFLM_OK;
}
else
{
goto Exit;
}
}
}
if (RC_BAD( rc = pDb->getElmAttrInfo( uiType,
ui64DocumentID, &defInfo, TRUE, FALSE)))
{
goto Exit;
}
if( puiDataType)
{
*puiDataType = defInfo.m_uiDataType;
}
if (puiTagNum)
{
*puiTagNum = uiDictNum;
}
}
else
{
rc = RC_SET( NE_XFLM_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_XFLM_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 F_NameTable::addTag(
FLMUINT uiType,
FLMUNICODE * puzTagName,
const char * pszTagName,
FLMUINT uiTagNum,
FLMUINT uiDataType,
FLMUNICODE * puzNamespace,
FLMBOOL bCheckDuplicates,
FLMBOOL bLimitNumToLoad)
{
RCODE rc = NE_XFLM_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_XFLM_INVALID_PARM);
goto Exit;
}
// Tag number of zero not allowed.
if (!uiTagNum)
{
rc = RC_SET_AND_ASSERT( NE_XFLM_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_XFLM_EXISTS);
goto Exit;
}
// Make sure that the tag type + number is not already used.
if (findTagByTypeAndNum( uiType, uiTagNum,
&uiTagTypeAndNumTblInsertPos))
{
rc = RC_SET( NE_XFLM_EXISTS);
goto Exit;
}
}
else
{
uiTagTypeAndNameTblInsertPos =
uiTagTypeAndNumTblInsertPos = m_uiNumTags;
m_bTablesSorted = FALSE;
}
if (uiType == ELM_ELEMENT_TAG)
{
if (m_uiNumElementsLoaded >= MAX_ELEMENTS_TO_LOAD &&
bLimitNumToLoad)
{
// We purposely limit the number of elements that can be
// loaded into the table.
m_bLoadedAllElements = FALSE;
goto Exit; // Will return NE_XFLM_OK
}
}
else if (uiType == ELM_ATTRIBUTE_TAG)
{
if (m_uiNumAttributesLoaded >= MAX_ATTRIBUTES_TO_LOAD &&
bLimitNumToLoad)
{
// We purposely limit the number of elements that can be
// loaded into the table.
m_bLoadedAllAttributes = FALSE;
goto Exit; // Will return NE_XFLM_OK
}
}
// 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;
}
if (uiType == ELM_ELEMENT_TAG)
{
m_uiNumElementsLoaded++;
}
else if (uiType == ELM_ATTRIBUTE_TAG)
{
m_uiNumAttributesLoaded++;
}
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 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)
{
if (uiType == ELM_ELEMENT_TAG || uiType == ELM_ATTRIBUTE_TAG)
{
puzNamespace = pTagInfo->puzNamespace;
bMatchNamespace = TRUE;
}
else
{
bMatchNamespace = FALSE; // Really doesn't matter
puzNamespace = NULL;
}
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
****************************************************************************/
RCODE F_NameTable::cloneNameTable(
F_NameTable * pSrcNameTable
)
{
RCODE rc = NE_XFLM_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 (pTagInfo->uiType == ELM_ELEMENT_TAG ||
pTagInfo->uiType == ELM_ATTRIBUTE_TAG)
{
if (RC_BAD( rc = addTag( pTagInfo->uiType, pTagInfo->puzTagName, NULL,
pTagInfo->uiTagNum,
pTagInfo->uiDataType,
pTagInfo->puzNamespace, FALSE)))
{
goto Exit;
}
}
else
{
if (RC_BAD( rc = addTag( pTagInfo->uiType, pTagInfo->puzTagName, NULL,
pTagInfo->uiTagNum, 0, NULL, FALSE)))
{
goto Exit;
}
}
}
sortTags();
Exit:
return( rc);
}
/****************************************************************************
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.
****************************************************************************/
RCODE F_NameTable::importFromNameTable(
F_NameTable * pSrcNameTable
)
{
RCODE rc = NE_XFLM_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 (pTagInfo->uiType == ELM_ELEMENT_TAG ||
pTagInfo->uiType == ELM_ATTRIBUTE_TAG)
{
if (RC_BAD( rc = addTag( pTagInfo->uiType, pTagInfo->puzTagName, NULL,
pTagInfo->uiTagNum,
pTagInfo->uiDataType,
pTagInfo->puzNamespace, FALSE)))
{
if (rc != NE_XFLM_EXISTS)
{
goto Exit;
}
else
{
rc = NE_XFLM_OK;
}
}
}
else
{
if (RC_BAD( rc = addTag( pTagInfo->uiType, pTagInfo->puzTagName, NULL,
pTagInfo->uiTagNum, 0, NULL, FALSE)))
{
if (rc != NE_XFLM_EXISTS)
{
goto Exit;
}
else
{
rc = NE_XFLM_OK;
}
}
}
}
sortTags();
Exit:
return( rc);
}
/****************************************************************************
Desc: Increment use count on this object.
****************************************************************************/
FLMUINT32 XFLMAPI F_NameTable::AddRef( void)
{
return( (FLMUINT32)(ftkAtomicIncrement( &m_ui32RefCnt)));
}
/****************************************************************************
Desc: Decrement the use count and delete if use count goes to zero.
****************************************************************************/
FLMUINT32 XFLMAPI F_NameTable::Release( void)
{
FLMUINT32 ui32RefCnt;
if ((ui32RefCnt = (FLMUINT32)ftkAtomicDecrement( &m_ui32RefCnt)) == 0)
{
delete this;
}
return( ui32RefCnt);
}
/****************************************************************************
Desc: Get the name table for an FDB, if any. If it has no current
dictionary, get the name table for the FDB's FFILE's first dictionary,
if any. Increment the use count on any name table returned.
It is the caller's responsibility to release the name table when it
is done with it.
****************************************************************************/
RCODE F_Db::getNameTable(
F_NameTable ** ppNameTable
)
{
RCODE rc = NE_XFLM_OK;
FLMBOOL bMutexLocked = FALSE;
*ppNameTable = NULL;
if (m_pDict)
{
if ((*ppNameTable = m_pDict->getNameTable()) == NULL)
{
rc = RC_SET_AND_ASSERT( NE_XFLM_NO_NAME_TABLE);
goto Exit;
}
(*ppNameTable)->AddRef();
}
else
{
m_pDatabase->lockMutex();
bMutexLocked = TRUE;
if (m_pDatabase && m_pDatabase->m_pDictList)
{
if ((*ppNameTable = m_pDatabase->m_pDictList->getNameTable()) == NULL)
{
rc = RC_SET_AND_ASSERT( NE_XFLM_NO_NAME_TABLE);
goto Exit;
}
(*ppNameTable)->AddRef();
}
else
{
rc = RC_SET( NE_XFLM_NO_NAME_TABLE);
goto Exit;
}
}
Exit:
if (bMutexLocked)
{
m_pDatabase->unlockMutex();
}
return( rc);
}
/****************************************************************************
Desc: Get the name for a dictionary item.
****************************************************************************/
RCODE XFLMAPI F_Db::getDictionaryName(
FLMUINT uiDictType,
FLMUINT uiDictNumber,
char * pszName,
FLMUINT * puiNameBufSize,
char * pszNamespace,
FLMUINT * puiNamespaceBufSize
)
{
RCODE rc = NE_XFLM_OK;
F_NameTable * pNameTable = NULL;
if (RC_BAD(rc = getNameTable( &pNameTable)))
{
goto Exit;
}
if (pszNamespace &&
(uiDictType == ELM_ELEMENT_TAG || uiDictType == ELM_ATTRIBUTE_TAG))
{
flmAssert( puiNamespaceBufSize);
}
else
{
flmAssert( !pszNamespace && !puiNamespaceBufSize);
pszNamespace = NULL;
puiNamespaceBufSize = NULL;
}
if (RC_BAD( rc = pNameTable->getFromTagTypeAndNum( this, uiDictType,
uiDictNumber, NULL,
pszName, puiNameBufSize, NULL,
NULL, pszNamespace,
puiNamespaceBufSize, TRUE)))
{
goto Exit;
}
Exit:
if (pNameTable)
{
pNameTable->Release();
}
return( rc);
}
/****************************************************************************
Desc: Get the name for a dictionary item.
****************************************************************************/
RCODE XFLMAPI F_Db::getDictionaryName(
FLMUINT uiDictType,
FLMUINT uiDictNumber,
FLMUNICODE * puzName,
FLMUINT * puiNameBufSize,
FLMUNICODE * puzNamespace,
FLMUINT * puiNamespaceBufSize
)
{
RCODE rc = NE_XFLM_OK;
F_NameTable * pNameTable = NULL;
if (RC_BAD(rc = getNameTable( &pNameTable)))
{
goto Exit;
}
if (uiDictType == ELM_ELEMENT_TAG || uiDictType == ELM_ATTRIBUTE_TAG)
{
flmAssert( puiNamespaceBufSize);
}
else
{
flmAssert( !puiNamespaceBufSize);
puiNamespaceBufSize = NULL;
}
if (RC_BAD( rc = pNameTable->getFromTagTypeAndNum( this, uiDictType,
uiDictNumber, puzName,
NULL, puiNameBufSize, NULL,
puzNamespace, NULL,
puiNamespaceBufSize, TRUE)))
{
goto Exit;
}
Exit:
if (pNameTable)
{
pNameTable->Release();
}
return( rc);
}