blob: b8b31fef302107ea13985df02ade3617ef42a33b [file] [log] [blame]
/** \file listfs.cpp .
-----------------------------------------------------------------------------
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
-----------------------------------------------------------------------------
Description:
-----------------------------------------------------------------------------
-------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------- */
/* Include dependencies */
/* ----------------------------------------------------------------------- */
#include "uima/listfs.hpp"
#include "uima/featurestructure.hpp"
#include "uima/lowlevel_fsheap.hpp"
#include "uima/msg.h"
#include "uima/internal_fspromoter.hpp"
#include "uima/internal_typeshortcuts.hpp"
#include "uima/internal_fsvalue_accessors.hpp"
/* ----------------------------------------------------------------------- */
/* Constants */
/* ----------------------------------------------------------------------- */
/* ----------------------------------------------------------------------- */
/* Forward declarations */
/* ----------------------------------------------------------------------- */
/* ----------------------------------------------------------------------- */
/* Types / Classes */
/* ----------------------------------------------------------------------- */
/* ----------------------------------------------------------------------- */
/* Implementation */
/* ----------------------------------------------------------------------- */
namespace uima {
/* ----------------------------------------------------------------------- */
/* Exceptions Implementation */
/* ----------------------------------------------------------------------- */
UIMA_EXC_CLASSIMPLEMENT(FSIsNotListException, CASException);
UIMA_EXC_CLASSIMPLEMENT(ListIsEmptyException, CASException);
UIMA_EXC_CLASSIMPLEMENT(ListIsCircularException, CASException);
/* ----------------------------------------------------------------------- */
/* Tool Functions Implementation */
/* ----------------------------------------------------------------------- */
template< class T,
const uima::lowlevel::TyFSType LIST_TYPE,
const uima::lowlevel::TyFSType ELIST_TYPE,
const uima::lowlevel::TyFSType NELIST_TYPE,
const uima::lowlevel::TyFSFeature HEAD_FEATURE,
const uima::lowlevel::TyFSFeature TAIL_FEATURE >
void
BasicListFS<T, LIST_TYPE, ELIST_TYPE, NELIST_TYPE, HEAD_FEATURE, TAIL_FEATURE>::
checkList(lowlevel::TyFS tyFS, TyMessageId tyContext) const {
assert(EXISTS(iv_cas));
lowlevel::TyFSType tyType = iv_cas->getHeap()->getType( tyFS );
if ( ! iv_cas->getHeap()->getTypeSystem().subsumes( LIST_TYPE, tyType) ) {
UIMA_EXC_THROW_NEW(FSIsNotListException,
UIMA_ERR_FS_IS_NOT_LIST,
UIMA_MSG_ID_EXC_FS_IS_NOT_LIST,
ErrorMessage(tyContext),
ErrorInfo::recoverable
);
}
}
template< class T,
const uima::lowlevel::TyFSType LIST_TYPE,
const uima::lowlevel::TyFSType ELIST_TYPE,
const uima::lowlevel::TyFSType NELIST_TYPE,
const uima::lowlevel::TyFSFeature HEAD_FEATURE,
const uima::lowlevel::TyFSFeature TAIL_FEATURE >
void
BasicListFS<T, LIST_TYPE, ELIST_TYPE, NELIST_TYPE, HEAD_FEATURE, TAIL_FEATURE>::
checkNEList(lowlevel::TyFS tyFS, TyMessageId tyContext) const {
assert(EXISTS(iv_cas));
lowlevel::FSHeap const & crHeap = *iv_cas->getHeap();
lowlevel::TyFSType tyType = crHeap.getType( tyFS );
if (tyType != NELIST_TYPE) {
UIMA_EXC_THROW_NEW(ListIsEmptyException,
UIMA_ERR_LIST_IS_EMPTY,
UIMA_MSG_ID_EXC_LIST_IS_EMPTY,
ErrorMessage(tyContext),
ErrorInfo::recoverable);
}
}
template< class T,
const uima::lowlevel::TyFSType LIST_TYPE,
const uima::lowlevel::TyFSType ELIST_TYPE,
const uima::lowlevel::TyFSType NELIST_TYPE,
const uima::lowlevel::TyFSFeature HEAD_FEATURE,
const uima::lowlevel::TyFSFeature TAIL_FEATURE >
void
BasicListFS<T, LIST_TYPE, ELIST_TYPE, NELIST_TYPE, HEAD_FEATURE, TAIL_FEATURE>::
checkCircularity(lowlevel::TyFS tyFS1, lowlevel::TyFS tyFS2, TyMessageId tyContext) const {
assert(EXISTS(iv_cas));
if ( tyFS1 == tyFS2 ) {
lowlevel::FSHeap const & crHeap = *iv_cas->getHeap();
lowlevel::TyFSType tyType1 = crHeap.getType( tyFS1 );
lowlevel::TyFSType tyType2 = crHeap.getType( tyFS2 );
// if both lists are empty we don't have any problem
if ( tyType1 == ELIST_TYPE
&& tyType2 == ELIST_TYPE) {
return;
}
UIMA_EXC_THROW_NEW(ListIsCircularException,
UIMA_ERR_LIST_IS_CIRCULAR,
UIMA_MSG_ID_EXC_LIST_IS_CIRCULAR,
ErrorMessage(tyContext),
ErrorInfo::recoverable
);
}
}
template< class T,
const uima::lowlevel::TyFSType LIST_TYPE,
const uima::lowlevel::TyFSType ELIST_TYPE,
const uima::lowlevel::TyFSType NELIST_TYPE,
const uima::lowlevel::TyFSFeature HEAD_FEATURE,
const uima::lowlevel::TyFSFeature TAIL_FEATURE >
lowlevel::TyFS
BasicListFS<T, LIST_TYPE, ELIST_TYPE, NELIST_TYPE, HEAD_FEATURE, TAIL_FEATURE>::
getLastListElement(lowlevel::TyFS tyListFS, size_t & rOutSize) const {
assert(EXISTS(iv_cas));
rOutSize = 0;
lowlevel::FSHeap & rHeap = *iv_cas->getHeap();
assert( rHeap.getType(tyListFS) == NELIST_TYPE );
lowlevel::TyFS tyCurrentList = tyListFS;
while (true) {
assert( rHeap.getType(tyCurrentList) == NELIST_TYPE );
lowlevel::TyFS tyNextList = rHeap.getFSValue(tyCurrentList, TAIL_FEATURE);
if ( rHeap.getType(tyNextList) != NELIST_TYPE ) {
assert( rHeap.getType(tyNextList) == ELIST_TYPE );
break;
}
tyCurrentList = tyNextList;
++rOutSize;
}
return tyCurrentList;
}
template< class T,
const uima::lowlevel::TyFSType LIST_TYPE,
const uima::lowlevel::TyFSType ELIST_TYPE,
const uima::lowlevel::TyFSType NELIST_TYPE,
const uima::lowlevel::TyFSFeature HEAD_FEATURE,
const uima::lowlevel::TyFSFeature TAIL_FEATURE >
lowlevel::TyFS
BasicListFS<T, LIST_TYPE, ELIST_TYPE, NELIST_TYPE, HEAD_FEATURE, TAIL_FEATURE>::
addLastLowlevel(lowlevel::TyFS tyListFS, T tyNewElement) {
assert(EXISTS(iv_cas));
lowlevel::FSHeap & rHeap = *iv_cas->getHeap();
assert( rHeap.getType(tyListFS) == NELIST_TYPE );
size_t ui = 0;
lowlevel::TyFS tyLastListElement = getLastListElement(tyListFS, ui);
lowlevel::TyFS tyEmptyList = rHeap.getFSValue( tyLastListElement, TAIL_FEATURE);
assert( ! rHeap.isUntouchedFSValue(tyLastListElement, TAIL_FEATURE) );
assert( rHeap.getType( tyEmptyList ) == ELIST_TYPE );
lowlevel::TyFS tyNewListElement = rHeap.createFS(NELIST_TYPE);
internal::setFSValueTempl((uima::CAS *)iv_cas, tyNewListElement, HEAD_FEATURE, tyNewElement);
rHeap.setFSValue( tyNewListElement, TAIL_FEATURE, tyEmptyList );
rHeap.setFSValue( tyLastListElement, TAIL_FEATURE, tyNewListElement );
return tyNewListElement;
}
template< class T,
const uima::lowlevel::TyFSType LIST_TYPE,
const uima::lowlevel::TyFSType ELIST_TYPE,
const uima::lowlevel::TyFSType NELIST_TYPE,
const uima::lowlevel::TyFSFeature HEAD_FEATURE,
const uima::lowlevel::TyFSFeature TAIL_FEATURE >
void
BasicListFS<T, LIST_TYPE, ELIST_TYPE, NELIST_TYPE, HEAD_FEATURE, TAIL_FEATURE>::
appendLowlevel(lowlevel::TyFS tyListFS1, lowlevel::TyFS tyListFS2) {
assert(EXISTS(iv_cas));
lowlevel::FSHeap & rHeap = *iv_cas->getHeap();
assert( rHeap.getType(tyListFS1) == NELIST_TYPE );
size_t ui = 0;
lowlevel::TyFS tyLastListElement = getLastListElement(tyListFS1, ui);
#ifndef NDEBUG
lowlevel::TyFS tyEmptyList = rHeap.getFSValue( tyLastListElement, TAIL_FEATURE);
assert( ! rHeap.isUntouchedFSValue(tyLastListElement, TAIL_FEATURE) );
assert( rHeap.getType( tyEmptyList ) == ELIST_TYPE );
#endif /* debug mode only */
rHeap.setFSValue( tyLastListElement, TAIL_FEATURE, tyListFS2);
}
/* ----------------------------------------------------------------------- */
/* BasicListFS Implementation */
/* ----------------------------------------------------------------------- */
template< class T,
const uima::lowlevel::TyFSType LIST_TYPE,
const uima::lowlevel::TyFSType ELIST_TYPE,
const uima::lowlevel::TyFSType NELIST_TYPE,
const uima::lowlevel::TyFSFeature HEAD_FEATURE,
const uima::lowlevel::TyFSFeature TAIL_FEATURE >
BasicListFS<T, LIST_TYPE, ELIST_TYPE, NELIST_TYPE, HEAD_FEATURE, TAIL_FEATURE>::
BasicListFS(lowlevel::TyFS anFS, uima::CAS & cas, bool bDoChecks) :
FeatureStructure(anFS, cas) {
if (bDoChecks) {
checkValidity(UIMA_MSG_ID_EXCON_CREATING_LISTFS);
checkList(iv_tyFS, UIMA_MSG_ID_EXCON_CREATING_LISTFS);
}
}
template< class T,
const uima::lowlevel::TyFSType LIST_TYPE,
const uima::lowlevel::TyFSType ELIST_TYPE,
const uima::lowlevel::TyFSType NELIST_TYPE,
const uima::lowlevel::TyFSFeature HEAD_FEATURE,
const uima::lowlevel::TyFSFeature TAIL_FEATURE >
BasicListFS<T, LIST_TYPE, ELIST_TYPE, NELIST_TYPE, HEAD_FEATURE, TAIL_FEATURE>::
BasicListFS() :
FeatureStructure() {}
template< class T,
const uima::lowlevel::TyFSType LIST_TYPE,
const uima::lowlevel::TyFSType ELIST_TYPE,
const uima::lowlevel::TyFSType NELIST_TYPE,
const uima::lowlevel::TyFSFeature HEAD_FEATURE,
const uima::lowlevel::TyFSFeature TAIL_FEATURE >
BasicListFS<T, LIST_TYPE, ELIST_TYPE, NELIST_TYPE, HEAD_FEATURE, TAIL_FEATURE>::
BasicListFS( FeatureStructure const & fs) :
FeatureStructure(fs) {
if (isValid()) {
checkList(iv_tyFS, UIMA_MSG_ID_EXCON_CREATING_LISTFS);
}
// we should not have any additional members
assert(sizeof(BasicListFS) == sizeof(FeatureStructure));
}
template< class T,
const uima::lowlevel::TyFSType LIST_TYPE,
const uima::lowlevel::TyFSType ELIST_TYPE,
const uima::lowlevel::TyFSType NELIST_TYPE,
const uima::lowlevel::TyFSFeature HEAD_FEATURE,
const uima::lowlevel::TyFSFeature TAIL_FEATURE >
bool
BasicListFS<T, LIST_TYPE, ELIST_TYPE, NELIST_TYPE, HEAD_FEATURE, TAIL_FEATURE>::
isEmpty() const {
checkValidity(UIMA_MSG_ID_EXCON_GETTING_LIST_ISEMPTY);
assert(EXISTS(iv_cas));
lowlevel::FSHeap const & crHeap = *iv_cas->getHeap();
lowlevel::TyFSType tyType = crHeap.getType( iv_tyFS );
return(tyType != NELIST_TYPE);
}
template< class T,
const uima::lowlevel::TyFSType LIST_TYPE,
const uima::lowlevel::TyFSType ELIST_TYPE,
const uima::lowlevel::TyFSType NELIST_TYPE,
const uima::lowlevel::TyFSFeature HEAD_FEATURE,
const uima::lowlevel::TyFSFeature TAIL_FEATURE >
size_t
BasicListFS<T, LIST_TYPE, ELIST_TYPE, NELIST_TYPE, HEAD_FEATURE, TAIL_FEATURE>::
getLength() const {
checkValidity(UIMA_MSG_ID_EXCON_GETTING_LIST_LENGTH);
assert(EXISTS(iv_cas));
lowlevel::FSHeap & rFSHeap = *iv_cas->getHeap();
if ( rFSHeap.getType( iv_tyFS ) != NELIST_TYPE ) {
return 0;
}
size_t uiResult = 0;
(void) getLastListElement(iv_tyFS, uiResult);
return uiResult+1;
}
template< class T,
const uima::lowlevel::TyFSType LIST_TYPE,
const uima::lowlevel::TyFSType ELIST_TYPE,
const uima::lowlevel::TyFSType NELIST_TYPE,
const uima::lowlevel::TyFSFeature HEAD_FEATURE,
const uima::lowlevel::TyFSFeature TAIL_FEATURE >
T
BasicListFS<T, LIST_TYPE, ELIST_TYPE, NELIST_TYPE, HEAD_FEATURE, TAIL_FEATURE>::
getHead() const {
checkValidity(UIMA_MSG_ID_EXCON_GETTING_LIST_HEAD);
checkNEList(iv_tyFS, UIMA_MSG_ID_EXCON_GETTING_LIST_HEAD);
assert(EXISTS(iv_cas));
lowlevel::FSHeap const & crHeap = *iv_cas->getHeap();
assert( crHeap.getType(iv_tyFS) == NELIST_TYPE );
T result;
internal::getFSValueTempl((uima::CAS *)iv_cas, iv_tyFS, HEAD_FEATURE, result);
return result;
}
template< class T,
const uima::lowlevel::TyFSType LIST_TYPE,
const uima::lowlevel::TyFSType ELIST_TYPE,
const uima::lowlevel::TyFSType NELIST_TYPE,
const uima::lowlevel::TyFSFeature HEAD_FEATURE,
const uima::lowlevel::TyFSFeature TAIL_FEATURE >
void
BasicListFS<T, LIST_TYPE, ELIST_TYPE, NELIST_TYPE, HEAD_FEATURE, TAIL_FEATURE>::
setHead( T const & fs ) {
checkValidity(UIMA_MSG_ID_EXCON_SETTING_LIST_HEAD);
checkNEList(iv_tyFS, UIMA_MSG_ID_EXCON_SETTING_LIST_HEAD);
assert(EXISTS(iv_cas));
lowlevel::FSHeap & rHeap = *iv_cas->getHeap();
assert( rHeap.getType(iv_tyFS) == NELIST_TYPE );
internal::setFSValueTempl((uima::CAS *)iv_cas, iv_tyFS, HEAD_FEATURE, fs);
}
template< class T,
const uima::lowlevel::TyFSType LIST_TYPE,
const uima::lowlevel::TyFSType ELIST_TYPE,
const uima::lowlevel::TyFSType NELIST_TYPE,
const uima::lowlevel::TyFSFeature HEAD_FEATURE,
const uima::lowlevel::TyFSFeature TAIL_FEATURE >
BasicListFS<T, LIST_TYPE, ELIST_TYPE, NELIST_TYPE, HEAD_FEATURE, TAIL_FEATURE>
BasicListFS<T, LIST_TYPE, ELIST_TYPE, NELIST_TYPE, HEAD_FEATURE, TAIL_FEATURE>::
getTail() const {
checkValidity(UIMA_MSG_ID_EXCON_GETTING_LIST_TAIL);
checkNEList(iv_tyFS, UIMA_MSG_ID_EXCON_GETTING_LIST_TAIL);
assert(EXISTS(iv_cas));
lowlevel::FSHeap const & crHeap = *iv_cas->getHeap();
assert( crHeap.getType(iv_tyFS) == NELIST_TYPE );
lowlevel::TyFS tyNextList = crHeap.getFSValue(iv_tyFS, TAIL_FEATURE);
return BasicListFS(tyNextList, *iv_cas, false);
}
template< class T,
const uima::lowlevel::TyFSType LIST_TYPE,
const uima::lowlevel::TyFSType ELIST_TYPE,
const uima::lowlevel::TyFSType NELIST_TYPE,
const uima::lowlevel::TyFSFeature HEAD_FEATURE,
const uima::lowlevel::TyFSFeature TAIL_FEATURE >
void
BasicListFS<T, LIST_TYPE, ELIST_TYPE, NELIST_TYPE, HEAD_FEATURE, TAIL_FEATURE>::
setTail( BasicListFS fs ) {
checkValidity(UIMA_MSG_ID_EXCON_SETTING_LIST_TAIL);
fs.checkValidity(UIMA_MSG_ID_EXCON_SETTING_LIST_TAIL);
checkNEList(iv_tyFS, UIMA_MSG_ID_EXCON_SETTING_LIST_TAIL);
assert(EXISTS(iv_cas));
lowlevel::FSHeap & rHeap = *iv_cas->getHeap();
assert( rHeap.getType(iv_tyFS) == NELIST_TYPE );
rHeap.setFSValue(iv_tyFS, TAIL_FEATURE, fs.iv_tyFS);
}
template< class T,
const uima::lowlevel::TyFSType LIST_TYPE,
const uima::lowlevel::TyFSType ELIST_TYPE,
const uima::lowlevel::TyFSType NELIST_TYPE,
const uima::lowlevel::TyFSFeature HEAD_FEATURE,
const uima::lowlevel::TyFSFeature TAIL_FEATURE >
BasicListFS<T, LIST_TYPE, ELIST_TYPE, NELIST_TYPE, HEAD_FEATURE, TAIL_FEATURE>
BasicListFS<T, LIST_TYPE, ELIST_TYPE, NELIST_TYPE, HEAD_FEATURE, TAIL_FEATURE>::
addFirst( T const & fs ) {
checkValidity(UIMA_MSG_ID_EXCON_ADDING_LIST_VALUE);
lowlevel::FSHeap & rHeap = *iv_cas->getHeap();
lowlevel::TyFS tyNEFS = rHeap.createFS( NELIST_TYPE );
rHeap.setFSValue(tyNEFS, TAIL_FEATURE, iv_tyFS);
internal::setFSValueTempl((uima::CAS *)iv_cas, tyNEFS, HEAD_FEATURE, fs);
iv_tyFS = tyNEFS;
return(*this);
}
template< class T,
const uima::lowlevel::TyFSType LIST_TYPE,
const uima::lowlevel::TyFSType ELIST_TYPE,
const uima::lowlevel::TyFSType NELIST_TYPE,
const uima::lowlevel::TyFSFeature HEAD_FEATURE,
const uima::lowlevel::TyFSFeature TAIL_FEATURE >
BasicListFS<T, LIST_TYPE, ELIST_TYPE, NELIST_TYPE, HEAD_FEATURE, TAIL_FEATURE>
BasicListFS<T, LIST_TYPE, ELIST_TYPE, NELIST_TYPE, HEAD_FEATURE, TAIL_FEATURE>::
addLast( T const & fs ) {
checkValidity(UIMA_MSG_ID_EXCON_ADDING_LIST_VALUE);
lowlevel::FSHeap & rHeap = *iv_cas->getHeap();
lowlevel::TyFS tyNewEnd;
if (rHeap.getType( iv_tyFS ) == NELIST_TYPE) {
// if this list is not empty we search for the end and put fs there
tyNewEnd = addLastLowlevel(iv_tyFS, fs);
} else {
// if this list is empty we create an inital terminated list
assert(rHeap.getType( iv_tyFS ) == ELIST_TYPE);
lowlevel::TyFS tyEFS = iv_tyFS;
iv_tyFS = rHeap.createFS( NELIST_TYPE );
internal::setFSValueTempl((uima::CAS *)iv_cas, iv_tyFS, HEAD_FEATURE, fs);
rHeap.setFSValue(iv_tyFS, TAIL_FEATURE, tyEFS);
tyNewEnd = iv_tyFS;
}
return BasicListFS(tyNewEnd, *iv_cas, false);
}
template< class T,
const uima::lowlevel::TyFSType LIST_TYPE,
const uima::lowlevel::TyFSType ELIST_TYPE,
const uima::lowlevel::TyFSType NELIST_TYPE,
const uima::lowlevel::TyFSFeature HEAD_FEATURE,
const uima::lowlevel::TyFSFeature TAIL_FEATURE >
BasicListFS<T, LIST_TYPE, ELIST_TYPE, NELIST_TYPE, HEAD_FEATURE, TAIL_FEATURE>
BasicListFS<T, LIST_TYPE, ELIST_TYPE, NELIST_TYPE, HEAD_FEATURE, TAIL_FEATURE>::
append( BasicListFS fs ) {
checkValidity(UIMA_MSG_ID_EXCON_APPENDING_TO_LIST);
fs.checkValidity(UIMA_MSG_ID_EXCON_APPENDING_TO_LIST);
lowlevel::FSHeap & rHeap = *iv_cas->getHeap();
checkCircularity(iv_tyFS, fs.iv_tyFS, UIMA_MSG_ID_EXCON_APPENDING_TO_LIST);
if (rHeap.getType( iv_tyFS ) == NELIST_TYPE) {
// if this list is not empty we do a full append
appendLowlevel(iv_tyFS, fs.iv_tyFS);
} else {
// if this list is empty we just replace it with with fs
iv_tyFS = fs.iv_tyFS;
}
return(*this);
}
template< class T,
const uima::lowlevel::TyFSType LIST_TYPE,
const uima::lowlevel::TyFSType ELIST_TYPE,
const uima::lowlevel::TyFSType NELIST_TYPE,
const uima::lowlevel::TyFSFeature HEAD_FEATURE,
const uima::lowlevel::TyFSFeature TAIL_FEATURE >
BasicListFS<T, LIST_TYPE, ELIST_TYPE, NELIST_TYPE, HEAD_FEATURE, TAIL_FEATURE>
BasicListFS<T, LIST_TYPE, ELIST_TYPE, NELIST_TYPE, HEAD_FEATURE, TAIL_FEATURE>::
prepend( BasicListFS fs ) {
checkValidity(UIMA_MSG_ID_EXCON_PREPENDING_TO_LIST);
fs.checkValidity(UIMA_MSG_ID_EXCON_PREPENDING_TO_LIST);
lowlevel::FSHeap & rHeap = *iv_cas->getHeap();
checkCircularity(iv_tyFS, fs.iv_tyFS, UIMA_MSG_ID_EXCON_PREPENDING_TO_LIST);
// only do something if fs does have some elements
if (rHeap.getType( fs.iv_tyFS ) == NELIST_TYPE) {
appendLowlevel(fs.iv_tyFS, iv_tyFS);
iv_tyFS = fs.iv_tyFS;
}
return(*this);
}
template< class T,
const uima::lowlevel::TyFSType LIST_TYPE,
const uima::lowlevel::TyFSType ELIST_TYPE,
const uima::lowlevel::TyFSType NELIST_TYPE,
const uima::lowlevel::TyFSFeature HEAD_FEATURE,
const uima::lowlevel::TyFSFeature TAIL_FEATURE >
void
BasicListFS<T, LIST_TYPE, ELIST_TYPE, NELIST_TYPE, HEAD_FEATURE, TAIL_FEATURE>::
moveToNext() {
checkValidity(UIMA_MSG_ID_EXCON_MOVING_LIST_TO_NEXT);
checkNEList(iv_tyFS, UIMA_MSG_ID_EXCON_MOVING_LIST_TO_NEXT);
assert(EXISTS(iv_cas));
lowlevel::FSHeap const & crHeap = *iv_cas->getHeap();
assert( crHeap.getType(iv_tyFS) == NELIST_TYPE );
lowlevel::TyFS tyNextList = crHeap.getFSValue(iv_tyFS, TAIL_FEATURE);
iv_tyFS = tyNextList;
#ifndef NDEBUG
checkList(iv_tyFS, UIMA_MSG_ID_EXCON_MOVING_LIST_TO_NEXT);
#endif
}
template < class T,
const uima::lowlevel::TyFSType LIST_TYPE,
const uima::lowlevel::TyFSType ELIST_TYPE,
const uima::lowlevel::TyFSType NELIST_TYPE,
const uima::lowlevel::TyFSFeature HEAD_FEATURE,
const uima::lowlevel::TyFSFeature TAIL_FEATURE >
void terminateList(BasicListFS<T, LIST_TYPE, ELIST_TYPE, NELIST_TYPE, HEAD_FEATURE, TAIL_FEATURE> & aList,
uima::lowlevel::FSHeap & heap) {
uima::lowlevel::TyFS emptyList = heap.createFS(ELIST_TYPE);
uima::lowlevel::TyFS tailElement = uima::internal::FSPromoter::demoteFS( aList );
heap.setFSValue( tailElement, TAIL_FEATURE, emptyList );
}
template < class T,
const uima::lowlevel::TyFSType LIST_TYPE,
const uima::lowlevel::TyFSType ELIST_TYPE,
const uima::lowlevel::TyFSType NELIST_TYPE,
const uima::lowlevel::TyFSFeature HEAD_FEATURE,
const uima::lowlevel::TyFSFeature TAIL_FEATURE >
BasicListFS<T, LIST_TYPE, ELIST_TYPE, NELIST_TYPE, HEAD_FEATURE, TAIL_FEATURE>
deleteElementFromList(BasicListFS<T, LIST_TYPE, ELIST_TYPE, NELIST_TYPE, HEAD_FEATURE, TAIL_FEATURE> & aList,
uima::lowlevel::FSHeap & heap,
T const & element) {
assert(! aList.isEmpty() );
BasicListFS<T, LIST_TYPE, ELIST_TYPE, NELIST_TYPE, HEAD_FEATURE, TAIL_FEATURE> tail = aList.getTail();
if (! tail.isEmpty() ) {
if (tail.getHead() == element) {
aList.setTail(tail.getTail());
terminateList(tail, heap);
return tail;
} else {
return deleteElementFromList(tail, heap, element);
}
}
return BasicListFS<T, LIST_TYPE, ELIST_TYPE, NELIST_TYPE, HEAD_FEATURE, TAIL_FEATURE>();
}
template< class T,
const uima::lowlevel::TyFSType LIST_TYPE,
const uima::lowlevel::TyFSType ELIST_TYPE,
const uima::lowlevel::TyFSType NELIST_TYPE,
const uima::lowlevel::TyFSFeature HEAD_FEATURE,
const uima::lowlevel::TyFSFeature TAIL_FEATURE >
BasicListFS<T, LIST_TYPE, ELIST_TYPE, NELIST_TYPE, HEAD_FEATURE, TAIL_FEATURE>
BasicListFS<T, LIST_TYPE, ELIST_TYPE, NELIST_TYPE, HEAD_FEATURE, TAIL_FEATURE>::removeElement( T const & element ) {
checkValidity(UIMA_MSG_ID_EXCON_UNKNOWN_CONTEXT);
if (! isEmpty() ) {
// if the first element of list is to be deleted
if (getHead() == element) {
BasicListFS<T, LIST_TYPE, ELIST_TYPE, NELIST_TYPE, HEAD_FEATURE, TAIL_FEATURE> result = *this;
*this = getTail();
terminateList(result, *iv_cas->getHeap() );
return result;
} else {
BasicListFS<T, LIST_TYPE, ELIST_TYPE, NELIST_TYPE, HEAD_FEATURE, TAIL_FEATURE> result = deleteElementFromList(*this, *iv_cas->getHeap(), element);
return result;
}
}
return BasicListFS<T, LIST_TYPE, ELIST_TYPE, NELIST_TYPE, HEAD_FEATURE, TAIL_FEATURE>();
}
template< class T,
const uima::lowlevel::TyFSType LIST_TYPE,
const uima::lowlevel::TyFSType ELIST_TYPE,
const uima::lowlevel::TyFSType NELIST_TYPE,
const uima::lowlevel::TyFSFeature HEAD_FEATURE,
const uima::lowlevel::TyFSFeature TAIL_FEATURE >
/*static*/ bool
BasicListFS<T, LIST_TYPE, ELIST_TYPE, NELIST_TYPE, HEAD_FEATURE, TAIL_FEATURE>::
hasListElements(FeatureStructure fs, Feature const & f) {
// there are several ways a feature can have zero values
uima::lowlevel::FSHeap const & crHeap = *internal::FSPromoter::getFSHeap(fs);
lowlevel::TyFSFeature tyFeat = internal::FSPromoter::demoteFeature( f );
lowlevel::TyFS tyFS = internal::FSPromoter::demoteFS( fs );
// 1: it is untouched. So we don't touch it either and return false
if ( crHeap.isUntouchedFSValue(tyFS, tyFeat) ) {
return false;
}
lowlevel::TyFS tyFSResult = internal::FSPromoter::getFSHeap(fs)->getFSValue(tyFS, tyFeat);
// the value can be either
// 1: a generic list type (should not happen but is a valid possiblity)
// 2: an empty list (no elements in the list)
// 3: a non-empty list (some elements in the list)
assert( crHeap.getType( tyFSResult ) == LIST_TYPE
|| crHeap.getType( tyFSResult ) == ELIST_TYPE
|| crHeap.getType( tyFSResult ) == NELIST_TYPE);
// Return true, if the value is of type non-empty list
return(crHeap.getType( tyFSResult ) == NELIST_TYPE);
}
template< class T,
const uima::lowlevel::TyFSType LIST_TYPE,
const uima::lowlevel::TyFSType ELIST_TYPE,
const uima::lowlevel::TyFSType NELIST_TYPE,
const uima::lowlevel::TyFSFeature HEAD_FEATURE,
const uima::lowlevel::TyFSFeature TAIL_FEATURE >
/*static*/ BasicListFS<T, LIST_TYPE, ELIST_TYPE, NELIST_TYPE, HEAD_FEATURE, TAIL_FEATURE>
BasicListFS<T, LIST_TYPE, ELIST_TYPE, NELIST_TYPE, HEAD_FEATURE, TAIL_FEATURE>::
getListFSValue( FeatureStructure const & fs, Feature const & f ) {
assert(fs.isValid());
uima::CAS & rCas = *internal::FSPromoter::getFSCas(fs);
uima::lowlevel::FSHeap & rHeap = *internal::FSPromoter::getFSHeap(fs);
lowlevel::TyFSFeature tyF = internal::FSPromoter::demoteFeature( f );
lowlevel::TyFS tyFS = internal::FSPromoter::demoteFS( fs );
// check range type
lowlevel::TyFSType tyRangeType = rHeap.getTypeSystem().getRangeType(tyF);
if ( ! rHeap.getTypeSystem().subsumes( LIST_TYPE, tyRangeType) ) {
UIMA_EXC_THROW_NEW(FSIsNotListException,
UIMA_ERR_FS_IS_NOT_LIST,
UIMA_MSG_ID_EXC_FS_IS_NOT_LIST,
ErrorMessage(UIMA_MSG_ID_EXCON_GETTING_FIRST_LIST_ELEMENT),
ErrorInfo::recoverable
);
}
// it is untouched. We have to create a proper empty terminated list
if ( rHeap.isUntouchedFSValue(tyFS, tyF) ) {
lowlevel::TyFS tyFSEList = rHeap.createFS(ELIST_TYPE);
rHeap.setFSValue(tyFS, tyF, tyFSEList);
return BasicListFS(tyFSEList, rCas);
}
return BasicListFS(rHeap.getFSValue(tyFS, tyF), rCas, false);
}
template< class T,
const uima::lowlevel::TyFSType LIST_TYPE,
const uima::lowlevel::TyFSType ELIST_TYPE,
const uima::lowlevel::TyFSType NELIST_TYPE,
const uima::lowlevel::TyFSFeature HEAD_FEATURE,
const uima::lowlevel::TyFSFeature TAIL_FEATURE >
/*static*/ BasicListFS<T, LIST_TYPE, ELIST_TYPE, NELIST_TYPE, HEAD_FEATURE, TAIL_FEATURE>
BasicListFS<T, LIST_TYPE, ELIST_TYPE, NELIST_TYPE, HEAD_FEATURE, TAIL_FEATURE>::
createListFS( CAS & cas, bool bIsPermanent ) {
lowlevel::FSHeap & rHeap = *uima::internal::FSPromoter::getFSHeap(cas);
lowlevel::TyFS tyFS = rHeap.createFS(ELIST_TYPE);
return BasicListFS(tyFS, cas, false);
}
template< class T,
const uima::lowlevel::TyFSType LIST_TYPE,
const uima::lowlevel::TyFSType ELIST_TYPE,
const uima::lowlevel::TyFSType NELIST_TYPE,
const uima::lowlevel::TyFSFeature HEAD_FEATURE,
const uima::lowlevel::TyFSFeature TAIL_FEATURE >
/*static*/ BasicListFS<T, LIST_TYPE, ELIST_TYPE, NELIST_TYPE, HEAD_FEATURE, TAIL_FEATURE>
BasicListFS<T, LIST_TYPE, ELIST_TYPE, NELIST_TYPE, HEAD_FEATURE, TAIL_FEATURE>::
createListFS( CAS & cas, T const & head, bool bIsPermanent ) {
lowlevel::FSHeap & rHeap = *uima::internal::FSPromoter::getFSHeap(cas);
lowlevel::TyFS tyFS = rHeap.createFS( NELIST_TYPE );
lowlevel::TyFS tyEFS = rHeap.createFS( ELIST_TYPE );
internal::setFSValueTempl(&cas, tyFS, HEAD_FEATURE, head);
rHeap.setFSValue(tyFS, TAIL_FEATURE, tyEFS);
return BasicListFS(tyFS, cas, false);
}
// explicit instantiation
template class BasicListFS< FeatureStructure, internal::gs_tyFSListType, internal::gs_tyEListType, internal::gs_tyNEListType, internal::gs_tyHeadFeature, internal::gs_tyTailFeature >;
// explicit instantiation
template class BasicListFS< float, internal::gs_tyFloatListType, internal::gs_tyEFloatListType, internal::gs_tyNEFloatListType, internal::gs_tyFloatHeadFeature, internal::gs_tyFloatTailFeature >;
// explicit instantiation
template class BasicListFS< int, internal::gs_tyIntListType, internal::gs_tyEIntListType, internal::gs_tyNEIntListType, internal::gs_tyIntHeadFeature, internal::gs_tyIntTailFeature >;
// explicit instantiation
template class BasicListFS< UnicodeStringRef, internal::gs_tyStringListType, internal::gs_tyEStringListType, internal::gs_tyNEStringListType, internal::gs_tyStringHeadFeature, internal::gs_tyStringTailFeature >;
} // namespace uima
/* ----------------------------------------------------------------------- */
/* <EOF> */