@@ -27,8 +27,11 @@ program ESMF_HConfigEx
27
27
type (ESMF_HConfig) :: hconfig, hconfigTemp, hconfigTemp2
28
28
type (ESMF_HConfigIter) :: hconfigIter, hconfigIterBegin, hconfigIterEnd
29
29
type (ESMF_Config) :: config
30
+ type (ESMF_HConfigMatch_Flag) :: match
30
31
logical :: asOkay, valueL, isDefined
31
32
logical :: isNull, isScalar, isSequence, isMap
33
+ logical :: isAlias, isNotAlias, isExact, isMatch
34
+ logical :: isNone
32
35
logical , allocatable :: valueLSeq(:)
33
36
character (len= :), allocatable :: string, stringKey, tag
34
37
character (len= :), allocatable :: valueSSeq(:)
@@ -966,6 +969,8 @@ program ESMF_HConfigEx
966
969
call ESMF_HConfigFileLoad(hconfig, filename= " exampleWithTags.yaml" , rc= rc)
967
970
! EOC
968
971
if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag= ESMF_END_ABORT)
972
+ call ESMF_HConfigLog(hconfig, prefix= " WithTagsStart: " , rc= rc)
973
+ if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag= ESMF_END_ABORT)
969
974
! BOE
970
975
! The file contains the following YAML:
971
976
! \begin{verbatim}
@@ -981,6 +986,8 @@ program ESMF_HConfigEx
981
986
! value_ten: Null
982
987
! value_eleven:
983
988
! value_twelve: !myStuff xyz
989
+ ! value_thirteen: NO
990
+ ! value_fourteen: "NO"
984
991
! \end{verbatim}
985
992
!
986
993
! The value associated with {\em map key} "value\_ten" is explicitly set to
@@ -1120,9 +1127,72 @@ program ESMF_HConfigEx
1120
1127
if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag= ESMF_END_ABORT)
1121
1128
! BOE
1122
1129
! The Core schema tag resolves to {\tt{\bf tag:yaml.org,2002:bool}}. The
1123
- ! supported boolean values are {\tt true}, {\tt True}, {\tt TRUE},
1124
- ! {\tt false}, {\tt False}, and {\tt FALSE}.
1130
+ ! supported boolean values are:
1131
+ ! \begin{verbatim}
1132
+ ! true | false
1133
+ ! True | False
1134
+ ! TRUE | FALSE
1135
+ ! \end{verbatim}
1125
1136
!
1137
+ ! \paragraph{Additional Boolean values and the "Norway problem"}
1138
+ ! The YAMLCPP backend used by {\tt ESMF\_HConfig} interprets all of the values
1139
+ ! recognized as such under \htmladdnormallink{YAML 1.1}
1140
+ ! {https://yaml.org/type/bool.html} as boolean. This extends the above list with
1141
+ ! additional options:
1142
+ ! \begin{verbatim}
1143
+ ! yes | no
1144
+ ! Yes | No
1145
+ ! YES | NO
1146
+ ! y | n
1147
+ ! Y | N
1148
+ ! on | off
1149
+ ! On | Off
1150
+ ! ON | OFF
1151
+ ! \end{verbatim}
1152
+ ! The interpretation of value {\tt NO} as a boolean, instead of a literal
1153
+ ! string, can be problematic. It leads to the so-called {\em "Norway problem"},
1154
+ ! because the same string is often used as country code instead. The underlying
1155
+ ! problem is the misinterpretation of values by YAML.
1156
+ ! EOE
1157
+ tag = ESMF_HConfigGetTag(hconfig, keyString= " value_thirteen" , rc= rc)
1158
+ if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag= ESMF_END_ABORT)
1159
+ write (msgString, ' ("value_thirteen HConfig tag: ", A30)' ) tag
1160
+ call ESMF_LogWrite(trim (msgString), ESMF_LOGMSG_INFO, rc= rc)
1161
+ if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag= ESMF_END_ABORT)
1162
+ ! BOE
1163
+ ! Strictly speaking this is not a YAML problem, but instead a schema specific
1164
+ ! issue. Fortunately there are two simple solutions to ensure the correct and
1165
+ ! intended interpretation of values by {\tt ESMF\_HConfig}:
1166
+ !
1167
+ ! \begin{enumerate}
1168
+ ! \item Explicit quotation of strings: See for instance the {\em map value}
1169
+ ! for {\tt value\_fourteen} in the current example. Using explicit quotes for
1170
+ ! {\tt "NO"}, the entry is safely interpreted as a literal string, and if
1171
+ ! queried for its tag, will return {\tt tag:yaml.org,2002:str}.
1172
+ !
1173
+ ! \item Explicit standard tags: This option allows explicit specificaiton of any
1174
+ ! tag, e.g. the standard short-hand tag {\tt !str} for literal strings. This
1175
+ ! approach is discussed in more detal below.
1176
+ ! \end{enumerate}
1177
+ ! EOE
1178
+ tag = ESMF_HConfigGetTag(hconfig, keyString= " value_fourteen" , rc= rc)
1179
+ if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag= ESMF_END_ABORT)
1180
+ write (msgString, ' ("value_fourteen HConfig tag: ", A30)' ) tag
1181
+ call ESMF_LogWrite(trim (msgString), ESMF_LOGMSG_INFO, rc= rc)
1182
+ if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag= ESMF_END_ABORT)
1183
+
1184
+ call ESMF_HConfigAdd(hconfig, addKeyString= " value_added" ,content= " 'NO'" ,rc= rc)
1185
+ if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag= ESMF_END_ABORT)
1186
+
1187
+ tag = ESMF_HConfigGetTag(hconfig, keyString= " value_added" , rc= rc)
1188
+ if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag= ESMF_END_ABORT)
1189
+ write (msgString, ' ("value_added HConfig tag: ", A30)' ) tag
1190
+ call ESMF_LogWrite(trim (msgString), ESMF_LOGMSG_INFO, rc= rc)
1191
+ if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag= ESMF_END_ABORT)
1192
+
1193
+ call ESMF_HConfigLog(hconfig, prefix= " WithTagsFinish: " , rc= rc)
1194
+ if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag= ESMF_END_ABORT)
1195
+ ! BOE
1126
1196
! \paragraph{Explicit standard tags}
1127
1197
! Standard short-hand tags can be specified to change the default resolution.
1128
1198
! This is demonstrated for {\em map keys} "value\_four", "value\_six", and
@@ -1184,6 +1254,159 @@ program ESMF_HConfigEx
1184
1254
! EOC
1185
1255
if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag= ESMF_END_ABORT)
1186
1256
1257
+ !- ------------------------------------------------------------------------------
1258
+ ! BOE
1259
+ ! \subsubsection{Comparing HConfig objects}
1260
+ !
1261
+ ! The HConfig class follows the standard behavior of ESMF deep classes as
1262
+ ! described in section \ref{assignment_equality_copy_compare}. To demonstrate
1263
+ ! the operations of assignment, equality, and comparison based on content, we
1264
+ ! start by creating a simple HConfig object.
1265
+ ! EOE
1266
+ ! BOC
1267
+ ! type(ESMF_HConfig) :: hconfig
1268
+ hconfig = ESMF_HConfigCreate(content= " {car: red, bike: 22, plane: TRUE}" , rc= rc)
1269
+ ! EOC
1270
+ if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag= ESMF_END_ABORT)
1271
+ ! BOE
1272
+ ! A simple assignment results in an alias to the same deep HConfig object.
1273
+ ! EOE
1274
+ ! BOC
1275
+ ! type(ESMF_HConfig) :: hconfigTemp
1276
+ hconfigTemp = hconfig
1277
+ ! EOC
1278
+ ! BOE
1279
+ ! The equality {\tt (==)} and inequality {\tt (/=)} operators are
1280
+ ! overloaded to check for the alias condition when used between two
1281
+ ! HConfig objects.
1282
+ ! EOE
1283
+ ! BOC
1284
+ ! logical :: isAlias
1285
+ isAlias = (hconfigTemp == hconfig)
1286
+ ! EOC
1287
+ write (msgString, ' ("isAlias: ", l2)' ) isAlias
1288
+ call ESMF_LogWrite(trim (msgString), ESMF_LOGMSG_INFO, rc= rc)
1289
+ if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag= ESMF_END_ABORT)
1290
+ ! BOC
1291
+ ! logical :: isNotAlias
1292
+ isNotAlias = (hconfigTemp /= hconfig)
1293
+ ! EOC
1294
+ write (msgString, ' ("isNotAlias: ", l2)' ) isNotAlias
1295
+ call ESMF_LogWrite(trim (msgString), ESMF_LOGMSG_INFO, rc= rc)
1296
+ if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag= ESMF_END_ABORT)
1297
+ ! BOE
1298
+ ! Alias equality can also be tested by using the {\tt ESMF\_HConfigMatch()}
1299
+ ! function. The return value of this function is of type
1300
+ ! {\tt ESMF\_HConfigMatch\_Flag}, which allows for a wider range of possible
1301
+ ! comparison results. See section~\ref{const:hconfigmatch} for all the
1302
+ ! implemented return values.
1303
+ ! EOE
1304
+ ! BOC
1305
+ ! type(ESMF_HConfigMatch_Flag) :: match
1306
+ match = ESMF_HConfigMatch(hconfig, hconfigTemp, rc= rc)
1307
+ ! EOC
1308
+ if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag= ESMF_END_ABORT)
1309
+ ! BOE
1310
+ ! For the case of an alias match, the value of {\tt ESMF\_HCONFIGMATCH\_ALIAS}
1311
+ ! is returned.
1312
+ ! EOE
1313
+ ! BOC
1314
+ isAlias = (match == ESMF_HCONFIGMATCH_ALIAS)
1315
+ ! EOC
1316
+ write (msgString, ' ("isAlias from match: ", l2)' ) isAlias
1317
+ call ESMF_LogWrite(trim (msgString), ESMF_LOGMSG_INFO, rc= rc)
1318
+ if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag= ESMF_END_ABORT)
1319
+ ! BOE
1320
+ ! To demonstrate content matching for HConfig objects that are not aliases, we
1321
+ ! create a separate object with the same content as {\tt hconfig}.
1322
+ ! EOE
1323
+ ! BOC
1324
+ ! type(ESMF_HConfig) :: hconfigTemp
1325
+ hconfigTemp = ESMF_HConfigCreate(content= " {car: red, bike: 22, plane: TRUE}" , rc= rc)
1326
+ ! EOC
1327
+ if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag= ESMF_END_ABORT)
1328
+ ! BOE
1329
+ ! The simple alias check now returns {\tt .false.}.
1330
+ ! EOE
1331
+ ! BOC
1332
+ ! logical :: isAlias
1333
+ isAlias = (hconfigTemp == hconfig)
1334
+ ! EOC
1335
+ write (msgString, ' ("isAlias for diff objects: ", l2)' ) isAlias
1336
+ call ESMF_LogWrite(trim (msgString), ESMF_LOGMSG_INFO, rc= rc)
1337
+ if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag= ESMF_END_ABORT)
1338
+ ! BOE
1339
+ ! However, for two separate HConfig objects that have exactly matching
1340
+ ! content, as is the case for {\tt hconfig} and {\tt hconfigTemp}, function
1341
+ ! {\tt ESMF\_HConfigMatch()} returns value {\tt ESMF\_HCONFIGMATCH\_EXACT}.
1342
+ ! EOE
1343
+ ! BOC
1344
+ ! type(ESMF_HConfigMatch_Flag) :: match
1345
+ match = ESMF_HConfigMatch(hconfig, hconfigTemp, rc= rc)
1346
+ ! EOC
1347
+ if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag= ESMF_END_ABORT)
1348
+ ! BOC
1349
+ ! logical :: isExact
1350
+ isExact = (match == ESMF_HCONFIGMATCH_EXACT)
1351
+ ! EOC
1352
+ write (msgString, ' ("isExact: ", l2)' ) isExact
1353
+ call ESMF_LogWrite(trim (msgString), ESMF_LOGMSG_INFO, rc= rc)
1354
+ if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag= ESMF_END_ABORT)
1355
+ ! BOE
1356
+ ! The values returned by {\tt ESMF\_HConfigMatch()} are constructed in
1357
+ ! a monotonically increasing manner to simplify general comparisons that
1358
+ ! ensure two objects are either aliases of each other {\em or} their content
1359
+ ! matches exactly. This common case is demonstrated in the following code that
1360
+ ! sets {\tt isMatch} to {\tt .true.} for the alias or exact match condition,
1361
+ ! and {\tt .false.} otherwise, using {\tt (>=)} logic.
1362
+ ! EOE
1363
+ ! BOC
1364
+ ! logical :: isMatch
1365
+ isMatch = (match >= ESMF_HCONFIGMATCH_EXACT)
1366
+ ! EOC
1367
+ write (msgString, ' ("isMatch: ", l2)' ) isMatch
1368
+ call ESMF_LogWrite(trim (msgString), ESMF_LOGMSG_INFO, rc= rc)
1369
+ if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag= ESMF_END_ABORT)
1370
+ ! BOE
1371
+ ! While there is an exact match of the content of {\tt hconfig} and
1372
+ ! {\tt hconfigTemp}, they are distinct objects in memory, which can be modified
1373
+ ! independent of each other. E.g. another key-value pair can be added to
1374
+ ! {\tt hconfigTemp} without affecting the content of {\tt hconfig}.
1375
+ ! EOE
1376
+ ! BOC
1377
+ call ESMF_HConfigAdd(hconfigTemp, addKeyString= " kNew" , content= 7 , rc= rc)
1378
+ ! EOC
1379
+ if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag= ESMF_END_ABORT)
1380
+ ! BOE
1381
+ ! Now that the content of {\tt hconfig} and {\tt hconfigTemp} differs, function
1382
+ ! {\tt ESMF\_HConfigMatch()} returns value {\tt ESMF\_HCONFIGMATCH\_NONE}.
1383
+ ! EOE
1384
+ ! BOC
1385
+ ! type(ESMF_HConfigMatch_Flag) :: match
1386
+ match = ESMF_HConfigMatch(hconfig, hconfigTemp, rc= rc)
1387
+ ! EOC
1388
+ if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag= ESMF_END_ABORT)
1389
+ ! BOC
1390
+ ! logical :: isNone
1391
+ isNone = (match == ESMF_HCONFIGMATCH_NONE)
1392
+ ! EOC
1393
+ write (msgString, ' ("isNone: ", l2)' ) isNone
1394
+ call ESMF_LogWrite(trim (msgString), ESMF_LOGMSG_INFO, rc= rc)
1395
+ if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag= ESMF_END_ABORT)
1396
+ ! BOE
1397
+ ! Finally clean up both HConfig objects.
1398
+ ! EOE
1399
+ ! BOC
1400
+ ! Destroy hconfig when done with it.
1401
+ call ESMF_HConfigDestroy(hconfig, rc= rc)
1402
+ ! EOC
1403
+ if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag= ESMF_END_ABORT)
1404
+ ! BOC
1405
+ ! Destroy hconfigTemp when done with it.
1406
+ call ESMF_HConfigDestroy(hconfigTemp, rc= rc)
1407
+ ! EOC
1408
+ if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag= ESMF_END_ABORT)
1409
+
1187
1410
!- ------------------------------------------------------------------------------
1188
1411
! BOE
1189
1412
! \subsubsection{Adding, Setting, and Removing elements from HConfig object}
@@ -1597,9 +1820,16 @@ program ESMF_HConfigEx
1597
1820
! ...
1598
1821
! \end{verbatim}
1599
1822
!
1600
- ! The optional {\tt doc} argument can be specified when saving the
1601
- ! multi-document {\tt hconfig} to file. Only the specified document, by index,
1602
- ! is written to file.
1823
+ ! The content of the {\tt hconfig} object can be written to the ESMF log file
1824
+ ! as usual.
1825
+ ! EOE
1826
+ ! BOC
1827
+ call ESMF_HConfigLog(hconfig, prefix= " my-multi-doc: " , rc= rc)
1828
+ ! EOC
1829
+ if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag= ESMF_END_ABORT)
1830
+ ! BOE
1831
+ ! The optional {\tt doc} argument can be specified to save or log a specific
1832
+ ! document of the multi-document {\tt hconfig} object.
1603
1833
! EOE
1604
1834
! BOC
1605
1835
call ESMF_HConfigFileSave(hconfig, filename= " multi_01.yaml" , doc= 2 , rc= rc)
0 commit comments