Program Listing for File EnvironmentDirectedGraphDescription.cuh

Return to documentation for file (include/flamegpu/model/EnvironmentDirectedGraphDescription.cuh)

#ifndef INCLUDE_FLAMEGPU_MODEL_ENVIRONMENTDIRECTEDGRAPHDESCRIPTION_CUH_
#define INCLUDE_FLAMEGPU_MODEL_ENVIRONMENTDIRECTEDGRAPHDESCRIPTION_CUH_

#include <vector>
#include <memory>
#include <string>

#include "flamegpu/model/EnvironmentDirectedGraphData.cuh"
#include "flamegpu/model/EnvironmentDescription.h"

namespace flamegpu {
class CEnvironmentDirectedGraphDescription {
    friend struct EnvironmentDirectedGraphData;

 public:
    explicit CEnvironmentDirectedGraphDescription(std::shared_ptr<EnvironmentDirectedGraphData> data);
    explicit CEnvironmentDirectedGraphDescription(std::shared_ptr<const EnvironmentDirectedGraphData> data);
    CEnvironmentDirectedGraphDescription(const CEnvironmentDirectedGraphDescription& other_graph) = default;
    CEnvironmentDirectedGraphDescription(CEnvironmentDirectedGraphDescription&& other_graph) = default;
    CEnvironmentDirectedGraphDescription& operator=(const CEnvironmentDirectedGraphDescription& other_graph) = default;
    CEnvironmentDirectedGraphDescription& operator=(CEnvironmentDirectedGraphDescription&& other_graph) = default;
    bool operator==(const CEnvironmentDirectedGraphDescription& rhs) const;
    bool operator!=(const CEnvironmentDirectedGraphDescription& rhs) const;

    std::string getName() const;
    const std::type_index& getVertexPropertyType(const std::string& property_name) const;
    const std::type_index& getEdgePropertyType(const std::string& property_name) const;
    size_t getVertexPropertySize(const std::string& property_name) const;
    size_t getEdgePropertySize(const std::string& property_name) const;
    flamegpu::size_type getVertexPropertyLength(const std::string& property_name) const;
    flamegpu::size_type getEdgePropertyLength(const std::string& property_name) const;
    flamegpu::size_type geVertexPropertiesCount() const;
    flamegpu::size_type getEdgePropertiesCount() const;
    bool hasVertexProperty(const std::string& property_name) const;
    bool hasEdgeProperty(const std::string& property_name) const;

 protected:
    std::shared_ptr<EnvironmentDirectedGraphData> graph;
};
class EnvironmentDirectedGraphDescription : public CEnvironmentDirectedGraphDescription {
 public:
    explicit EnvironmentDirectedGraphDescription(std::shared_ptr<EnvironmentDirectedGraphData> data);
    EnvironmentDirectedGraphDescription(const EnvironmentDirectedGraphDescription& other_graph) = default;
    EnvironmentDirectedGraphDescription(EnvironmentDirectedGraphDescription&& other_graph) = default;
    EnvironmentDirectedGraphDescription& operator=(const EnvironmentDirectedGraphDescription& other_graph) = default;
    EnvironmentDirectedGraphDescription& operator=(EnvironmentDirectedGraphDescription&& other_graph) = default;

    template<typename T, size_type N>
    void newVertexProperty(const std::string& property_name, const std::array<T, N>& default_value = {});
    template<typename T, size_type N>
    void newEdgeProperty(const std::string& property_name, const std::array<T, N>& default_value = {});
#ifndef SWIG
    template<typename T>
    void newVertexProperty(const std::string& property_name, const T& default_value = {});
    template<typename T>
    void newEdgeProperty(const std::string& property_name, const T& default_value = {});
#else
    template<typename T>
    void newVertexProperty(const std::string& property_name, const T& default_value = 0);
    template<typename T>
    void newVertexPropertyArray(const std::string& property_name, size_type length, const std::vector<T>& default_value = {});
    template<typename T>
    void newEdgeProperty(const std::string& property_name, const T& default_value = 0);
    template<typename T>
    void newEdgePropertyArray(const std::string& property_name, size_type length, const std::vector<T>& default_value = {});
#endif
};

template<typename T>
void EnvironmentDirectedGraphDescription::newVertexProperty(const std::string& property_name, const T& default_value) {
    newVertexProperty<T, 1>(property_name, { default_value });
}
template<typename T, flamegpu::size_type N>
void EnvironmentDirectedGraphDescription::newVertexProperty(const std::string& property_name, const std::array<T, N>& default_value) {
    if (!property_name.empty() && property_name[0] == '_') {
        THROW exception::ReservedName("Graph property names cannot begin with '_', this is reserved for internal usage, "
            "in EnvironmentDirectedGraphDescription::newVertexProperty().");
    }
    // Array length 0 makes no sense
    static_assert(detail::type_decode<T>::len_t * N > 0, "A property cannot have 0 elements.");
    if (graph->vertexProperties.find(property_name) == graph->vertexProperties.end()) {
        const std::array<typename detail::type_decode<T>::type_t, detail::type_decode<T>::len_t* N>* casted_default =
            reinterpret_cast<const std::array<typename detail::type_decode<T>::type_t, detail::type_decode<T>::len_t* N>*>(&default_value);
        graph->vertexProperties.emplace(property_name, Variable(*casted_default));
        return;
    }
    THROW exception::InvalidGraphProperty("Graph ('%s') already contains vertex property '%s', "
        "in EnvironmentDirectedGraphDescription::newVertexProperty().",
        graph->name.c_str(), property_name.c_str());
}
template<typename T>
void EnvironmentDirectedGraphDescription::newEdgeProperty(const std::string& property_name, const T& default_value) {
    newEdgeProperty<T, 1>(property_name, { default_value });
}
template<typename T, flamegpu::size_type N>
void EnvironmentDirectedGraphDescription::newEdgeProperty(const std::string& property_name, const std::array<T, N>& default_value) {
    if (!property_name.empty() && property_name[0] == '_') {
        THROW exception::ReservedName("Graph property names cannot begin with '_', this is reserved for internal usage, "
            "in EnvironmentDirectedGraphDescription::newEdgeProperty().");
    }
    // Array length 0 makes no sense
    static_assert(detail::type_decode<T>::len_t * N > 0, "A property cannot have 0 elements.");
    if (graph->edgeProperties.find(property_name) == graph->edgeProperties.end()) {
        const std::array<typename detail::type_decode<T>::type_t, detail::type_decode<T>::len_t* N>* casted_default =
            reinterpret_cast<const std::array<typename detail::type_decode<T>::type_t, detail::type_decode<T>::len_t* N>*>(&default_value);
        graph->edgeProperties.emplace(property_name, Variable(*casted_default));
        return;
    }
    THROW exception::InvalidGraphProperty("Graph ('%s') already contains edge property '%s', "
        "in EnvironmentDirectedGraphDescription::newEdgeProperty().",
        graph->name.c_str(), property_name.c_str());
}
#ifdef SWIG
template<typename T>
void EnvironmentDirectedGraphDescription::newVertexPropertyArray(const std::string& property_name, const size_type length, const std::vector<T>& default_value) {
    if (!property_name.empty() && property_name[0] == '_') {
        THROW exception::ReservedName("Graph property names cannot begin with '_', this is reserved for internal usage, "
            "in EnvironmentDirectedGraphDescription::newVertexPropertyArray().");
    }
    if (length == 0) {
        THROW exception::InvalidGraphProperty("Graph property arrays must have a length greater than 0."
            "in EnvironmentDirectedGraphDescription::newVertexPropertyArray().");
    }
    if (default_value.size() && default_value.size() != length) {
        THROW exception::InvalidGraphProperty("Graph vertex property array length specified as %d, but default value provided with %llu elements, "
            "in EnvironmentDirectedGraphDescription::newVertexPropertyArray().",
            length, static_cast<unsigned int>(default_value.size()));
    }
    if (graph->vertexProperties.find(property_name) == graph->vertexProperties.end()) {
        std::vector<typename detail::type_decode<T>::type_t> temp(static_cast<size_t>(detail::type_decode<T>::len_t * length));
        if (default_value.size()) {
            memcpy(temp.data(), default_value.data(), sizeof(typename detail::type_decode<T>::type_t) * detail::type_decode<T>::len_t * length);
        }
        graph->vertexProperties.emplace(property_name, Variable(detail::type_decode<T>::len_t * length, temp));
        return;
    }
    THROW exception::InvalidGraphProperty("Graph ('%s') already contains vertex property '%s', "
        "in EnvironmentDirectedGraphDescription::newVertexPropertyArray().",
        graph->name.c_str(), property_name.c_str());
}
template<typename T>
void EnvironmentDirectedGraphDescription::newEdgePropertyArray(const std::string& property_name, const size_type length, const std::vector<T>& default_value) {
    if (!property_name.empty() && property_name[0] == '_') {
        THROW exception::ReservedName("Graph property names cannot begin with '_', this is reserved for internal usage, "
            "in EnvironmentDirectedGraphDescription::newEdgePropertyArray().");
    }
    if (length == 0) {
        THROW exception::InvalidGraphProperty("Graph property arrays must have a length greater than 0."
            "in EnvironmentDirectedGraphDescription::newEdgePropertyArray().");
    }
    if (default_value.size() && default_value.size() != length) {
        THROW exception::InvalidGraphProperty("Graph vertex property array length specified as %d, but default value provided with %llu elements, "
            "in EnvironmentDirectedGraphDescription::newEdgePropertyArray().",
            length, static_cast<unsigned int>(default_value.size()));
    }
    if (graph->edgeProperties.find(property_name) == graph->edgeProperties.end()) {
        std::vector<typename detail::type_decode<T>::type_t> temp(static_cast<size_t>(detail::type_decode<T>::len_t * length));
        if (default_value.size()) {
            memcpy(temp.data(), default_value.data(), sizeof(typename detail::type_decode<T>::type_t) * detail::type_decode<T>::len_t * length);
        }
        graph->edgeProperties.emplace(property_name, Variable(detail::type_decode<T>::len_t * length, temp));
        return;
    }
    THROW exception::InvalidGraphProperty("Graph ('%s') already contains edge property '%s', "
        "in EnvironmentDirectedGraphDescription::newEdgePropertyArray().",
        graph->name.c_str(), property_name.c_str());
}
#endif

}  // namespace flamegpu

#endif  // INCLUDE_FLAMEGPU_MODEL_ENVIRONMENTDIRECTEDGRAPHDESCRIPTION_CUH_