123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553 |
- !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
- !BOP -------------------------------------------------------------------
- !
- ! !MODULE: m_StringLinkedList - A linked-list of String
- !
- ! !DESCRIPTION:
- !
- ! !INTERFACE:
- module m_StringLinkedList
- use m_String,only : String
- implicit none
- private ! except
- public :: StringLinkedList ! The class data structure
- ! o An object of a StringLinkedList should be defined
- ! as a pointer of a StringLinkedList. It is often
- ! represented by a pointer to the head-node of the
- ! linked-list.
- !
- ! o A node in a StringLinkedList is specificed by a
- ! reference pointer. A reference pointer is a
- ! logical reference of a node in the list. However,
- ! it does not physically point to that node. In
- ! fact, a reference pointer normally references to
- ! the node physically pointed by the pointer in the
- ! node physically pointed by the reference pointer,
- !
- ! [this] -> [..|next] -> [..|next]
- !
- ! where the last node is the logically referenced
- ! node.
- public :: StringLinkedList_init ! constructor
- public :: StringLinkedList_clean ! destructor
- ! A _clean() action will reset a StringLinkedList to its
- ! pre-_init() status.
- public :: StringLinkedList_insert ! grower, insert a node
- public :: StringLinkedList_delete ! ungrower, delete a node
- ! Both procedures processing the node through a given
- ! reference pointer. The reference pointer will not
- ! be modified directly through either _insert() or
- ! _delete(). It is the pointer in the node physically
- ! pointed by a reference pointer got modified. Also,
- ! the node logically referenced by the reference
- ! pointer is either the new node for an _insert(), and
- ! the removed node for a _delete().
- public :: StringLinkedList_eol ! inquirer, is an end-node?
- ! An end-of-list situation occurs when the reference
- ! pointer is logically referencing to the end-node or
- ! beyond. Note that an end-node links to itself.
- public :: StringLinkedList_next ! iterator, go to the next node.
- public :: StringLinkedList_count ! counter
-
- ! Count the number of nodes from this reference pointer,
- ! starting from and including the logical node but
- ! excluding the end-node.
- public :: StringLinkedList_get ! fetcher
- ! Get the value logically referenced by a reference
- ! pointer. Return EOL if the referenced node is an
- ! EOL(). The reference pointer will be iterated to
- ! the next node if the referenced node is not an EOL.
- type StringLinkedList
- type(String) :: str
- type(StringLinkedList),pointer :: next
- end type StringLinkedList
- interface StringLinkedList_init ; module procedure &
- init_
- end interface
- interface StringLinkedList_clean ; module procedure &
- clean_
- end interface
- interface StringLinkedList_insert; module procedure &
- insertc_, & ! insert a CHARACTER(len=*) argument
- inserts_ ! insert a String argument
- end interface
- interface StringLinkedList_delete; module procedure &
- delete_
- end interface
- interface StringLinkedList_eol ; module procedure &
- eol_
- end interface
- interface StringLinkedList_next ; module procedure &
- next_
- end interface
- interface StringLinkedList_count ; module procedure &
- count_
- end interface
- interface StringLinkedList_get ; module procedure &
- getc_, & ! get as a CHARACTER(len=*)
- gets_ ! get as a String
- end interface
- ! !REVISION HISTORY:
- ! 16Feb00 - Jing Guo <guo@dao.gsfc.nasa.gov>
- ! - initial prototype/prolog/code
- !EOP ___________________________________________________________________
- character(len=*),parameter :: myname='MCT(MPEU)::m_StringLinkedList'
- ! Examples:
- !
- ! 1) Creating a first-in-first-out linked-list,
- !
- ! type(StringLinkedList),pointer :: head,this
- ! character(len=80) :: aline
- !
- ! call StringLinkedList_init(head)
- ! this => head
- ! do
- ! read(*,'(a)',iostat=ier) aline
- ! if(ier/=0) exit
- ! call StringLinkedList_insert(trim(aline),this)
- ! call StringLinkedList_next(this)
- ! end do
- !
- ! 2) Creating a last-in-first-out linked-list, Note that the only
- ! difference from Example (1) is without a call to
- ! StringLinkedList_next().
- !
- ! type(StringLinkedList),pointer :: head,this
- ! character(len=80) :: aline
- !
- ! call StringLinkedList_init(head)
- ! this => head
- ! do
- ! read(*,'(a)',iostat=ier) aline
- ! if(ier/=0) exit
- ! call StringLinkedList_insert(trim(aline),this)
- ! end do
- !
- contains
- !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
- !BOP -------------------------------------------------------------------
- !
- ! !IROUTINE: init_ - initialize a StringLinkedList from a pointer
- !
- ! !DESCRIPTION:
- !
- ! !INTERFACE:
- subroutine init_(head)
- use m_die, only : die
- use m_mall,only : mall_ison,mall_ci
- implicit none
- type(StringLinkedList),pointer :: head ! (out) a list
- ! !REVISION HISTORY:
- ! 22Feb00 - Jing Guo <guo@dao.gsfc.nasa.gov>
- ! - initial prototype/prolog/code
- !EOP ___________________________________________________________________
- character(len=*),parameter :: myname_=myname//'::init_'
- type(StringLinkedList),pointer :: tail
- integer :: ier
- ! Two special nodes are needed for a linked-list, according to
- ! Robert Sedgewick (Algorithms, QA76.6.S435, page 21).
- !
- ! It seems only _head_ will be needed for external references.
- ! Node _tail_ will be used to denote an end-node.
- allocate(head,tail,stat=ier)
- if(ier/=0) call die(myname_,'allocate()',ier)
- if(mall_ison()) call mall_ci(2,myname) ! for two nodes
- head%next => tail
- tail%next => tail
- nullify(tail)
- end subroutine init_
- !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
- !BOP -------------------------------------------------------------------
- !
- ! !IROUTINE: insertc_ - insert before the logically referenced node
- !
- ! !DESCRIPTION:
- !
- ! !INTERFACE:
- subroutine insertc_(cstr,this)
- use m_String,only : String_init
- use m_mall, only : mall_ison,mall_ci
- use m_die, only : die
- implicit none
- character(len=*),intent(in) :: cstr ! a new entry
- type(StringLinkedList),pointer :: this ! (in) a node
- ! !REVISION HISTORY:
- ! 16Feb00 - Jing Guo <guo@dao.gsfc.nasa.gov>
- ! - initial prototype/prolog/code
- !EOP ___________________________________________________________________
- character(len=*),parameter :: myname_=myname//'::insertc_'
- type(StringLinkedList),pointer :: tmpl
- integer :: ier
- ! Create a memory cell for the new entry of StringLinkedList
- allocate(tmpl,stat=ier)
- if(ier/=0) call die(myname_,'allocate()',ier)
- if(mall_ison()) call mall_ci(1,myname) ! for one nodes
- ! Store the data
- call String_init(tmpl%str,cstr)
- ! Rebuild the links, if the List was not empty
- tmpl%next => this%next
- this%next => tmpl
- ! Clean the working pointer
- nullify(tmpl)
- end subroutine insertc_
- !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
- !BOP -------------------------------------------------------------------
- !
- ! !IROUTINE: inserts_ - insert before the logically referenced node
- !
- ! !DESCRIPTION:
- !
- ! !INTERFACE:
- subroutine inserts_(str,this)
- use m_String,only : String,String_init
- use m_mall, only : mall_ison,mall_ci
- use m_die, only : die
- implicit none
- type(String),intent(in) :: str ! a new entry
- type(StringLinkedList),pointer :: this ! (in) a node
- ! !REVISION HISTORY:
- ! 16Feb00 - Jing Guo <guo@dao.gsfc.nasa.gov>
- ! - initial prototype/prolog/code
- !EOP ___________________________________________________________________
- character(len=*),parameter :: myname_=myname//'::inserts_'
- type(StringLinkedList),pointer :: tmpl
- integer :: ier
- ! Create a memory cell for the new entry of StringLinkedList
- allocate(tmpl,stat=ier)
- if(ier/=0) call die(myname_,'allocate()',ier)
- if(mall_ison()) call mall_ci(1,myname) ! for one nodes
- ! Store the data
- call String_init(tmpl%str,str)
- ! Rebuild the links, if the List was not empty
- tmpl%next => this%next
- this%next => tmpl
- ! Clean the working pointer, if it mean anyting
- nullify(tmpl)
- end subroutine inserts_
- !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
- !BOP -------------------------------------------------------------------
- !
- ! !IROUTINE: delete_ - delete the logically referenced node
- !
- ! !DESCRIPTION:
- !
- ! !INTERFACE:
- subroutine delete_(this)
- use m_String,only : String_clean
- use m_mall, only : mall_ison,mall_co
- use m_die, only : die
- implicit none
- type(StringLinkedList),pointer :: this ! (in) a node
- ! !REVISION HISTORY:
- ! 17Feb00 - Jing Guo <guo@dao.gsfc.nasa.gov>
- ! - initial prototype/prolog/code
- !EOP ___________________________________________________________________
- character(len=*),parameter :: myname_=myname//'::delete_'
- type(StringLinkedList),pointer :: tmpl
- integer :: ier
- tmpl => this%next%next ! hold the next target
- call String_clean(this%next%str) ! remove the next storage
- if(mall_ison()) call mall_co(1,myname) ! removing one node
- deallocate(this%next,stat=ier) ! Clean memory gabage
- if(ier/=0) call die(myname_,'deallocate()',ier)
- ! Skip the current target. Rebuild the link to the target
- ! of the current target.
- this%next => tmpl
- ! Clean the working pointer, if it mean anything
- nullify(tmpl)
- end subroutine delete_
- !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
- !BOP -------------------------------------------------------------------
- !
- ! !IROUTINE: eol_ - if the logically referenced node is an end-node
- !
- ! !DESCRIPTION:
- !
- ! !INTERFACE:
- function eol_(this)
- implicit none
- type(StringLinkedList),pointer :: this ! (in) a node
- logical :: eol_ ! returned value
- ! !REVISION HISTORY:
- ! 23Feb00 - Jing Guo <guo@dao.gsfc.nasa.gov>
- ! - initial prototype/prolog/code
- !EOP ___________________________________________________________________
- character(len=*),parameter :: myname_=myname//'::eol_'
- eol_=associated(this%next,this%next%next)
- end function eol_
- !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
- !BOP -------------------------------------------------------------------
- !
- ! !IROUTINE: next_ - point a reference pointer to the next node
- !
- ! !DESCRIPTION:
- !
- ! !INTERFACE:
- subroutine next_(this)
- implicit none
- type(StringLinkedList),pointer :: this ! (inout) a node
- ! !REVISION HISTORY:
- ! 23Feb00 - Jing Guo <guo@dao.gsfc.nasa.gov>
- ! - initial prototype/prolog/code
- !EOP ___________________________________________________________________
- character(len=*),parameter :: myname_=myname//'::next_'
- this => this%next
- end subroutine next_
- !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
- !BOP -------------------------------------------------------------------
- !
- ! !IROUTINE: count_ - count the number of nodes
- !
- ! !DESCRIPTION:
- !
- ! !INTERFACE:
- function count_(this)
- implicit none
- type(StringLinkedList),pointer :: this ! (in) a node
- integer :: count_ ! returned value
- ! !REVISION HISTORY:
- ! 24Feb00 - Jing Guo <guo@dao.gsfc.nasa.gov>
- ! - initial prototype/prolog/code
- !EOP ___________________________________________________________________
- character(len=*),parameter :: myname_=myname//'::count_'
- type(StringLinkedList),pointer :: tmpl
- tmpl => this
- count_=0
- do while(.not.eol_(tmpl))
- count_=count_+1
- call next_(tmpl)
- end do
- nullify(tmpl)
- end function count_
- !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
- !BOP -------------------------------------------------------------------
- !
- ! !IROUTINE: getc_ - get the logically referenced value as CHARACTERs
- !
- ! !DESCRIPTION:
- !
- ! !INTERFACE:
- subroutine getc_(this,cstr,eol)
- use m_String,only : String
- use m_String,only : String_init
- use m_String,only : String_clean
- use m_String,only : char
- implicit none
- type(StringLinkedList),pointer :: this ! (inout) a node
- character(len=*),intent(out) :: cstr ! the referenced value
- logical ,intent(out) :: eol ! if the node is an end-node
- ! !REVISION HISTORY:
- ! 17Feb00 - Jing Guo <guo@dao.gsfc.nasa.gov>
- ! - initial prototype/prolog/code
- !EOP ___________________________________________________________________
- character(len=*),parameter :: myname_=myname//'::getc_'
- type(String) :: str
- call gets_(this,str,eol)
- if(.not.eol) then
- cstr=char(str)
- call String_clean(str)
- endif
- end subroutine getc_
- !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
- !BOP -------------------------------------------------------------------
- !
- ! !IROUTINE: gets_ - get the logically referenced value as a String
- !
- ! !DESCRIPTION:
- !
- ! !INTERFACE:
- subroutine gets_(this,str,eol)
- use m_String,only : String
- use m_String,only : String_init
- implicit none
- type(StringLinkedList),pointer :: this ! (inout) a node
- type(String),intent(out) :: str ! the referenced value
- logical ,intent(out) :: eol ! if the node is an end-node
- ! !REVISION HISTORY:
- ! 17Feb00 - Jing Guo <guo@dao.gsfc.nasa.gov>
- ! - initial prototype/prolog/code
- !EOP ___________________________________________________________________
- character(len=*),parameter :: myname_=myname//'::gets_'
- eol=eol_(this)
- if(.not.eol) then
- call String_init(str,this%next%str)
- call next_(this)
- endif
- end subroutine gets_
- !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
- !BOP -------------------------------------------------------------------
- !
- ! !IROUTINE: clean_ - clean the whole object from this point
- !
- ! !DESCRIPTION:
- !
- ! !INTERFACE:
- subroutine clean_(head,stat)
- use m_die,only : die,perr
- use m_mall,only : mall_ison,mall_co
- implicit none
- type(StringLinkedList),pointer :: head ! (inout) a head-node
- integer,optional,intent(out) :: stat ! return status
- ! !REVISION HISTORY:
- ! 17Feb00 - Jing Guo <guo@dao.gsfc.nasa.gov>
- ! - initial prototype/prolog/code
- !EOP ___________________________________________________________________
- character(len=*),parameter :: myname_=myname//'::clean_'
- integer :: ier
- logical :: err
- if(present(stat)) stat=0
- ! Verify if the pointer is valid
- err=.not.associated(head)
- if(.not.err) err=.not.associated(head%next)
- if(err) then
- call perr(myname_,'Attempting to clean an uninitialized list')
- if(.not.present(stat)) call die(myname_)
- stat=-1
- return
- endif
- ! Clean the rest before delete the current one.
- do
- if(eol_(head)) exit
- call delete_(head)
- end do
- if(mall_ison()) call mall_co(2,myname) ! remove two nodes
- deallocate(head%next,stat=ier)
- if(ier==0) deallocate(head,stat=ier)
- if(ier/=0) then
- call perr(myname_,'deallocate()',ier)
- if(.not.present(stat)) call die(myname_)
- stat=-1
- return
- endif
- end subroutine clean_
- end module m_StringLinkedList
|