1 // Copyright (c) 2017-2021, Lawrence Livermore National Security, LLC and
2 // other Axom Project Developers. See the top-level LICENSE file for details.
3 //
4 // SPDX-License-Identifier: (BSD-3-Clause)
5 
6 #include "axom/inlet/inlet_utils.hpp"
7 
8 namespace axom
9 {
10 namespace inlet
11 {
setWarningFlag(axom::sidre::Group * root)12 void setWarningFlag(axom::sidre::Group* root)
13 {
14   if(!root->hasView("warningFlag"))
15   {
16     root->createViewScalar("warningFlag", 1);
17   }
18 }
19 
setFlag(axom::sidre::Group & target,axom::sidre::Group & root,const std::string & flag,bool value)20 void setFlag(axom::sidre::Group& target,
21              axom::sidre::Group& root,
22              const std::string& flag,
23              bool value)
24 {
25   const int8 bval = value ? 1 : 0;
26   if(target.hasView(flag))
27   {
28     auto flagView = target.getView(flag);
29     if(flagView->getData<int8>() != bval)
30     {
31       const std::string msg =
32         fmt::format("[Inlet] '{0}' value has already been defined for: {1}",
33                     flag,
34                     target.getName());
35 
36       SLIC_WARNING(msg);
37       setWarningFlag(&root);
38     }
39   }
40   else
41   {
42     if(value)
43     {
44       target.createViewScalar(flag, bval);
45     }
46     else
47     {
48       target.createViewScalar(flag, bval);
49     }
50   }
51 }
52 
checkFlag(const axom::sidre::Group & target,axom::sidre::Group & root,const std::string & flag)53 bool checkFlag(const axom::sidre::Group& target,
54                axom::sidre::Group& root,
55                const std::string& flag)
56 {
57   if(!target.hasView(flag))
58   {
59     return false;
60   }
61   const axom::sidre::View* valueView = target.getView(flag);
62   const int8 intValue = valueView->getScalar();
63   if(intValue < 0 || intValue > 1)
64   {
65     const std::string msg = fmt::format(
66       "[Inlet] Invalid integer value stored in "
67       " boolean value named {0} for flag '{1}'",
68       target.getName(),
69       flag);
70     SLIC_WARNING(msg);
71     setWarningFlag(&root);
72     return static_cast<bool>(intValue);
73   }
74 
75   return static_cast<bool>(intValue);
76 }
77 
verifyRequired(const axom::sidre::Group & target,const bool condition,const std::string & type,std::vector<VerificationError> * errors)78 bool verifyRequired(const axom::sidre::Group& target,
79                     const bool condition,
80                     const std::string& type,
81                     std::vector<VerificationError>* errors)
82 {
83   // Assume that it wasn't found
84   ReaderResult status = ReaderResult::NotFound;
85   if(target.hasView("retrieval_status"))
86   {
87     status = static_cast<ReaderResult>(
88       static_cast<int>(target.getView("retrieval_status")->getData()));
89   }
90 
91   if(target.hasView("required"))
92   {
93     int8 required = target.getView("required")->getData();
94     // If it wasn't found at all, it's only an error if the object was required and not provided
95     // The retrieval_status will typically (but not always) be NotFound in these cases, but that
96     // information isn't needed here unless it's a collection group - empty collections are permissible,
97     // so they shouldn't impede verification if they existed but were empty (hence Success check)
98     if(required && !condition &&
99        (!isCollectionGroup(target.getPathName()) ||
100         status != ReaderResult::Success))
101     {
102       const std::string msg = fmt::format(
103         "[Inlet] Required {0} not "
104         "specified: {1}",
105         type,
106         target.getPathName());
107       INLET_VERIFICATION_WARNING(target.getPathName(), msg, errors);
108       return false;
109     }
110   }
111 
112   // If it was the wrong type or part of a non-homogeneous array, it's always an error,
113   // even if the object wasn't marked as required
114   if(status == ReaderResult::WrongType || status == ReaderResult::NotHomogeneous)
115   {
116     const std::string reason = (status == ReaderResult::WrongType)
117       ? "of the wrong type"
118       : "not homogeneous";
119     const std::string msg =
120       fmt::format("[Inlet] {0} '{1}' was {2}", type, target.getPathName(), reason);
121     INLET_VERIFICATION_WARNING(target.getPathName(), msg, errors);
122     return false;
123   }
124   return true;
125 }
126 
markAsStructCollection(axom::sidre::Group & target)127 void markAsStructCollection(axom::sidre::Group& target)
128 {
129   if(target.hasView(detail::STRUCT_COLLECTION_FLAG))
130   {
131     // This flag should only ever be one, so we verify that and error otherwise
132     const sidre::View* flag = target.getView(detail::STRUCT_COLLECTION_FLAG);
133     SLIC_ERROR_IF(
134       !flag->isScalar(),
135       fmt::format(
136         "[Inlet] Struct collection flag of group '{0}' was not a scalar",
137         target.getName()));
138     const int8 value = flag->getScalar();
139     SLIC_ERROR_IF(value != 1,
140                   fmt::format("[Inlet] Struct collection flag of group '{0}' "
141                               "had a value other than 1",
142                               target.getName()));
143   }
144   else
145   {
146     target.createViewScalar(detail::STRUCT_COLLECTION_FLAG, static_cast<int8>(1));
147   }
148 }
149 
markRetrievalStatus(axom::sidre::Group & target,const ReaderResult result)150 void markRetrievalStatus(axom::sidre::Group& target, const ReaderResult result)
151 {
152   if(!target.hasView("retrieval_status"))
153   {
154     target.createViewScalar("retrieval_status", static_cast<int>(result));
155   }
156 }
157 
collectionRetrievalResult(const bool contains_other_type,const bool contains_requested_type)158 ReaderResult collectionRetrievalResult(const bool contains_other_type,
159                                        const bool contains_requested_type)
160 {
161   // First check if the collection was entirely the wrong type
162   if(contains_other_type && !contains_requested_type)
163   {
164     return ReaderResult::WrongType;
165   }
166   // Then check if some values were of the correct type, but others weren't
167   else if(contains_other_type)
168   {
169     return ReaderResult::NotHomogeneous;
170   }
171   // Otherwise we mark it as successful - having just an empty collection
172   // counts as success
173   return ReaderResult::Success;
174 }
175 
176 }  // namespace inlet
177 }  // namespace axom
178