libSplash
AttributeInfo.cpp
1 /*
2  * Copyright 2016 Alexander Grund
3  *
4  * This file is part of libSplash.
5  *
6  * libSplash is free software: you can redistribute it and/or modify
7  * it under the terms of of either the GNU General Public License or
8  * the GNU Lesser General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * libSplash is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License and the GNU Lesser General Public License
16  * for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * and the GNU Lesser General Public License along with libSplash.
20  * If not, see <http://www.gnu.org/licenses/>.
21  */
22 
23 #include "splash/AttributeInfo.hpp"
24 #include "splash/CollectionType.hpp"
25 #include "splash/basetypes/generateCollectionType.hpp"
26 #include <cassert>
27 #include <sstream>
28 
29 namespace splash
30 {
31 
32 AttributeInfo::AttributeInfo(hid_t attr): attr_(attr), colType_(NULL)
33 {
34 }
35 
36 AttributeInfo::AttributeInfo(H5AttributeId& attr): attr_(attr.release()), colType_(NULL)
37 {
38 }
39 
40 AttributeInfo::~AttributeInfo()
41 {
42  delete colType_;
43 }
44 
45 AttributeInfo::AttributeInfo(const AttributeInfo& other): attr_(other.attr_), colType_(NULL)
46 {
47 }
48 
49 AttributeInfo& AttributeInfo::operator=(const AttributeInfo& other)
50 {
51  if(&other == this)
52  return *this;
53  attr_ = other.attr_;
54  // Reset lazy loaded values!
55  delete colType_;
56  colType_ = NULL;
57  type_.release();
58  space_.release();
59  return *this;
60 }
61 
62 std::string AttributeInfo::getExceptionString(const std::string& msg)
63 {
64  return (std::string("Exception for DCAttribute [") + readName() +
65  std::string("] ") + msg);
66 }
67 
68 inline void AttributeInfo::loadType() throw(DCException)
69 {
70  if(!type_)
71  {
72  type_.reset(H5Aget_type(attr_));
73  if (!type_)
74  throw DCException(getExceptionString("Could not get type"));
75  }
76 }
77 
78 inline void AttributeInfo::loadSpace() throw(DCException)
79 {
80  if(!space_)
81  {
82  space_.reset(H5Aget_space(attr_));
83  if (!space_)
84  throw DCException(getExceptionString("Could not get dataspace"));
85  // Currently only simple dataspaces exist and are supported by this library
86  if (H5Sis_simple(space_) <= 0)
87  throw DCException(getExceptionString("Dataspace is not simple"));
88  H5S_class_t spaceClass = H5Sget_simple_extent_type(space_);
89  if (spaceClass == H5S_SCALAR)
90  nDims_ = 0;
91  else
92  {
93  int nDims = H5Sget_simple_extent_ndims(space_);
94  if (nDims < 0)
95  throw DCException(getExceptionString("Could not get dimensionality of dataspace"));
96  nDims_ = static_cast<uint32_t>(nDims);
97  }
98  }
99 }
100 
102 {
103  ssize_t nameLen = H5Aget_name(attr_, 0, NULL);
104  if(nameLen <= 0)
105  return std::string();
106  char* name = new char[nameLen + 1];
107  // Read and in error case (unlikely) just store a zero-len string
108  if(H5Aget_name(attr_, nameLen + 1, name) < 0)
109  name[0] = 0;
110  std::string strName(name);
111  delete[] name;
112  return strName;
113 }
114 
116 {
117  loadType();
118  // For variable length strings the storage size is always the size of 2 pointers
119  // So we need the types size for that
120  if(H5Tis_variable_str(type_))
121  return H5Tget_size(type_);
122  else
123  {
124  size_t result = H5Aget_storage_size(attr_);
125  // This should be the same, but the above does not require getting the dims
126  assert(result == H5Tget_size(type_) * getDims().getScalarSize());
127  return result;
128  }
129 }
130 
132 {
133  if(!colType_)
134  {
135  loadType();
136  colType_ = generateCollectionType(type_);
137  }
138  return *colType_;
139 }
140 
142 {
143  loadSpace();
144  Dimensions dims(1, 1, 1);
145  // For scalars we don't need more info on the dataspace
146  if (nDims_ > 0)
147  {
148  if (nDims_ > DSP_DIM_MAX)
149  throw DCException(getExceptionString("Dimensionality of dataspace is greater than the maximum supported value"));
150  int nDims2 = H5Sget_simple_extent_dims(space_, dims.getPointer(), NULL);
151  // Conversion to int is save due to limited range
152  if (nDims2 != static_cast<int>(nDims_))
153  throw DCException(getExceptionString("Could not get dimensions of dataspace"));
154  dims.swapDims(nDims_);
155  }
156  return dims;
157 }
158 
160 {
161  loadSpace();
162  // A value of 0 means a scalar, treat as 1D
163  return nDims_ == 0 ? 1 : nDims_;
164 }
165 
167 {
168  loadType();
169  return H5Tis_variable_str(type_);
170 }
171 
172 void AttributeInfo::read(const CollectionType& colType, void* buf) throw(DCException)
173 {
174  if(!readNoThrow(colType, buf))
175  throw DCException(getExceptionString("Could not read or convert data"));
176 }
177 
178 bool AttributeInfo::readNoThrow(const CollectionType& colType, void* buf)
179 {
180  return H5Aread(attr_, colType.getDataType(), buf) >= 0;
181 }
182 
183 void AttributeInfo::read(void* buf, size_t bufSize) throw(DCException)
184 {
185  loadType();
186  if(getMemSize() != bufSize)
187  {
188  std::stringstream ss;
189  ss << "Buffer size (" << bufSize << ") does not match attribute size (" << getMemSize() << ")";
190  throw DCException(getExceptionString(ss.str()));
191  }
192  if(H5Aread(attr_, type_, buf) < 0)
193  throw DCException(getExceptionString("Could not read data"));
194 }
195 
197 {
198  AttributeInfo tmp(-1);
199  swap(*this, tmp);
200 }
201 
202 void swap(AttributeInfo& lhs, AttributeInfo& rhs)
203 {
204  using std::swap;
205  swap(lhs.attr_, rhs.attr_);
206  swap(lhs.colType_, rhs.colType_);
207  swap(lhs.type_, rhs.type_);
208  swap(lhs.space_, rhs.space_);
209  swap(lhs.nDims_, rhs.nDims_);
210 }
211 
212 } // namespace splash
hsize_t * getPointer()
Definition: Dimensions.hpp:192
void reset(hid_t id)
const CollectionType & getType()
CollectionType * generateCollectionType(hid_t datatype_id)
void swapDims(uint32_t dims)
Definition: Dimensions.hpp:269
const H5DataType & getDataType() const
bool readNoThrow(const CollectionType &colType, void *buf)
void read(const CollectionType &colType, void *buf)