STIR 6.4.0
write_data_1d.inl
Go to the documentation of this file.
1
9/*
10 Copyright (C) 2004- 2009, Hammersmith Imanet Ltd
11 Copyright (C) 2024, University College London
12 This file is part of STIR.
13
14 SPDX-License-Identifier: Apache-2.0
15
16 See STIR/LICENSE.txt for details
17*/
18#include "stir/Array.h"
19#include "stir/Succeeded.h"
20#include "stir/ByteOrder.h"
21#include "stir/warning.h"
22#include <fstream>
23
24START_NAMESPACE_STIR
25
26namespace detail
27{
28
29/***************** version for ostream *******************************/
30
31template <int num_dimensions, class elemT>
32inline Succeeded
33write_data_1d(std::ostream& s, const Array<num_dimensions, elemT>& data, const ByteOrder byte_order, const bool can_corrupt_data)
34{
35 if (!s || (dynamic_cast<std::ofstream*>(&s) != 0 && !dynamic_cast<std::ofstream*>(&s)->is_open())
36 || (dynamic_cast<std::fstream*>(&s) != 0 && !dynamic_cast<std::fstream*>(&s)->is_open()))
37 {
38 warning("write_data: error before writing to stream.\n");
39 return Succeeded::no;
40 }
41
42 // While writing, the array is potentially byte-swapped.
43 // We catch exceptions to prevent problems with this.
44 // Alternative and safe way: (but involves creating an extra copy of the data)
45 /*
46 if (!byte_order.is_native_order())
47 {
48 Array<num_dimensions, elemT> a_copy(data);
49 for(int i=data.get_min_index(); i<=data.get_max_index(); i++)
50 ByteOrder::swap_order(a_copy[i]);
51 return write_data(s, a_copy, ByteOrder::native, true);
52 }
53 */
54 if (!byte_order.is_native_order())
55 {
57 for (auto iter = data_ref.begin_all(); iter != data_ref.end_all(); ++iter)
59 }
60
61 // note: find num_to_write (using size()) outside of s.write() function call
62 // otherwise Array::check_state() in size() might abort if
63 // get_const_data_ptr() is called before size() (which is compiler dependent)
64 const std::streamsize num_to_write = static_cast<std::streamsize>(data.size_all()) * sizeof(elemT);
65 bool writing_ok = true;
66 try
67 {
68 s.write(reinterpret_cast<const char*>(data.get_const_full_data_ptr()), num_to_write);
69 }
70 catch (...)
71 {
72 writing_ok = false;
73 }
74
76
77 if (!can_corrupt_data && !byte_order.is_native_order())
78 {
80 for (auto iter = data_ref.begin_all(); iter != data_ref.end_all(); ++iter)
82 }
83
84 if (!writing_ok || !s)
85 {
86 warning("write_data: error after writing to stream.\n");
87 return Succeeded::no;
88 }
89
90 return Succeeded::yes;
91}
92
93/***************** version for FILE *******************************/
94// largely a copy of above, but with calls to stdio function
95
96template <int num_dimensions, class elemT>
97inline Succeeded
98write_data_1d(FILE*& fptr_ref, const Array<num_dimensions, elemT>& data, const ByteOrder byte_order, const bool can_corrupt_data)
99{
100 FILE* fptr = fptr_ref;
101 if (fptr == 0 || ferror(fptr))
102 {
103 warning("write_data: error before writing to FILE.\n");
104 return Succeeded::no;
105 }
106
107 // While writing, the array is potentially byte-swapped.
108 // We catch exceptions to prevent problems with this.
109 // Alternative and safe way: (but involves creating an extra copy of the data)
110 /*
111 if (!byte_order.is_native_order())
112 {
113 Array<num_dimensions, elemT> a_copy(data);
114 for(int i=data.get_min_index(); i<=data.get_max_index(); i++)
115 ByteOrder::swap_order(a_copy[i]);
116 return write_data(s, a_copy, ByteOrder::native, true);
117 }
118 */
119 if (!byte_order.is_native_order())
120 {
121 Array<num_dimensions, elemT>& data_ref = const_cast<Array<num_dimensions, elemT>&>(data);
122 for (auto iter = data_ref.begin_all(); iter != data_ref.end_all(); ++iter)
123 ByteOrder::swap_order(*iter);
124 }
125
126 // note: find num_to_write (using size()) outside of s.write() function call
127 // otherwise Array::check_state() in size() might abort if
128 // get_const_data_ptr() is called before size() (which is compiler dependent)
129 const std::size_t num_to_write = static_cast<std::size_t>(data.size_all());
130 const std::size_t num_written
131 = fwrite(reinterpret_cast<const char*>(data.get_const_full_data_ptr()), sizeof(elemT), num_to_write, fptr);
132
134
135 if (!can_corrupt_data && !byte_order.is_native_order())
136 {
137 Array<num_dimensions, elemT>& data_ref = const_cast<Array<num_dimensions, elemT>&>(data);
138 for (auto iter = data_ref.begin_all(); iter != data_ref.end_all(); ++iter)
139 ByteOrder::swap_order(*iter);
140 }
141
142 if (num_written != num_to_write || ferror(fptr))
143 {
144 warning("write_data: error after writing to FILE.\n");
145 return Succeeded::no;
146 }
147
148 return Succeeded::yes;
149}
150
151} // end of namespace detail
152END_NAMESPACE_STIR
defines the stir::Array class for multi-dimensional (numeric) arrays
This file declares the stir::ByteOrder class.
Declaration of class stir::Succeeded.
This class defines multi-dimensional (numeric) arrays.
Definition Array.h:78
full_iterator begin_all()
start value for iterating through all elements in the array, see full_iterator
Definition Array.inl:213
size_t size_all() const
return the total number of elements in this array
Definition Array.inl:262
const elemT * get_const_full_data_ptr() const
member function for access to the data via a const elemT*
Definition Array.inl:311
void release_const_full_data_ptr() const
signal end of access to const elemT*
Definition Array.inl:345
full_iterator end_all()
end value for iterating through all elements in the array, see full_iterator
Definition Array.inl:185
This class provides member functions to find out what byte-order your machine is and to swap numbers.
Definition ByteOrder.h:100
bool is_native_order() const
check if the object refers to the native order.
Definition ByteOrder.inl:39
static void swap_order(NUMBER &value)
swap the byteorder of the argument
Definition ByteOrder.h:122
a class containing an enumeration type that can be used by functions to signal successful operation o...
Definition Succeeded.h:44
Succeeded write_data_1d(std::ostream &s, const Array< num_dimensions, elemT > &data, const ByteOrder byte_order, const bool can_corrupt_data)
This is an internal function called by write_data(). It does the actual writing to std::ostream.
Definition write_data_1d.inl:33
void warning(const char *const s,...)
Print warning with format string a la printf.
Definition warning.cxx:41
Declaration of stir::warning()