Katana Plug-in APIs 0.1

FnSampleAccessor.h

00001 #ifndef KATANA_PLUGINAPI_FNATTRIBUTE_FNSAMPLEACCESSOR_H_
00002 #define KATANA_PLUGINAPI_FNATTRIBUTE_FNSAMPLEACCESSOR_H_
00003 #include <stdint.h>
00004 #include <cmath>
00005 #include <cstring>
00006 #include <iterator>
00007 #include <stdexcept>
00008 #include <string>
00009 #include <utility>
00010 #include <vector>
00011 
00012 #include "FnPlatform/ArrayView.h"
00013 #include "FnPlatform/StringView.h"
00014 #include "FnPlatform/internal/Portability.h"
00015 #include "FnPlatform/internal/TypeTraits.h"
00016 #include "FnPluginSystem/FnPluginSystem.h"
00017 
00018 #include "FnAttribute/FnAttributeAPI.h"
00019 #include "FnAttribute/FnAttributeBase.h"
00020 #include "FnAttribute/ns.h"
00021 #include "FnAttribute/suite/FnAttributeSuite.h"
00022 
00023 #if FNKAT_CXX11
00024 #include "FnPlatform/internal/IndexSequence.h"
00025 #endif
00026 
00027 FNATTRIBUTE_NAMESPACE_ENTER
00028 {
00033 template <typename ValueT>
00034 class SampleIterator;
00035 
00036 template <typename ValueT>
00037 class SampleAccessorBase
00038 {
00039 public:
00040     SampleAccessorBase() : _accessor(NULL), _inlineStorage() {}
00041  explicit SampleAccessorBase(const Attribute& attr)
00045         : _accessor(), _inlineStorage()
00046     {
00047         _accessor = Attribute::getSuite()->createAccessor(
00048             attr.getHandle(), GetAttributeType<ValueT>(),
00049             kFnKatAttributeSampleAccessorRefCounted, &_inlineStorage);
00050         _attr = attr;
00051     }
00052 
00056     explicit SampleAccessorBase(const Attribute* attr)
00057         : _accessor(), _inlineStorage()
00058     {
00059         _accessor = Attribute::getSuite()->createAccessor(
00060             attr->getHandle(), GetAttributeType<ValueT>(), 0, &_inlineStorage);
00061     }
00062 
00063 #ifdef FNKAT_CXX11
00064 
00065     explicit SampleAccessorBase(Attribute&& attr)
00066         : _accessor(), _inlineStorage()
00067     {
00068         _accessor = Attribute::getSuite()->createAccessor(
00069             attr.getHandle(), GetAttributeType<ValueT>(),
00070             kFnKatAttributeSampleAccessorRefCounted, &_inlineStorage);
00071         _attr = std::move(attr);
00072     }
00073 #endif  // FNKAT_CXX11
00074 
00075     ~SampleAccessorBase() { release(); }
00076 
00077     SampleAccessorBase(const SampleAccessorBase& rhs)
00078     {
00079         if (rhs.usesInlineStorage())
00080         {
00081             _accessor = &_inlineStorage;
00082             _inlineStorage = rhs._inlineStorage;
00083         }
00084         else
00085         {
00086             _accessor = rhs._accessor;
00087             std::memset(&_inlineStorage, 0, sizeof(_inlineStorage));
00088         }
00089         retain();
00090         _attr = rhs._attr;
00091     }
00092 
00093 #ifdef FNKAT_CXX11
00094     SampleAccessorBase(SampleAccessorBase&& rhs)
00095     {
00096         if (rhs.usesInlineStorage())
00097         {
00098             _accessor = &_inlineStorage;
00099             _inlineStorage = rhs._inlineStorage;
00100             rhs._accessor = nullptr;
00101         }
00102         else
00103         {
00104             _accessor = rhs._accessor;
00105             rhs._accessor = nullptr;
00106             std::memset(&_inlineStorage, 0, sizeof(_inlineStorage));
00107         }
00108         _attr = std::move(rhs._attr);
00109     }
00110 #endif  // FNKAT_CXX11
00111 
00112     SampleAccessorBase& operator=(const SampleAccessorBase& rhs)
00113     {
00114         if (_accessor != rhs._accessor)
00115         {
00116             release();
00117             if (rhs.usesInlineStorage())
00118             {
00119                 _accessor = &_inlineStorage;
00120                 _inlineStorage = rhs._inlineStorage;
00121             }
00122             else
00123             {
00124                 _accessor = rhs._accessor;
00125                 std::memset(&_inlineStorage, 0, sizeof(_inlineStorage));
00126             }
00127             retain();
00128             _attr = rhs._attr;
00129         }
00130         return *this;
00131     }
00132 
00133 #ifdef FNKAT_CXX11
00134     SampleAccessorBase& operator=(SampleAccessorBase&& rhs)
00135     {
00136         if (_accessor != rhs._accessor)
00137         {
00138             release();
00139             if (rhs.usesInlineStorage())
00140             {
00141                 _accessor = &_inlineStorage;
00142                 _inlineStorage = rhs._inlineStorage;
00143                 rhs._accessor = nullptr;
00144             }
00145             else
00146             {
00147                 _accessor = rhs._accessor;
00148                 rhs._accessor = nullptr;
00149                 std::memset(&_inlineStorage, 0, sizeof(_inlineStorage));
00150             }
00151             _attr = std::move(rhs._attr);
00152         }
00153         return *this;
00154     }
00155 #endif  // FNKAT_CXX11
00156 
00161     bool isValid() const { return _accessor != NULL; }
00162 
00166     int64_t getNumberOfTimeSamples() const
00167     {
00168         return isValid() ? _accessor->sampleCount : 0;
00169     }
00170 
00174     int64_t getNumberOfValues() const
00175     {
00176         return isValid() ? _accessor->valueCount : 0;
00177     }
00178 
00182     size_t size() const
00183     {
00184         return static_cast<size_t>(getNumberOfTimeSamples());
00185     }
00186 
00191     bool empty() const { return getNumberOfTimeSamples() == 0; }
00192 
00195     const FnAttributeSampleAccessor* getRawAccessor() const
00196     {
00197         return _accessor;
00198     }
00201 private:
00202     // Maps a DataAttribute's raw value type to its FnKatAttributeType.
00203     template <typename T>
00204     static FnKatAttributeType GetAttributeType()
00205     {
00206         return GetAttributeTypeImpl(Identity<T>());
00207     }
00208 
00209     // Used for tag-dispatching in GetAttributeTypeImpl.
00210     template <typename T>
00211     struct Identity
00212     {
00213         typedef T type;
00214     };
00215 
00216     static FnKatAttributeType GetAttributeTypeImpl(Identity<int>)
00217     {
00218         return kFnKatAttributeTypeInt;
00219     }
00220     static FnKatAttributeType GetAttributeTypeImpl(Identity<float>)
00221     {
00222         return kFnKatAttributeTypeFloat;
00223     }
00224     static FnKatAttributeType GetAttributeTypeImpl(Identity<double>)
00225     {
00226         return kFnKatAttributeTypeDouble;
00227     }
00228     static FnKatAttributeType GetAttributeTypeImpl(Identity<const char*>)
00229     {
00230         return kFnKatAttributeTypeString;
00231     }
00232     template <typename T>
00233     static FnKatAttributeType GetAttributeTypeImpl(Identity<T>)
00234     {
00235         return kFnKatAttributeTypeError;
00236     }
00237 
00238     bool usesInlineStorage() const { return _accessor == &_inlineStorage; }
00239 
00240     void retain()
00241     {
00242         if (_accessor &&
00243             (_accessor->options & kFnKatAttributeSampleAccessorRefCounted))
00244         {
00245             Attribute::getSuite()->retainAccessor(_accessor);
00246         }
00247     }
00248 
00249     void release()
00250     {
00251         if (_accessor &&
00252             (_accessor->options & kFnKatAttributeSampleAccessorRefCounted))
00253         {
00254             Attribute::getSuite()->releaseAccessor(_accessor);
00255         }
00256     }
00257 
00258     FnAttributeSampleAccessor* _accessor;
00259     FnAttributeSampleAccessorStorage _inlineStorage;
00260     // When not borrowing the caller's reference, ensures attribute data remains
00261     // valid for the lifetime of the accessor.
00262     Attribute _attr;
00263 };
00264 
00310 template <typename ValueT>
00311 class SampleAccessor : public SampleAccessorBase<ValueT>
00312 {
00313 public:
00314     typedef SampleIterator<ValueT> iterator;
00315     typedef iterator const_iterator;
00316     typedef size_t size_type;
00317     typedef typename std::iterator_traits<iterator>::difference_type
00318         difference_type;
00319     typedef typename std::iterator_traits<iterator>::value_type value_type;
00320     typedef typename std::iterator_traits<iterator>::reference reference;
00321     typedef reference const_reference;
00322 
00329     explicit SampleAccessor(const Attribute& attr)
00330         : SampleAccessorBase<ValueT>(attr)
00331     {
00332     }
00333 
00337     explicit SampleAccessor(const Attribute* attr)
00338         : SampleAccessorBase<ValueT>(attr)
00339     {
00340     }
00341 
00342 #ifdef FNKAT_CXX11
00343 
00346     explicit SampleAccessor(Attribute&& attr)
00347         : SampleAccessorBase<ValueT>(std::move(attr))
00348     {
00349     }
00350 #endif  // FNKAT_CXX11
00351 
00356     SampleAccessor() {}  // = default;
00357 
00358     // NOLINTNEXTLINE(runtime/explicit)
00359     /* implicit */ SampleAccessor(const SampleAccessorBase<ValueT>& other)
00360         : SampleAccessorBase<ValueT>(other)
00361     {
00362     }
00363 
00367     const_iterator begin() const FNKAT_LVALUE_REF_QUALIFIER
00368     {
00369         return const_iterator(*this);
00370     }
00371 
00375     const_iterator end() const FNKAT_LVALUE_REF_QUALIFIER
00376     {
00377         return const_iterator(*this, this->getNumberOfTimeSamples());
00378     }
00379 
00383     const_reference front() const FNKAT_LVALUE_REF_QUALIFIER
00384     {
00385         assert(!this->empty());
00386         return *begin();
00387     }
00388 
00392     const_reference back() const FNKAT_LVALUE_REF_QUALIFIER
00393     {
00394         assert(!this->empty());
00395         return *(--end());
00396     }
00397 
00401     const_reference operator[](difference_type i) const
00402         FNKAT_LVALUE_REF_QUALIFIER
00403     {
00404         assert(0 <= i && static_cast<size_t>(i) < this->size());
00405         return begin()[i];
00406     }
00407 
00413     const_reference at(difference_type i) const FNKAT_LVALUE_REF_QUALIFIER
00414     {
00415         if (!(0 <= i && static_cast<size_t>(i) < this->size()))
00416         {
00417             throw std::out_of_range("SampleAccessor::at");
00418         }
00419         return begin()[i];
00420     }
00421 
00425     FnPlatform::ArrayView<float> getSampleTimes() const
00426         FNKAT_LVALUE_REF_QUALIFIER
00427     {
00428         if (!this->isValid())
00429             return FnPlatform::ArrayView<float>();
00430 
00431         const FnAttributeSampleAccessor* acc = this->getRawAccessor();
00432         return FnPlatform::ArrayView<float>(
00433             acc->sampleTimes, static_cast<size_t>(acc->sampleCount));
00434     }
00435 
00440     const_reference getNearestSample(float t) const FNKAT_LVALUE_REF_QUALIFIER
00441     {
00442         return !this->empty() ? (*this)[this->getNearestSampleIndex(t)]
00443                               : const_reference();
00444     }
00445 
00450     int64_t getNearestSampleIndex(float t) const
00451     {
00452         if (!this->isValid())
00453             return 0;
00454 
00455         const FnAttributeSampleAccessor* acc = this->getRawAccessor();
00456         FnPlatform::ArrayView<float> sampleTimes(
00457             acc->sampleTimes, static_cast<size_t>(acc->sampleCount));
00458 
00459         if (sampleTimes.size() <= 1)
00460             return 0;
00461 
00462         size_t currentIndex = 0;
00463         float currentDelta = std::fabs(sampleTimes[0] - t);
00464 
00465         for (size_t i = 1; i < sampleTimes.size(); ++i)
00466         {
00467             float localDelta = std::fabs(sampleTimes[i] - t);
00468             if (localDelta < currentDelta)
00469             {
00470                 currentDelta = localDelta;
00471                 currentIndex = i;
00472             }
00473         }
00474         return static_cast<int64_t>(currentIndex);
00475     }
00476 
00477 #ifdef FNKAT_CXX11
00478 
00479     const_iterator begin() && = delete;
00480     const_iterator end() && = delete;
00481 
00482     const_reference front() && = delete;
00483     const_reference back() && = delete;
00484 
00485     const_reference operator[](difference_type i) && = delete;
00486     const_reference at(difference_type i) && = delete;
00487 
00488     FnPlatform::ArrayView<float> getSampleTimes() && = delete;
00489     const_reference getNearestSample(float t) && = delete;
00491 #endif  // FNKAT_CXX11
00492 };
00493 
00501 template <typename ValueT>
00502 class Sample : public FnPlatform::ArrayView<ValueT>
00503 {
00504 public:
00505     Sample(const ValueT* data,
00506            int64_t valueCount,
00507            int64_t sampleIndex,
00508            float time)
00509         : FnPlatform::ArrayView<ValueT>(data, static_cast<size_t>(valueCount)),
00510           _sampleIndex(sampleIndex),
00511           _sampleTime(time)
00512     {
00513     }
00514 
00515     Sample() : _sampleIndex(), _sampleTime() {}
00516 
00517     float getSampleTime() const { return _sampleTime; }
00518     int64_t getSampleIndex() const { return _sampleIndex; }
00519     int64_t getNumberOfValues() const
00520     {
00521         return static_cast<int64_t>(this->size());
00522     }
00523 
00538     template <typename T, size_t N>
00539     T getAs(const T& defValue = T()) const
00540     {
00541         if (this->size() < N)
00542             return defValue;
00543 #if FNKAT_CXX11
00544         using FnPlatform::internal::MakeIndexSequence;
00545         return getAsImpl<T>(this->data(), MakeIndexSequence<N>());
00546 #else
00547         using FnPlatform::internal::IntegralConstant;
00548         return getAsImpl<T>(this->data(), IntegralConstant<size_t, N>());
00549 #endif  // FNKAT_CXX11
00550     }
00551 
00552 private:
00553 #if FNKAT_CXX11
00554 #ifdef __GNUC__
00555 // Suppress C++11 warning about aggregate initialization requiring two sets
00556 // of braces until C++14.
00557 #pragma GCC diagnostic push
00558 #pragma GCC diagnostic ignored "-Wmissing-braces"
00559 #endif  // __GNUC__
00560     template <typename T, size_t... I>
00561     static T getAsImpl(const ValueT* p,
00562                        FnPlatform::internal::IndexSequence<I...>)
00563     {
00564         (void)p;  // Suppress unused variable warnings.
00565         return T{p[I]...};
00566     }
00567 #ifdef __GNUC__
00568 #pragma GCC diagnostic pop
00569 #endif  // __GNUC__
00570 #else
00571     // C++98 Path.
00572     template <typename T>
00573     static T getAsImpl(const ValueT*,
00574                        FnPlatform::internal::IntegralConstant<size_t, 0>)
00575     {
00576         return T();
00577     }
00578 
00579     template <typename T>
00580     static T getAsImpl(const ValueT* p,
00581                        FnPlatform::internal::IntegralConstant<size_t, 1>)
00582     {
00583         return T(p[0]);
00584     }
00585 
00586     template <typename T>
00587     static T getAsImpl(const ValueT* p,
00588                        FnPlatform::internal::IntegralConstant<size_t, 2>)
00589     {
00590         return T(p[0], p[1]);
00591     }
00592 
00593     template <typename T>
00594     static T getAsImpl(const ValueT* p,
00595                        FnPlatform::internal::IntegralConstant<size_t, 3>)
00596     {
00597         return T(p[0], p[1], p[2]);
00598     }
00599 
00600     template <typename T>
00601     static T getAsImpl(const ValueT* p,
00602                        FnPlatform::internal::IntegralConstant<size_t, 4>)
00603     {
00604         return T(p[0], p[1], p[2], p[3]);
00605     }
00606 
00607     template <typename T>
00608     static T getAsImpl(const ValueT* p,
00609                        FnPlatform::internal::IntegralConstant<size_t, 5>)
00610     {
00611         return T(p[0], p[1], p[2], p[3], p[4]);
00612     }
00613 
00614     template <typename T>
00615     static T getAsImpl(const ValueT* p,
00616                        FnPlatform::internal::IntegralConstant<size_t, 6>)
00617     {
00618         return T(p[0], p[1], p[2], p[3], p[4], p[5]);
00619     }
00620 
00621     template <typename T>
00622     static T getAsImpl(const ValueT* p,
00623                        FnPlatform::internal::IntegralConstant<size_t, 7>)
00624     {
00625         return T(p[0], p[1], p[2], p[3], p[4], p[5], p[6]);
00626     }
00627 
00628     template <typename T>
00629     static T getAsImpl(const ValueT* p,
00630                        FnPlatform::internal::IntegralConstant<size_t, 8>)
00631     {
00632         return T(p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
00633     }
00634 
00635     template <typename T>
00636     static T getAsImpl(const ValueT* p,
00637                        FnPlatform::internal::IntegralConstant<size_t, 9>)
00638     {
00639         return T(p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8]);
00640     }
00641 
00642     template <typename T>
00643     static T getAsImpl(const ValueT* p,
00644                        FnPlatform::internal::IntegralConstant<size_t, 10>)
00645     {
00646         return T(p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], p[9]);
00647     }
00648 
00649     template <typename T>
00650     static T getAsImpl(const ValueT* p,
00651                        FnPlatform::internal::IntegralConstant<size_t, 11>)
00652     {
00653         return T(p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], p[9],
00654                  p[10]);
00655     }
00656 
00657     template <typename T>
00658     static T getAsImpl(const ValueT* p,
00659                        FnPlatform::internal::IntegralConstant<size_t, 12>)
00660     {
00661         return T(p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], p[9],
00662                  p[10], p[11]);
00663     }
00664 
00665     template <typename T>
00666     static T getAsImpl(const ValueT* p,
00667                        FnPlatform::internal::IntegralConstant<size_t, 13>)
00668     {
00669         return T(p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], p[9],
00670                  p[10], p[11], p[12]);
00671     }
00672 
00673     template <typename T>
00674     static T getAsImpl(const ValueT* p,
00675                        FnPlatform::internal::IntegralConstant<size_t, 14>)
00676     {
00677         return T(p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], p[9],
00678                  p[10], p[11], p[12], p[13]);
00679     }
00680 
00681     template <typename T>
00682     static T getAsImpl(const ValueT* p,
00683                        FnPlatform::internal::IntegralConstant<size_t, 15>)
00684     {
00685         return T(p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], p[9],
00686                  p[10], p[11], p[12], p[13], p[14]);
00687     }
00688 
00689     template <typename T>
00690     static T getAsImpl(const ValueT* p,
00691                        FnPlatform::internal::IntegralConstant<size_t, 16>)
00692     {
00693         return T(p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], p[9],
00694                  p[10], p[11], p[12], p[13], p[14], p[15]);
00695     }
00696 #endif  // FNKAT_CXX11
00697 
00698     int64_t _sampleIndex;
00699     float _sampleTime;
00700 };
00701 
00702 template <typename ValueT>
00703 class SampleIterator
00704 {
00705     class Pointer;
00706 
00707 public:
00708     typedef std::ptrdiff_t difference_type;
00709     typedef Sample<ValueT> value_type;
00710     typedef Pointer pointer;
00711     typedef Sample<ValueT> reference;
00712     typedef std::random_access_iterator_tag iterator_category;
00713 
00714     SampleIterator() : _accessor(), _sampleIdx() {}
00715 
00716     explicit SampleIterator(const SampleAccessor<ValueT>& acc,
00717                             int64_t sampleIndex = 0)
00718         : _accessor(acc.getRawAccessor()), _sampleIdx(sampleIndex)
00719     {
00720     }
00721 
00722     reference operator*() const
00723     {
00724         assert((_accessor->options & kFnKatAttributeSampleAccessorContiguous) ^
00725                (_accessor->options & kFnKatAttributeSampleAccessorIndirected));
00726         assert(_sampleIdx < _accessor->sampleCount);
00727 
00728         const ValueT* data;
00729         if (_accessor->options & kFnKatAttributeSampleAccessorContiguous)
00730         {
00731             data = static_cast<const ValueT*>(_accessor->values) +
00732                    _sampleIdx * _accessor->valueCount;
00733         }
00734         else
00735         {
00736             data = static_cast<const ValueT*>(_accessor->samples[_sampleIdx]);
00737         }
00738         return reference(data, _accessor->valueCount, _sampleIdx,
00739                          _accessor->sampleTimes[_sampleIdx]);
00740     }
00741 
00742     pointer operator->() const { return pointer(**this); }
00743 
00744     reference operator[](difference_type n) const { return *(*this + n); }
00745 
00746     friend bool operator==(SampleIterator lhs, SampleIterator rhs)
00747     {
00748         return operator-(lhs, rhs) == 0;
00749     }
00750     friend bool operator!=(SampleIterator lhs, SampleIterator rhs)
00751     {
00752         return operator-(lhs, rhs) != 0;
00753     }
00754     friend bool operator<(SampleIterator lhs, SampleIterator rhs)
00755     {
00756         return operator-(lhs, rhs) < 0;
00757     }
00758     friend bool operator>(SampleIterator lhs, SampleIterator rhs)
00759     {
00760         return operator-(lhs, rhs) > 0;
00761     }
00762     friend bool operator<=(SampleIterator lhs, SampleIterator rhs)
00763     {
00764         return operator-(lhs, rhs) <= 0;
00765     }
00766     friend bool operator>=(SampleIterator lhs, SampleIterator rhs)
00767     {
00768         return operator-(lhs, rhs) >= 0;
00769     }
00770 
00771     SampleIterator& operator++() { return *this += 1; }
00772     SampleIterator& operator--() { return *this -= 1; }
00773 
00774     SampleIterator operator++(int)
00775     {
00776         SampleIterator ret(*this);
00777         operator++();
00778         return ret;
00779     }
00780     SampleIterator operator--(int)
00781     {
00782         SampleIterator ret(*this);
00783         operator--();
00784         return ret;
00785     }
00786 
00787     SampleIterator& operator+=(difference_type n) { return advance(n); }
00788     SampleIterator& operator-=(difference_type n) { return advance(-n); }
00789 
00790     friend SampleIterator operator+(SampleIterator lhs, difference_type n)
00791     {
00792         return lhs.operator+=(n);
00793     }
00794     friend SampleIterator operator+(difference_type n, SampleIterator rhs)
00795     {
00796         return rhs.operator+=(n);
00797     }
00798 
00799     friend SampleIterator operator-(SampleIterator lhs, difference_type n)
00800     {
00801         return lhs.operator-=(n);
00802     }
00803 
00804     friend difference_type operator-(SampleIterator lhs, SampleIterator rhs)
00805     {
00806         return lhs._sampleIdx - rhs._sampleIdx;
00807     }
00808 
00809 private:
00810     // Proxy object to support operator->().
00811     class Pointer
00812     {
00813     public:
00814         explicit Pointer(const Sample<ValueT>& s) : _sample(s) {}
00815         const Sample<ValueT>* operator->() const { return &_sample; }
00816 
00817     private:
00818         Sample<ValueT> _sample;
00819     };
00820 
00821     // Advances the iterator by \a n samples.
00822     SampleIterator& advance(difference_type n)
00823     {
00824         _sampleIdx += n;
00825         assert(_sampleIdx <= _accessor->sampleCount);
00826         return *this;
00827     }
00828 
00829     const FnAttributeSampleAccessor* _accessor;
00830     int64_t _sampleIdx;  // index of the current sample
00831 };
00835 }
00836 FNATTRIBUTE_NAMESPACE_EXIT
00837 
00838 #endif  // KATANA_PLUGINAPI_FNATTRIBUTE_FNSAMPLEACCESSOR_H_
 All Classes Functions Variables Typedefs Enumerations Enumerator