Skip to content

Commit

Permalink
Added support for basic Channel Array (CA) writing (#95). Fixed corre…
Browse files Browse the repository at this point in the history
…ct invalid/valid handling at reading bug.
  • Loading branch information
ihedvall committed Aug 5, 2024
1 parent 4f7f1d7 commit 4010e33
Show file tree
Hide file tree
Showing 17 changed files with 1,280 additions and 432 deletions.
49 changes: 27 additions & 22 deletions include/mdf/ichannel.h
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,8 @@ class IChannel : public IBlock {
* @param valid True if the value is valid.
*/
template <typename T>
void SetChannelValue(const T &value, bool valid = true);
void SetChannelValue(const T &value, bool valid = true,
uint64_t array_index = 0);

/** \brief Internally used function mainly for fetching VLSD index values.
*
Expand Down Expand Up @@ -504,23 +505,24 @@ class IChannel : public IBlock {
[[nodiscard]] virtual std::vector<uint8_t> &SampleBuffer() const = 0;

/** \brief Support function that sets the valid flag. */
virtual void SetValid(bool valid);
virtual void SetValid(bool valid, uint64_t array_index);

/** \brief Support function that return true if the valid bit is set.*/
virtual bool GetValid(const std::vector<uint8_t> &record_buffer) const;
virtual bool GetValid(const std::vector<uint8_t> &record_buffer,
uint64_t array_index) const;

/** \brief Support function that sets unsigned little endian values */
void SetUnsignedValueLe(uint64_t value, bool valid);
void SetUnsignedValueLe(uint64_t value, bool valid, uint64_t array_index);
/** \brief Support function that sets unsigned big endian values */
void SetUnsignedValueBe(uint64_t value, bool valid);
void SetUnsignedValueBe(uint64_t value, bool valid, uint64_t array_index);
/** \brief Support function that sets signed little endian values */
void SetSignedValueLe(int64_t value, bool valid);
void SetSignedValueLe(int64_t value, bool valid, uint64_t array_index);
/** \brief Support function that sets signed big endian values */
void SetSignedValueBe(int64_t value, bool valid);
void SetSignedValueBe(int64_t value, bool valid, uint64_t array_index);
/** \brief Support function that sets float little endian values */
void SetFloatValueLe(double value, bool valid);
void SetFloatValueLe(double value, bool valid, uint64_t array_index);
/** \brief Support function that sets float big endian values */
void SetFloatValueBe(double value, bool valid);
void SetFloatValueBe(double value, bool valid, uint64_t array_index);
/** \brief Support function that sets text values */
virtual void SetTextValue(const std::string &value, bool valid);
/** \brief Support function that sets array values */
Expand Down Expand Up @@ -597,7 +599,7 @@ bool IChannel::GetChannelValue(const std::vector<uint8_t> &record_buffer,
break;
}
if (valid) {
valid = GetValid(record_buffer);
valid = GetValid(record_buffer, array_index);
}
return valid;
}
Expand All @@ -613,30 +615,31 @@ bool IChannel::GetChannelValue(const std::vector<uint8_t> &record_buffer,
std::string &dest, uint64_t array_index) const;

template <typename T>
void IChannel::SetChannelValue(const T &value, bool valid) {
void IChannel::SetChannelValue(const T &value, bool valid,
uint64_t array_index ) {
switch (DataType()) {
case ChannelDataType::UnsignedIntegerLe:
SetUnsignedValueLe(static_cast<uint64_t>(value), valid);
SetUnsignedValueLe(static_cast<uint64_t>(value), valid, array_index);
break;

case ChannelDataType::UnsignedIntegerBe:
SetUnsignedValueBe(static_cast<uint64_t>(value), valid);
SetUnsignedValueBe(static_cast<uint64_t>(value), valid, array_index);
break;

case ChannelDataType::SignedIntegerLe:
SetSignedValueLe(static_cast<int64_t>(value), valid);
SetSignedValueLe(static_cast<int64_t>(value), valid, array_index);
break;

case ChannelDataType::SignedIntegerBe:
SetSignedValueBe(static_cast<int64_t>(value), valid);
SetSignedValueBe(static_cast<int64_t>(value), valid, array_index);
break;

case ChannelDataType::FloatLe:
SetFloatValueLe(static_cast<double>(value), valid);
SetFloatValueLe(static_cast<double>(value), valid, array_index);
break;

case ChannelDataType::FloatBe:
SetFloatValueBe(static_cast<double>(value), valid);
SetFloatValueBe(static_cast<double>(value), valid, array_index);
break;

case ChannelDataType::StringUTF8:
Expand All @@ -658,7 +661,7 @@ void IChannel::SetChannelValue(const T &value, bool valid) {
MdfHelper::NsToCanOpenDateArray(static_cast<uint64_t>(value));
SetByteArray(date_array, valid);
} else {
SetValid(false);
SetValid(false, array_index);
}
break;

Expand All @@ -668,22 +671,24 @@ void IChannel::SetChannelValue(const T &value, bool valid) {
MdfHelper::NsToCanOpenTimeArray(static_cast<uint64_t>(value));
SetByteArray(time_array, valid);
} else {
SetValid(false);
SetValid(false, array_index);
}
break;


default:
SetValid(false);
SetValid(false, array_index);
break;
}
};

/** \brief Support function that sets a string value to a record buffer. */
template <>
void IChannel::SetChannelValue(const std::string &value, bool valid);
void IChannel::SetChannelValue(const std::string &value, bool valid,
uint64_t array_index);

/** \brief Support function that sets a string value to a record buffer. */
template <>
void IChannel::SetChannelValue(const std::vector<uint8_t> &value, bool valid);
void IChannel::SetChannelValue(const std::vector<uint8_t> &value, bool valid,
uint64_t array_index);
} // namespace mdf
123 changes: 98 additions & 25 deletions include/mdf/ichannelarray.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,18 @@
*/

/** \file ichannelarray.h
* \brief Defines a channel array (CA) block. Its functionality is described
* in the MDF 4 documentation.
* \brief Defines a channel array (CA) block.
*
* The interface class define a channel array definition. The channel array (CA)
* is appended to an channel block (CN). The channel shall now be treated an
* array channel.
*
* Note that only simple single arrays are supported.
*/
#pragma once
#include <cstdint>
#include <vector>
#include <optional>
#include "mdf/iblock.h"

namespace mdf {
Expand Down Expand Up @@ -58,30 +64,54 @@ struct CaTripleReference {
};


/** \brief Channel array */
/** \brief Defines an interface against an array (CA) block.
*
* This interface class defines an array of channel values. A channel (CN)
* block is defined as an array by appending a channel array (CA) block. The
* CN block defines an array value while the CA block defines the array
* dimension and its size(s).
*/
class IChannelArray : public IBlock {
public:

virtual void Type(ArrayType type) = 0; ///< Type.
[[nodiscard]] virtual ArrayType Type() const = 0; ///< Type of array
virtual void Type(ArrayType type) = 0; ///< Sets the type of array..
[[nodiscard]] virtual ArrayType Type() const = 0; ///< Type of array.

virtual void Storage(ArrayStorage storage) = 0; ///< Storage type
[[nodiscard]] virtual ArrayStorage Storage() const = 0; ///< Storage type

virtual void Flags(uint32_t flags) = 0; ///< Flags
[[nodiscard]] virtual uint32_t Flags() const = 0; ///< Flags

[[nodiscard]] virtual uint16_t Dimensions() const = 0; ///< Number of dimensions
virtual void DimensionSize(uint16_t dimension, uint64_t dimension_size ) = 0; ///< Size for a dimension
[[nodiscard]] virtual uint64_t DimensionSize(uint16_t dimension) const = 0; ///< Size for a dimension
[[nodiscard]] virtual size_t Dimensions() const = 0; ///< Number of dimensions.

/** \brief Sets the dimension and each dimension size.
*
* The function sets the number of dimensions and each dimension size.
* @param dim_sizes Array of dimension sizes.
*/
virtual void Shape(const std::vector<uint64_t>& dim_sizes) = 0;

/** \brief Returns the dimension and each dimension size.
*
* @return Array of dimension sizes.
*/
[[nodiscard]] virtual const std::vector<uint64_t>& Shape() const = 0;

/** \brief Returns a dimension size. */
[[nodiscard]] virtual uint64_t DimensionSize(size_t dimension) const = 0;

/** \brief Returns the fixed axis value list for reading only. */
[[nodiscard]] virtual const std::vector<double>& AxisValues() const = 0;

[[nodiscard]] virtual uint64_t AxisValues() const = 0; ///< Number of axis values
virtual void AxisValue(uint64_t index, double value ) = 0; ///< Setting an axis value
[[nodiscard]] virtual double AxisValue(uint64_t index) const = 0; ///< Getting an axis value
/** \brief Returns the fixed axis value list for write. */
[[nodiscard]] virtual std::vector<double>& AxisValues() = 0;

[[nodiscard]] virtual uint64_t CycleCounts() const = 0; ///< Number of cycle counts
virtual void CycleCountOffset(uint64_t cycle_count, uint64_t offset ) = 0; ///< Setting an offset value
[[nodiscard]] virtual uint64_t CycleCountOffset(uint64_t cycle_count) const = 0; ///< Getting an axis value
/** \brief Returns a list of cycle counts. */
[[nodiscard]] virtual const std::vector<uint64_t>& CycleCounts() const = 0;

/** \brief Returns a list of cycle counts. */
[[nodiscard]] virtual std::vector<uint64_t>& CycleCounts() = 0;

/** \brief Returns the number of values in the array.
*
Expand All @@ -97,50 +127,93 @@ class IChannelArray : public IBlock {

/** \brief Converts the array link indexes into pointers.
*
* This function must be called before getting any of the
* This function can be called before setting any of the
* link lists on the array object. It must be called later after the
* entire file been read as the link reference blocks that are read
* after this block.
* block have been configured i.e. sized and all flags have been set.
*
* Note that this is a convenient function. It is possible to do it manual
* as well.
*/
virtual void CreateLinkLists() = 0;
virtual void ResizeArrays();

/** \brief Returns a list of data kink indexes. */
[[nodiscard]] const std::vector<int64_t>& DataLinks() const {
return data_links_;
}
/** \brief Returns a list of data kink indexes. */
[[nodiscard]] std::vector<int64_t>& DataLinks();

/** \brief Returns the dynamic size list. */
[[nodiscard]] const std::vector<CaTripleReference>& DynamicSizeList() const {
return dynamic_size_list_;
}
/** \brief Returns the dynamic size list. */
[[nodiscard]] std::vector<CaTripleReference>& DynamicSizeList();

/** \brief Returns the input quantity list. */
[[nodiscard]] const std::vector<CaTripleReference>& InputQuantityList() const {
return input_quantity_list_;
}
/** \brief Returns the output quantity list. */
[[nodiscard]] const std::vector<CaTripleReference>& OutputQuantityList() const {
return output_quantity_list_;
/** \brief Returns the input quantity list. */
[[nodiscard]] std::vector<CaTripleReference>& InputQuantityList();

/** \brief Returns the output quantity reference if it exist. */
[[nodiscard]] const CaTripleReference& OutputQuantity() const {
return output_quantity_;
}
/** \brief Returns the output quantity reference if it exist. */
[[nodiscard]] CaTripleReference& OutputQuantity() {
return output_quantity_;
}

/** \brief Returns the comparison quantity list. */
[[nodiscard]] const std::vector<CaTripleReference>& ComparisonQuantityList() const {
return comparison_quantity_list_;
[[nodiscard]] const CaTripleReference& ComparisonQuantity() const {
return comparison_quantity_;
}
/** \brief Returns the comparison quantity list. */
[[nodiscard]] CaTripleReference& ComparisonQuantity() {
return comparison_quantity_;
}

/** \brief Returns the axis conversion list. */
[[nodiscard]] const std::vector<const IChannelConversion*>& AxisConversionList() const {
return axis_conversion_list_;
}
/** \brief Returns the axis conversion list. */
[[nodiscard]] std::vector<const IChannelConversion*>& AxisConversionList();

/** \brief Returns the axis list. */
[[nodiscard]] const std::vector<CaTripleReference>& AxisList() const {
return axis_list_;
}
/** \brief Returns the axis list. */
[[nodiscard]] std::vector<CaTripleReference>& AxisList();

/** \brief Summation of all array dimensions.
*
* Support function that summarizes the dimension sizes. This
* function is mainly used internally to size
* @return
*/
[[nodiscard]] virtual size_t SumOfArray() const = 0;

/** \brief Calculates the product of array dimension sizes.
*
* Returns the product of array sizes. This defines number of
* values in an array sample.
* @return Number of array values in a sample.
*/
[[nodiscard]] virtual size_t ProductOfArray() const = 0;
protected:
std::vector<int64_t> data_links_; ///< List of index to data blocks.
std::vector<CaTripleReference> dynamic_size_list_; ///< Dynamic size list.
std::vector<CaTripleReference> input_quantity_list_; ///< Input quantity list.
std::vector<CaTripleReference> output_quantity_list_; ///< Output quantity list.
std::vector<CaTripleReference> comparison_quantity_list_; ///< Comparison quantity list.
CaTripleReference output_quantity_; ///< Output quantity list.
CaTripleReference comparison_quantity_; ///< Comparison quantity list.
std::vector<const IChannelConversion*> axis_conversion_list_; ///< Axis_conversion list.
std::vector<CaTripleReference> axis_list_; ///< Axis list.


};

} // namespace mdf
2 changes: 1 addition & 1 deletion mdf2csv/test/testcreatefiles.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ TEST(CreateFileList, TestBasicFunction) {
}
}

TEST(CreateFileList, TestCssLog) {
TEST(CreateFileList, TestCsvLog) {
auto& arguments = ProgramArgument::Instance();
arguments.Clear();

Expand Down
Loading

0 comments on commit 4010e33

Please sign in to comment.