// // Varying.h // render/src/task // // Created by Zach Pomerantz on 1/6/2016. // Copyright 2016 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // #ifndef hifi_task_Varying_h #define hifi_task_Varying_h #include #include namespace task { // A varying piece of data, to be used as Job/Task I/O class Varying { public: Varying() {} Varying(const Varying& var) : _concept(var._concept) {} Varying& operator=(const Varying& var) { _concept = var._concept; return (*this); } template Varying(const T& data) : _concept(std::make_shared>(data)) {} template bool canCast() const { return !!std::dynamic_pointer_cast>(_concept); } template const T& get() const { return std::static_pointer_cast>(_concept)->_data; } template T& edit() { return std::static_pointer_cast>(_concept)->_data; } // access potential sub varyings contained in this one. Varying operator[] (uint8_t index) const { return (*_concept)[index]; } uint8_t length() const { return (*_concept).length(); } template Varying getN (uint8_t index) const { return get()[index]; } template Varying editN (uint8_t index) { return edit()[index]; } bool isNull() const { return _concept == nullptr; } protected: class Concept { public: virtual ~Concept() = default; virtual Varying operator[] (uint8_t index) const = 0; virtual uint8_t length() const = 0; }; template class Model : public Concept { public: using Data = T; Model(const Data& data) : _data(data) {} virtual ~Model() = default; virtual Varying operator[] (uint8_t index) const override { Varying var; return var; } virtual uint8_t length() const override { return 0; } Data _data; }; std::shared_ptr _concept; }; using VaryingPairBase = std::pair; template < typename T0, typename T1 > class VaryingSet2 : public VaryingPairBase { public: using Parent = VaryingPairBase; typedef void is_proxy_tag; VaryingSet2() : Parent(Varying(T0()), Varying(T1())) {} VaryingSet2(const VaryingSet2& pair) : Parent(pair.first, pair.second) {} VaryingSet2(const Varying& first, const Varying& second) : Parent(first, second) {} const T0& get0() const { return first.get(); } T0& edit0() { return first.edit(); } const T1& get1() const { return second.get(); } T1& edit1() { return second.edit(); } virtual Varying operator[] (uint8_t index) const { if (index == 1) { return std::get<1>((*this)); } else { return std::get<0>((*this)); } } virtual uint8_t length() const { return 2; } Varying asVarying() const { return Varying((*this)); } }; template class VaryingSet3 : public std::tuple{ public: using Parent = std::tuple; VaryingSet3() : Parent(Varying(T0()), Varying(T1()), Varying(T2())) {} VaryingSet3(const VaryingSet3& src) : Parent(std::get<0>(src), std::get<1>(src), std::get<2>(src)) {} VaryingSet3(const Varying& first, const Varying& second, const Varying& third) : Parent(first, second, third) {} const T0& get0() const { return std::get<0>((*this)).template get(); } T0& edit0() { return std::get<0>((*this)).template edit(); } const T1& get1() const { return std::get<1>((*this)).template get(); } T1& edit1() { return std::get<1>((*this)).template edit(); } const T2& get2() const { return std::get<2>((*this)).template get(); } T2& edit2() { return std::get<2>((*this)).template edit(); } virtual Varying operator[] (uint8_t index) const { if (index == 2) { return std::get<2>((*this)); } else if (index == 1) { return std::get<1>((*this)); } else { return std::get<0>((*this)); } } virtual uint8_t length() const { return 3; } Varying asVarying() const { return Varying((*this)); } }; template class VaryingSet4 : public std::tuple{ public: using Parent = std::tuple; VaryingSet4() : Parent(Varying(T0()), Varying(T1()), Varying(T2()), Varying(T3())) {} VaryingSet4(const VaryingSet4& src) : Parent(std::get<0>(src), std::get<1>(src), std::get<2>(src), std::get<3>(src)) {} VaryingSet4(const Varying& first, const Varying& second, const Varying& third, const Varying& fourth) : Parent(first, second, third, fourth) {} const T0& get0() const { return std::get<0>((*this)).template get(); } T0& edit0() { return std::get<0>((*this)).template edit(); } const T1& get1() const { return std::get<1>((*this)).template get(); } T1& edit1() { return std::get<1>((*this)).template edit(); } const T2& get2() const { return std::get<2>((*this)).template get(); } T2& edit2() { return std::get<2>((*this)).template edit(); } const T3& get3() const { return std::get<3>((*this)).template get(); } T3& edit3() { return std::get<3>((*this)).template edit(); } virtual Varying operator[] (uint8_t index) const { if (index == 3) { return std::get<3>((*this)); } else if (index == 2) { return std::get<2>((*this)); } else if (index == 1) { return std::get<1>((*this)); } else { return std::get<0>((*this)); } } virtual uint8_t length() const { return 4; } Varying asVarying() const { return Varying((*this)); } }; template class VaryingSet5 : public std::tuple{ public: using Parent = std::tuple; VaryingSet5() : Parent(Varying(T0()), Varying(T1()), Varying(T2()), Varying(T3()), Varying(T4())) {} VaryingSet5(const VaryingSet5& src) : Parent(std::get<0>(src), std::get<1>(src), std::get<2>(src), std::get<3>(src), std::get<4>(src)) {} VaryingSet5(const Varying& first, const Varying& second, const Varying& third, const Varying& fourth, const Varying& fifth) : Parent(first, second, third, fourth, fifth) {} const T0& get0() const { return std::get<0>((*this)).template get(); } T0& edit0() { return std::get<0>((*this)).template edit(); } const T1& get1() const { return std::get<1>((*this)).template get(); } T1& edit1() { return std::get<1>((*this)).template edit(); } const T2& get2() const { return std::get<2>((*this)).template get(); } T2& edit2() { return std::get<2>((*this)).template edit(); } const T3& get3() const { return std::get<3>((*this)).template get(); } T3& edit3() { return std::get<3>((*this)).template edit(); } const T4& get4() const { return std::get<4>((*this)).template get(); } T4& edit4() { return std::get<4>((*this)).template edit(); } virtual Varying operator[] (uint8_t index) const { if (index == 4) { return std::get<4>((*this)); } else if (index == 3) { return std::get<3>((*this)); } else if (index == 2) { return std::get<2>((*this)); } else if (index == 1) { return std::get<1>((*this)); } else { return std::get<0>((*this)); } } virtual uint8_t length() const { return 5; } Varying asVarying() const { return Varying((*this)); } }; template class VaryingSet6 : public std::tuple{ public: using Parent = std::tuple; VaryingSet6() : Parent(Varying(T0()), Varying(T1()), Varying(T2()), Varying(T3()), Varying(T4()), Varying(T5())) {} VaryingSet6(const VaryingSet6& src) : Parent(std::get<0>(src), std::get<1>(src), std::get<2>(src), std::get<3>(src), std::get<4>(src), std::get<5>(src)) {} VaryingSet6(const Varying& first, const Varying& second, const Varying& third, const Varying& fourth, const Varying& fifth, const Varying& sixth) : Parent(first, second, third, fourth, fifth, sixth) {} const T0& get0() const { return std::get<0>((*this)).template get(); } T0& edit0() { return std::get<0>((*this)).template edit(); } const T1& get1() const { return std::get<1>((*this)).template get(); } T1& edit1() { return std::get<1>((*this)).template edit(); } const T2& get2() const { return std::get<2>((*this)).template get(); } T2& edit2() { return std::get<2>((*this)).template edit(); } const T3& get3() const { return std::get<3>((*this)).template get(); } T3& edit3() { return std::get<3>((*this)).template edit(); } const T4& get4() const { return std::get<4>((*this)).template get(); } T4& edit4() { return std::get<4>((*this)).template edit(); } const T5& get5() const { return std::get<5>((*this)).template get(); } T5& edit5() { return std::get<5>((*this)).template edit(); } virtual Varying operator[] (uint8_t index) const { switch (index) { default: return std::get<0>((*this)); case 1: return std::get<1>((*this)); case 2: return std::get<2>((*this)); case 3: return std::get<3>((*this)); case 4: return std::get<4>((*this)); case 5: return std::get<5>((*this)); }; } virtual uint8_t length() const { return 6; } Varying asVarying() const { return Varying((*this)); } }; template class VaryingSet7 : public std::tuple{ public: using Parent = std::tuple; VaryingSet7() : Parent(Varying(T0()), Varying(T1()), Varying(T2()), Varying(T3()), Varying(T4()), Varying(T5()), Varying(T6())) {} VaryingSet7(const VaryingSet7& src) : Parent(std::get<0>(src), std::get<1>(src), std::get<2>(src), std::get<3>(src), std::get<4>(src), std::get<5>(src), std::get<6>(src)) {} VaryingSet7(const Varying& first, const Varying& second, const Varying& third, const Varying& fourth, const Varying& fifth, const Varying& sixth, const Varying& seventh) : Parent(first, second, third, fourth, fifth, sixth, seventh) {} const T0& get0() const { return std::get<0>((*this)).template get(); } T0& edit0() { return std::get<0>((*this)).template edit(); } const T1& get1() const { return std::get<1>((*this)).template get(); } T1& edit1() { return std::get<1>((*this)).template edit(); } const T2& get2() const { return std::get<2>((*this)).template get(); } T2& edit2() { return std::get<2>((*this)).template edit(); } const T3& get3() const { return std::get<3>((*this)).template get(); } T3& edit3() { return std::get<3>((*this)).template edit(); } const T4& get4() const { return std::get<4>((*this)).template get(); } T4& edit4() { return std::get<4>((*this)).template edit(); } const T5& get5() const { return std::get<5>((*this)).template get(); } T5& edit5() { return std::get<5>((*this)).template edit(); } const T6& get6() const { return std::get<6>((*this)).template get(); } T6& edit6() { return std::get<6>((*this)).template edit(); } Varying asVarying() const { return Varying((*this)); } }; template < class T, int NUM > class VaryingArray : public std::array { public: VaryingArray() { for (size_t i = 0; i < NUM; i++) { (*this)[i] = Varying(T()); } } VaryingArray(std::initializer_list list) { assert(list.size() == NUM); std::copy(list.begin(), list.end(), std::array::begin()); } }; } #endif // hifi_task_Varying_h