EleFits
4.0.1
A modern C++ API on top of CFitsIO
|
Which types to use?
Indices in the Fits namespace are 0-based long
s. Here is why.
There is no way to make everybody happy:
int
for column count and long
or LONGLONG
for row count).Following the C++ Core Guidelines, we've opted for signed integers, and precisely for long
's. To reduce the noise, we did not create a custom type like "index", "length" or "size". We do not rely on ptrdiff_t
as suggested in the Guidelines, because it would create issues when interfacing internally with CFitsIO. Using long
s conveys the following message: trying to use something larger than the max of long
won't work.
Having signed indices also enables backard indexing, where -1 means the last index. This is supported, for example, by the Raster::at()
and Column::at()
methods.
Since indices in std::vector
s are 0-based, and we use a lot of std::vector
s, we follow the same convention to provide a fully consistent API. This way, the user code only copes with 0-based indices.
As shown in the CFitsIO type mapping table, handling data types right with CFitsIO can be very cumbersome. EleFits aims at carrying the boilerplate internally, so that the user doesn't need to know the underlying architecture or CFitsIO implementation. Template functions and methods are provided to simply let the user set the desired type, e.g.:
When possible, conversions are performed internally when the template type does not correspond to the file type.
Integer types are numerous. There are two main categories: fixed-size integers (e.g. std::int32_t
) and C integers (e.g. int
). It is strongly recommended to use fixed-size integers to avoid bad surprises when changing the system. Indeed, if an image of pixel type int
is written on a system where it is encoded as a 64-bit integers, and read on a system where it is encoded as a 32-bit integer, values will be corrupted. This is avoided by using std::int32_t
instead.
The Fits format doesn't natively support unsigned integers or signed bytes. Yet, CFitsIO and EleFits rely on the scaling mechanism to support them: an unsigned integer value will be internally offset to get a signed integer in the file. The offset is written in the file as a BZERO
(image HDU) or TZERO
(binary table HDU) keyword record, used to correctly recover the value at reading.
Strings are represented as std::string
and not const char*
in general. Yet, a few sevices are overloaded with const char*
for convenience.
In addition to CFitsIO data types, EleFits provides some of the services for VariantValue
(e.g., to read records). In this case, the underlying type is wrapped in a VariantValue
object, which can be cast later.
Development efforts have been put to allow the user to get whatever compatible type from the VariantValue
object. For example, assume some unsigned long
record value is read as a VariantValue
. The library will allow the user casting to long long
because this is a mathematically valid conversion, where std::any_cast<long long>()
and the likes would throw an exception.