Loading...
Searching...
No Matches
dc_url.f90
Go to the documentation of this file.
1!== dc_url.f90 - 変数 URL の文字列解析
2!
3! Authors:: Yasuhiro MORIKAWA, Eizi TOYODA
4! Version:: $Id: dc_url.f90,v 1.1 2009-03-20 09:09:52 morikawa Exp $
5! Tag Name:: $Name: $
6! Copyright:: Copyright (C) GFD Dennou Club, 2000-2005. All rights reserved.
7! License:: See COPYRIGHT[link:../../COPYRIGHT]
8!
9! This file provides dc_url
10!
11
12module dc_url
13 !
14 !== Overview
15 !
16 ! このモジュールは gtool4 変数 URL の文字列解析
17 ! を行うための手続きを提供します。
18 !
19 ! gtool4 変数の書式に関しては,
20 ! {gtool4 netCDF 規約}[link:../xref.htm#label-6]
21 ! の「5. 各種の文字列書式」を参照ください。
22 !
23 !== Procedures Summary
24 !
25 ! 手続き群の要約
26 !
27 ! UrlSplit :: 変数 URL を分解しファイル名、変数名、
28 ! 属性名および入出力範囲指定を取り出す
29 ! UrlMerge :: ファイル名、変数名、属性名および入出力範囲指定
30 ! を連結して変数 URL を作成
31 ! UrlResolve :: 変数 URL の補完
32 ! Url_Chop_IOrange :: 変数 URL から iorange を除去
33 ! UrlSearchIORange :: 変数 URL 内の iorange うち, ある次元に関する
34 ! 入出力範囲指定の値を取得
35 ! dc_url#operator(.OnTheSameFile.) :: 2 つの変数 URL
36 ! が同じファイルを指すかどうか判定
37 !
38 ! このモジュールは gtool4 変数において特別な役割を果たす
39 ! 文字のニーモニックを提供します。gtool4 変数解析の際には、
40 ! 直接文字を用いるのではなく、ここで提供する変数群
41 ! (GT_ATMARK 等) を利用してください。
42 !
43
44
45 implicit none
46 private
47
48 public:: url_chop_iorange
49 public:: operator(.onthesamefile.)
50
51 public:: urlmerge
52 interface urlmerge
53! module procedure url_merge_v_vvv
54 module procedure url_merge_cc
55 module procedure url_merge_cccc
56 module procedure url_merge_cccca
57 end interface
58
59 public:: urlsplit
60 interface urlsplit
61! module procedure url_split_v
62 module procedure url_split_c
63 end interface
64
65 public:: urlresolve
66 interface urlresolve
67 module procedure url_resolve_c
68 end interface
69
70 public:: urlsearchiorange
72 module procedure url_search_iorange
73 end interface
74
75 interface operator(.onthesamefile.)
76 module procedure urlonthesamefile
77 end interface
78
79 character, public, parameter:: gt_atmark = "@"
80 ! ファイル名と変数名の区切りに用いられます。
81 character, public, parameter:: gt_question = "?"
82 ! ファイル名と変数名の区切りに用いられます。
83 character, public, parameter:: gt_colon = ":"
84 ! 変数の属性を示す時に用いられます。
85 character, public, parameter:: gt_comma = ","
86 ! 入出力範囲の限定に用いられます。
87 character, public, parameter:: gt_equal = "="
88 ! 入出力範囲の限定に用いられます。
89 character, public, parameter:: gt_circumflex = "^"
90 ! 座標の位置を値ではなく、
91 ! 格子点番号で指定する時に用いられます。
92 character, public, parameter:: gt_plus = "+"
93 ! 属性の行頭にこの文字がつく場合、大域属性を示します。
94
95contains
96
97 ! ANUrlMerge - 変数 URL の合成
98 ! 空文字列の成分はないとみなされる。
99
100! type(VSTRING) function &
101! & url_merge_v_vvv(file, var, attr, iorange) result(result) !:nodoc:
102! use dcstring_base, only: VSTRING, operator(.cat.), operator(/=), &
103! & extract, operator(==) !:nodoc:
104! implicit none
105! type(VSTRING), intent(in):: file
106! type(VSTRING), intent(in), optional:: var
107! type(VSTRING), intent(in), optional:: attr
108! type(VSTRING), intent(in), optional:: iorange
109! result = file .cat. GT_ATMARK
110! if (present(var)) result = result .cat. var
111! if (present(attr)) then
112! if (attr /= "") result = result .cat. GT_COLON .cat. attr
113! endif
114! if (present(iorange)) then
115! if (extract(iorange, 1, 1) == GT_COMMA) then
116! result = result .cat. iorange
117! else if (iorange /= "") then
118! result = result .cat. GT_COMMA .cat. iorange
119! endif
120! endif
121! end function
122
123 function url_merge_cc(file, var) result(result)
124 !
125 ! ファイル名 file、変数名 var を結合して relsult として返します。
126 !
127 use dc_types, only: string
128 character(len = STRING):: result
129 character(len = *), intent(in):: file
130 character(len = *), intent(in):: var
131 continue
132 result = url_merge_cccc(file, var, "", "")
133 end function url_merge_cc
134
135 function url_merge_cccca(file, var, attr, iorange) result(result)
136 !
137 ! ファイル名 file、変数名 var、属性 attr、
138 ! 入出力範囲 iorange を結合して relsult として返します。
139 ! iorange には文字型配列を与えます。文字型配列のそれぞれの要素は
140 ! GT_COMMA で連結されてから結合されます。
141 !
142 use dc_types, only: string
143 character(len = STRING):: result
144 character(len = *), intent(in):: file
145 character(len = *), intent(in):: var
146 character(len = *), intent(in):: attr
147 character(len = *), intent(in):: iorange(:)
148 integer:: i
149 continue
150 if (file /= "") then
151 result = trim(file) // gt_atmark
152 else
153 result = gt_atmark
154 endif
155 if (var /= "") result = trim(result) // var
156 if (attr /= "") then
157 result = trim(result) // gt_colon // attr
158 endif
159 do i = 1, size(iorange)
160 if (iorange(i) /= "") then
161 if (iorange(i)(1:1) == gt_comma) then
162 result = trim(result) // trim(iorange(i))
163 else
164 result = trim(result) // gt_comma // trim(iorange(i))
165 endif
166 endif
167 end do
168 end function url_merge_cccca
169
170 function url_merge_cccc(file, var, attr, iorange) result(result)
171 !
172 ! ファイル名 file、変数名 var、属性 attr、
173 ! 入出力範囲 iorange を結合して relsult として返します。
174 !
175 use dc_types, only: string
176 character(len = STRING):: result
177 character(len = *), intent(in):: file
178 character(len = *), intent(in):: var
179 character(len = *), intent(in):: attr
180 character(len = *), intent(in):: iorange
181 continue
182 if (trim(file) /= "") then
183 result = trim(file) // gt_atmark
184 else
185 result = gt_atmark
186 endif
187 if (trim(var) /= "") result = trim(result) // var
188 if (trim(attr) /= "") then
189 result = trim(result) // gt_colon // attr
190 endif
191 if (trim(iorange) /= "") then
192 if (iorange(1:1) == gt_comma) then
193 result = trim(result) // iorange
194 else
195 result = trim(result) // gt_comma // iorange
196 endif
197 endif
198 end function url_merge_cccc
199
200 subroutine url_chop_iorange(fullname, iorange, remainder)
201 !
202 ! fullname で与えられる変数 URL の入出力範囲指定部分と
203 ! 残りの部分とを分離し、それぞれ iorange と remainder に返します。
204 !
205 use dc_types, only: string
206 character(len = *), intent(in):: fullname
207 character(len = *), intent(out):: iorange ! 入出力範囲指定部分
208 character(len = *), intent(out):: remainder ! 残りの部分
209 character(STRING):: file, var, attr
210 call urlsplit(fullname, file=file, var=var, attr=attr, iorange=iorange)
211 remainder = url_merge_cccc(file=file, var=var, attr=attr, iorange="")
212 end subroutine url_chop_iorange
213
214 function url_search_iorange(fullname, dimvar) result(result)
215 !
216 ! 変数 URL *fullname* 内の, 次元 *dimvar* に関する
217 ! 入出力範囲指定の値を取得します。
218 !
219 ! fullname には gtool4 変数全体または入出力範囲指定部分の値を与えます。
220 ! dimvar には入出力範囲指定部分に含まれる次元変数名を与えます。
221 ! dimvar に対応する次元変数が存在する場合、その値を返します。
222 ! dimvar に対応する次元変数が存在しない場合、空文字を返します。
223 !
224 use dc_types, only: string
225 use dc_string, only: split
226 character(len = *), intent(in):: fullname
227 character(len = *), intent(in):: dimvar
228 character(len = STRING):: result
229 character(STRING):: file, var, attr, iorange
230 character(STRING), pointer :: ioranges_slice(:) => null()
231 integer :: i, eqpos, atmark
232 continue
233 result = ""
234 ! @ または ? が含まれているなら urlsplit で分離
235 atmark = index(fullname, gt_question)
236 if (atmark == 0) atmark = index(fullname, gt_atmark)
237 if (atmark /= 0) then
238 call urlsplit(fullname, file=file, var=var, attr=attr, iorange=iorange)
239 else
240 iorange = fullname
241 end if
242 call split(iorange, ioranges_slice, gt_comma)
243 do i = 1, size(ioranges_slice)
244 eqpos = index(ioranges_slice(i), gt_equal)
245 if (ioranges_slice(i)(1:eqpos-1) == trim(dimvar)) then
246 result = trim(ioranges_slice(i)(eqpos+1:))
247 exit
248 end if
249 end do
250 deallocate(ioranges_slice)
251 end function url_search_iorange
252
253 subroutine url_split_c(fullname, file, var, attr, iorange)
254 !
255 ! fullname で与えられる変数 URL を、ファイル名 file、 変数名 var、
256 ! 属性名 attr、入出力範囲指定 iorange に分解して返します。
257 ! 見つからない成分には空文字列が代入されます。
258 !
259 use dc_types, only: string
260 character(len = *), intent(in):: fullname
261 character(len = *), intent(out), optional:: file, var, attr, iorange
262 character(len = STRING):: varpart
263 integer:: atmark, colon, comma
264 character(len = *), parameter:: VARNAME_SET &
265 = "0123456789eEdD+-=^,.:_" &
266 // "ABCDEFGHIJKLMNOPQRSTUVWXYZ" &
267 // "abcdefghijklmnopqrstuvwxyz"
268 continue
269 ! まず URL と変数属性指定 (? または @ 以降) を分離する。
270 ! URL は @ を含みうるため、最後の @ 以降に対して変数属性
271 ! として許されない文字(典型的には '/')が含まれていたら
272 ! 当該 @ は URL の一部とみなす。
273 atmark = index(fullname, gt_question)
274 if (atmark == 0) then
275 atmark = index(fullname, gt_atmark, back=.true.)
276 if (atmark /= 0) then
277 if (verify(trim(fullname(atmark+1: )), varname_set) /= 0) then
278 atmark = 0
279 endif
280 endif
281 endif
282 if (atmark == 0) then
283 ! 変数属性指定はなかった。
284 if (present(file)) file = fullname
285 if (present(var)) var = ''
286 if (present(attr)) attr = ''
287 if (present(iorange)) iorange = ''
288 return
289 endif
290 varpart = fullname(atmark+1: )
291 ! 変数属性指定があった。
292 if (present(file)) file = fullname(1: atmark - 1)
293 ! 範囲指定を探索する。
294 comma = index(varpart, gt_comma)
295 if (comma /= 0) then
296 ! 範囲指定がみつかった。
297 if (present(var)) var = varpart(1: comma - 1)
298 if (present(attr)) attr = ''
299 if (present(iorange)) iorange = varpart(comma + 1: )
300 return
301 endif
302 if (present(iorange)) iorange = ''
303 ! 範囲指定がなかったので、属性名の検索をする。
304 colon = index(varpart, gt_colon)
305 if (colon == 0) then
306 if (present(var)) var = varpart
307 if (present(attr)) attr = ''
308 varpart = ''
309 return
310 endif
311 if (present(var)) var = varpart(1: colon - 1)
312 if (present(attr)) attr = varpart(colon + 1: )
313 varpart = ''
314 end subroutine url_split_c
315
316! subroutine url_split_v(fullname, file, var, attr, iorange) !:nodoc:
317! use dcstring_base, only: VSTRING, operator(.cat.), operator(/=), &
318! & extract, operator(==) !:nodoc:
319! use dc_string
320! implicit none
321! type(VSTRING), intent(in):: fullname
322! type(VSTRING), intent(out), optional:: file, var, attr, iorange
323! type(VSTRING):: varpart
324! integer:: atmark, colon, comma
325! character(len = *), parameter:: VARNAME_SET &
326! = "0123456789eEdD+-=^,.:_" &
327! // "ABCDEFGHIJKLMNOPQRSTUVWXYZ" &
328! // "abcdefghijklmnopqrstuvwxyz"
329! continue
330! ! まず URL と変数属性指定 (? または @ 以降) を分離する。
331! ! URL は @ を含みうるため、最後の @ 以降に対して変数属性
332! ! として許されない文字(典型的には '/')が含まれていたら
333! ! 当該 @ は URL の一部とみなす。
334! atmark = vindex(fullname, GT_QUESTION)
335! if (atmark == 0) then
336! atmark = vindex(fullname, GT_ATMARK, .TRUE.)
337! if (atmark /= 0) then
338! varpart = extract(fullname, atmark + 1)
339! if (vverify(varpart, VARNAME_SET) /= 0) then
340! atmark = 0
341! endif
342! endif
343! endif
344! if (atmark == 0) then
345! ! 変数属性指定はなかった。
346! if (present(file)) file = fullname
347! if (present(var)) var = ''
348! if (present(attr)) attr = ''
349! if (present(iorange)) iorange = ''
350! return
351! endif
352! varpart = extract(fullname, atmark + 1)
353! ! 変数属性指定があった。
354! if (present(file)) file = extract(fullname, 1, atmark - 1)
355! ! 範囲指定を探索する。
356! comma = vindex(varpart, GT_COMMA)
357! if (comma /= 0) then
358! ! 範囲指定がみつかった。
359! if (present(var)) var = extract(varpart, 1, comma - 1)
360! if (present(attr)) attr = ''
361! if (present(iorange)) iorange = extract(varpart, comma + 1)
362! return
363! endif
364! if (present(iorange)) iorange = ''
365! ! 範囲指定がなかったので、属性名の検索をする。
366! colon = vindex(varpart, GT_COLON)
367! if (colon == 0) then
368! if (present(var)) var = varpart
369! if (present(attr)) attr = ''
370! varpart = ''
371! return
372! endif
373! if (present(var)) var = extract(varpart, 1, colon - 1)
374! if (present(attr)) attr = extract(varpart, colon + 1)
375! varpart = ''
376! end subroutine url_split_v
377
378 !
379 ! === 同じファイルに載っているかどうか判定 ===
380 !
381
382 logical function urlonthesamefile(url_a, url_b) result(result)
383 !
384 ! 1 つ目の引数に与えられる変数 URL と 2 つ目の引数に与えられる
385 ! 変数 URL とが同じファイルを指しているかどうか判定します。
386 ! もしも同じファイルであれば <b><tt>.true.</tt></b> を、
387 ! 異なるファイルであれば <b><tt>.false.</tt></b> を返します。
388 !
389 use dc_string
390 use dc_types, only: string
391 character(len = *), intent(in) :: url_a
392 character(len = *), intent(in) :: url_b
393 character(len = STRING) :: filepart_a
394 character(len = STRING) :: filepart_b
395 call urlsplit(url_a, file=filepart_a)
396 call urlsplit(url_b, file=filepart_b)
397 result = (filepart_a == filepart_b)
398 end function urlonthesamefile
399
400 !
401 ! === 相対リンクを解決 ===
402 !
403
404 function url_resolve_c(relative, base) result(result)
405 !
406 ! relative で与えられる変数 URL が完全でない (ファイル名、 変数名、
407 ! 属性名、入出力範囲指定のどれかが無い) 場合に、 base
408 ! から補完します。
409 !
410 use dc_string, only: strhead
411 use dc_types, only: string
412 use dc_trace, only: beginsub, endsub, dbgmessage
413 implicit none
414 character(len = *), intent(in):: relative
415 character(len = *), intent(in):: base
416 character(len = STRING):: result
417 integer, parameter:: file = 1, var = 2, attr = 3, ior = 4
418 character(len = STRING):: rel(file:ior), bas(file:ior)
419 character(3), parameter:: pathdelim = "/:" // achar(94)
420 integer:: idir_r, idir_b
421 continue
422 call beginsub('urlresolve', 'rel=<%c> base=<%c>', c1=relative, c2=base)
423 call urlsplit(trim(relative), file=rel(file), var=rel(var), &
424 & attr=rel(attr), iorange=rel(ior))
425 call dbgmessage('rel -> file=<%c> var=<%c> attr=<%c>', &
426 & c1=trim(rel(file)), c2=trim(rel(var)), &
427 & c3=(trim(rel(attr)) // '> ior=<' // trim(rel(ior))))
428 call urlsplit(base, file=bas(file), var=bas(var), &
429 & attr=bas(attr), iorange=bas(ior))
430 call dbgmessage('base -> file=<%s> var=<%s> attr=<%s> ior=<%s>', &
431 & c1=trim(bas(file)), c2=trim(bas(var)), &
432 & c3=(trim(bas(attr)) // '> ior=<' // trim(bas(ior))))
433 ! --- ファイル名を欠くばあいは単に補う ---
434 if (rel(file) == "") then
435 rel(file) = bas(file)
436 if (rel(var) == "") &
437 & rel(var) = bas(var)
438 result = urlmerge(file=rel(file), var=rel(var), &
439 & attr=rel(attr), iorange=rel(ior))
440 call endsub('urlresolve', '1 result=%c', c1=trim(result))
441 return
442 endif
443 ! --- 絶対パス (と見られる) ファイル名はそのまま使用 ---
444 if (strhead(rel(file), "file:") &
445 & .OR. strhead(rel(file), "http:") &
446 & .OR. strhead(rel(file), "ftp:") &
447 & .OR. strhead(rel(file), "news:") &
448 & .OR. strhead(rel(file), "www") &
449 & .OR. strhead(rel(file), "/") &
450 & .OR. strhead(rel(file), achar(94)) &
451 & .OR. rel(file)(2:2) == ":" &
452 ) then
453 result = relative
454 call endsub('urlresolve', '2 result=%c', c1=trim(result))
455 return
456 endif
457 ! ディレクトリ名の取り出し
458 idir_b = scan(bas(file), pathdelim, back=.true.)
459 if (idir_b == 0) then
460 ! が、できなければ、(エラーとすべきかもしれぬが)
461 ! 相対パスをそのまま使用
462 result = relative
463 call endsub('urlresolve', '3 result=%c', c1=trim(result))
464 return
465 endif
466 ! 相対パスのほうのディレクトリ名の取り出し
467 idir_r = scan(rel(file), pathdelim, back=.true.)
468 if (idir_r == 0) then
469 ! ができなければ全体を使用
470 idir_r = 1
471 endif
472 result = base(1: idir_b) // relative(idir_r: )
473 call endsub('urlresolve', '4 result=%c', c1=trim(result))
474 end function url_resolve_c
475
476end module
Provides kind type parameter values.
Definition dc_types.f90:49
integer, parameter, public string
Character length for string
Definition dc_types.f90:118
character, parameter, public gt_atmark
Definition dc_url.f90:79
character, parameter, public gt_plus
Definition dc_url.f90:92
character, parameter, public gt_comma
Definition dc_url.f90:85
subroutine, public url_chop_iorange(fullname, iorange, remainder)
Definition dc_url.f90:201
character, parameter, public gt_equal
Definition dc_url.f90:87
character, parameter, public gt_colon
Definition dc_url.f90:83
character, parameter, public gt_circumflex
Definition dc_url.f90:89
character, parameter, public gt_question
Definition dc_url.f90:81