Skip to content
Snippets Groups Projects
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
BP3Base.tcc 11.79 KiB
/*
 * Distributed under the OSI-approved Apache License, Version 2.0.  See
 * accompanying file Copyright.txt for details.
 *
 * BP3Base.tcc
 *
 *  Created on: May 19, 2017
 *      Author: William F Godoy godoywf@ornl.gov
 */

#ifndef ADIOS2_TOOLKIT_FORMAT_BP3_BP3BASE_TCC_
#define ADIOS2_TOOLKIT_FORMAT_BP3_BP3BASE_TCC_

#include "BP3Base.h"

#include <cmath> //std::min

#include "adios2/helper/adiosFunctions.h" //NextExponentialSize, CopyFromBuffer

namespace adios2
{
namespace format
{

// PROTECTED
template <>
int8_t BP3Base::GetDataType<std::string>() const noexcept
{
    const int8_t type = static_cast<int8_t>(type_string);
    return type;
}

template <>
int8_t BP3Base::GetDataType<char>() const noexcept
{
    const int8_t type = static_cast<int8_t>(type_byte);
    return type;
}

template <>
int8_t BP3Base::GetDataType<signed char>() const noexcept
{
    const int8_t type = static_cast<int8_t>(type_byte);
    return type;
}

template <>
int8_t BP3Base::GetDataType<short>() const noexcept
{
    const int8_t type = static_cast<int8_t>(type_short);
    return type;
}

template <>
int8_t BP3Base::GetDataType<int>() const noexcept
{
    const int8_t type = static_cast<int8_t>(type_integer);
    return type;
}

template <>
int8_t BP3Base::GetDataType<long int>() const noexcept
{
    int8_t type = static_cast<int8_t>(type_long);
    if (sizeof(long int) == sizeof(int))
    {
        type = static_cast<int8_t>(type_integer);
    }

    return type;
}

template <>
int8_t BP3Base::GetDataType<long long int>() const noexcept
{
    const int8_t type = static_cast<int8_t>(type_long);
    return type;
}

template <>
int8_t BP3Base::GetDataType<unsigned char>() const noexcept
{
    const int8_t type = static_cast<int8_t>(type_unsigned_byte);
    return type;
}

template <>
int8_t BP3Base::GetDataType<unsigned short>() const noexcept
{
    const int8_t type = static_cast<int8_t>(type_unsigned_short);
    return type;
}

template <>
int8_t BP3Base::GetDataType<unsigned int>() const noexcept
{
    const int8_t type = static_cast<int8_t>(type_unsigned_integer);
    return type;
}

template <>
int8_t BP3Base::GetDataType<unsigned long int>() const noexcept
{
    int8_t type = static_cast<int8_t>(type_unsigned_long);
    if (sizeof(unsigned long int) == sizeof(unsigned int))
    {
        type = static_cast<int8_t>(type_unsigned_integer);
    }

    return type;
}

template <>
int8_t BP3Base::GetDataType<unsigned long long int>() const noexcept
{
    const int8_t type = static_cast<int8_t>(type_unsigned_long);
    return type;
}

template <>
int8_t BP3Base::GetDataType<float>() const noexcept
{
    const int8_t type = static_cast<int8_t>(type_real);
    return type;
}

template <>
int8_t BP3Base::GetDataType<double>() const noexcept
{
    const int8_t type = static_cast<int8_t>(type_double);
    return type;
}

template <>
int8_t BP3Base::GetDataType<long double>() const noexcept
{
    const int8_t type = static_cast<int8_t>(type_long_double);
    return type;
}
template <>
int8_t BP3Base::GetDataType<cfloat>() const noexcept
{
    const int8_t type = static_cast<int8_t>(type_complex);
    return type;
}

template <>
int8_t BP3Base::GetDataType<cdouble>() const noexcept
{
    const int8_t type = static_cast<int8_t>(type_double_complex);
    return type;
}

template <>
int8_t BP3Base::GetDataType<cldouble>() const noexcept
{
    const int8_t type = static_cast<int8_t>(type_long_double_complex);
    return type;
}

template <class T>
BP3Base::Characteristics<T> BP3Base::ReadElementIndexCharacteristics(
    const std::vector<char> &buffer, size_t &position, const DataTypes dataType,
    const bool untilTimeStep) const
{
    Characteristics<T> characteristics;
    characteristics.EntryCount = ReadValue<uint8_t>(buffer, position);
    characteristics.EntryLength = ReadValue<uint32_t>(buffer, position);

    ParseCharacteristics(buffer, position, dataType, untilTimeStep,
                         characteristics);

    return characteristics;
}

template <>
inline void BP3Base::ParseCharacteristics(
    const std::vector<char> &buffer, size_t &position, const DataTypes dataType,
    const bool untilTimeStep,
    Characteristics<std::string> &characteristics) const
{
    const size_t start = position;
    size_t localPosition = 0;

    bool foundTimeStep = false;

    while (localPosition < characteristics.EntryLength)
    {
        const uint8_t id = ReadValue<uint8_t>(buffer, position);

        switch (id)
        {
        case (characteristic_time_index):
        {
            characteristics.Statistics.Step =
                ReadValue<uint32_t>(buffer, position);
            foundTimeStep = true;
            break;
        }

        case (characteristic_file_index):
        {
            characteristics.Statistics.FileIndex =
                ReadValue<uint32_t>(buffer, position);
            break;
        }

        case (characteristic_value):
        {
            if (dataType == type_string)
            {
                // first get the length of the string
                const size_t length =
                    static_cast<size_t>(ReadValue<uint16_t>(buffer, position));

                characteristics.Statistics.Value =
                    std::string(&buffer[position], length);

                characteristics.Statistics.IsValue = true;
                position += length;
            }
            else if (dataType == type_string_array)
            {
                if (characteristics.Count.size() != 1)
                {
                    // TODO: add exception here?
                    break;
                }

                const size_t elements = characteristics.Count.front();
                characteristics.Statistics.Values.reserve(elements);

                for (size_t e = 0; e < elements; ++e)
                {
                    const size_t length = static_cast<size_t>(
                        ReadValue<uint16_t>(buffer, position));

                    characteristics.Statistics.Values.push_back(
                        std::string(&buffer[position], length));

                    position += length;
                }
            }

            break;
        }

        case (characteristic_offset):
        {
            characteristics.Statistics.Offset =
                ReadValue<uint64_t>(buffer, position);
            break;
        }

        case (characteristic_payload_offset):
        {
            characteristics.Statistics.PayloadOffset =
                ReadValue<uint64_t>(buffer, position);
            break;
        }

        case (characteristic_dimensions):
        {
            const unsigned int dimensionsSize =
                static_cast<unsigned int>(ReadValue<uint8_t>(buffer, position));

            characteristics.Shape.reserve(dimensionsSize);
            characteristics.Start.reserve(dimensionsSize);
            characteristics.Count.reserve(dimensionsSize);
            position += 2; // skip length (not required)

            for (unsigned int d = 0; d < dimensionsSize; ++d)
            {
                characteristics.Count.push_back(
                    static_cast<size_t>(ReadValue<uint64_t>(buffer, position)));

                characteristics.Shape.push_back(
                    static_cast<size_t>(ReadValue<uint64_t>(buffer, position)));
                characteristics.Start.push_back(
                    static_cast<size_t>(ReadValue<uint64_t>(buffer, position)));
            }
            break;
        }
        // TODO: implement compression and BP1 Stats characteristics
        default:
        {
            throw std::invalid_argument("ERROR: characteristic ID " +
                                        std::to_string(id) +
                                        " not supported\n");
        }

        } // end id switch

        if (untilTimeStep && foundTimeStep)
        {
            break;
        }

        localPosition = position - start;
    }
}

template <class T>
inline void
BP3Base::ParseCharacteristics(const std::vector<char> &buffer, size_t &position,
                              const DataTypes /*dataType*/,
                              const bool untilTimeStep,
                              Characteristics<T> &characteristics) const
{
    const size_t start = position;
    size_t localPosition = 0;

    bool foundTimeStep = false;

    while (localPosition < characteristics.EntryLength)
    {
        const CharacteristicID id =
            static_cast<CharacteristicID>(ReadValue<uint8_t>(buffer, position));

        switch (id)
        {
        case (characteristic_time_index):
        {
            characteristics.Statistics.Step =
                ReadValue<uint32_t>(buffer, position);
            foundTimeStep = true;
            break;
        }

        case (characteristic_file_index):
        {
            characteristics.Statistics.FileIndex =
                ReadValue<uint32_t>(buffer, position);
            break;
        }

        case (characteristic_value):
        {
            // we are relying that count contains the dimensions
            if (characteristics.Count.empty() || characteristics.Count[0] == 1)
            {
                characteristics.Statistics.Value =
                    ReadValue<typename TypeInfo<T>::ValueType>(buffer,
                                                               position);
                characteristics.Statistics.IsValue = true;
            }
            else // used for attributes
            {
                const size_t size = characteristics.Count[0];
                characteristics.Statistics.Values.resize(size);
                CopyFromBuffer(buffer, position,
                               characteristics.Statistics.Values.data(), size);
            }
            break;
        }

        case (characteristic_min):
        {
            characteristics.Statistics.Min =
                ReadValue<typename TypeInfo<T>::ValueType>(buffer, position);
            break;
        }

        case (characteristic_max):
        {
            characteristics.Statistics.Max =
                ReadValue<typename TypeInfo<T>::ValueType>(buffer, position);
            break;
        }

        case (characteristic_offset):
        {
            characteristics.Statistics.Offset =
                ReadValue<uint64_t>(buffer, position);
            break;
        }

        case (characteristic_payload_offset):
        {
            characteristics.Statistics.PayloadOffset =
                ReadValue<uint64_t>(buffer, position);
            break;
        }

        case (characteristic_dimensions):
        {
            const unsigned int dimensionsSize =
                static_cast<unsigned int>(ReadValue<uint8_t>(buffer, position));

            characteristics.Shape.reserve(dimensionsSize);
            characteristics.Start.reserve(dimensionsSize);
            characteristics.Count.reserve(dimensionsSize);
            position += 2; // skip length (not required)

            for (unsigned int d = 0; d < dimensionsSize; ++d)
            {
                characteristics.Count.push_back(
                    static_cast<size_t>(ReadValue<uint64_t>(buffer, position)));

                characteristics.Shape.push_back(
                    static_cast<size_t>(ReadValue<uint64_t>(buffer, position)));

                characteristics.Start.push_back(
                    static_cast<size_t>(ReadValue<uint64_t>(buffer, position)));
            }
            break;
        }
        // TODO: implement compression and BP1 Stats characteristics
        default:
        {
            throw std::invalid_argument("ERROR: characteristic ID " +
                                        std::to_string(id) +
                                        " not supported\n");
        }

        } // end id switch

        if (untilTimeStep && foundTimeStep)
        {
            break;
        }

        localPosition = position - start;
    }
}

} // end namespace format
} // end namespace adios2

#endif /* ADIOS2_TOOLKIT_FORMAT_BP3_BP3Base_TCC_ */