SheafSystem  0.0.0.0
data_converter.cc
1 
2 //
3 // Copyright (c) 2014 Limit Point Systems, Inc.
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17 
18 // Implementation for class data_converter
19 
20 
21 
22 #include "SheafSystem/data_converter.h"
23 
24 #include "SheafSystem/assert_contract.h"
25 #include "SheafSystem/error_message.h"
26 #include "SheafSystem/primitive_attributes.h"
27 #include "SheafSystem/sheaf_file.h"
28 #include "SheafSystem/std_cstring.h"
29 #include "SheafSystem/std_iostream.h"
30 
31 // PUBLIC MEMBER FUNCTIONS
32 
33 // CANONICAL MEMBERS
34 
35 
36 // Virtual constructor
40 clone() const
41 {
43 
44  // Preconditions:
45 
46  // Body:
47 
48  result = new data_converter();
49 
50  // Postconditions:
51 
52  ensure(result != 0);
53  ensure(is_same_type(result));
54 
55  // Exit:
56 
57  return result;
58 }
59 
60 
61 // Destructor
65 {
66 
67  // Preconditions:
68 
69  // Body:
70 
71  // HDF types closed by data_type_map, which created/opened them.
72 
73  // Delete the result buffer
74 
75  if(_result != 0)
76  {
77  delete [] static_cast<char*>(_result);
78  }
79 
80  _result = 0;
81 
82  // Close the transfer property list
83 
84  H5Pclose(_transfer_plist);
85 
87 
88  // if(H5Pclose(_transfer_plist) < 0);
89  // {
90  // // Close failed.
91 
92  // post_fatal_error_message("can't close transfer property list");
93  // }
94 
95  // Postconditions:
96 
97  // Exit:
98 
99  return;
100 }
101 
102 
103 // Class invariant
105 bool
107 invariant() const
108 {
109  bool result = true;
110 
111  // Preconditions:
112 
113  // Body:
114 
115  // Must satisfy base class invariant
116 
117  result = result && any::invariant();
118 
119  if(invariant_check())
120  {
121  // Prevent recursive calls to invariant
122 
124 
125  result = result && (_result != 0);
126  result = result && (result_size() == max_size());
127 
128  // Finished, turn invariant checking back on.
129 
131  }
132 
133  // Postconditions:
134 
135  // Exit
136 
137  return result;
138 }
139 
140 // Conformance test
142 bool
144 is_ancestor_of(const any* other) const
145 {
146 
147  // Preconditions:
148 
149  require(other != 0);
150 
151  // Body:
152 
153  // True if other conforms to this
154 
155  bool result = dynamic_cast<const data_converter*>(other) != 0;
156 
157  // Postconditions:
158 
159  return result;
160 
161 }
162 
163 
164 
165 // DATA_CONVERTER INTERFACE
166 
168 sheaf::data_converter::
169 data_converter(hid_t xexternal_type,
170  hid_t xinternal_type,
171  int xinternal_index)
172 {
173 
174  // Preconditions:
175 
176  require(is_primitive_index(xinternal_index));
177 
178  // Initialize the properties of the external type.
179 
180  _external_type = xexternal_type;
181  _external_size = H5Tget_size(_external_type);
182 
183  // Initialize the properties of the internal type.
184 
185  _internal_type = xinternal_type;
186  _internal_index = xinternal_index;
187  _internal_size = H5Tget_size(_internal_type);
188  primitive_descriptor lprim_desc = primitive_attributes::descriptor(_internal_index);
189 
190  // sheaf and hdf must agree on size of internal type.
191 
192  if(!is_string_type() && lprim_desc.size != _internal_size)
193  {
194  post_fatal_error_message("fatal conflict between HDF internal type and sheaf primitive type");
195  }
196 
197  _internal_alignment = lprim_desc.alignment;
198 
199  // Create the result buffer
200 
201  _result_size = max_size();
202  _result = new char[_result_size];
203 
204  // Create the transfer property list.
205 
206  _transfer_plist = H5Pcreate(H5P_DATASET_XFER);
207  if(_transfer_plist < 0)
208  {
209  post_fatal_error_message("Unable to create transfer property list.");
210  }
211 
212  // Determine whether conversion is needed.
213 
214  htri_t ltri = H5Tequal(_internal_type, _external_type);
215  if(ltri > 0)
216  {
217  // Types are equal, no conversion required.
218 
219  _conversion_required = false;
220  }
221  else if(ltri == 0)
222  {
223  // Types are not equal, conversion required.
224 
225  _conversion_required = true;
226  }
227  else
228  {
229  // Error determining equality.
230 
231  post_fatal_error_message("error while checking for type equality");
232  }
233 
234  // Postconditions:
235 
236  ensure(invariant());
237 }
238 
239 
241 void
243 externalize(const void* xint_buf,
244  size_t xint_buf_ub,
245  void* xext_buf,
246  size_t xext_buf_ub,
247  int xitem_ct)
248 {
249  // Preconditions:
250 
251  require(xitem_ct > 0);
252  require(xint_buf != 0);
253  require(is_string_type() ? xint_buf_ub >= xitem_ct*sizeof(char*) : xint_buf_ub >= xitem_ct*internal_size());
254  require(xext_buf != 0);
255  require(is_string_type() ? xext_buf_ub >= string_length_total(xint_buf, xitem_ct) : xext_buf_ub >= xitem_ct*max_size());
256  require(is_string_type() ? external_size() == 1 : !internal_size_greater());
257 
258 
259  // Body:
260 
261  if(is_string_type())
262  {
263  char** lint_buf = reinterpret_cast<char**>(const_cast<void*>(xint_buf));
264  char* lext_buf = reinterpret_cast<char*>(xext_buf);
265 
266  for(int i=0; i<xitem_ct; i++)
267  {
268  // Get the length of the string; includes terminator
269 
270  size_t lstrlen = string_length(lint_buf[i]);
271 
272  // Copy the string to the external buffer;
273  // Assumes !internal_size_greater
274 
275  (void) memcpy(lext_buf, lint_buf[i], lstrlen);
276  externalize(lext_buf, lstrlen, lstrlen);
277 
278  // Move the external buffer pointer past the string.
279  // Assumes external_size() == 1;
280 
281  lext_buf += lstrlen;
282  }
283  }
284  else
285  {
286  // Copy the data to the external buffer and
287  // then convert it to external format.
288 
289  (void) memcpy(xext_buf, xint_buf, xitem_ct*_internal_size);
290  externalize(xext_buf, xext_buf_ub, xitem_ct);
291  }
292 
294 
295  // Postconditions:
296 
297  // Exit
298 
299  return;
300 }
301 
303 void
305 externalize(void* xext_buf, size_t xext_buf_ub, int xitem_ct)
306 {
307  // Preconditions:
308 
309  require(xitem_ct > 0);
310  require(xext_buf != 0);
311  require(xext_buf_ub >= xitem_ct*max_size());
312 
313  // Body:
314 
316 
317  // Convert the data, if required.
318 
319  if(conversion_required())
320  {
321  herr_t lerr = H5Tconvert(_internal_type, _external_type, xitem_ct, xext_buf, 0, _transfer_plist);
322  }
323 
325 
326  // Postconditions:
327 
328  // Exit
329 
330  return;
331 }
332 
334 void
336 externalize(const void* xint_buf, size_t xint_buf_ub)
337 {
338  // Preconditions:
339 
340  require(xint_buf != 0);
341  require(xint_buf_ub >= internal_size());
342  require(result_size() >= max_size());
343 
344  // Body:
345 
347 
348  // Copy input buffer to result buffer.
349 
350  (void) memcpy(_result, xint_buf, _internal_size);
351 
352  // Convert the data, if required.
353 
354  if(conversion_required())
355  {
356  herr_t lerr = H5Tconvert(_internal_type, _external_type, 1, _result, 0, _transfer_plist);
357  }
358 
360 
361  // Postconditions:
362 
363  // Exit
364 
365  return;
366 }
367 
368 
369 
371 size_t
373 string_length(const char* xbuf)
374 {
375  size_t result;
376 
377  // Preconditions:
378 
379  require(xbuf != 0);
380 
381  // Body:
382 
383  result = strlen(xbuf)+1;
384 
386 
387  // Postconditions:
388 
389  ensure(result > 0);
390 
391  // Exit
392 
393  return result;
394 }
395 
396 
397 
399 size_t
401 string_length_total(const void* xbuf, int xitem_ct) const
402 {
403  size_t result = 0;
404 
405  // Preconditions:
406 
407  require(is_string_type());
408 
409  // Body:
410 
411  char** lbuf = reinterpret_cast<char**>(const_cast<void*>(xbuf));
412 
413  // Add up the length of the strings in xbuf
414 
415  for(int i=0; i<xitem_ct; i++)
416  {
417  result += string_length(lbuf[i]);
418  }
419 
420  // Postconditions:
421 
422  ensure(result > 0);
423 
424  // Exit
425 
426  return result;
427 }
428 
430 void
432 internalize(const void* xext_buf,
433  size_t xext_buf_ub,
434  void* xint_buf,
435  size_t xint_buf_ub,
436  int xitem_ct)
437 {
438  // Preconditions:
439 
440  require(xitem_ct > 0);
441  require(xext_buf != 0);
442  require(is_string_type() ? true : xext_buf_ub >= xitem_ct*external_size());
443  require(xint_buf != 0);
444  require(is_string_type() ? xint_buf_ub >= xitem_ct*internal_size() : xint_buf_ub >= xitem_ct*max_size());
445  require(is_string_type() ? external_size() == 1 : !external_size_greater());
446 
447  // Body:
448 
450 
451  // Copy input buffer to output buffer.
452  //
453  // Note:
454  // To be useful, the converted, internalized data
455  // must be properly aligned for the internal type.
456  // But there is no way to ensure that the space in
457  // the external buffer is properly aligned, so even
458  // if we convert in place, we'll have to copy the
459  // result to another buffer sooner or later.
460  // The assumption here is that xint_buf is
461  // properly aligned for the internal type.
462  //
463  // Note: The C++ standard ensures that char array is
464  // allocated with most restrictive alignment, so
465  // _result will match any alignment.
466 
467  if(is_string_type())
468  {
469  char* lext_buf = reinterpret_cast<char*>(const_cast<void*>(xext_buf));
470  char** lint_buf = reinterpret_cast<char**>(xint_buf);
471 
472  for(int i=0; i<xitem_ct; i++)
473  {
474  // Get the length of the string
475 
476  size_t lstrlen = string_length(lext_buf);
477 
478  // Allocate the internal string;
479  // assumes internal_size() == 1
481 
482  char* lstring = new char[lstrlen];
483 
484  // Copy the data to the internal string and
485  // then convert it to internal format.
486  // Assumes external_size() == 1.
487 
488  (void) strncpy(lstring, lext_buf, lstrlen);
489  internalize(lstring, lstrlen, lstrlen);
490 
491  // Make the internal buffer point at the internal string.
492 
493  lint_buf[i] = lstring;
494 
495  // Move the external buffer pointer to the next string.
496  // Assumes external_size() == 1.
497 
498  lext_buf += lstrlen;
499  }
500  }
501  else
502  {
503  // Copy the data to the internal buffer and
504  // then convert it to internal format.
505 
506  (void) memcpy(xint_buf, xext_buf, xitem_ct*_external_size);
507  internalize(xint_buf, xint_buf_ub, xitem_ct);
508  }
509 
510 
512 
513  // Postconditions:
514 
515  // Exit
516 
517  return;
518 }
519 
521 void
523 internalize(void* xbuf, size_t xbuf_ub, int xitem_ct)
524 {
525  // Preconditions:
526 
527  require(xitem_ct > 0);
528  require(xbuf != 0);
529  require(xbuf_ub >= xitem_ct*max_size());
530 
531  // Body:
532 
534 
535  // Convert the data in place, if required.
536 
537  if(conversion_required())
538  {
539  herr_t lerr = H5Tconvert(_external_type, _internal_type, xitem_ct, xbuf, 0, _transfer_plist);
540  }
541 
543 
544  // Postconditions:
545 
546  // Exit
547 
548  return;
549 }
550 
552 void
554 internalize(void* xbuf, size_t xbuf_ub)
555 {
556  // Preconditions:
557 
558  require(xbuf != 0);
559  require(xbuf_ub >= external_size());
560  require(result_size() >= max_size());
561 
562 
563  // Body:
564 
566 
567 
568  (void) memcpy(_result, xbuf, _external_size);
569 
570  // Convert the data, if required.
571 
572  if(conversion_required())
573  {
574  herr_t lerr = H5Tconvert(_external_type, _internal_type, 1, _result, 0, _transfer_plist);
575  }
576 
578 
579  // Postconditions:
580 
581  // Exit
582 
583  return;
584 }
585 
586 // PRIVATE MEMBER FUNCTIONS
587 
588 // Default constructor
589 // Private to prevent default construction
590 
591 sheaf::data_converter::
592 data_converter()
593 {
594 
595  // Preconditions:
596 
597 
598  // Body:
599 
600 
601  // Postconditions:
602 
603  ensure(invariant());
604 
605  // Exit:
606 
607  return;
608 }
609 
611 sheaf::data_converter::
612 data_converter(const data_converter& xother)
613 {
614 
615  // Preconditions:
616 
617 
618  // Body:
619 
620  data_converter& lother = const_cast<data_converter&>(xother);
621 
622  _external_type = lother.external_type();
623  _external_size = lother.external_size();
624 
625  _internal_type = lother.internal_type();
626  _internal_index = lother.internal_index();
627  _internal_size = lother.internal_size();
628  _internal_alignment = lother.internal_alignment();
629 
630  _result_size = lother.result_size();
631  _result = new char[_result_size];
632 
633  _transfer_plist = H5Pcreate(H5P_DATASET_XFER);
634 
635  // Determine whether conversion is needed.
636 
637  htri_t ltri = H5Tequal(_internal_type, _external_type);
638  if(ltri > 0)
639  {
640  // Types are equal, no conversion required.
641 
642  _conversion_required = false;
643  }
644  else if(ltri == 0)
645  {
646  // Types are not equal, conversion required.
647 
648  _conversion_required = true;
649  }
650  else
651  {
652  // Error determining equality.
653 
654  post_fatal_error_message("error while checking for type equality");
655  }
656 
657  // Postconditions:
658 
659  ensure(invariant());
660 }
virtual bool invariant() const
Class invariant, intended to be redefined in each descendant. See below for template for invariant in...
Definition: any.cc:153
bool external_size_greater() const
True if the external size is greater than the internal size.
virtual data_converter * clone() const
Virtual constructor; makes a new instance of the same type as this.
hid_t external_type() const
The external type identifier.
static primitive_descriptor descriptor(pod_index_type xid)
Primitive descriptor for the primitive type with id xid.
size_t internal_size() const
The size in bytes of the internal type.
void externalize(const void *xint_buf, size_t xint_buf_ub, void *xext_buf, size_t xext_buf_ub, int xitem_ct)
Copy xitem_ct data items from xint_buf to xext_buf and then convert them from internal to external fo...
bool is_string_type() const
True if this is a converter for a string type.
bool conversion_required() const
True if internal and external types are not identical.
size_t internal_alignment() const
The alignment of the internal type.
void internalize(const void *xext_buf, size_t xext_buf_ub, void *xint_buf, size_t xint_buf_ub, int xitem_ct)
Convert xitem_ct data items in xext_buf from external to internal format and place the result in xint...
Abstract base class with useful features for all objects.
Definition: any.h:39
hid_t internal_index() const
The primitives poset member index for the internal type.
virtual bool is_ancestor_of(const any *other) const
Conformance test; true if other conforms to this.
virtual bool invariant() const
Class invariant.
size_t result_size() const
The allocated size of the result buffer.
virtual ~data_converter()
Destructor.
size_t string_length_total(const void *xbuf, int xitem_ct) const
The total number of characters, including the terminators in all the strings in the array of strings ...
SHEAF_DLL_SPEC bool is_primitive_index(pod_index_type xindex)
True if xindex is a valid primitive index.
void disable_invariant_check() const
Disable invariant check. Intended for preventing recursive calls to invariant and for suppressing inv...
Definition: any.h:97
size_t external_size() const
The size in bytes of the external type.
bool invariant_check() const
True if invariant checking is enabled.
Definition: any.h:79
bool internal_size_greater() const
True if the internal size is greater than the external size.
Function object to convert between internal and external data formats.
size_t max_size() const
The maximum of internal_size() and external_size().
hid_t internal_type() const
The HDF type identifier for the internal type.
static size_t string_length(const char *xbuf)
The number of characters in the string, including the terminator.
void * result() const
The result of the conversion.
bool is_same_type(const any *other) const
True if other is the same type as this.
Definition: any.cc:79
void enable_invariant_check() const
Enable invariant checking.
Definition: any.h:87