Field3D
Field3DOutputFile Class Reference

Provides writing of .f3d (internally, hdf5) files. More...

#include <Field3DFile.h>

Inheritance diagram for Field3DOutputFile:
Field3DFileBase

Public Types

enum  CreateMode { OverwriteMode, FailOnExisting }
 
- Public Types inherited from Field3DFileBase
typedef std::map< std::string,
std::string > 
GroupMembershipMap
 

Public Member Functions

bool create (const std::string &filename, CreateMode cm=OverwriteMode)
 Creates a .f3d file on disk.
 
template<class Data_T >
File::Partition::Ptr createNewPartition (const std::string &partitionName, const std::string &layerName, typename Field< Data_T >::Ptr field)
 create newPartition given the input config
 
std::string incrementPartitionName (std::string &pname)
 increment the partition or make it zero if there's not an integer suffix
 
bool writeGlobalMetadata ()
 This routine is call if you want to write out global metadata to disk.
 
bool writeGroupMembership ()
 This routine is called just before closing to write out any group membership to disk.
 
Constructors & destructor
 Field3DOutputFile ()
 
virtual ~Field3DOutputFile ()
 
Writing layer to disk
template<class Data_T >
bool writeScalarLayer (const std::string &layerName, typename Field< Data_T >::Ptr layer)
 Writes a scalar layer to the "Default" partition.
 
template<class Data_T >
bool writeVectorLayer (const std::string &layerName, typename Field< FIELD3D_VEC3_T< Data_T > >::Ptr layer)
 Writes a vector layer to the "Default" partition.
 
template<class Data_T >
bool writeScalarLayer (const std::string &partitionName, const std::string &layerName, typename Field< Data_T >::Ptr layer)
 Writes a layer to a specific partition. The partition will be created if not specified.
 
template<class Data_T >
bool writeScalarLayer (typename Field< Data_T >::Ptr layer)
 Writes a layer to a specific partition. The field name and attribute name are used for partition and layer, respectively.
 
template<class Data_T >
bool writeVectorLayer (const std::string &partitionName, const std::string &layerName, typename Field< FIELD3D_VEC3_T< Data_T > >::Ptr layer)
 Writes a layer to a specific partition. The partition will be created if not specified.
 
template<class Data_T >
bool writeVectorLayer (typename Field< FIELD3D_VEC3_T< Data_T > >::Ptr layer)
 Writes a layer to a specific partition. The field name and attribute name are used for partition and layer, respectively.
 
- Public Member Functions inherited from Field3DFileBase
void clear ()
 Clear the data structures and close the file.
 
bool close ()
 Closes the file. No need to call this unless you specifically want to close the file early. It will close once the File object goes out of scope.
 
FieldMetadata< Field3DFileBase > & metadata ()
 accessor to the m_metadata class
 
const FieldMetadata
< Field3DFileBase > & 
metadata () const
 Read only access to the m_metadata class.
 
virtual void metadataHasChanged (const std::string &)
 This function should implemented by concrete classes to get the callback when metadata changes.
 
 Field3DFileBase ()
 
virtual ~Field3DFileBase ()=0
 Pure virtual destructor to ensure we never instantiate this class.
 
void getPartitionNames (std::vector< std::string > &names) const
 Gets the names of all the partitions in the file.
 
void getScalarLayerNames (std::vector< std::string > &names, const std::string &partitionName) const
 Gets the names of all the scalar layers in a given partition.
 
void getVectorLayerNames (std::vector< std::string > &names, const std::string &partitionName) const
 Gets the names of all the vector layers in a given partition.
 
File::Partition::Ptr getPartition (const std::string &partitionName) const
 Returns a pointer to the given partition.
 
std::string intPartitionName (const std::string &partitionName, const std::string &layerName, FieldRes::Ptr field)
 Returns a unique partition name given the requested name. This ensures that partitions with matching mappings get the same name but each subsequent differing mapping gets a new, separate name.
 
std::string removeUniqueId (const std::string &partitionName) const
 Strips any unique identifiers from the partition name and returns the original name.
 
void addGroupMembership (const GroupMembershipMap &groupMembers)
 Add to the group membership.
 
void printHierarchy () const
 

Private Member Functions

template<class Data_T >
bool writeLayer (const std::string &partitionName, const std::string &layerName, bool isVectorLayer, typename Field< Data_T >::Ptr layer)
 Performs the actual writing of the layer to disk.
 
bool writeMapping (hid_t partitionLocation, FieldMapping::Ptr mapping)
 Writes the mapping to the given hdf5 node. Mappings are assumed to be light-weight enough to be stored as plain attributes under a group.
 
bool writeMetadata (hid_t metadataGroup, FieldBase::Ptr layer)
 Writes metadata for this layer.
 
bool writeMetadata (hid_t metadataGroup)
 Writes metadata for this file.
 

Additional Inherited Members

- Protected Types inherited from Field3DFileBase
typedef std::map< std::string,
int > 
PartitionCountMap
 
typedef std::vector
< File::Partition::Ptr
PartitionList
 
- Protected Member Functions inherited from Field3DFileBase
void closeInternal ()
 Closes the file if open.
 
File::Partition::Ptr partition (const std::string &partitionName)
 Returns a pointer to the given partition.
 
File::Partition::Ptr partition (const std::string &partitionName) const
 Returns a pointer to the given partition.
 
void getIntPartitionNames (std::vector< std::string > &names) const
 Gets the names of all the -internal- partitions in the file.
 
void getIntScalarLayerNames (std::vector< std::string > &names, const std::string &intPartitionName) const
 Gets the names of all the scalar layers in a given partition, but assumes that partition name is the -internal- partition name.
 
void getIntVectorLayerNames (std::vector< std::string > &names, const std::string &intPartitionName) const
 Gets the names of all the vector layers in a given partition, but assumes that partition name is the -internal- partition name.
 
int numIntPartitions (const std::string &partitionName) const
 Returns the number of internal partitions for a given partition name.
 
std::string makeIntPartitionName (const std::string &partitionsName, int i) const
 Makes an internal partition name given the external partition name. Effectively just tacks on .X to the name, where X is the number.
 
- Protected Attributes inherited from Field3DFileBase
hid_t m_file
 The hdf5 id of the current file. Will be -1 if no file is open.
 
GroupMembershipMap m_groupMembership
 Keeps track of group membership for each layer of partition name. The key is the "group" and the value is a space separated list of "partitionName.0:Layer1 partitionName.1:Layer0 ...".
 
std::vector< LayerInfom_layerInfo
 This stores layer info.
 
FieldMetadata< Field3DFileBasem_metadata
 metadata
 
PartitionCountMap m_partitionCount
 Contains a counter for each partition name. This is used to keep multiple fields with the same name unique in the file.
 
std::vector< std::string > m_partitionNames
 This stores partition names.
 
PartitionList m_partitions
 Vector of partitions.
 

Detailed Description

Provides writing of .f3d (internally, hdf5) files.

Refer to using_files for examples of how to use this in your code.

Note
We distinguish between scalar and vector layers even though both are templated. A scalarField<float> layer is interchangeable with a scalarField<double> (conceptually) but not with a scalar<V3f>, and thus not with vectorField<float>.

Definition at line 626 of file Field3DFile.h.

Member Enumeration Documentation

Enumerator:
OverwriteMode 
FailOnExisting 

Definition at line 632 of file Field3DFile.h.

Constructor & Destructor Documentation

Field3DOutputFile::Field3DOutputFile ( )

Definition at line 1199 of file Field3DFile.cpp.

{
// Empty
}
Field3DOutputFile::~Field3DOutputFile ( )
virtual

Definition at line 1206 of file Field3DFile.cpp.

{
}

Member Function Documentation

template<class Data_T >
bool Field3DOutputFile::writeScalarLayer ( const std::string &  layerName,
typename Field< Data_T >::Ptr  layer 
)
inline

Writes a scalar layer to the "Default" partition.

Definition at line 654 of file Field3DFile.h.

{ return writeScalarLayer<Data_T>(layerName, std::string("default"), layer); }
template<class Data_T >
bool Field3DOutputFile::writeVectorLayer ( const std::string &  layerName,
typename Field< FIELD3D_VEC3_T< Data_T > >::Ptr  layer 
)
inline

Writes a vector layer to the "Default" partition.

Definition at line 660 of file Field3DFile.h.

{ return writeVectorLayer<Data_T>(layerName, std::string("default"), layer); }
template<class Data_T >
bool Field3DOutputFile::writeScalarLayer ( const std::string &  partitionName,
const std::string &  layerName,
typename Field< Data_T >::Ptr  layer 
)

Writes a layer to a specific partition. The partition will be created if not specified.

Definition at line 1511 of file Field3DFile.h.

{
return writeLayer<Data_T>(partitionName, layerName, false, field);
}
template<class Data_T >
bool Field3DOutputFile::writeScalarLayer ( typename Field< Data_T >::Ptr  layer)

Writes a layer to a specific partition. The field name and attribute name are used for partition and layer, respectively.

Definition at line 1522 of file Field3DFile.h.

References FieldBase::attribute, FieldBase::name, Msg::print(), and Msg::SevWarning.

{
if (layer->name.size() == 0) {
Msg::print(Msg::SevWarning, "Field3DOutputFile::writeScalarLayer: "
"Tried to write a scalar layer with no name");
return false;
}
if (layer->attribute.size() == 0) {
Msg::print(Msg::SevWarning, "Field3DOutputFile::writeScalarLayer: "
"Tried to write a scalar layer with no attribute name");
return false;
}
return writeScalarLayer<Data_T>(layer->name, layer->attribute, layer);
}
template<class Data_T >
bool Field3DOutputFile::writeVectorLayer ( const std::string &  partitionName,
const std::string &  layerName,
typename Field< FIELD3D_VEC3_T< Data_T > >::Ptr  layer 
)

Writes a layer to a specific partition. The partition will be created if not specified.

Definition at line 1542 of file Field3DFile.h.

{
return writeLayer<FIELD3D_VEC3_T<Data_T> >(partitionName, layerName,
true, field);
}
template<class Data_T >
bool Field3DOutputFile::writeVectorLayer ( typename Field< FIELD3D_VEC3_T< Data_T > >::Ptr  layer)

Writes a layer to a specific partition. The field name and attribute name are used for partition and layer, respectively.

Definition at line 1555 of file Field3DFile.h.

References Msg::print(), and Msg::SevWarning.

{
if (layer->name.size() == 0) {
Msg::print(Msg::SevWarning, "Field3DOutputFile::writeVectorLayer: "
"Tried to write a vector layer with no name");
return false;
}
if (layer->attribute.size() == 0) {
Msg::print(Msg::SevWarning, "Field3DOutputFile::writeVectorLayer: "
"Tried to write a vector layer with no attribute name");
return false;
}
return writeVectorLayer<Data_T>(layer->name, layer->attribute, layer);
}
bool Field3DOutputFile::create ( const std::string &  filename,
CreateMode  cm = OverwriteMode 
)

Creates a .f3d file on disk.

Todo:
If the file can't be created hdf5 spits out an ugly error msg, we should make sure that doesn't happen.

Definition at line 1215 of file Field3DFile.cpp.

References Field3DFileBase::closeInternal(), Field3DFileBase::m_file, Msg::print(), Msg::SevWarning, and Hdf5Util::writeAttribute().

{
bool success = true;
try {
hid_t faid = H5Pcreate(H5P_FILE_ACCESS);
H5Pset_libver_bounds(faid, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST);
// Create new file
switch (cm) {
m_file = H5Fcreate(filename.c_str(),
H5F_ACC_TRUNC, H5P_DEFAULT, faid);
break;
m_file = H5Fcreate(filename.c_str(),
H5F_ACC_EXCL, H5P_DEFAULT, faid);
break;
}
// Check that file was created
if (m_file < 0)
throw ErrorCreatingFileException(filename);
// Create a version attribute on the root node
if (!writeAttribute(m_file, k_versionAttrName, 3,
k_currentFileVersion[0])) {
Msg::print(Msg::SevWarning, "Adding version number.");
return false;
}
}
catch (ErrorCreatingFileException &e) {
Msg::print(Msg::SevWarning, "Couldn't create file: " + string(e.what()) );
success = false;
}
catch (WriteAttributeException &e) {
Msg::print(Msg::SevWarning, "In file : " + filename +
" - Couldn't add attribute " + string(e.what()) );
success = false;
}
catch (...) {
"Unknown error when creating file: " + filename );
success = false;
}
return success;
}
bool Field3DOutputFile::writeGlobalMetadata ( )

This routine is call if you want to write out global metadata to disk.

Definition at line 1455 of file Field3DFile.cpp.

References Hdf5Util::H5Base::id(), Field3DFileBase::m_file, Msg::print(), and Msg::SevWarning.

{
// Add metadata group and write it out
H5ScopedGcreate metadataGroup(m_file, "field3d_global_metadata");
if (metadataGroup.id() < 0) {
Msg::print(Msg::SevWarning, "Error creating group: file metadata");
return false;
}
if (!writeMetadata(metadataGroup.id())) {
Msg::print(Msg::SevWarning, "Error writing file metadata.");
return false;
}
return true;
}
bool Field3DOutputFile::writeGroupMembership ( )

This routine is called just before closing to write out any group membership to disk.

Definition at line 1475 of file Field3DFile.cpp.

References Field3DFileBase::m_file, Field3DFileBase::m_groupMembership, Msg::print(), Msg::SevWarning, and Hdf5Util::writeAttribute().

{
using namespace std;
using namespace Hdf5Util;
if (!m_groupMembership.size())
return true;
H5ScopedGcreate group(m_file, "field3d_group_membership");
if (group < 0) {
"Error creating field3d_group_membership group.");
return false;
}
if (!writeAttribute(group, "is_field3d_group_membership", "1")) {
"Failed to write field3d_group_membership attribute.");
return false;
}
std::map<std::string, std::string>::const_iterator iter =
std::map<std::string, std::string>::const_iterator iEnd =
for (; iter != iEnd; ++iter) {
if (!writeAttribute(group, iter->first, iter->second)) {
"Failed to write groupMembership string: "+ iter->first);
return false;
}
}
return true;
}
std::string Field3DOutputFile::incrementPartitionName ( std::string &  pname)

increment the partition or make it zero if there's not an integer suffix

Definition at line 1515 of file Field3DFile.cpp.

References Field3DFileBase::m_partitionCount, Field3DFileBase::makeIntPartitionName(), and Field3DFileBase::removeUniqueId().

{
std::string myPartitionName = removeUniqueId(partitionName);
int nextIdx = -1;
if (m_partitionCount.find(myPartitionName) != m_partitionCount.end()) {
nextIdx = ++m_partitionCount[myPartitionName];
} else {
nextIdx = 0;
m_partitionCount[myPartitionName] = 0;
}
return makeIntPartitionName(myPartitionName, nextIdx);
}
template<class Data_T >
File::Partition::Ptr Field3DOutputFile::createNewPartition ( const std::string &  partitionName,
const std::string &  layerName,
typename Field< Data_T >::Ptr  field 
)

create newPartition given the input config

Todo:
We should probably remove the group on disk if we can't write the mapping

Definition at line 1317 of file Field3DFile.h.

References Field3DFileBase::m_file, Field3DFileBase::m_partitions, FieldRes::mapping(), Field3DFileBase::partition(), Msg::print(), Msg::SevWarning, and Hdf5Util::writeAttribute().

{
using namespace Hdf5Util;
using namespace Exc;
newPart->name = partitionName;
H5ScopedGcreate partGroup(m_file, newPart->name.c_str());
if (partGroup.id() < 0) {
"Error creating partition: " + newPart->name);
}
m_partitions.push_back(newPart);
// Pick up new pointer
File::Partition::Ptr part = partition(partitionName);
// Add mapping group to the partition
try {
if (!writeMapping(partGroup.id(), field->mapping())) {
"writeMapping returned false for an unknown reason ");
}
}
catch (WriteMappingException &e) {
Msg::print(Msg::SevWarning, "Couldn't write mapping for partition: "
+ partitionName);
}
catch (...) {
"Unknown error when writing mapping for partition: "
+ partitionName);
}
// Set the mapping of the partition. Since all layers share their
// partition's mapping, we can just pick this first one. All subsequent
// additions to the same partition are checked to have the same mapping
part->mapping = field->mapping();
// Tag node as partition
// Create a version attribute on the root node
if (!writeAttribute(partGroup.id(), "is_field3d_partition", "1")) {
Msg::print(Msg::SevWarning, "Adding partition string.");
}
return part;
}
bool Field3DOutputFile::writeMapping ( hid_t  partitionLocation,
FieldMapping::Ptr  mapping 
)
private

Writes the mapping to the given hdf5 node. Mappings are assumed to be light-weight enough to be stored as plain attributes under a group.

Definition at line 1271 of file Field3DFile.cpp.

References Hdf5Util::H5Base::id(), Msg::print(), Msg::SevWarning, and writeFieldMapping().

{
try {
// Make a group under the partition to store the mapping data
H5ScopedGcreate mappingGroup(partitionGroup, k_mappingStr);
if (mappingGroup.id() < 0)
throw CreateGroupException(k_mappingStr);
// Let FieldMappingIO handle the rest
if (!writeFieldMapping(mappingGroup.id(), mapping))
throw WriteMappingException(k_mappingStr);
}
catch (CreateGroupException &e) {
Msg::print(Msg::SevWarning, "Couldn't create group: " + string(e.what()) );
throw WriteMappingException(k_mappingStr);
}
return true;
}
template<class Data_T >
bool Field3DOutputFile::writeLayer ( const std::string &  partitionName,
const std::string &  layerName,
bool  isVectorLayer,
typename Field< Data_T >::Ptr  layer 
)
private

Performs the actual writing of the layer to disk.

Definition at line 1381 of file Field3DFile.h.

References Field3DFileBase::intPartitionName(), Field3DFileBase::m_file, FieldRes::mapping(), File::Layer::name, Field3DFileBase::partition(), Msg::print(), Msg::SevWarning, Hdf5Util::writeAttribute(), and writeField().

{
using namespace std;
using namespace Exc;
using namespace Hdf5Util;
if (!field) {
"Called writeLayer with null pointer. Ignoring...");
return false;
}
if (m_file < 0) {
"Attempting to write layer without opening file first. ");
return false;
}
string partitionName = intPartitionName(userPartitionName, layerName, field);
// See if the partition already exists or if we need to make it ---
File::Partition::Ptr part = partition(partitionName);
if (!part) {
part = createNewPartition<Data_T>(partitionName,layerName,field);
if (!part)
return false;
} else {
if (!field->mapping()) {
"Couldn't add layer \"" + layerName + "\" to partition \""
+ partitionName + "\" because the layer's mapping is null.");
return false;
}
// If the partition already existed, we need to make sure that the layer
// doesn't also exist
if (!isVectorLayer) {
if (part->scalarLayer(layerName)) {
//need to create a new partition and then add the layer to that
std::string newPartitionName = incrementPartitionName(partitionName);
part = createNewPartition<Data_T>(newPartitionName,layerName,field);
if (!part)
return false;
}
} else {
if (part->vectorLayer(layerName)) {
//need to create a new partition and then add the layer to that
std::string newPartitionName = incrementPartitionName(partitionName);
part = createNewPartition<Data_T>(newPartitionName,layerName,field);
if (!part)
return false;
}
}
}
if (!part->mapping) {
Msg::print(Msg::SevWarning, "Severe error - partition mapping is null: "
+ partitionName);
return false;
}
// Check that the mapping matches what's already in the Partition
if (!field->mapping()->isIdentical(part->mapping)) {
Msg::print(Msg::SevWarning, "Couldn't add layer \"" + layerName
+ "\" to partition \"" + partitionName
+ "\" because mapping doesn't match");
return false;
}
// Open the partition
H5ScopedGopen partGroup(m_file, part->name.c_str(), H5P_DEFAULT);
// Build a Layer object ---
File::Layer layer;
layer.name = layerName;
layer.parent = partitionName;
// Add Layer to file ---
H5ScopedGcreate layerGroup(partGroup.id(), layerName.c_str(),
H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
if (layerGroup.id() < 0) {
Msg::print(Msg::SevWarning, "Error creating layer: " + layerName);
return false;
}
// Tag as layer
if (!writeAttribute(layerGroup.id(), "class_type", "field3d_layer")) {
Msg::print(Msg::SevWarning, "Error adding layer string.");
return false;
}
// Add metadata group and write it out
H5ScopedGcreate metadataGroup(layerGroup.id(), "metadata");
if (metadataGroup.id() < 0) {
Msg::print(Msg::SevWarning, "Error creating group: metadata");
return false;
}
if (!writeMetadata(metadataGroup.id(), field)) {
Msg::print(Msg::SevWarning, "Error writing metadata.");
return false;
}
if (!writeField(layerGroup.id(), field)) {
Msg::print(Msg::SevWarning, "Error writing layer: " + layer.name);
return false;
}
// Add layer to partition ---
if (isVectorLayer)
part->addVectorLayer(layer);
else
part->addScalarLayer(layer);
return true;
}
bool Field3DOutputFile::writeMetadata ( hid_t  metadataGroup,
FieldBase::Ptr  layer 
)
private

Writes metadata for this layer.

Definition at line 1292 of file Field3DFile.cpp.

References FieldMetadata< CallBack_T >::floatMetadata(), FieldMetadata< CallBack_T >::intMetadata(), Msg::print(), Msg::SevWarning, FieldMetadata< CallBack_T >::strMetadata(), FieldMetadata< CallBack_T >::vecFloatMetadata(), FieldMetadata< CallBack_T >::vecIntMetadata(), and Hdf5Util::writeAttribute().

{
using namespace Hdf5Util;
{
field->metadata().strMetadata().begin();
field->metadata().strMetadata().end();
for (; i != end; ++i) {
if (!writeAttribute(metadataGroup, i->first, i->second))
{
Msg::print(Msg::SevWarning, "Writing attribute " + i->first );
return false;
}
}
}
{
field->metadata().intMetadata().begin();
field->metadata().intMetadata().end();
for (; i != end; ++i) {
if (!writeAttribute(metadataGroup, i->first, 1, i->second))
{
Msg::print(Msg::SevWarning, "Writing attribute " + i->first);
return false;
}
}
}
{
field->metadata().floatMetadata().begin();
field->metadata().floatMetadata().end();
for (; i != end; ++i) {
if (!writeAttribute(metadataGroup, i->first, 1, i->second))
{
Msg::print(Msg::SevWarning, "Writing attribute " + i->first);
return false;
}
}
}
{
field->metadata().vecIntMetadata().begin();
field->metadata().vecIntMetadata().end();
for (; i != end; ++i) {
if (!writeAttribute(metadataGroup, i->first, 3, i->second.x))
{
Msg::print(Msg::SevWarning, "Writing attribute " + i->first);
return false;
}
}
}
{
field->metadata().vecFloatMetadata().begin();
field->metadata().vecFloatMetadata().end();
for (; i != end; ++i) {
if (!writeAttribute(metadataGroup, i->first, 3, i->second.x))
{
Msg::print(Msg::SevWarning, "Writing attribute " + i->first);
return false;
}
}
}
return true;
}
bool Field3DOutputFile::writeMetadata ( hid_t  metadataGroup)
private

Writes metadata for this file.

Definition at line 1373 of file Field3DFile.cpp.

References FieldMetadata< CallBack_T >::floatMetadata(), FieldMetadata< CallBack_T >::intMetadata(), Field3DFileBase::metadata(), Msg::print(), Msg::SevWarning, FieldMetadata< CallBack_T >::strMetadata(), FieldMetadata< CallBack_T >::vecFloatMetadata(), FieldMetadata< CallBack_T >::vecIntMetadata(), and Hdf5Util::writeAttribute().

{
using namespace Hdf5Util;
{
metadata().strMetadata().begin();
metadata().strMetadata().end();
for (; i != end; ++i) {
if (!writeAttribute(metadataGroup, i->first, i->second))
{
Msg::print(Msg::SevWarning, "Writing attribute " + i->first );
return false;
}
}
}
{
metadata().intMetadata().begin();
metadata().intMetadata().end();
for (; i != end; ++i) {
if (!writeAttribute(metadataGroup, i->first, 1, i->second))
{
Msg::print(Msg::SevWarning, "Writing attribute " + i->first);
return false;
}
}
}
{
metadata().floatMetadata().begin();
for (; i != end; ++i) {
if (!writeAttribute(metadataGroup, i->first, 1, i->second))
{
Msg::print(Msg::SevWarning, "Writing attribute " + i->first);
return false;
}
}
}
{
metadata().vecIntMetadata().begin();
for (; i != end; ++i) {
if (!writeAttribute(metadataGroup, i->first, 3, i->second.x))
{
Msg::print(Msg::SevWarning, "Writing attribute " + i->first);
return false;
}
}
}
{
for (; i != end; ++i) {
if (!writeAttribute(metadataGroup, i->first, 3, i->second.x))
{
Msg::print(Msg::SevWarning, "Writing attribute " + i->first);
return false;
}
}
}
return true;
}

The documentation for this class was generated from the following files: