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 /*! 7 ****************************************************************************** 8 * 9 * \file AttrValue.hpp 10 * 11 * \brief Header file containing definition of AttrValue class. 12 * 13 ****************************************************************************** 14 */ 15 16 // Standard C++ headers 17 #include <string> 18 #include <vector> 19 20 // Other axom headers 21 #include "axom/config.hpp" 22 #include "axom/core/Macros.hpp" 23 #include "axom/slic/interface/slic.hpp" 24 25 // Sidre project headers 26 #include "axom/sidre/core/Attribute.hpp" 27 #include "axom/sidre/core/SidreTypes.hpp" 28 29 #ifndef SIDRE_ATTRVALUES_HPP_ 30 #define SIDRE_ATTRVALUES_HPP_ 31 32 namespace axom 33 { 34 namespace sidre 35 { 36 class View; 37 38 /*! 39 * \class AttrValue 40 * 41 * \brief Store Attribute values. 42 * 43 * Each attribute is defined by an instance of Attribute in the DataStore. 44 * The attribute has an associated type and index. 45 * 46 * The assumption is made that attributes will be looked up more often than 47 * set. So getAttribute should be optimized over setAttribute. 48 * 49 * Another assumption is that the View should not pay for attributes if they 50 * are not being used. 51 * 52 * Space can be minimized by creating more common Attribute first so that they 53 * will have a lower index. 54 * 55 * Methods which accept a Attribute pointer will check for 56 * nullptr but will not print a message. The calling routines in 57 * the View class are expected to print any error message. This will 58 * avoid multiple messages for the same error. For example, if the 59 * index cannot be converted to an Attribute pointer in the View 60 * class, an error message will be printing and then a NULL pointer 61 * passed to the AttrValues class which will not print another 62 * message. 63 */ 64 class AttrValues 65 { 66 public: 67 /*! 68 * Friend declarations to constrain usage via controlled access to 69 * private members. 70 */ 71 friend class View; 72 73 private: 74 //DISABLE_DEFAULT_CTOR(AttrValues); 75 DISABLE_MOVE_AND_ASSIGNMENT(AttrValues); 76 77 /*! 78 * \brief Return true if attribute is set in value. 79 */ isEmpty(Node & value)80 static bool isEmpty(Node& value) { return value.schema().dtype().is_empty(); } 81 82 /*! 83 * \brief Return true if the attribute has been explicitly set; else false. 84 */ 85 bool hasValue(const Attribute* attr) const; 86 87 /*! 88 * \brief Create a Conduit Node to store an attribute. 89 * 90 * Create vector of Nodes and push empty nodes up to attr's index. 91 * Called as part of View::createAttributeScalar and 92 * View::createAttributeString. 93 */ 94 bool createNode(IndexType idx); 95 96 /*! 97 * \brief Set attribute to its default value. 98 */ 99 bool setToDefault(const Attribute* attr); 100 101 /*! 102 * \brief Set attribute value from a scalar. 103 */ 104 template <typename ScalarType> setScalar(const Attribute * attr,ScalarType value)105 bool setScalar(const Attribute* attr, ScalarType value) 106 { 107 DataTypeId arg_id = detail::SidreTT<ScalarType>::id; 108 if(arg_id != attr->getTypeID()) 109 { 110 SLIC_CHECK_MSG(arg_id == attr->getTypeID(), 111 "setScalar: Incorrect type for attribute '" 112 << attr->getName() << "' of type " 113 << attr->getDefaultNodeRef().dtype().name() << ": " 114 << DataType::id_to_name(arg_id) << "."); 115 return false; 116 } 117 118 IndexType iattr = attr->getIndex(); 119 bool ok = createNode(iattr); 120 if(ok) 121 { 122 (*m_values)[iattr] = value; 123 } 124 return ok; 125 } 126 127 /*! 128 * \brief Set attribute value from a string. 129 */ setString(const Attribute * attr,const std::string & value)130 bool setString(const Attribute* attr, const std::string& value) 131 { 132 DataTypeId arg_id = CHAR8_STR_ID; 133 if(arg_id != attr->getTypeID()) 134 { 135 SLIC_CHECK_MSG(arg_id == attr->getTypeID(), 136 "setString: Incorrect type for attribute '" 137 << attr->getName() << "' of type " 138 << attr->getDefaultNodeRef().dtype().name() << ": " 139 << DataType::id_to_name(arg_id) << "."); 140 return false; 141 } 142 143 IndexType iattr = attr->getIndex(); 144 bool ok = createNode(iattr); 145 if(ok) 146 { 147 (*m_values)[iattr] = value; 148 } 149 return ok; 150 } 151 152 /*! 153 * \brief Set attribute value from a Node. 154 * 155 * Used when restoring attributes from a file. 156 * The type of node is not check. 157 */ setNode(const Attribute * attr,const Node & node)158 bool setNode(const Attribute* attr, const Node& node) 159 { 160 IndexType iattr = attr->getIndex(); 161 bool ok = createNode(iattr); 162 if(ok) 163 { 164 (*m_values)[iattr] = node; 165 } 166 return ok; 167 } 168 169 /*! 170 * \brief Remove all attribute values. 171 */ clear()172 void clear() 173 { 174 if(m_values != nullptr) 175 { 176 delete m_values; 177 m_values = nullptr; 178 } 179 } 180 181 /*! 182 * \brief Return a scalar attribute value. 183 */ 184 Node::ConstValue getScalar(const Attribute* attr) const; 185 186 /*! 187 * \brief Return a string attribute value. 188 */ 189 const char* getString(const Attribute* attr) const; 190 191 /*! 192 * \brief Return reference to value Node. 193 */ 194 const Node& getValueNodeRef(const Attribute* attr) const; 195 196 /*! 197 * \brief Return a reference to an empty Node. 198 * 199 * Used as error return value from getValueNodeRef. 200 */ getEmptyNodeRef() const201 const Node& getEmptyNodeRef() const 202 { 203 static const Node empty; 204 return empty; 205 } 206 207 /*! 208 * \brief Return first valid Attribute index for a set Attribute. 209 * (i.e., smallest index over all Attributes). 210 * 211 * sidre::InvalidIndex is returned if AttrValue has no Attributes. 212 */ 213 IndexType getFirstValidAttrValueIndex() const; 214 215 /*! 216 * \brief Return next valid Attribute index for a set Attribute 217 * after given index (i.e., smallest index over all Attribute 218 * indices larger than given one). 219 * 220 * sidre::InvalidIndex is returned if there is no valid index greater 221 * than given one. 222 * getNextAttrValueIndex(InvalidIndex) returns InvalidIndex. 223 */ 224 IndexType getNextValidAttrValueIndex(IndexType idx) const; 225 226 //@{ 227 //! @name Private AttrValues ctor and dtor 228 //! (callable only by DataStore methods). 229 230 /*! 231 * \brief Private ctor. 232 */ 233 AttrValues(); 234 235 /*! 236 * \brief Private copy ctor. 237 */ 238 AttrValues(const AttrValues& source); 239 240 /*! 241 * \brief Private dtor. 242 */ 243 ~AttrValues(); 244 245 //@} 246 247 /////////////////////////////////////////////////////////////////// 248 // 249 using Values = std::vector<Node>; 250 /////////////////////////////////////////////////////////////////// 251 252 /// Attributes values. 253 Values* m_values; 254 }; 255 256 } /* end namespace sidre */ 257 } /* end namespace axom */ 258 259 #endif /* SIDRE_ATTRVALUES_HPP_ */ 260