| /** \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> */ |
| |