|
Katana Plug-in APIs 0.1
|
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_
1.7.3