hdf5: fix crashes on extraction of compound fields integer 64 bits ( signed and
[scilab.git] / scilab / modules / hdf5 / src / cpp / H5CompoundData.cpp
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2012 - Scilab Enterprises - Calixte DENIZET
4  *
5  * Copyright (C) 2012 - 2016 - Scilab Enterprises
6  *
7  * This file is hereby licensed under the terms of the GNU GPL v2.0,
8  * pursuant to article 5.3.4 of the CeCILL v.2.1.
9  * This file was originally licensed under the terms of the CeCILL v2.1,
10  * and continues to be available under such terms.
11  * For more information, see the COPYING file which you should have received
12  * along with this program.
13  *
14  */
15
16 #include "H5Options.hxx"
17 #include "H5CompoundData.hxx"
18 #include "H5DataFactory.hxx"
19
20 namespace org_modules_hdf5
21 {
22
23 H5CompoundData::H5CompoundData(H5Object & _parent, const hsize_t _totalSize, const hsize_t _dataSize, const hsize_t _ndims, const hsize_t * _dims, char * _data, hid_t compoundType, const hsize_t _stride, const size_t _offset, const bool _dataOwner) : H5BasicData<char>(_parent, _totalSize, _dataSize, _ndims, _dims, _data, _stride, _offset, _dataOwner), type(compoundType), cumprod(H5Object::getCumProd(_ndims, dims))
24 {
25     nfields = (unsigned int)H5Tget_nmembers(compoundType);
26     infos = new std::map<std::string, FieldInfo *>();
27     fieldinfos = new FieldInfo *[nfields];
28     for (unsigned int i = 0; i < nfields; i++)
29     {
30         hid_t mtype = H5Tget_member_type(compoundType, i);
31         hsize_t size = H5Tget_size(mtype);
32         char * mname = H5Tget_member_name(compoundType, i);
33         std::string name(mname);
34
35         //free crash: it will be fix with hdf5 libs >= 1.8.16 with new function h5free_memory
36         //h5free_memory(mname);
37
38         size_t offs = H5Tget_member_offset(compoundType, i);
39         FieldInfo * info = 0;
40         if (H5Tget_class(type) == H5T_STRING && !H5Tis_variable_str(type))
41         {
42             // We have a C-string so it is null terminated
43             size++;
44         }
45
46         info = new FieldInfo(mtype, size, offs, name);
47         (*infos)[name] = info;
48         fieldinfos[i] = info;
49     }
50 }
51
52 H5CompoundData::~H5CompoundData()
53 {
54     infos->erase(infos->begin(), infos->end());
55     delete infos;
56     delete[] fieldinfos;
57     delete[] cumprod;
58     H5Tclose(type);
59 }
60
61 void H5CompoundData::toScilab(void * pvApiCtx, const int lhsPosition, int * parentList, const int listPosition, const bool flip) const
62 {
63     H5Object::toScilab(pvApiCtx, lhsPosition, parentList, listPosition, flip);
64 }
65
66 bool H5CompoundData::isCompound() const
67 {
68     return true;
69 }
70
71 void H5CompoundData::getAccessibleAttribute(const std::string & _name, const int pos, void * pvApiCtx) const
72 {
73     H5Data & data = getData(_name);
74     data.toScilab(pvApiCtx, pos, 0, 0, H5Options::isReadFlip());
75
76     if (data.mustDelete())
77     {
78         delete &data;
79     }
80 }
81
82 H5Data & H5CompoundData::getData(const std::string fieldname) const
83 {
84     std::map<std::string, FieldInfo *>::const_iterator it = infos->find(fieldname);
85
86     if (it != infos->end())
87     {
88         return H5DataFactory::getObjectData(*const_cast<H5CompoundData *>(this), totalSize, it->second->size, it->second->type, ndims, dims, data, stride ? stride : dataSize, offset + it->second->offset, false);
89     }
90
91     throw H5Exception(__LINE__, __FILE__, _("Invalid field name: %s"), fieldname.c_str());
92 }
93
94 H5Object & H5CompoundData::getData(const unsigned int size, const unsigned int * index) const
95 {
96     unsigned int pos = 0;
97     unsigned int cumprod = 1;
98     hsize_t * _dims = 0;
99
100     for (unsigned int i = 0; i < size; i++)
101     {
102         pos += cumprod * index[i];
103     }
104
105     if (pos >= totalSize)
106     {
107         throw H5Exception(__LINE__, __FILE__, _("Invalid index.\n"));
108     }
109
110     _dims = new hsize_t[1];
111     _dims[0] = 1;
112
113     return *new H5CompoundData(*const_cast<H5CompoundData *>(this), 1, dataSize, 1, _dims, static_cast<char *>(data) + offset + pos * (dataSize + stride), type, 0, 0, false);
114 }
115
116 void H5CompoundData::getFieldNames(const int position, void * pvApiCtx)
117 {
118     std::vector<std::string> names;
119     names.reserve(nfields);
120
121     for (unsigned int i = 0; i < nfields; i++)
122     {
123         names.push_back(fieldinfos[i]->name);
124     }
125     H5BasicData<char>::putStringVectorOnStack(names, (int)names.size(), 1, position, pvApiCtx);
126 }
127
128 std::string H5CompoundData::toString(const unsigned int indentLevel) const
129 {
130     std::ostringstream os;
131     std::string indentString = H5Object::getIndentString(indentLevel + 1);
132
133     os << H5Object::getIndentString(indentLevel) << "HDF5 Compound data" << std::endl
134        << indentString << _("Dimensions") << ": [";
135
136     if (ndims == 0)
137     {
138         os << "1 x 1]";
139     }
140     else if (ndims == 1)
141     {
142         os << "1 x " << dims[0] << "]";
143     }
144     else
145     {
146         for (unsigned int i = 0; i < ndims - 1; i++)
147         {
148             os << dims[i] << " x ";
149         }
150         os << dims[ndims - 1] << "]" << std::endl;
151     }
152
153     os << indentString << _("Fields Names") << ": [";
154     for (unsigned int i = 0; i < nfields - 1; i++)
155     {
156         os << fieldinfos[i]->name << ", ";
157     }
158     os << fieldinfos[nfields - 1]->name << "]";
159
160     return os.str();
161 }
162
163 std::string H5CompoundData::dump(std::map<haddr_t, std::string> & alreadyVisited, const unsigned int indentLevel) const
164 {
165     return H5DataConverter::dump(alreadyVisited, indentLevel, (int)ndims, dims, *this, false);
166 }
167
168 void H5CompoundData::printData(std::ostream & os, const unsigned int pos, const unsigned int indentLevel) const
169 {
170     os << "{" << std::endl;
171     std::string indent = H5Object::getIndentString(indentLevel + 2);
172
173     for (unsigned int i = 0; i < nfields; i++)
174     {
175         H5Data & hdata = H5DataFactory::getObjectData(*const_cast<H5CompoundData *>(this), totalSize, fieldinfos[i]->size, fieldinfos[i]->type, ndims, dims, data, stride ? stride : dataSize, offset + fieldinfos[i]->offset, false);
176         os << indent;
177         hdata.printData(os, pos, indentLevel + 2);
178
179         if (i != nfields - 1)
180         {
181             os << ", " << std::endl;
182         }
183
184         delete &hdata;
185     }
186
187     os << std::endl << H5Object::getIndentString(indentLevel + 1) << "}";
188 }
189 }