Line data Source code
1 : !!****m* ABINIT/m_yaml
2 : !! NAME
3 : !! m_yaml
4 : !!
5 : !! FUNCTION
6 : !! This module defines low-level routines to format data into YAML documents.
7 : !! Supported data include numeric arrays of one and two dimensions,
8 : !! strings, numbers, dictionaries from m_pair_list and 1D arrays of dictionaries.
9 : !!
10 : !! COPYRIGHT
11 : !! Copyright (C) 2009-2026 ABINIT group (TC, MG)
12 : !! This file is distributed under the terms of the
13 : !! GNU General Public License, see ~abinit/COPYING
14 : !! or http://www.gnu.org/copyleft/gpl.txt .
15 : !!
16 : !! SOURCE
17 :
18 : #if defined HAVE_CONFIG_H
19 : #include "config.h"
20 : #endif
21 :
22 : #include "abi_common.h"
23 :
24 : module m_yaml
25 :
26 : use defs_basis
27 : #ifdef HAVE_FC_IEEE_ARITHMETIC
28 : use ieee_arithmetic
29 : #endif
30 : use m_errors
31 : use m_pair_list
32 : use m_stream_string
33 :
34 : use m_fstrings, only : sjoin, char_count, itoa, sjoin
35 : use m_io_tools, only : is_open
36 :
37 : implicit none
38 :
39 : private
40 : !!***
41 :
42 : !----------------------------------------------------------------------
43 :
44 : !!****t* m_yaml/yamldoc_t
45 : !! NAME
46 : !! yamldoc_t
47 : !!
48 : !! FUNCTION
49 : !! High-level API to write (simple) Yaml documents.
50 : !!
51 : !! SOURCE
52 :
53 : type,public :: yamldoc_t
54 :
55 : integer :: default_keysize = 30
56 : ! Default key size
57 :
58 : integer :: default_stringsize = 500
59 : ! Default string size
60 :
61 : integer :: default_width = 0
62 : ! impose a minimum width of the field name side of the column (padding with spaces)
63 :
64 : integer :: default_multiline_trig = 8
65 : ! minimum number of elements before switching to multiline representation.
66 :
67 : character(len=20) :: default_ifmt = '(I0)'
68 : ! Default format for integer
69 :
70 : character(len=20) :: default_rfmt = '(ES16.8)'
71 : ! Default format for real
72 :
73 : character(len=20) :: default_kfmt = "(A)"
74 : ! Default format for keys
75 :
76 : character(len=20) :: default_sfmt = "(A)"
77 : ! Default format for strings
78 :
79 : type(stream_string) :: stream
80 : ! Stream object used to build yaml string.
81 :
82 : contains
83 :
84 : procedure :: write_and_free => yamldoc_write_unit_and_free
85 : ! Write Yaml document to unit and free memory.
86 :
87 : procedure :: write_units_and_free => yamldoc_write_units_and_free
88 : ! Write Yaml document to a list of units and free memory.
89 :
90 : procedure :: add_real => yamldoc_add_real
91 : ! Add a real number field to a document
92 :
93 : procedure :: add_reals => yamldoc_add_reals
94 : ! Add a list of real number fields to a document
95 :
96 : procedure :: add_paired_real2d => yamldoc_add_paired_real2d
97 : ! Add a field containing two 2D array of real numbers with the same shape.
98 :
99 : procedure :: add_int => yamldoc_add_int
100 : ! Add an integer field to a document
101 :
102 : procedure :: add_ints => yamldoc_add_ints
103 : ! Add a list of integers to a document
104 :
105 : procedure :: add_string => yamldoc_add_string
106 : ! Add a string field to a document
107 :
108 : procedure :: add_real1d => yamldoc_add_real1d
109 : ! Add a field containing a 1D array of real numbers
110 :
111 : procedure :: add_real2d => yamldoc_add_real2d
112 : ! Add a field containing a 2D real number array
113 :
114 : procedure :: add_int1d => yamldoc_add_int1d
115 : ! Add a field containing a 1D integer array
116 :
117 : procedure :: add_int2d => yamldoc_add_int2d
118 : ! Add a field containing a 2D integer array
119 :
120 : !procedure :: add_tabular => yamldoc_add_tabular
121 : ! Add a field with a complete table data
122 :
123 : procedure :: open_tabular => yamldoc_open_tabular
124 : ! Open a field for tabular data
125 :
126 : procedure :: add_tabular_line => yamldoc_add_tabular_line
127 : ! Add a line of tabular data in an already opened table field
128 :
129 : procedure :: add_dict => yamldoc_add_dict
130 : ! Add a field containing a dictionary/pair_list
131 :
132 : procedure :: add_dictlist => yamldoc_add_dictlist
133 : ! Add a field containing a list of dictionaries/array of pair_list
134 :
135 : procedure :: set_keys_to_string => yamldoc_set_keys_to_string
136 : ! Set all keys to a common (string) value
137 :
138 : end type yamldoc_t
139 : !!***
140 :
141 : public :: yamldoc_open
142 : ! Open a yaml document
143 :
144 : public :: yaml_single_dict
145 : ! Create a full document from a single dictionary
146 :
147 : public :: yaml_write_dict
148 : ! Write a dictionary in a Yaml document.
149 :
150 : public :: yaml_iterstart
151 : ! Set the value of the iteration indices used to build the iteration_state dict in the Yaml documents
152 :
153 : character(len=1),parameter :: eol = char(10)
154 :
155 : ! This is a list of reserved_keywords that shall not be used as keys in Yaml dictionaries.
156 : character(len=12),parameter :: reserved_keywords(10) = [character(len=12) :: &
157 : "tol_abs", "tol_rel", "tol_vec", "tol_eq", "ignore", &
158 : "ceil", "equation", "equations", "callback", "callbacks"]
159 :
160 : ! Global variables used to save the iteration state in Abinit.
161 : ! Set by yaml_iterstart
162 : integer,public,save,protected :: DTSET_IDX = -1
163 : integer,public,save,protected :: TIMIMAGE_IDX = -1
164 : integer,public,save,protected :: IMAGE_IDX = -1
165 : integer,public,save,protected :: ITIME_IDX = -1
166 : integer,public,save,protected :: ICYCLE_IDX = -1
167 :
168 : integer,parameter,private :: MAGIC_IGNORE_INT = huge(0) - 1
169 : real(dp),parameter,private :: MAGIC_IGNORE_REAL = huge(one) - one
170 :
171 : contains
172 :
173 : !!****f* m_yaml/yaml_iterstart
174 : !! NAME
175 : !! yaml_iterstart
176 : !!
177 : !! FUNCTION
178 : !! Mark the start of an iteration named by label and numbered by file
179 : !!
180 : !! INPUTS
181 : !! label=key name
182 : !! val=value
183 : !! [newline] = set to false to prevent adding newlines after fields
184 : !!
185 : !! SOURCE
186 :
187 22510 : subroutine yaml_iterstart(label, val, unit, use_yaml, newline)
188 :
189 : !Arguments ------------------------------------
190 : integer,intent(in) :: val, unit, use_yaml
191 : character(len=*),intent(in) :: label
192 : logical,intent(in),optional :: newline
193 :
194 : !Local variables-------------------------------
195 : character(len=6) :: tmp_i
196 : logical :: nl
197 : type(stream_string) :: stream
198 : ! *************************************************************************
199 :
200 5285 : select case (label)
201 : case ("dtset")
202 5285 : DTSET_IDX = val
203 5285 : TIMIMAGE_IDX = -1
204 5285 : IMAGE_IDX = -1
205 5285 : ITIME_IDX = -1
206 5285 : ICYCLE_IDX = -1
207 : case ("timimage")
208 358 : TIMIMAGE_IDX = val
209 : case ("image")
210 1716 : IMAGE_IDX = val
211 : case ("itime")
212 3655 : ITIME_IDX = val
213 : case ("icycle")
214 11496 : ICYCLE_IDX = val
215 : case default
216 0 : ABI_ERROR(sjoin("Invalid value for label:", label))
217 : end select
218 :
219 22510 : if (use_yaml == 1) then
220 48 : if (unit == dev_null .or. .not. is_open(unit)) return
221 12 : ABI_DEFAULT(nl, newline, .true.)
222 12 : write(tmp_i, '(I6)') val
223 12 : call stream%push('--- !IterStart'//eol//label//':'//tmp_i//eol//'...')
224 12 : if (nl) call stream%push(eol)
225 12 : call stream%flush(unit)
226 : end if
227 :
228 22510 : end subroutine yaml_iterstart
229 : !!***
230 :
231 : !!****f* m_yaml/yamldoc_open
232 : !! NAME
233 : !! yamldoc_open
234 : !!
235 : !! FUNCTION
236 : !! Open a yaml document
237 : !!
238 : !! INPUTS
239 : !! tag: add a tag to the field
240 : !! [info]: info about document.
241 : !! [newline]: optional, set to false to prevent adding newlines after fields
242 : !! [width]: optional, impose a minimum width of the field name side of the column (padding with spaces)
243 : !! [int_fmt]: Default format for integers.
244 : !! [real_fmt]: Default format for real.
245 : !! [with_iter_state]: True if dict with iteration state should be added. Default: True
246 : !!
247 : !! SOURCE
248 :
249 63537 : type(yamldoc_t) function yamldoc_open(tag, info, newline, width, int_fmt, real_fmt, with_iter_state) result(new)
250 :
251 : !Arguments ------------------------------------
252 : character(len=*),intent(in) :: tag
253 : character(len=*),optional,intent(in) :: info
254 : logical,intent(in),optional :: newline
255 : integer,intent(in),optional :: width
256 : character(len=*),optional,intent(in) :: int_fmt, real_fmt
257 : logical,optional,intent(in) :: with_iter_state
258 :
259 : !Local variables-------------------------------
260 : logical :: nl, with_iter_state_
261 : type(pair_list) :: dict
262 : ! *************************************************************************
263 :
264 0 : ABI_DEFAULT(nl, newline, .False.)
265 :
266 63537 : if (present(width)) new%default_width = width
267 63537 : if (present(int_fmt)) new%default_ifmt = int_fmt
268 63537 : if (present(real_fmt)) new%default_rfmt = real_fmt
269 :
270 63537 : call new%stream%push(ch10//'---'//' !'//trim(tag)//ch10)
271 :
272 63537 : with_iter_state_ = .True.; if (present(with_iter_state)) with_iter_state_ = with_iter_state
273 63537 : if (with_iter_state_ .and. DTSET_IDX /= -1) then
274 : ! Write dictionary with iteration state.
275 62847 : call dict%set('dtset', i=DTSET_IDX)
276 62847 : if (TIMIMAGE_IDX /= -1) call dict%set("timimage", i=TIMIMAGE_IDX)
277 62847 : if (IMAGE_IDX /= -1) call dict%set("image", i=IMAGE_IDX)
278 62847 : if (ITIME_IDX /= -1) call dict%set("itime", i=ITIME_IDX)
279 62847 : if (ICYCLE_IDX /= -1) call dict%set("icycle", i=ICYCLE_IDX)
280 62847 : call new%add_dict('iteration_state', dict, int_fmt="(i0)")
281 62847 : call dict%free()
282 : end if
283 :
284 63537 : if (present(info)) then
285 12756 : if (len_trim(info) /= 0) then
286 : ! TODO: Replace comment with info
287 12756 : call new%stream%push('comment')
288 123844 : if (new%default_width > 7) call new%stream%push(repeat(' ', new%default_width - 7))
289 12756 : call new%stream%push(': ')
290 12756 : call yaml_print_string(new%stream, info)
291 12756 : call new%stream%push(eol)
292 : end if
293 : end if
294 :
295 63537 : if (nl) call new%stream%push(eol)
296 :
297 63537 : end function yamldoc_open
298 : !!***
299 :
300 : !!****f* m_yaml/yamldoc_add_real
301 : !! NAME
302 : !! yamldoc_add_real
303 : !!
304 : !! FUNCTION
305 : !! Add a real number field to a document
306 : !!
307 : !! INPUTS
308 : !! label = key name
309 : !! val = value
310 : !! [tag] = optional, add a tag to the field
311 : !! [real_fmt] = override the default formatting
312 : !! [newline] = set to false to prevent adding newlines after fields
313 : !! [width] = impose a minimum width of the field name side of the column (padding with spaces)
314 : !! [comment]: optional Yaml comment added after the value
315 : !! [ignore]= If present, ignore entry if value is equal to ignore.
316 : !!
317 : !! SOURCE
318 :
319 279247 : subroutine yamldoc_add_real(self, label, val, tag, real_fmt, newline, width, comment, ignore)
320 :
321 : !Arguments ------------------------------------
322 : class(yamldoc_t),intent(inout) :: self
323 : character(len=*),intent(in) :: label
324 : real(dp),intent(in) :: val
325 : character(len=*),intent(in),optional :: tag, real_fmt
326 : logical,intent(in),optional :: newline
327 : integer,intent(in),optional :: width
328 : character(len=*),intent(in),optional :: comment
329 : real(dp),optional,intent(in) :: ignore
330 :
331 : !Local variables-------------------------------
332 : integer :: w
333 : character(len=50) :: tmp_r
334 : character(len=30) :: rfmt
335 : logical :: nl
336 : ! *************************************************************************
337 :
338 279247 : if (present(ignore)) then
339 16448 : if (val == ignore) return
340 : end if
341 :
342 279247 : ABI_DEFAULT(nl, newline, .true.)
343 279247 : ABI_DEFAULT(w, width, self%default_width)
344 279247 : ABI_DEFAULT(rfmt, real_fmt, self%default_rfmt)
345 :
346 279247 : if (present(tag)) then
347 0 : call yaml_start_field(self%stream, label, width=w, tag=tag)
348 : else
349 279247 : call yaml_start_field(self%stream, label, width=w)
350 : end if
351 :
352 279247 : call self%stream%push(' ')
353 279247 : call format_real(val, tmp_r, trim(rfmt))
354 279247 : call self%stream%push(trim(tmp_r))
355 :
356 279247 : if (present(comment)) call self%stream%push(' # '//trim(comment))
357 279247 : if (nl) call self%stream%push(eol)
358 :
359 279247 : end subroutine yamldoc_add_real
360 : !!***
361 :
362 : !!****f* m_yaml/yamldoc_add_reals
363 : !! NAME
364 : !! yamldoc_add_reals
365 : !!
366 : !! FUNCTION
367 : !! Add a list of real numbers to the document
368 : !!
369 : !! INPUTS
370 : !! keylist = List of comma-separated keywords
371 : !! values = List of values
372 : !! [real_fmt] = override the default formatting
373 : !! [width] = impose a minimum width of the field name side of the column (padding with spaces)
374 : !! [dict_key]=If present, a dictionary with key `dict_key` is created instead of a list.
375 : !! [multiline_trig] = optional minimum number of elements before switching to multiline representation
376 : !! [ignore]= If present, ignore entries whose values is equal to ignore.
377 : !!
378 : !! SOURCE
379 :
380 66514 : subroutine yamldoc_add_reals(self, keylist, values, real_fmt, width, dict_key, multiline_trig, ignore)
381 :
382 : !Arguments ------------------------------------
383 : class(yamldoc_t),intent(inout) :: self
384 : character(len=*),intent(in) :: keylist
385 : real(dp),intent(in) :: values(:)
386 : character(len=*),intent(in),optional :: real_fmt, dict_key
387 : integer,intent(in),optional :: width, multiline_trig
388 : real(dp),optional,intent(in) :: ignore
389 :
390 : !Local variables-------------------------------
391 : integer :: i, n, w, start, stp, vmax
392 : character(len=30) :: rfmt
393 : real(dp) :: my_ignore
394 : type(pair_list) :: dict
395 : ! *************************************************************************
396 :
397 0 : ABI_DEFAULT(w, width, self%default_width)
398 33257 : ABI_DEFAULT(rfmt, real_fmt, self%default_rfmt)
399 33257 : ABI_DEFAULT(my_ignore, ignore, MAGIC_IGNORE_REAL)
400 :
401 33257 : n = char_count(keylist, ",") + 1
402 33257 : ABI_CHECK(size(values) == n, sjoin("size of values:", itoa(size(values)), " != len(tokens):", keylist))
403 :
404 33257 : start = 1
405 :
406 33257 : if (.not. present(dict_key)) then
407 21932 : do i=1,n
408 16448 : stp = index(keylist(start:), ",")
409 21932 : if (stp == 0) then
410 5484 : call self%add_real(adjustl(keylist(start:)), values(i), real_fmt=rfmt, width=w, ignore=my_ignore)
411 : else
412 10964 : call self%add_real(adjustl(keylist(start: start + stp - 2)), values(i), real_fmt=rfmt, width=w, ignore=my_ignore)
413 10964 : start = start + stp
414 10964 : ABI_CHECK(start < len_trim(keylist), sjoin("Invalid keylist:", keylist))
415 : end if
416 : end do
417 :
418 : else
419 :
420 : ! Create and insert dictionary.
421 142367 : do i=1,n
422 114594 : stp = index(keylist(start:), ",")
423 142367 : if (stp == 0) then
424 27773 : if (values(i) /= my_ignore) call dict%set(adjustl(keylist(start:)), r=values(i))
425 : else
426 86821 : if (values(i) /= my_ignore) call dict%set(adjustl(keylist(start: start + stp - 2)), r=values(i))
427 86821 : start = start + stp
428 86821 : ABI_CHECK(start < len_trim(keylist), sjoin("Invalid keylist:", keylist))
429 : end if
430 : end do
431 27773 : ABI_DEFAULT(vmax, multiline_trig, self%default_multiline_trig)
432 27773 : call self%add_dict(trim(dict_key), dict, multiline_trig=vmax, real_fmt=rfmt, width=w)
433 27773 : call dict%free()
434 : end if
435 :
436 33257 : end subroutine yamldoc_add_reals
437 : !!***
438 :
439 : !!****f* m_yaml/yamldoc_add_int
440 : !! NAME
441 : !! yamldoc_add_int
442 : !!
443 : !! FUNCTION
444 : !! Add an integer field to a document
445 : !!
446 : !! INPUTS
447 : !! label = key name
448 : !! val = value
449 : !! [tag] = optional, add a tag to the field
450 : !! [int_fmt] = optional override the default formatting
451 : !! [newline] = set to false to prevent adding newlines after fields
452 : !! [width] = impose a minimum width of the field name side of the column (padding with spaces)
453 : !! [comment]: optional Yaml comment added after the value
454 : !! [ignore]= If present, ignore entrie if values is equal to ignore.
455 : !!
456 : !! SOURCE
457 :
458 76362 : subroutine yamldoc_add_int(self, label, val, tag, int_fmt, newline, width, comment, ignore)
459 :
460 : !Arguments ------------------------------------
461 : class(yamldoc_t),intent(inout) :: self
462 : integer,intent(in) :: val
463 : character(len=*),intent(in) :: label
464 : character(len=*),intent(in),optional :: tag, int_fmt
465 : logical,intent(in),optional :: newline
466 : integer,intent(in),optional :: width
467 : character(len=*),intent(in),optional :: comment
468 : integer,intent(in),optional :: ignore
469 :
470 : !Local variables-------------------------------
471 : integer :: w
472 : character(50) :: tmp_i
473 : character(len=30) :: ifmt
474 : logical :: nl
475 : ! *************************************************************************
476 :
477 76362 : if (present(ignore)) then
478 2637 : if (val == ignore) return
479 : end if
480 :
481 76362 : ABI_DEFAULT(nl, newline, .true.)
482 76362 : ABI_DEFAULT(w, width, self%default_width)
483 76362 : ABI_DEFAULT(ifmt, int_fmt, self%default_ifmt)
484 :
485 76362 : if (present(tag)) then
486 0 : call yaml_start_field(self%stream, label, width=w, tag=tag)
487 : else
488 76362 : call yaml_start_field(self%stream, label, width=w)
489 : end if
490 :
491 76362 : call self%stream%push(' ')
492 76362 : write(tmp_i, trim(ifmt)) val
493 76362 : call self%stream%push(trim(tmp_i))
494 :
495 76362 : if (present(comment)) call self%stream%push(' # '//trim(comment))
496 76362 : if (nl) call self%stream%push(eol)
497 :
498 76362 : end subroutine yamldoc_add_int
499 : !!***
500 :
501 : !!****f* m_yaml/yamldoc_add_ints
502 : !! NAME
503 : !! yamldoc_add_ints
504 : !!
505 : !! FUNCTION
506 : !! Add a list of integer numbers to the document
507 : !!
508 : !! INPUTS
509 : !! keylist = List of comma-separated keywords e.g. "foo, bar"
510 : !! values = List of integer values
511 : !! [int_fmt] = override the default formatting
512 : !! [width] = impose a minimum width of the field name side of the column (padding with spaces)
513 : !! [dict_key]=If present, a dictionary with key `dict_key` is created instead of a list.
514 : !! [multiline_trig] = minimum number of elements before switching to multiline representation
515 : !! [ignore]= If present, ignore entrie if values is equal to ignore.
516 : !!
517 : !! SOURCE
518 :
519 36160 : subroutine yamldoc_add_ints(self, keylist, values, int_fmt, width, dict_key, multiline_trig, ignore)
520 :
521 : !Arguments ------------------------------------
522 : class(yamldoc_t),intent(inout) :: self
523 : character(len=*),intent(in) :: keylist
524 : integer,intent(in) :: values(:)
525 : character(len=*),intent(in),optional :: int_fmt, dict_key
526 : integer,intent(in),optional :: width, multiline_trig
527 : integer,intent(in),optional :: ignore
528 :
529 : !Local variables-------------------------------
530 : integer :: i, n, w, start, stp, vmax, my_ignore
531 : character(len=30) :: ifmt
532 : type(pair_list) :: dict
533 : ! *************************************************************************
534 :
535 0 : ABI_DEFAULT(w, width, self%default_width)
536 18080 : ABI_DEFAULT(ifmt, int_fmt, self%default_ifmt)
537 18080 : ABI_DEFAULT(my_ignore, ignore, MAGIC_IGNORE_INT)
538 :
539 18080 : n = char_count(keylist, ",") + 1
540 18080 : ABI_CHECK(size(values) == n, sjoin("size of values:", itoa(size(values)), " != len(tokens):", keylist))
541 :
542 18080 : start = 1
543 :
544 18080 : if (.not. present(dict_key)) then
545 : ! one line per entry.
546 3295 : do i=1,n
547 2637 : stp = index(keylist(start:), ",")
548 3295 : if (stp == 0) then
549 658 : call self%add_int(adjustl(keylist(start:)), values(i), int_fmt=ifmt, width=w, ignore=my_ignore)
550 : else
551 1979 : call self%add_int(adjustl(keylist(start: start + stp - 2)), values(i), int_fmt=ifmt, width=w, ignore=my_ignore)
552 1979 : start = start + stp
553 1979 : ABI_CHECK(start < len_trim(keylist), sjoin("Invalid keylist:", keylist))
554 : end if
555 : end do
556 :
557 : else
558 : ! Create and insert dictionary.
559 103768 : do i=1,n
560 86346 : stp = index(keylist(start:), ",")
561 103768 : if (stp == 0) then
562 17422 : if (values(i) /= my_ignore) call dict%set(adjustl(keylist(start:)), i=values(i))
563 : else
564 68924 : if (values(i) /= my_ignore) call dict%set(adjustl(keylist(start: start + stp - 2)), i=values(i))
565 68924 : start = start + stp
566 68924 : ABI_CHECK(start < len_trim(keylist), sjoin("Invalid keylist:", keylist))
567 : end if
568 : end do
569 :
570 17422 : ABI_DEFAULT(vmax, multiline_trig, self%default_multiline_trig)
571 17422 : call self%add_dict(trim(dict_key), dict, multiline_trig=vmax, int_fmt=ifmt, width=w)
572 17422 : call dict%free()
573 : end if
574 :
575 18080 : end subroutine yamldoc_add_ints
576 : !!***
577 :
578 : !!****f* m_yaml/yamldoc_add_string
579 : !! NAME
580 : !! yamldoc_add_string
581 : !!
582 : !! FUNCTION
583 : !! Add a string field to a document
584 : !!
585 : !! INPUTS
586 : !! label = key name
587 : !! val = value
588 : !! [tag] = optional, add a tag to the field
589 : !! [newline] = set to false to prevent adding newlines after fields
590 : !! [width] = impose a minimum width of the field name side of the column (padding with spaces)
591 : !!
592 : !! SOURCE
593 :
594 38184 : subroutine yamldoc_add_string(self, label, val, tag, newline, width)
595 :
596 : !Arguments ------------------------------------
597 : class(yamldoc_t),intent(inout) :: self
598 : character(len=*),intent(in) :: val
599 : character(len=*),intent(in) :: label
600 : character(len=*),intent(in),optional :: tag
601 : logical,intent(in),optional :: newline
602 : integer,intent(in),optional :: width
603 :
604 : !Local variables-------------------------------
605 : integer :: w
606 : logical :: nl
607 : ! *************************************************************************
608 :
609 38184 : ABI_DEFAULT(nl, newline, .true.)
610 38184 : ABI_DEFAULT(w, width, self%default_width)
611 :
612 38184 : if (present(tag)) then
613 0 : call yaml_start_field(self%stream, label, width=w, tag=tag)
614 : else
615 38184 : call yaml_start_field(self%stream, label, width=w)
616 : end if
617 :
618 38184 : call self%stream%push(' ')
619 38184 : call yaml_print_string(self%stream, trim(val))
620 38184 : if (nl) call self%stream%push(eol)
621 :
622 38184 : end subroutine yamldoc_add_string
623 : !!***
624 :
625 : !!****f* m_yaml/yamldoc_add_real1d
626 : !! NAME
627 : !! yamldoc_add_real1d
628 : !!
629 : !! FUNCTION
630 : !! Add a field containing a 1D array of real numbers
631 : !!
632 : !! INPUTS
633 : !! label = key name
634 : !! arr(:)
635 : !! [multiline_trig] = optional minimum number of elements before switching to multiline representation
636 : !! [tag] = optional, add a tag to the field
637 : !! [real_fmt] = override the default formatting
638 : !! [newline] = set to false to prevent adding newlines after fields
639 : !! [width] = impose a minimum width of the field name side of the column (padding with spaces)
640 : !! [comment]: optional Yaml comment added after the value
641 : !!
642 : !! SOURCE
643 :
644 22810 : subroutine yamldoc_add_real1d(self, label, arr, tag, real_fmt, multiline_trig, newline, width, comment)
645 :
646 : !Arguments ------------------------------------
647 : class(yamldoc_t),intent(inout) :: self
648 : integer,intent(in),optional :: multiline_trig
649 : real(dp),intent(in) :: arr(:)
650 : character(len=*),intent(in) :: label
651 : character(len=*),intent(in),optional :: tag, real_fmt
652 : logical,intent(in),optional :: newline
653 : integer,intent(in),optional :: width
654 : character(len=*),intent(in),optional :: comment
655 :
656 : !Local variables-------------------------------
657 : integer :: w, length, vmax
658 : character(len=30) :: rfmt
659 : logical :: nl
660 : ! *************************************************************************
661 :
662 11405 : length = size(arr)
663 :
664 11405 : ABI_DEFAULT(nl, newline, .true.)
665 11405 : ABI_DEFAULT(w, width, self%default_width)
666 11405 : ABI_DEFAULT(rfmt, real_fmt, self%default_rfmt)
667 11405 : ABI_DEFAULT(vmax, multiline_trig, self%default_multiline_trig)
668 :
669 11405 : if (present(tag)) then
670 0 : call yaml_start_field(self%stream, label, width=w, tag=tag)
671 : else
672 11405 : call yaml_start_field(self%stream, label, width=w)
673 : end if
674 :
675 11405 : call yaml_print_real1d(self%stream, length, arr, trim(rfmt), vmax)
676 11405 : if (present(comment)) call self%stream%push(' # '//trim(comment))
677 11405 : if (nl) call self%stream%push(eol)
678 :
679 11405 : end subroutine yamldoc_add_real1d
680 : !!***
681 :
682 : !!****f* m_yaml/yamldoc_add_int1d
683 : !! NAME
684 : !! yamldoc_add_int1d
685 : !!
686 : !! FUNCTION
687 : !! Add a field containing a 1D integer array
688 : !!
689 : !! INPUTS
690 : !! label = key name
691 : !! arr(:) <integer>=
692 : !! [multiline_trig] = optional minimum number of elements before switching to multiline representation
693 : !! [tag] : add a tag to the field
694 : !! int_fmt <character(len=*)>=optional override the default formatting
695 : !! [newline] = set to false to prevent adding newlines after fields
696 : !! [width] = impose a minimum width of the field name side of the column (padding with spaces)
697 : !! [comment]: optional Yaml comment added after the value
698 : !!
699 : !! SOURCE
700 :
701 0 : subroutine yamldoc_add_int1d(self, label, arr, tag, int_fmt, multiline_trig, newline, width, comment)
702 :
703 : !Arguments ------------------------------------
704 : class(yamldoc_t),intent(inout) :: self
705 : integer,intent(in),optional :: multiline_trig
706 : integer,intent(in) :: arr(:)
707 : character(len=*),intent(in) :: label
708 : character(len=*),intent(in),optional :: tag, int_fmt
709 : logical,intent(in),optional :: newline
710 : integer,intent(in),optional :: width
711 : character(len=*),intent(in),optional :: comment
712 :
713 : !Local variables-------------------------------
714 : character(len=30) :: ifmt
715 : integer :: w, length, vmax
716 : logical :: nl
717 : ! *************************************************************************
718 :
719 0 : ABI_DEFAULT(nl, newline, .true.)
720 0 : ABI_DEFAULT(w, width, self%default_width)
721 0 : ABI_DEFAULT(ifmt, int_fmt, self%default_ifmt)
722 0 : ABI_DEFAULT(vmax, multiline_trig, self%default_multiline_trig)
723 0 : length = size(arr)
724 :
725 0 : if (present(tag)) then
726 0 : call yaml_start_field(self%stream, label, width=w, tag=tag)
727 : else
728 0 : call yaml_start_field(self%stream, label, width=w)
729 : end if
730 :
731 0 : call yaml_print_int1d(self%stream, length, arr, trim(ifmt), vmax)
732 0 : if (present(comment)) call self%stream%push(' # '//trim(comment))
733 0 : if (nl) call self%stream%push(eol)
734 :
735 0 : end subroutine yamldoc_add_int1d
736 : !!***
737 :
738 : !!****f* m_yaml/yamldoc_add_dict
739 : !! NAME
740 : !! yamldoc_add_dict
741 : !!
742 : !! FUNCTION
743 : !! Add a field containing a dictionary/pair_list
744 : !!
745 : !! INPUTS
746 : !! label <character(len=*)>=
747 : !! pl <type(pair_list)>=
748 : !! string_size <integer>=optional maximum storage size for strings found in a pair_list
749 : !! key_size <integer>=optional maximum storage size for keys of a pair_list
750 : !! multiline_trig <integer>=optional minimum number of elements before switching to multiline representation
751 : !! tag <character(len=*)>=optional add a tag to the field
752 : !! key_fmt <character(len=*)>=optional override the default formatting
753 : !! int_fmt <character(len=*)>=optional override the default formatting
754 : !! real_fmt <character(len=*)>=optional override the default formatting
755 : !! string_fmt <character(len=*)>=optional override the default formatting
756 : !! newline <logical>=optional set to false to prevent adding newlines after fields
757 : !! width <integer>=optional impose a minimum width of the field name side of the column (padding with spaces)
758 : !! [comment]: optional Yaml comment added after the value
759 : !!
760 : !! OUTPUT
761 : !! pl <type(pair_list)>=
762 : !!
763 : !! SOURCE
764 :
765 108709 : subroutine yamldoc_add_dict(self, label, pl, tag, key_size, string_size, key_fmt, &
766 : int_fmt, real_fmt, string_fmt, multiline_trig, newline, width, comment)
767 :
768 : !Arguments ------------------------------------
769 : class(yamldoc_t),intent(inout) :: self
770 : type(pair_list),intent(inout) :: pl
771 : character(len=*),intent(in) :: label
772 : integer,intent(in),optional :: string_size, key_size, multiline_trig
773 : character(len=*),intent(in),optional :: tag, key_fmt, int_fmt, real_fmt, string_fmt
774 : logical,intent(in),optional :: newline
775 : integer,intent(in),optional :: width
776 : character(len=*),intent(in),optional :: comment
777 :
778 : !Local variables-------------------------------
779 : integer :: w, vmax, ks, ss
780 : character(len=30) :: kfmt, ifmt, rfmt, sfmt
781 : logical :: nl
782 : ! *************************************************************************
783 :
784 0 : ABI_DEFAULT(nl, newline, .true.)
785 108709 : ABI_DEFAULT(w, width, self%default_width)
786 108709 : ABI_DEFAULT(ks, key_size, self%default_keysize)
787 108709 : ABI_DEFAULT(ss, string_size, self%default_stringsize)
788 108709 : ABI_DEFAULT(kfmt, key_fmt, self%default_kfmt)
789 108709 : ABI_DEFAULT(rfmt, real_fmt, self%default_rfmt)
790 108709 : ABI_DEFAULT(ifmt, int_fmt, self%default_ifmt)
791 108709 : ABI_DEFAULT(sfmt, string_fmt, self%default_sfmt)
792 108709 : ABI_DEFAULT(vmax, multiline_trig, self%default_multiline_trig)
793 :
794 108709 : if (present(tag)) then
795 0 : call yaml_start_field(self%stream, label, width=w, tag=tag)
796 : else
797 108709 : call yaml_start_field(self%stream, label, width=w)
798 : end if
799 :
800 108709 : call yaml_print_dict(self%stream, pl, ks, ss, trim(kfmt), trim(ifmt), trim(rfmt), trim(sfmt), vmax)
801 108709 : if (present(comment)) call self%stream%push(' # '//trim(comment))
802 108709 : if (nl) call self%stream%push(eol)
803 :
804 108709 : end subroutine yamldoc_add_dict
805 : !!***
806 :
807 : !!****f* m_yaml/yamldoc_add_real2d
808 : !! NAME
809 : !! yamldoc_add_real2d
810 : !!
811 : !! FUNCTION
812 : !! Add a field containing a 2D array of real numbers
813 : !!
814 : !! INPUTS
815 : !! label = key name
816 : !! arr(:, :) = input array.
817 : !! [slist(:)]= List of strings (same length as the first dim or second dime of arr, depending on mode).
818 : !! If present, the string will be included in the the row.
819 : !! [tag]= add a tag to the field
820 : !! [real_fmt]= override the default formatting
821 : !! [multiline_trig]: optional minimum number of elements before switching to multiline representation
822 : !! [newline]: set to false to prevent adding newlines after fields
823 : !! [width]: impose a minimum width of the field name side of the column (padding with spaces)
824 : !! [mode]: "T" to write the transpose of arr i.e columns become rows in output (DEFAULT), "N" for normal order
825 : !! [comment]: optional Yaml comment added after the key.
826 : !!
827 : !! SOURCE
828 :
829 20777 : subroutine yamldoc_add_real2d(self, label, arr, slist, tag, real_fmt, multiline_trig, newline, width, mode, comment)
830 :
831 : !Arguments ------------------------------------
832 : class(yamldoc_t),intent(inout) :: self
833 : real(dp),intent(in) :: arr(:, :)
834 : character(len=*),intent(in) :: label
835 : character(len=*),optional,intent(in) :: slist(:)
836 : character(len=*),intent(in),optional :: tag, real_fmt
837 : integer,intent(in),optional :: multiline_trig
838 : logical,intent(in),optional :: newline
839 : integer,intent(in),optional :: width
840 : character(len=1),intent(in),optional :: mode
841 : character(len=*),intent(in),optional :: comment
842 :
843 : !Local variables-------------------------------
844 : integer :: m, n, w, i, vmax
845 41554 : real(dp) :: line(max(size(arr, dim=1), size(arr, dim=2)))
846 : character(len=30) :: rfmt
847 : character(len=1) :: my_mode
848 : logical :: nl
849 : ! *************************************************************************
850 :
851 20777 : m = size(arr, dim=1)
852 20777 : n = size(arr, dim=2)
853 :
854 20777 : ABI_DEFAULT(nl, newline, .true.)
855 20777 : ABI_DEFAULT(w, width, self%default_width)
856 20777 : ABI_DEFAULT(my_mode, mode, "T")
857 20777 : ABI_DEFAULT(rfmt, real_fmt, self%default_rfmt)
858 20777 : ABI_DEFAULT(vmax, multiline_trig, self%default_multiline_trig)
859 :
860 20777 : if (present(tag)) then
861 0 : call yaml_start_field(self%stream, label, width=w, tag=tag)
862 : else
863 20777 : call yaml_start_field(self%stream, label, width=w)
864 : end if
865 20777 : if (present(comment)) call self%stream%push(' # '//trim(comment))
866 :
867 20777 : if (my_mode == "T") then
868 81531 : do i=1,n
869 60754 : call self%stream%push(eol//'-')
870 243016 : line(1:m) = arr(:,i)
871 81531 : if (.not. present(slist)) then
872 45357 : call yaml_print_real1d(self%stream, m, line, rfmt, vmax)
873 : else
874 15397 : call yaml_print_real1d(self%stream, m, line, rfmt, vmax, string=trim(slist(i)))
875 : end if
876 : end do
877 : else
878 0 : do i=1,m
879 0 : call self%stream%push(eol//'-')
880 0 : line(1:n) = arr(i,:)
881 0 : if (.not. present(slist)) then
882 0 : call yaml_print_real1d(self%stream, n, line, rfmt, vmax)
883 : else
884 0 : call yaml_print_real1d(self%stream, n, line, rfmt, vmax, string=trim(slist(i)))
885 : end if
886 : end do
887 : end if
888 :
889 20777 : if (nl) call self%stream%push(eol)
890 :
891 20777 : end subroutine yamldoc_add_real2d
892 : !!***
893 :
894 : !!****f* m_yaml/yamldoc_add_paired_real2d
895 : !! NAME
896 : !! yamldoc_add_paired_real2d
897 : !!
898 : !! FUNCTION
899 : !! Add a field containing two 2D real arrays with the same shape.
900 : !!
901 : !! Example:
902 : !! cartesian_forces_and_xred:
903 : !! - [ [ -0.0000E+00, -0.0000E+00, -0.0000E+00, ], [ 0.0000E+00, 0.0000E+00, 0.0000E+00, ] ]
904 : !! - [ [ -0.0000E+00, -0.0000E+00, -0.0000E+00, ], [ 2.5000E-01, 2.5000E-01, 2.5000E-01, ] ]
905 : !!
906 : !! INPUTS
907 : !! label = key name
908 : !! arr1(:,:), arr2(:,:) = input arrays.
909 : !! [slist(:)]= List of strings (same length as the first dim or second dime of arr, depending on mode).
910 : !! If present, the string will be included in the the row.
911 : !! [tag]= add a tag to the field
912 : !! [real_fmt]= override the default formatting
913 : !! [multiline_trig]: optional minimum number of elements before switching to multiline representation
914 : !! [newline]: set to false to prevent adding newlines after fields
915 : !! [width]: impose a minimum width of the field name side of the column (padding with spaces)
916 : !! [mode]: "T" to write the transpose of arr i.e columns become rows in output (DEFAULT), "N" for normal order
917 : !! [comment]: optional Yaml comment added after the key
918 : !!
919 : !! SOURCE
920 :
921 0 : subroutine yamldoc_add_paired_real2d(self, label, arr1, arr2, slist, tag, real_fmt, &
922 : multiline_trig, newline, width, mode, comment)
923 :
924 : !Arguments ------------------------------------
925 : class(yamldoc_t),intent(inout) :: self
926 : real(dp),intent(in) :: arr1(:, :), arr2(:,:)
927 : character(len=*),intent(in) :: label
928 : character(len=*),intent(in),optional :: tag, real_fmt
929 : integer,intent(in),optional :: multiline_trig
930 : logical,intent(in),optional :: newline
931 : integer,intent(in),optional :: width
932 : character(len=1),intent(in),optional :: mode
933 : character(len=*),optional,intent(in) :: slist(:)
934 : character(len=*),intent(in),optional :: comment
935 :
936 : !Local variables-------------------------------
937 : integer :: m, n, w, i, vmax
938 0 : real(dp) :: line(2 * max(size(arr1, dim=1), size(arr1, dim=2)))
939 : character(len=30) :: rfmt
940 : character(len=1) :: my_mode
941 : logical :: nl
942 : ! *************************************************************************
943 :
944 0 : m = size(arr1, dim=1)
945 0 : n = size(arr1, dim=2)
946 :
947 0 : ABI_CHECK(all(shape(arr1) == shape(arr2)), "arr1 and arr2 must have same shape")
948 :
949 0 : ABI_DEFAULT(nl, newline, .true.)
950 0 : ABI_DEFAULT(w, width, self%default_width)
951 0 : ABI_DEFAULT(my_mode, mode, "T")
952 0 : ABI_DEFAULT(rfmt, real_fmt, self%default_rfmt)
953 0 : ABI_DEFAULT(vmax, multiline_trig, self%default_multiline_trig)
954 :
955 0 : if (present(tag)) then
956 0 : call yaml_start_field(self%stream, label, width=w, tag=tag)
957 : else
958 0 : call yaml_start_field(self%stream, label, width=w)
959 : end if
960 0 : if (present(comment)) call self%stream%push(' # '//trim(comment))
961 :
962 0 : if (my_mode == "T") then
963 0 : if (present(slist)) then
964 0 : ABI_CHECK(size(slist) == n, "size(slist) != n")
965 : end if
966 0 : do i=1,n
967 0 : call self%stream%push(eol//'- [')
968 0 : line(1:m) = arr1(:,i)
969 0 : call yaml_print_real1d(self%stream, m, line, rfmt, vmax)
970 0 : call self%stream%push(',')
971 0 : line(1:m) = arr2(:,i)
972 0 : call yaml_print_real1d(self%stream, m, line, rfmt, vmax)
973 0 : if (present(slist)) call self%stream%push(', '//trim(slist(i)))
974 0 : call self%stream%push(' ]')
975 : end do
976 : else
977 0 : if (present(slist)) then
978 0 : ABI_CHECK(size(slist) == n, "size(slist) != m")
979 : end if
980 0 : do i=1,m
981 0 : call self%stream%push(eol//'- [')
982 0 : line(1:n) = arr1(i,:)
983 0 : call yaml_print_real1d(self%stream, n, line, rfmt, vmax)
984 0 : call self%stream%push(',')
985 0 : line(1:n) = arr2(i,:)
986 0 : call yaml_print_real1d(self%stream, n, line, rfmt, vmax)
987 0 : if (present(slist)) call self%stream%push(', '//trim(slist(i)))
988 0 : call self%stream%push(']')
989 : end do
990 : end if
991 :
992 0 : if (nl) call self%stream%push(eol)
993 :
994 0 : end subroutine yamldoc_add_paired_real2d
995 : !!***
996 :
997 : !!****f* m_yaml/yamldoc_add_int2d
998 : !! NAME
999 : !! yamldoc_add_int2d
1000 : !!
1001 : !! FUNCTION
1002 : !! Add a field containing a 2D integer array
1003 : !!
1004 : !! INPUTS
1005 : !! label = key name
1006 : !! arr(:, :) <integer>=
1007 : !! [slist(:)]= List of strings (same length as the first dim or second dime of arr, depending on mode).
1008 : !! If present, the string will be included in the the row.
1009 : !! [tag]= add a tag to the field
1010 : !! [int_fmt]: override the default formatting
1011 : !! multiline_trig <integer>=optional minimum number of elements before switching to multiline representation
1012 : !! [newline] = set to false to prevent adding newlines after fields
1013 : !! [width] = impose a minimum width of the field name side of the column (padding with spaces)
1014 : !! [mode] = "T" to write the transpose of arr i.e columns become rows in output (DEFAULT), "N" for normal order
1015 : !! [comment]: optional Yaml comment added after the key.
1016 : !!
1017 : !! SOURCE
1018 :
1019 0 : subroutine yamldoc_add_int2d(self, label, arr, slist, tag, int_fmt, multiline_trig, newline, width, mode, comment)
1020 :
1021 : !Arguments ------------------------------------
1022 : class(yamldoc_t),intent(inout) :: self
1023 : integer,intent(in) :: arr(:, :)
1024 : character(len=*),intent(in) :: label
1025 : character(len=*),optional,intent(in) :: slist(:)
1026 : character(len=*),intent(in),optional :: tag, int_fmt
1027 : integer,intent(in),optional :: multiline_trig
1028 : logical,intent(in),optional :: newline
1029 : integer,intent(in),optional :: width
1030 : character(len=1),intent(in),optional :: mode
1031 : character(len=*),intent(in),optional :: comment
1032 :
1033 : !Local variables-------------------------------
1034 : integer :: m, n, w, i, vmax
1035 0 : integer :: line(max(size(arr, dim=1), size(arr, dim=2)))
1036 : character(len=30) :: ifmt
1037 : character(len=1) :: my_mode
1038 : logical :: nl
1039 : ! *************************************************************************
1040 :
1041 0 : m = size(arr, dim=1)
1042 0 : n = size(arr, dim=2)
1043 :
1044 0 : ABI_DEFAULT(nl, newline, .true.)
1045 0 : ABI_DEFAULT(w, width, self%default_width)
1046 0 : ABI_DEFAULT(my_mode, mode, "T")
1047 0 : ABI_DEFAULT(ifmt, int_fmt, self%default_ifmt)
1048 0 : ABI_DEFAULT(vmax, multiline_trig, self%default_multiline_trig)
1049 :
1050 0 : if (present(tag)) then
1051 0 : call yaml_start_field(self%stream, label, width=w, tag=tag)
1052 : else
1053 0 : call yaml_start_field(self%stream, label, width=w)
1054 : end if
1055 0 : if (present(comment)) call self%stream%push(' # '//trim(comment))
1056 :
1057 0 : if (my_mode == "T") then
1058 0 : do i=1,n
1059 0 : call self%stream%push(eol//'-')
1060 0 : line(1:m) = arr(:,i)
1061 0 : if (.not. present(slist)) then
1062 0 : call yaml_print_int1d(self%stream, m, line, ifmt, vmax)
1063 : else
1064 0 : call yaml_print_int1d(self%stream, m, line, ifmt, vmax, string=slist(i))
1065 : end if
1066 : end do
1067 : else
1068 0 : do i=1,m
1069 0 : call self%stream%push(eol//'-')
1070 0 : line(1:n) = arr(i,:)
1071 0 : if (.not. present(slist)) then
1072 0 : call yaml_print_int1d(self%stream, n, line, ifmt, vmax)
1073 : else
1074 0 : call yaml_print_int1d(self%stream, n, line, ifmt, vmax, string=slist(i))
1075 : end if
1076 : end do
1077 : end if
1078 :
1079 0 : if (nl) call self%stream%push(eol)
1080 :
1081 0 : end subroutine yamldoc_add_int2d
1082 : !!***
1083 :
1084 : !!****f* m_yaml/yamldoc_add_dictlist
1085 : !! NAME
1086 : !! yamldoc_add_dictlist
1087 : !!
1088 : !! FUNCTION
1089 : !! Add a field containing a list of dictionaries/array of pair_list
1090 : !!
1091 : !! INPUTS
1092 : !! label = key name
1093 : !! n <integer>=
1094 : !! plarr(n) <type(pair_list)>=
1095 : !! key_size <integer>=optional maximum storage size for keys of a pair_list
1096 : !! string_size <integer>=optional maximum storage size for strings of a pair_list
1097 : !! multiline_trig <integer>=optional minimum number of elements before switching to multiline representation
1098 : !! [tag]= add a tag to the field
1099 : !! key_fmt <character(len=*)>=optional override the default formatting
1100 : !! int_fmt <character(len=*)>=optional override the default formatting
1101 : !! real_fmt <character(len=*)>=optional override the default formatting
1102 : !! string_fmt <character(len=*)>=optional override the default formatting
1103 : !! [newline] = set to false to prevent adding newlines after fields
1104 : !! [width] = impose a minimum width of the field name side of the column (padding with spaces)
1105 : !!
1106 : !! SOURCE
1107 :
1108 0 : subroutine yamldoc_add_dictlist(self, label, n, plarr, tag, key_size, string_size, key_fmt, int_fmt, &
1109 : real_fmt, string_fmt, multiline_trig, newline, width)
1110 :
1111 : !Arguments ------------------------------------
1112 : class(yamldoc_t),intent(inout) :: self
1113 : integer,intent(in) :: n
1114 : type(pair_list),intent(inout) :: plarr(n)
1115 : character(len=*),intent(in) :: label
1116 : integer,intent(in),optional :: key_size, string_size
1117 : integer,intent(in),optional :: multiline_trig
1118 : character(len=*),intent(in),optional :: tag, key_fmt, int_fmt, real_fmt, string_fmt
1119 : logical,intent(in),optional :: newline
1120 : integer,intent(in),optional :: width
1121 :
1122 : !Local variables-------------------------------
1123 : integer :: w
1124 : character(len=30) :: kfmt, ifmt, rfmt, sfmt
1125 : integer :: vmax, ks, i, ss
1126 : logical :: nl
1127 : ! *************************************************************************
1128 :
1129 0 : ABI_DEFAULT(nl, newline, .true.)
1130 0 : ABI_DEFAULT(w, width, self%default_width)
1131 0 : ABI_DEFAULT(kfmt, key_fmt, self%default_kfmt)
1132 0 : ABI_DEFAULT(rfmt, real_fmt, self%default_rfmt)
1133 0 : ABI_DEFAULT(ifmt, int_fmt, self%default_ifmt)
1134 0 : ABI_DEFAULT(sfmt, string_fmt, self%default_sfmt)
1135 0 : ABI_DEFAULT(vmax, multiline_trig, self%default_multiline_trig)
1136 0 : ABI_DEFAULT(ks, key_size, self%default_keysize)
1137 0 : ABI_DEFAULT(ss, string_size, self%default_keysize)
1138 :
1139 0 : if (present(tag)) then
1140 0 : call yaml_start_field(self%stream, label, width=w, tag=tag)
1141 : else
1142 0 : call yaml_start_field(self%stream, label, width=w)
1143 : end if
1144 0 : call self%stream%push(eol)
1145 :
1146 0 : do i=1,n
1147 0 : call self%stream%push('- ')
1148 0 : call yaml_print_dict(self%stream, plarr(i), ks, ss, trim(kfmt), trim(ifmt), trim(rfmt), trim(sfmt), vmax)
1149 0 : if (nl .or. i /= n) call self%stream%push(eol)
1150 : end do
1151 :
1152 0 : end subroutine yamldoc_add_dictlist
1153 : !!***
1154 :
1155 : !!****f* m_yaml/yamldoc_open_tabular
1156 : !! NAME
1157 : !! yamldoc_open_tabular
1158 : !!
1159 : !! FUNCTION
1160 : !! Open a field for tabular data
1161 : !!
1162 : !! INPUTS
1163 : !! label = key name
1164 : !! [tag] <character(len=*)>=optional add a tag to the field
1165 : !! [newline] = set to false to prevent adding newlines after fields
1166 : !! [indent] = optional number of spaces to add to the header
1167 : !! [comment]: optional Yaml comment added after the value
1168 : !!
1169 : !! SOURCE
1170 :
1171 1158 : subroutine yamldoc_open_tabular(self, label, tag, indent, newline, comment)
1172 :
1173 : !Arguments ------------------------------------
1174 : class(yamldoc_t),intent(inout) :: self
1175 : character(len=*),intent(in) :: label
1176 : character(len=*),intent(in),optional :: tag
1177 : logical,intent(in),optional :: newline
1178 : integer,intent(in),optional :: indent
1179 : character(len=*),intent(in),optional :: comment
1180 :
1181 : !Local variables-------------------------------
1182 : integer :: n
1183 : logical :: nl
1184 : ! *************************************************************************
1185 :
1186 1158 : ABI_DEFAULT(nl, newline, .true.)
1187 1158 : ABI_DEFAULT(n, indent, 4)
1188 :
1189 0 : if (n > 4) then
1190 0 : call self%stream%push(repeat(' ', n-4))
1191 : end if
1192 :
1193 1158 : if (present(tag)) then
1194 505 : call yaml_start_field(self%stream, label, tag=tag)
1195 : else
1196 653 : call yaml_start_field(self%stream, label, tag='Tabular')
1197 : end if
1198 :
1199 1158 : if (present(comment)) then
1200 0 : call self%stream%push(' | # '//trim(comment)//eol)
1201 : else
1202 1158 : call self%stream%push(' |'//eol)
1203 : end if
1204 :
1205 1158 : end subroutine yamldoc_open_tabular
1206 : !!***
1207 :
1208 : !!****f* m_yaml/yamldoc_add_tabular_line
1209 : !! NAME
1210 : !! yamldoc_add_tabular_line
1211 : !!
1212 : !! FUNCTION
1213 : !! Add a line of tabular data in an already opened table field
1214 : !!
1215 : !! INPUTS
1216 : !! line <character(len=*)>=
1217 : !! [newline] = set to false to prevent adding newlines after fields
1218 : !! [indent] = optional number of spaces to add to the header
1219 : !!
1220 : !! SOURCE
1221 :
1222 7377 : subroutine yamldoc_add_tabular_line(self, line, newline, indent)
1223 :
1224 : !Arguments ------------------------------------
1225 : class(yamldoc_t),intent(inout) :: self
1226 : character(len=*),intent(in) :: line
1227 : logical,intent(in),optional :: newline
1228 : integer,intent(in),optional :: indent
1229 :
1230 : !Local variables-------------------------------
1231 : integer :: n
1232 : logical :: nl
1233 : ! *************************************************************************
1234 :
1235 7377 : ABI_DEFAULT(nl, newline, .true.)
1236 7377 : ABI_DEFAULT(n, indent, 4)
1237 :
1238 28249 : call self%stream%push(repeat(' ', n)//trim(line))
1239 7377 : if (nl) call self%stream%push(eol)
1240 :
1241 7377 : end subroutine yamldoc_add_tabular_line
1242 : !!***
1243 :
1244 : !!****f* m_yaml/yamldoc_add_tabular
1245 : !! NAME
1246 : !! yamldoc_add_tabular
1247 : !!
1248 : !! FUNCTION
1249 : !! Add a field with a complete table data
1250 : !!
1251 : !! INPUTS
1252 : !! label <character(len=*)>=
1253 : !! input <type(stream_string)>=stream containing an already built table
1254 : !! tag <character(len=*)>=optional add a tag to the field
1255 : !! newline <logical>=optional set to false to prevent adding newlines after fields
1256 : !! indent <integer>=optional number of spaces to add to each line
1257 : !!
1258 : !! SOURCE
1259 :
1260 : !subroutine yamldoc_add_tabular(self, label, input, tag, newline, indent)
1261 : !
1262 : !!Arguments ------------------------------------
1263 : ! class(yamldoc_t),intent(inout) :: self
1264 : ! character(len=*),intent(in) :: label
1265 : ! type(stream_string),intent(inout) :: input
1266 : ! character(len=*),intent(in),optional :: tag
1267 : ! logical,intent(in),optional :: newline
1268 : ! integer,intent(in),optional :: indent
1269 : !
1270 : !!Local variables-------------------------------
1271 : ! integer :: n
1272 : ! character(len=100) :: t
1273 : ! logical :: nl
1274 : !! *************************************************************************
1275 : !
1276 : ! ABI_DEFAULT(nl, newline, .true.)
1277 : ! ABI_DEFAULT(n, indent, 4)
1278 : ! ABI_DEFAULT(t, tag, 'Tabular')
1279 : !
1280 : ! call yaml_open_tabular(label, tag=t, stream=self%stream, newline=nl)
1281 : !
1282 : ! if (n > 4) call self%stream%push(repeat(' ', n - 4))
1283 : !
1284 : ! call write_indent(input, self%stream, n)
1285 : ! if (nl) call self%stream%push(eol)
1286 : !
1287 : !end subroutine yamldoc_add_tabular
1288 : !!***
1289 :
1290 : !!****f* m_yaml/yaml_single_dict
1291 : !! NAME
1292 : !! yaml_single_dict
1293 : !!
1294 : !! FUNCTION
1295 : !! Create a full document from a single dictionary
1296 : !!
1297 : !! INPUTS
1298 : !! unit
1299 : !! tag <character(len=*)>=
1300 : !! comment <character(len=*)>=
1301 : !! pl <type(pair_list)>=
1302 : !! key_size <integer>=maximum storage size for the keys of pl
1303 : !! string_size <integer>=maximum storage size for the strings found in pl
1304 : !! tag <character(len=*)>=optional add a tag to the field
1305 : !! int_fmt <character(len=*)>=optional override the default formatting
1306 : !! real_fmt <character(len=*)>=optional override the default formatting
1307 : !! string_fmt <character(len=*)>=optional override the default formatting
1308 : !! width <integer>=optional impose a minimum width of the field name side of the column (padding with spaces)
1309 : !! newline <logical>=optional set to false to prevent adding newlines after fields
1310 : !!
1311 : !! OUTPUT
1312 : !! pl <type(pair_list)>=
1313 : !!
1314 : !! SOURCE
1315 :
1316 0 : subroutine yaml_single_dict(unit, tag, comment, pl, key_size, string_size, &
1317 : int_fmt, real_fmt, string_fmt, newline, width)
1318 :
1319 : !Arguments ------------------------------------
1320 : integer,intent(in) :: unit
1321 : type(pair_list),intent(inout) :: pl
1322 : character(len=*),intent(in) :: tag
1323 : character(len=*),intent(in) :: comment
1324 : integer,intent(in) :: key_size, string_size
1325 : character(len=*),intent(in),optional :: int_fmt, real_fmt, string_fmt
1326 : integer,intent(in), optional :: width
1327 : logical,intent(in),optional :: newline
1328 :
1329 : !Local variables-------------------------------
1330 : type(yamldoc_t) :: doc
1331 : character(len=30) :: ifmt, rfmt, sfmt
1332 0 : character(len=string_size) :: vs, tmp_s
1333 0 : character(len=key_size) :: key
1334 : integer :: vi, k, type_code, w
1335 : character(len=50) :: tmp_i, tmp_r
1336 : real(dp) :: vr
1337 : logical :: nl
1338 : ! *************************************************************************
1339 :
1340 0 : ABI_DEFAULT(nl, newline, .true.)
1341 0 : ABI_DEFAULT(rfmt, real_fmt, doc%default_rfmt)
1342 0 : ABI_DEFAULT(ifmt, int_fmt, doc%default_ifmt)
1343 0 : ABI_DEFAULT(sfmt, string_fmt, doc%default_sfmt)
1344 0 : ABI_DEFAULT(w, width, doc%default_width)
1345 :
1346 0 : call doc%stream%push('--- !'//tag)
1347 :
1348 0 : if (comment /= '') then
1349 0 : call doc%stream%push(eol)
1350 0 : call yaml_start_field(doc%stream, 'comment', width=w)
1351 0 : call yaml_print_string(doc%stream, comment)
1352 : end if
1353 0 : call doc%stream%push(eol)
1354 :
1355 0 : call pl%restart()
1356 0 : do k=1,pl%length()
1357 0 : call string_clear(key)
1358 0 : call string_clear(vs)
1359 0 : call pl%iter(key, type_code, vi, vr, vs)
1360 :
1361 0 : call yaml_start_field(doc%stream, trim(key), width=w)
1362 0 : call doc%stream%push(' ')
1363 0 : if (type_code == TC_INT) then
1364 0 : call string_clear(tmp_i)
1365 0 : write(tmp_i, ifmt) vi
1366 0 : call doc%stream%push(trim(tmp_i))
1367 0 : else if (type_code == TC_REAL) then
1368 0 : call string_clear(tmp_r)
1369 0 : call format_real(vr, tmp_r, rfmt)
1370 0 : call doc%stream%push(trim(tmp_r))
1371 0 : else if (type_code == TC_STRING) then
1372 0 : call string_clear(tmp_s)
1373 0 : write(tmp_s, sfmt) vs
1374 0 : call yaml_print_string(doc%stream, trim(tmp_s))
1375 : end if
1376 0 : call doc%stream%push(eol)
1377 : end do
1378 :
1379 0 : call doc%write_and_free(unit, newline=nl)
1380 :
1381 0 : end subroutine yaml_single_dict
1382 : !!***
1383 :
1384 : !!****f* m_yaml/yaml_write_dict
1385 : !! NAME
1386 : !! yaml_write_dict
1387 : !!
1388 : !! FUNCTION
1389 : !! Write a dictionary in a Yaml document.
1390 : !!
1391 : !! INPUTS
1392 : !! tag: Yaml tag
1393 : !! dict_name: Dictionary name
1394 : !! dict: Dictionary
1395 : !! unit: Unit numver
1396 : !! [with_iter_state]: True if dict with iteration state should be added. Default: False
1397 : !!
1398 : !! SOURCE
1399 :
1400 0 : subroutine yaml_write_dict(tag, dict_name, dict, unit, with_iter_state)
1401 :
1402 : !Arguments ------------------------------------
1403 : character(len=*),intent(in) :: tag, dict_name
1404 : type(pair_list),intent(inout) :: dict
1405 : integer,intent(in) :: unit
1406 : logical,optional,intent(in) :: with_iter_state
1407 :
1408 : !Local variables-------------------------------
1409 : type(yamldoc_t) :: ydoc
1410 : logical :: with_iter_state_
1411 : ! *************************************************************************
1412 :
1413 0 : with_iter_state_ = .False.; if (present(with_iter_state)) with_iter_state_ = with_iter_state
1414 :
1415 0 : ydoc = yamldoc_open(tag, with_iter_state=with_iter_state_)
1416 0 : call ydoc%add_dict(dict_name, dict)
1417 0 : call ydoc%write_and_free(unit)
1418 :
1419 0 : end subroutine yaml_write_dict
1420 : !!***
1421 :
1422 : !!****f* m_yaml/yamldoc_write_unit_and_free
1423 : !! NAME
1424 : !! yamldoc_write_unit_and_free
1425 : !!
1426 : !! FUNCTION
1427 : !! Write Yaml document to unit and free memory.
1428 : !!
1429 : !! INPUTS
1430 : !! [newline]= set to False to prevent adding newlines after fields. Default: True
1431 : !! [firstchar]= Add first char to each line. Useful if the Yaml document must be added after shell comments
1432 : !! with firstchar="#".
1433 : !!
1434 : !! SOURCE
1435 :
1436 26947 : subroutine yamldoc_write_unit_and_free(self, unit, newline, firstchar)
1437 :
1438 : !Arguments ------------------------------------
1439 : class(yamldoc_t),intent(inout) :: self
1440 : integer,intent(in) :: unit
1441 : logical,intent(in),optional :: newline
1442 : character(len=*),optional,intent(in) :: firstchar
1443 :
1444 : !Local variables-------------------------------
1445 : logical :: nl
1446 : ! *************************************************************************
1447 :
1448 26947 : if (self%stream%length == 0) return
1449 26944 : ABI_DEFAULT(nl, newline, .true.)
1450 :
1451 26944 : call self%stream%push('...')
1452 :
1453 : ! FIXME: In principle, we should not use is_open here but it seems that
1454 : ! ab_out is not set to dev_null if parallelism over images.
1455 26944 : if (is_open(unit)) then
1456 24291 : if (present(firstchar)) then
1457 5 : call self%stream%flush(unit, newline=nl, firstchar=firstchar)
1458 : else
1459 24286 : call self%stream%flush(unit, newline=nl)
1460 : end if
1461 : else
1462 2653 : call self%stream%free()
1463 : end if
1464 :
1465 : end subroutine yamldoc_write_unit_and_free
1466 : !!***
1467 :
1468 : !!****f* m_yaml/yamldoc_write_units_and_free
1469 : !! NAME
1470 : !! yamldoc_write_units_and_free
1471 : !!
1472 : !! FUNCTION
1473 : !! Write Yaml document to a list of units and free memory.
1474 : !!
1475 : !! INPUTS
1476 : !! units=List of unit numbers.
1477 : !! [newline]= set to false to prevent adding newlines after fields. Default: True
1478 : !!
1479 : !! SOURCE
1480 :
1481 36594 : subroutine yamldoc_write_units_and_free(self, units, newline)
1482 :
1483 : !Arguments ------------------------------------
1484 : class(yamldoc_t),intent(inout) :: self
1485 : integer,intent(in) :: units(:)
1486 : logical,intent(in),optional :: newline
1487 :
1488 : !Local variables-------------------------------
1489 : integer :: ii, cnt
1490 : logical :: nl
1491 : !arrays
1492 36594 : integer :: my_units(size(units))
1493 : ! *************************************************************************
1494 :
1495 36594 : if (self%stream%length == 0) return
1496 36594 : ABI_DEFAULT(nl, newline, .true.)
1497 :
1498 : ! Remove duplicated units (if any)
1499 : ! FIXME: In principle, we should not use is_open here but it seems that
1500 : ! ab_out is not set to dev_null if parallelism over images.
1501 36594 : my_units(1) = units(1); cnt = 1
1502 36597 : do ii=2,size(units)
1503 6 : if (any(units(ii) == my_units(1:cnt))) cycle
1504 36597 : if (is_open(units(ii))) then
1505 3 : cnt = cnt + 1
1506 3 : my_units(cnt) = units(ii)
1507 : end if
1508 : end do
1509 :
1510 36594 : call self%stream%push('...')
1511 36594 : call self%stream%flush_units(my_units, newline=nl)
1512 :
1513 : end subroutine yamldoc_write_units_and_free
1514 : !!***
1515 :
1516 : !!****f* m_yaml/yamldoc_set_keys_to_string
1517 : !! NAME
1518 : !! yamldoc_set_keys_to_string
1519 : !!
1520 : !! FUNCTION
1521 : !! Set all keys to a common (string) value
1522 : !!
1523 : !! INPUTS
1524 : !! keylist = List of comma-separated keywords
1525 : !! svalue = String Value
1526 : !! [width] = impose a minimum width of the field name side of the column (padding with spaces)
1527 : !! [dict_key]=If present, a dictionary with key `dict_key` is created instead of a list.
1528 : !! [multiline_trig] = optional minimum number of elements before switching to multiline representation
1529 : !!
1530 : !! SOURCE
1531 :
1532 1124 : subroutine yamldoc_set_keys_to_string(self, keylist, svalue, dict_key, width, multiline_trig)
1533 :
1534 : !Arguments ------------------------------------
1535 : class(yamldoc_t),intent(inout) :: self
1536 : character(len=*),intent(in) :: keylist, svalue
1537 : character(len=*),intent(in),optional :: dict_key
1538 : integer,intent(in),optional :: width, multiline_trig
1539 :
1540 : !Local variables-------------------------------
1541 : integer :: i, n, w, start, stp, vmax
1542 : type(pair_list) :: dict
1543 :
1544 : ! *************************************************************************
1545 :
1546 0 : ABI_DEFAULT(w, width, self%default_width)
1547 :
1548 1124 : n = char_count(keylist, ",") + 1
1549 1124 : start = 1
1550 :
1551 1124 : if (.not. present(dict_key)) then
1552 1581 : do i=1,n
1553 1054 : stp = index(keylist(start:), ",")
1554 1581 : if (stp == 0) then
1555 527 : call self%add_string(adjustl(keylist(start:)), svalue, width=w)
1556 : else
1557 527 : call self%add_string(adjustl(keylist(start: start + stp - 2)), svalue, width=w)
1558 527 : start = start + stp
1559 527 : ABI_CHECK(start < len_trim(keylist), sjoin("Invalid keylist:", keylist))
1560 : end if
1561 : end do
1562 :
1563 : else
1564 : ! Create and insert dictionary.
1565 2453 : do i=1,n
1566 1856 : stp = index(keylist(start:), ",")
1567 2453 : if (stp == 0) then
1568 597 : call dict%set(adjustl(keylist(start:)), s=svalue)
1569 : else
1570 1259 : call dict%set(adjustl(keylist(start: start + stp - 2)), s=svalue)
1571 1259 : start = start + stp
1572 1259 : ABI_CHECK(start < len_trim(keylist), sjoin("Invalid keylist:", keylist))
1573 : end if
1574 : end do
1575 597 : ABI_DEFAULT(vmax, multiline_trig, self%default_multiline_trig)
1576 597 : call self%add_dict(trim(dict_key), dict, multiline_trig=vmax, width=w)
1577 597 : call dict%free()
1578 : end if
1579 :
1580 1124 : end subroutine yamldoc_set_keys_to_string
1581 : !!***
1582 :
1583 : ! private
1584 464652 : subroutine string_clear(string)
1585 : character(len=*),intent(inout) :: string
1586 36848402 : string = repeat(' ', len(string))
1587 464652 : end subroutine string_clear
1588 :
1589 567232 : subroutine format_real(val, dest, formt)
1590 : real(dp),intent(in) :: val
1591 : character(len=*),intent(out) :: dest
1592 : character(len=*),intent(in) :: formt
1593 :
1594 : !#ifdef HAVE_FC_IEEE_ARITHMETIC
1595 : ! if (ieee_is_nan(val)) then ! NaN
1596 : ! write(dest, '(a)') '.nan'
1597 : ! else if (val == MAGIC_UNDEF) then
1598 : !#else
1599 : ! if (val == MAGIC_UNDEF) then
1600 : !#endif
1601 567232 : if (val == MAGIC_UNDEF) then
1602 2760 : write(dest, '(a)') 'null'
1603 : else
1604 564472 : write(dest, trim(formt)) val
1605 : end if
1606 :
1607 567232 : end subroutine format_real
1608 :
1609 : !subroutine write_indent(input, output, n)
1610 : ! class(stream_string),intent(inout) :: input, output
1611 : ! integer,intent(in) :: n
1612 : !
1613 : ! integer :: buffstart, buffstop, length
1614 : ! character(len=chunk_size) :: buffer
1615 : !
1616 : ! do while (input%length > 0)
1617 : ! length = input%length
1618 : ! call input%pop_chunk(buffer)
1619 : !
1620 : ! buffstart = 1
1621 : ! buffstop = 1
1622 : ! do while (buffstart < min(length, chunk_size))
1623 : ! buffstop = index(buffer(buffstart:), eol)
1624 : ! if (buffstop > 0) then
1625 : ! call output%push(buffer(buffstart:buffstop))
1626 : ! call output%push(repeat(' ', n))
1627 : ! buffstart = buffstop+1
1628 : ! else if (buffstart < min(length, chunk_size)) then
1629 : ! call output%push(buffer(buffstart:min(length, chunk_size)))
1630 : ! buffstart = chunk_size
1631 : ! end if
1632 : ! end do
1633 : ! end do
1634 : !end subroutine write_indent
1635 :
1636 784017 : subroutine forbid_reserved_label(label)
1637 : character(len=*),intent(in) :: label
1638 : integer :: i
1639 :
1640 8624187 : do i=1,size(reserved_keywords)
1641 8624187 : if (reserved_keywords(i) == label) then
1642 0 : ABI_ERROR(trim(label)//' is a reserved keyword and cannot be used as a YAML label.')
1643 : end if
1644 : end do
1645 784017 : end subroutine forbid_reserved_label
1646 :
1647 588638 : pure function yaml_quote_string(string) result(quoted)
1648 :
1649 : character(len=*),intent(in) :: string
1650 : character(len=len(string)+2) :: quoted
1651 : logical :: multiline, spec_char, quote
1652 588638 : spec_char = index(string, ':', back=.true.) /= 0
1653 588638 : spec_char = spec_char .or. index(string, '{') /= 0
1654 588638 : spec_char = spec_char .or. index(string, '}') /= 0
1655 588638 : spec_char = spec_char .or. index(string, '[') /= 0
1656 588638 : spec_char = spec_char .or. index(string, ']') /= 0
1657 588638 : spec_char = spec_char .or. index(string, ',') /= 0
1658 588144 : spec_char = spec_char .or. index(string, '&') /= 0
1659 588144 : spec_char = spec_char .or. index(string, '*') /= 0
1660 586401 : spec_char = spec_char .or. index(string, '#') /= 0
1661 586401 : spec_char = spec_char .or. index(string, '?') /= 0
1662 586401 : spec_char = spec_char .or. index(string, '|') /= 0
1663 586401 : spec_char = spec_char .or. index(string, '-') /= 0
1664 584596 : spec_char = spec_char .or. index(string, '<') /= 0
1665 584596 : spec_char = spec_char .or. index(string, '>') /= 0
1666 584596 : spec_char = spec_char .or. index(string, '=') /= 0
1667 584596 : spec_char = spec_char .or. index(string, '!') /= 0
1668 584596 : spec_char = spec_char .or. index(string, '%') /= 0
1669 584596 : spec_char = spec_char .or. index(string, '@') /= 0
1670 584596 : spec_char = spec_char .or. index(string, '`') /= 0
1671 :
1672 588638 : quote = index(string, "'") /= 0
1673 588638 : multiline = index(string, eol, back=.true.) /= 0
1674 :
1675 588638 : if (quote) then
1676 0 : quoted='"'//string//'"'
1677 588638 : else if (multiline .or. spec_char) then
1678 4042 : quoted="'"//string//"'"
1679 : else
1680 584596 : quoted=string
1681 : endif
1682 588638 : end function yaml_quote_string
1683 :
1684 535842 : subroutine yaml_start_field(stream, label, tag, width)
1685 :
1686 : type(stream_string),intent(inout) :: stream
1687 : character(len=*),intent(in) :: label
1688 : integer,optional,intent(in) :: width
1689 : character(len=*),intent(in),optional :: tag
1690 : !character(len=*),optional,intent(in) :: comment
1691 :
1692 535842 : character(len=len_trim(label)+2) :: quoted
1693 :
1694 : !#ifdef HAVE_DEBUG_MODE
1695 535842 : call forbid_reserved_label(trim(label))
1696 : !#endif
1697 :
1698 535842 : quoted = yaml_quote_string(label)
1699 535842 : if (present(width)) then
1700 534684 : if (width > len_trim(label)) then
1701 891155 : call stream%push(trim(quoted)//repeat(' ', width-len_trim(quoted))//':')
1702 : else
1703 436144 : call stream%push(trim(quoted)//':')
1704 : end if
1705 : else
1706 1158 : call stream%push(trim(quoted)//':')
1707 : end if
1708 535842 : if (present(tag)) call stream%push(' !'//trim(tag))
1709 : !if (present(comment)) call stream%push(' #'//trim(comment))
1710 :
1711 535842 : end subroutine yaml_start_field
1712 :
1713 72159 : subroutine yaml_print_real1d(stream, length, arr, rfmt, vmax, string)
1714 :
1715 : !Arguments ------------------------------------
1716 : type(stream_string),intent(inout) :: stream
1717 : integer,intent(in) :: vmax, length
1718 : real(dp),intent(in) :: arr(length)
1719 : character(len=*),intent(in) :: rfmt
1720 : character(len=*),optional,intent(in) :: string
1721 :
1722 : !Local variables-------------------------------
1723 : integer :: i
1724 : character(len=50) :: tmp_r
1725 : ! *************************************************************************
1726 :
1727 72159 : if (length > vmax) then
1728 0 : call stream%push(' ['//eol//' ')
1729 : else
1730 72159 : call stream%push(' [')
1731 : end if
1732 :
1733 288636 : do i=1,length
1734 216477 : call string_clear(tmp_r)
1735 216477 : call format_real(arr(i), tmp_r, rfmt)
1736 216477 : call stream%push(trim(tmp_r))
1737 288636 : if (i > 0 .and. mod(i, vmax) == 0 .and. i /= length) then
1738 0 : call stream%push(', '//eol//' ')
1739 : else
1740 216477 : call stream%push(', ')
1741 : end if
1742 : end do
1743 :
1744 72159 : if (length > vmax) call stream%push(eol)
1745 72159 : if (present(string)) call stream%push(trim(string))
1746 72159 : call stream%push(']')
1747 :
1748 72159 : end subroutine yaml_print_real1d
1749 :
1750 0 : subroutine yaml_print_int1d(stream, length, arr, ifmt, vmax, string)
1751 :
1752 : !Arguments ------------------------------------
1753 : type(stream_string),intent(inout) :: stream
1754 : integer,intent(in) :: vmax
1755 : integer,intent(in) :: length
1756 : integer,intent(in) :: arr(length)
1757 : character(len=*),intent(in) :: ifmt
1758 : character(len=*),optional,intent(in) :: string
1759 :
1760 : !Local variables-------------------------------
1761 : integer :: i
1762 : character(len=50) :: tmp_i
1763 : ! *************************************************************************
1764 :
1765 0 : if (length > vmax) then
1766 0 : call stream%push(' ['//eol//' ')
1767 : else
1768 0 : call stream%push(' [')
1769 : end if
1770 :
1771 0 : do i=1,length
1772 0 : call string_clear(tmp_i)
1773 0 : write(tmp_i, ifmt) arr(i)
1774 0 : call stream%push(trim(tmp_i))
1775 0 : if (i > 0 .and. mod(i, vmax) == 0 .and. i /= length) then
1776 0 : call stream%push(', '//eol//' ')
1777 : else
1778 0 : call stream%push(', ')
1779 : end if
1780 : end do
1781 :
1782 0 : if (length > vmax) call stream%push(eol)
1783 0 : if (present(string)) call stream%push(trim(string))
1784 0 : call stream%push(']')
1785 :
1786 0 : end subroutine yaml_print_int1d
1787 :
1788 108709 : subroutine yaml_print_dict(stream, pl, key_size, s_size, kfmt, ifmt, rfmt, sfmt, vmax)
1789 :
1790 : type(stream_string),intent(inout) :: stream
1791 : integer,intent(in) :: vmax
1792 : type(pair_list),intent(inout) :: pl
1793 : character(len=*),intent(in) :: ifmt, rfmt, kfmt, sfmt
1794 : integer,intent(in) :: key_size, s_size
1795 108709 : character(len=key_size) :: key
1796 108709 : character(len=key_size+5) :: tmp_key
1797 : character(len=100) :: tmp_r, tmp_i
1798 108709 : character(len=s_size) :: tmp_s
1799 :
1800 : integer :: i, vi, type_code
1801 : real(dp) :: vr
1802 108709 : character(len=s_size) :: vs
1803 :
1804 108709 : if (pl%length() > vmax) then
1805 0 : call stream%push(' {'//eol//' ')
1806 : else
1807 108709 : call stream%push(' {')
1808 : end if
1809 :
1810 108709 : call pl%restart()
1811 356884 : do i=1,pl%length()
1812 248175 : call pl%iter(key, type_code, vi, vr, vs)
1813 :
1814 : !#ifdef HAVE_DEBUG_MODE
1815 248175 : call forbid_reserved_label(trim(key))
1816 : !#endif
1817 :
1818 : ! TODO: Should enclose key in double quotation markers only if needed
1819 : !if has_whitespaces(key) then
1820 : ! call string_clear(tmp_key)
1821 : ! write(tmp_key, kfmt) '"'//trim(key)//'"'
1822 : !else
1823 : !end if
1824 248175 : write(tmp_key, kfmt) trim(key)
1825 :
1826 248175 : call stream%push(trim(tmp_key)//': ')
1827 :
1828 174811 : select case (type_code)
1829 : case (TC_INT)
1830 174811 : call string_clear(tmp_i)
1831 174811 : write(tmp_i, ifmt) vi
1832 174811 : call stream%push(trim(tmp_i))
1833 : case (TC_REAL)
1834 71508 : call string_clear(tmp_r)
1835 71508 : call format_real(vr, tmp_r, rfmt)
1836 71508 : call stream%push(trim(tmp_r))
1837 : case (TC_STRING)
1838 1856 : call string_clear(tmp_s)
1839 1856 : write(tmp_s, sfmt) vs
1840 1856 : call yaml_print_string(stream, trim(tmp_s))
1841 : case default
1842 248175 : ABI_ERROR(sjoin("Invalid type_code:", itoa(type_code)))
1843 : end select
1844 :
1845 356884 : if (i > 0 .and. mod(i, vmax) == 0 .and. i /= pl%length()) then
1846 0 : call stream%push(', '//eol//' ')
1847 : else
1848 248175 : call stream%push(', ')
1849 : end if
1850 : end do
1851 :
1852 108709 : if (pl%length() > vmax) call stream%push(eol)
1853 108709 : call stream%push('}')
1854 :
1855 108709 : end subroutine yaml_print_dict
1856 :
1857 52796 : subroutine yaml_print_string(stream, string)
1858 :
1859 : type(stream_string),intent(inout) :: stream
1860 : character(len=*),intent(in) :: string
1861 52796 : character(len=len_trim(string)+2) :: quoted
1862 :
1863 52796 : quoted = yaml_quote_string(string)
1864 52796 : call stream%push(trim(quoted))
1865 :
1866 52796 : end subroutine yaml_print_string
1867 :
1868 : !pure logical function has_whitespaces(string) result (ans)
1869 : !
1870 : ! character(len=*),intent(in) :: string
1871 : ! integer :: ii, jj
1872 : !
1873 : ! ans = .False.
1874 : ! do ii=len_trim(string), 1, -1
1875 : ! if (string(ii:ii) == " ") then
1876 : ! ans = .True.; exit
1877 : ! end if
1878 : ! end do
1879 : !
1880 : ! if (ans) then
1881 : ! do jj=1,ii-1
1882 : ! if (string(ii:ii) /= " ") exit
1883 : ! end do
1884 : ! if (jj == ii) ans = .False.
1885 : ! end do
1886 : !
1887 : !end function has_whitespaces
1888 :
1889 0 : end module m_yaml
1890 : !!***
|