m_StringLinkedList.F90 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553
  1. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2. ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
  3. !BOP -------------------------------------------------------------------
  4. !
  5. ! !MODULE: m_StringLinkedList - A linked-list of String
  6. !
  7. ! !DESCRIPTION:
  8. !
  9. ! !INTERFACE:
  10. module m_StringLinkedList
  11. use m_String,only : String
  12. implicit none
  13. private ! except
  14. public :: StringLinkedList ! The class data structure
  15. ! o An object of a StringLinkedList should be defined
  16. ! as a pointer of a StringLinkedList. It is often
  17. ! represented by a pointer to the head-node of the
  18. ! linked-list.
  19. !
  20. ! o A node in a StringLinkedList is specificed by a
  21. ! reference pointer. A reference pointer is a
  22. ! logical reference of a node in the list. However,
  23. ! it does not physically point to that node. In
  24. ! fact, a reference pointer normally references to
  25. ! the node physically pointed by the pointer in the
  26. ! node physically pointed by the reference pointer,
  27. !
  28. ! [this] -> [..|next] -> [..|next]
  29. !
  30. ! where the last node is the logically referenced
  31. ! node.
  32. public :: StringLinkedList_init ! constructor
  33. public :: StringLinkedList_clean ! destructor
  34. ! A _clean() action will reset a StringLinkedList to its
  35. ! pre-_init() status.
  36. public :: StringLinkedList_insert ! grower, insert a node
  37. public :: StringLinkedList_delete ! ungrower, delete a node
  38. ! Both procedures processing the node through a given
  39. ! reference pointer. The reference pointer will not
  40. ! be modified directly through either _insert() or
  41. ! _delete(). It is the pointer in the node physically
  42. ! pointed by a reference pointer got modified. Also,
  43. ! the node logically referenced by the reference
  44. ! pointer is either the new node for an _insert(), and
  45. ! the removed node for a _delete().
  46. public :: StringLinkedList_eol ! inquirer, is an end-node?
  47. ! An end-of-list situation occurs when the reference
  48. ! pointer is logically referencing to the end-node or
  49. ! beyond. Note that an end-node links to itself.
  50. public :: StringLinkedList_next ! iterator, go to the next node.
  51. public :: StringLinkedList_count ! counter
  52. ! Count the number of nodes from this reference pointer,
  53. ! starting from and including the logical node but
  54. ! excluding the end-node.
  55. public :: StringLinkedList_get ! fetcher
  56. ! Get the value logically referenced by a reference
  57. ! pointer. Return EOL if the referenced node is an
  58. ! EOL(). The reference pointer will be iterated to
  59. ! the next node if the referenced node is not an EOL.
  60. type StringLinkedList
  61. type(String) :: str
  62. type(StringLinkedList),pointer :: next
  63. end type StringLinkedList
  64. interface StringLinkedList_init ; module procedure &
  65. init_
  66. end interface
  67. interface StringLinkedList_clean ; module procedure &
  68. clean_
  69. end interface
  70. interface StringLinkedList_insert; module procedure &
  71. insertc_, & ! insert a CHARACTER(len=*) argument
  72. inserts_ ! insert a String argument
  73. end interface
  74. interface StringLinkedList_delete; module procedure &
  75. delete_
  76. end interface
  77. interface StringLinkedList_eol ; module procedure &
  78. eol_
  79. end interface
  80. interface StringLinkedList_next ; module procedure &
  81. next_
  82. end interface
  83. interface StringLinkedList_count ; module procedure &
  84. count_
  85. end interface
  86. interface StringLinkedList_get ; module procedure &
  87. getc_, & ! get as a CHARACTER(len=*)
  88. gets_ ! get as a String
  89. end interface
  90. ! !REVISION HISTORY:
  91. ! 16Feb00 - Jing Guo <guo@dao.gsfc.nasa.gov>
  92. ! - initial prototype/prolog/code
  93. !EOP ___________________________________________________________________
  94. character(len=*),parameter :: myname='MCT(MPEU)::m_StringLinkedList'
  95. ! Examples:
  96. !
  97. ! 1) Creating a first-in-first-out linked-list,
  98. !
  99. ! type(StringLinkedList),pointer :: head,this
  100. ! character(len=80) :: aline
  101. !
  102. ! call StringLinkedList_init(head)
  103. ! this => head
  104. ! do
  105. ! read(*,'(a)',iostat=ier) aline
  106. ! if(ier/=0) exit
  107. ! call StringLinkedList_insert(trim(aline),this)
  108. ! call StringLinkedList_next(this)
  109. ! end do
  110. !
  111. ! 2) Creating a last-in-first-out linked-list, Note that the only
  112. ! difference from Example (1) is without a call to
  113. ! StringLinkedList_next().
  114. !
  115. ! type(StringLinkedList),pointer :: head,this
  116. ! character(len=80) :: aline
  117. !
  118. ! call StringLinkedList_init(head)
  119. ! this => head
  120. ! do
  121. ! read(*,'(a)',iostat=ier) aline
  122. ! if(ier/=0) exit
  123. ! call StringLinkedList_insert(trim(aline),this)
  124. ! end do
  125. !
  126. contains
  127. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  128. ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
  129. !BOP -------------------------------------------------------------------
  130. !
  131. ! !IROUTINE: init_ - initialize a StringLinkedList from a pointer
  132. !
  133. ! !DESCRIPTION:
  134. !
  135. ! !INTERFACE:
  136. subroutine init_(head)
  137. use m_die, only : die
  138. use m_mall,only : mall_ison,mall_ci
  139. implicit none
  140. type(StringLinkedList),pointer :: head ! (out) a list
  141. ! !REVISION HISTORY:
  142. ! 22Feb00 - Jing Guo <guo@dao.gsfc.nasa.gov>
  143. ! - initial prototype/prolog/code
  144. !EOP ___________________________________________________________________
  145. character(len=*),parameter :: myname_=myname//'::init_'
  146. type(StringLinkedList),pointer :: tail
  147. integer :: ier
  148. ! Two special nodes are needed for a linked-list, according to
  149. ! Robert Sedgewick (Algorithms, QA76.6.S435, page 21).
  150. !
  151. ! It seems only _head_ will be needed for external references.
  152. ! Node _tail_ will be used to denote an end-node.
  153. allocate(head,tail,stat=ier)
  154. if(ier/=0) call die(myname_,'allocate()',ier)
  155. if(mall_ison()) call mall_ci(2,myname) ! for two nodes
  156. head%next => tail
  157. tail%next => tail
  158. nullify(tail)
  159. end subroutine init_
  160. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  161. ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
  162. !BOP -------------------------------------------------------------------
  163. !
  164. ! !IROUTINE: insertc_ - insert before the logically referenced node
  165. !
  166. ! !DESCRIPTION:
  167. !
  168. ! !INTERFACE:
  169. subroutine insertc_(cstr,this)
  170. use m_String,only : String_init
  171. use m_mall, only : mall_ison,mall_ci
  172. use m_die, only : die
  173. implicit none
  174. character(len=*),intent(in) :: cstr ! a new entry
  175. type(StringLinkedList),pointer :: this ! (in) a node
  176. ! !REVISION HISTORY:
  177. ! 16Feb00 - Jing Guo <guo@dao.gsfc.nasa.gov>
  178. ! - initial prototype/prolog/code
  179. !EOP ___________________________________________________________________
  180. character(len=*),parameter :: myname_=myname//'::insertc_'
  181. type(StringLinkedList),pointer :: tmpl
  182. integer :: ier
  183. ! Create a memory cell for the new entry of StringLinkedList
  184. allocate(tmpl,stat=ier)
  185. if(ier/=0) call die(myname_,'allocate()',ier)
  186. if(mall_ison()) call mall_ci(1,myname) ! for one nodes
  187. ! Store the data
  188. call String_init(tmpl%str,cstr)
  189. ! Rebuild the links, if the List was not empty
  190. tmpl%next => this%next
  191. this%next => tmpl
  192. ! Clean the working pointer
  193. nullify(tmpl)
  194. end subroutine insertc_
  195. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  196. ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
  197. !BOP -------------------------------------------------------------------
  198. !
  199. ! !IROUTINE: inserts_ - insert before the logically referenced node
  200. !
  201. ! !DESCRIPTION:
  202. !
  203. ! !INTERFACE:
  204. subroutine inserts_(str,this)
  205. use m_String,only : String,String_init
  206. use m_mall, only : mall_ison,mall_ci
  207. use m_die, only : die
  208. implicit none
  209. type(String),intent(in) :: str ! a new entry
  210. type(StringLinkedList),pointer :: this ! (in) a node
  211. ! !REVISION HISTORY:
  212. ! 16Feb00 - Jing Guo <guo@dao.gsfc.nasa.gov>
  213. ! - initial prototype/prolog/code
  214. !EOP ___________________________________________________________________
  215. character(len=*),parameter :: myname_=myname//'::inserts_'
  216. type(StringLinkedList),pointer :: tmpl
  217. integer :: ier
  218. ! Create a memory cell for the new entry of StringLinkedList
  219. allocate(tmpl,stat=ier)
  220. if(ier/=0) call die(myname_,'allocate()',ier)
  221. if(mall_ison()) call mall_ci(1,myname) ! for one nodes
  222. ! Store the data
  223. call String_init(tmpl%str,str)
  224. ! Rebuild the links, if the List was not empty
  225. tmpl%next => this%next
  226. this%next => tmpl
  227. ! Clean the working pointer, if it mean anyting
  228. nullify(tmpl)
  229. end subroutine inserts_
  230. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  231. ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
  232. !BOP -------------------------------------------------------------------
  233. !
  234. ! !IROUTINE: delete_ - delete the logically referenced node
  235. !
  236. ! !DESCRIPTION:
  237. !
  238. ! !INTERFACE:
  239. subroutine delete_(this)
  240. use m_String,only : String_clean
  241. use m_mall, only : mall_ison,mall_co
  242. use m_die, only : die
  243. implicit none
  244. type(StringLinkedList),pointer :: this ! (in) a node
  245. ! !REVISION HISTORY:
  246. ! 17Feb00 - Jing Guo <guo@dao.gsfc.nasa.gov>
  247. ! - initial prototype/prolog/code
  248. !EOP ___________________________________________________________________
  249. character(len=*),parameter :: myname_=myname//'::delete_'
  250. type(StringLinkedList),pointer :: tmpl
  251. integer :: ier
  252. tmpl => this%next%next ! hold the next target
  253. call String_clean(this%next%str) ! remove the next storage
  254. if(mall_ison()) call mall_co(1,myname) ! removing one node
  255. deallocate(this%next,stat=ier) ! Clean memory gabage
  256. if(ier/=0) call die(myname_,'deallocate()',ier)
  257. ! Skip the current target. Rebuild the link to the target
  258. ! of the current target.
  259. this%next => tmpl
  260. ! Clean the working pointer, if it mean anything
  261. nullify(tmpl)
  262. end subroutine delete_
  263. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  264. ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
  265. !BOP -------------------------------------------------------------------
  266. !
  267. ! !IROUTINE: eol_ - if the logically referenced node is an end-node
  268. !
  269. ! !DESCRIPTION:
  270. !
  271. ! !INTERFACE:
  272. function eol_(this)
  273. implicit none
  274. type(StringLinkedList),pointer :: this ! (in) a node
  275. logical :: eol_ ! returned value
  276. ! !REVISION HISTORY:
  277. ! 23Feb00 - Jing Guo <guo@dao.gsfc.nasa.gov>
  278. ! - initial prototype/prolog/code
  279. !EOP ___________________________________________________________________
  280. character(len=*),parameter :: myname_=myname//'::eol_'
  281. eol_=associated(this%next,this%next%next)
  282. end function eol_
  283. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  284. ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
  285. !BOP -------------------------------------------------------------------
  286. !
  287. ! !IROUTINE: next_ - point a reference pointer to the next node
  288. !
  289. ! !DESCRIPTION:
  290. !
  291. ! !INTERFACE:
  292. subroutine next_(this)
  293. implicit none
  294. type(StringLinkedList),pointer :: this ! (inout) a node
  295. ! !REVISION HISTORY:
  296. ! 23Feb00 - Jing Guo <guo@dao.gsfc.nasa.gov>
  297. ! - initial prototype/prolog/code
  298. !EOP ___________________________________________________________________
  299. character(len=*),parameter :: myname_=myname//'::next_'
  300. this => this%next
  301. end subroutine next_
  302. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  303. ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
  304. !BOP -------------------------------------------------------------------
  305. !
  306. ! !IROUTINE: count_ - count the number of nodes
  307. !
  308. ! !DESCRIPTION:
  309. !
  310. ! !INTERFACE:
  311. function count_(this)
  312. implicit none
  313. type(StringLinkedList),pointer :: this ! (in) a node
  314. integer :: count_ ! returned value
  315. ! !REVISION HISTORY:
  316. ! 24Feb00 - Jing Guo <guo@dao.gsfc.nasa.gov>
  317. ! - initial prototype/prolog/code
  318. !EOP ___________________________________________________________________
  319. character(len=*),parameter :: myname_=myname//'::count_'
  320. type(StringLinkedList),pointer :: tmpl
  321. tmpl => this
  322. count_=0
  323. do while(.not.eol_(tmpl))
  324. count_=count_+1
  325. call next_(tmpl)
  326. end do
  327. nullify(tmpl)
  328. end function count_
  329. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  330. ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
  331. !BOP -------------------------------------------------------------------
  332. !
  333. ! !IROUTINE: getc_ - get the logically referenced value as CHARACTERs
  334. !
  335. ! !DESCRIPTION:
  336. !
  337. ! !INTERFACE:
  338. subroutine getc_(this,cstr,eol)
  339. use m_String,only : String
  340. use m_String,only : String_init
  341. use m_String,only : String_clean
  342. use m_String,only : char
  343. implicit none
  344. type(StringLinkedList),pointer :: this ! (inout) a node
  345. character(len=*),intent(out) :: cstr ! the referenced value
  346. logical ,intent(out) :: eol ! if the node is an end-node
  347. ! !REVISION HISTORY:
  348. ! 17Feb00 - Jing Guo <guo@dao.gsfc.nasa.gov>
  349. ! - initial prototype/prolog/code
  350. !EOP ___________________________________________________________________
  351. character(len=*),parameter :: myname_=myname//'::getc_'
  352. type(String) :: str
  353. call gets_(this,str,eol)
  354. if(.not.eol) then
  355. cstr=char(str)
  356. call String_clean(str)
  357. endif
  358. end subroutine getc_
  359. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  360. ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
  361. !BOP -------------------------------------------------------------------
  362. !
  363. ! !IROUTINE: gets_ - get the logically referenced value as a String
  364. !
  365. ! !DESCRIPTION:
  366. !
  367. ! !INTERFACE:
  368. subroutine gets_(this,str,eol)
  369. use m_String,only : String
  370. use m_String,only : String_init
  371. implicit none
  372. type(StringLinkedList),pointer :: this ! (inout) a node
  373. type(String),intent(out) :: str ! the referenced value
  374. logical ,intent(out) :: eol ! if the node is an end-node
  375. ! !REVISION HISTORY:
  376. ! 17Feb00 - Jing Guo <guo@dao.gsfc.nasa.gov>
  377. ! - initial prototype/prolog/code
  378. !EOP ___________________________________________________________________
  379. character(len=*),parameter :: myname_=myname//'::gets_'
  380. eol=eol_(this)
  381. if(.not.eol) then
  382. call String_init(str,this%next%str)
  383. call next_(this)
  384. endif
  385. end subroutine gets_
  386. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  387. ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
  388. !BOP -------------------------------------------------------------------
  389. !
  390. ! !IROUTINE: clean_ - clean the whole object from this point
  391. !
  392. ! !DESCRIPTION:
  393. !
  394. ! !INTERFACE:
  395. subroutine clean_(head,stat)
  396. use m_die,only : die,perr
  397. use m_mall,only : mall_ison,mall_co
  398. implicit none
  399. type(StringLinkedList),pointer :: head ! (inout) a head-node
  400. integer,optional,intent(out) :: stat ! return status
  401. ! !REVISION HISTORY:
  402. ! 17Feb00 - Jing Guo <guo@dao.gsfc.nasa.gov>
  403. ! - initial prototype/prolog/code
  404. !EOP ___________________________________________________________________
  405. character(len=*),parameter :: myname_=myname//'::clean_'
  406. integer :: ier
  407. logical :: err
  408. if(present(stat)) stat=0
  409. ! Verify if the pointer is valid
  410. err=.not.associated(head)
  411. if(.not.err) err=.not.associated(head%next)
  412. if(err) then
  413. call perr(myname_,'Attempting to clean an uninitialized list')
  414. if(.not.present(stat)) call die(myname_)
  415. stat=-1
  416. return
  417. endif
  418. ! Clean the rest before delete the current one.
  419. do
  420. if(eol_(head)) exit
  421. call delete_(head)
  422. end do
  423. if(mall_ison()) call mall_co(2,myname) ! remove two nodes
  424. deallocate(head%next,stat=ier)
  425. if(ier==0) deallocate(head,stat=ier)
  426. if(ier/=0) then
  427. call perr(myname_,'deallocate()',ier)
  428. if(.not.present(stat)) call die(myname_)
  429. stat=-1
  430. return
  431. endif
  432. end subroutine clean_
  433. end module m_StringLinkedList