00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00027 #ifndef SHVARIANT_IMPL_HPP
00028 #define SHVARIANT_IMPL_HPP
00029
00030 #include <algorithm>
00031 #include <sstream>
00032 #include "ShDebug.hpp"
00033 #include "ShError.hpp"
00034 #include "ShCastManager.hpp"
00035 #include "ShVariant.hpp"
00036 #include "ShTypeInfo.hpp"
00037 #include "ShInterval.hpp"
00038
00039 namespace SH {
00040
00041 #ifdef SH_USE_MEMORY_POOL
00042 template<typename T, ShDataType DT>
00043 ShPool* ShDataVariant<T, DT>::m_pool = 0;
00044 #endif
00045
00046 template<typename T, ShDataType DT>
00047 ShDataVariant<T, DT>::ShDataVariant(int N)
00048 : m_managed(true)
00049 {
00050 alloc(N);
00051 std::fill(m_begin, m_end, ShDataTypeConstant<T, DT>::Zero);
00052 }
00053
00054 template<typename T, ShDataType DT>
00055 ShDataVariant<T, DT>::ShDataVariant(int N, const DataType &value)
00056 : m_managed(true)
00057 {
00058 alloc(N);
00059 std::fill(m_begin, m_end, value);
00060 }
00061
00062 template<typename T, ShDataType DT>
00063 ShDataVariant<T, DT>::ShDataVariant(std::string encodedValue)
00064 : m_managed(true)
00065 {
00066 std::istringstream in(encodedValue);
00067
00068 int size;
00069 in >> size;
00070 alloc(size);
00071
00072 for(iterator I = m_begin; I != m_end; ++I) {
00073 in.ignore(1, '$');
00074 in >> (*I);
00075 }
00076 }
00077
00078 template<typename T, ShDataType DT>
00079 ShDataVariant<T, DT>::ShDataVariant(void *data, int N, bool managed)
00080 : m_managed(managed)
00081 {
00082 if(m_managed) {
00083 alloc(N);
00084 memcpy(m_begin, data, N * datasize());
00085 } else {
00086 m_begin = reinterpret_cast<DataType*>(data);
00087 m_end = m_begin + N;
00088 }
00089 }
00090
00091 template<typename T, ShDataType DT>
00092 ShDataVariant<T, DT>::ShDataVariant(const ShDataVariant<T, DT> &other)
00093 : m_managed(true)
00094 {
00095 int size = other.size();
00096 alloc(size);
00097 memcpy(m_begin, other.m_begin, size * datasize());
00098 }
00099
00100 template<typename T, ShDataType DT>
00101 ShDataVariant<T, DT>::ShDataVariant(const ShDataVariant<T, DT> &other,
00102 bool neg, const ShSwizzle &swizzle)
00103 : m_managed(true)
00104 {
00105 alloc(swizzle.size());
00106 for(int i = 0; i < swizzle.size(); ++i) {
00107 m_begin[i] = other[swizzle[i]];
00108 }
00109 if(neg) negate();
00110 }
00111
00112 template<typename T, ShDataType DT>
00113 ShDataVariant<T, DT>::~ShDataVariant()
00114 {
00115 if(m_managed) delete m_begin;
00116 }
00117
00118 template<typename T, ShDataType DT>
00119 ShValueType ShDataVariant<T, DT>::valueType() const {
00120 return value_type;
00121 }
00122
00123 template<typename T, ShDataType DT>
00124 ShDataType ShDataVariant<T, DT>::dataType() const {
00125 return DT;
00126 }
00127
00128 template<typename T, ShDataType DT>
00129 bool ShDataVariant<T, DT>::typeMatches(
00130 ShValueType valueType, ShDataType dataType) const {
00131 return (valueType == value_type) && (dataType == DT);
00132 }
00133
00134
00135 template<typename T, ShDataType DT>
00136 const char* ShDataVariant<T, DT>::typeName() const {
00137 return ShStorageTypeInfo<T>::name;
00138 }
00139
00140 template<typename T, ShDataType DT>
00141 int ShDataVariant<T, DT>::size() const
00142 {
00143 return m_end - m_begin;
00144 }
00145
00146 template<typename T, ShDataType DT>
00147 int ShDataVariant<T, DT>::datasize() const
00148 {
00149 return sizeof(DataType);
00150 }
00151
00152 template<typename T, ShDataType DT>
00153 bool ShDataVariant<T, DT>::managed() const
00154 {
00155 return m_managed;
00156 }
00157
00158 template<typename T, ShDataType DT>
00159 void ShDataVariant<T, DT>::negate()
00160 {
00161 transform(m_begin, m_end, m_begin, std::negate<DataType>());
00162 }
00163
00164 template<typename T, ShDataType DT>
00165 void ShDataVariant<T, DT>::set(const ShVariant* other)
00166 {
00167 SH_DEBUG_ASSERT(other->size() == size());
00168 ShCastManager::instance()->doCast(this, other);
00169 }
00170
00171 template<typename T, ShDataType DT>
00172 void ShDataVariant<T, DT>::set(ShVariantCPtr other)
00173 {
00174 set(other.object());
00175 }
00176
00177 template<typename T, ShDataType DT>
00178 void ShDataVariant<T, DT>::set(const ShVariant* other, int index)
00179 {
00180 SH_DEBUG_ASSERT(other->size() == 1);
00181
00182 ShDataVariant *temp = new ShDataVariant(m_begin + index, 1, false);
00183 ShCastManager::instance()->doCast(temp, other);
00184 delete temp;
00185 }
00186
00187 template<typename T, ShDataType DT>
00188 void ShDataVariant<T, DT>::set(ShVariantCPtr other, int index)
00189 {
00190 set(other.object(), index);
00191 }
00192
00193 template<typename T, ShDataType DT>
00194 void ShDataVariant<T, DT>::set(const ShVariant* other, bool neg, const ShSwizzle &writemask)
00195 {
00196 int wmsize = writemask.size();
00197 SH_DEBUG_ASSERT(wmsize == other->size());
00198 if(writemask.identity() && (wmsize == size())) {
00199 set(other);
00200 if(neg) negate();
00201 return;
00202 }
00203
00204
00205 ShDataVariant *temp = new ShDataVariant(wmsize);
00206 ShCastManager::instance()->doCast(temp, other);
00207 for(int i = 0; i < wmsize; ++i) {
00208 m_begin[writemask[i]] = neg ? -(*temp)[i] : (*temp)[i];
00209 }
00210 delete temp;
00211 }
00212
00213 template<typename T, ShDataType DT>
00214 void ShDataVariant<T, DT>::set(ShVariantCPtr other, bool neg, const ShSwizzle &writemask)
00215 {
00216 set(other.object(), neg, writemask);
00217 }
00218
00219 template<typename T, ShDataType DT>
00220 ShVariantPtr ShDataVariant<T, DT>::get() const
00221 {
00222 return new ShDataVariant<T, DT>(*this);
00223 }
00224
00225 template<typename T, ShDataType DT>
00226 ShVariantPtr ShDataVariant<T, DT>::get(int index) const
00227 {
00228 return new ShDataVariant<T, DT>(1, m_begin[index]);
00229 }
00230
00231 template<typename T, ShDataType DT>
00232 ShVariantPtr ShDataVariant<T, DT>::get(bool neg, const ShSwizzle &swizzle) const
00233 {
00234 return new ShDataVariant<T, DT>(*this, neg, swizzle);
00235 }
00236
00237
00238 template<typename T, ShDataType DT>
00239 bool ShDataVariant<T, DT>::equals(const ShVariant* other) const
00240 {
00241 if(!other || (size() != other->size())
00242 || !other->typeMatches(valueType(), dataType())) return false;
00243
00244 const ShDataVariant* castOther = variant_cast<T, DT>(other);
00245 const_iterator I, J;
00246 I = m_begin;
00247 J = castOther->begin();
00248 for(;I != m_end; ++I, ++J) {
00249 if(!shDataTypeEqual((*I), (*J))) return false;
00250 }
00251 return true;
00252 }
00253
00254 template<typename T, ShDataType DT>
00255 bool ShDataVariant<T, DT>::equals(ShVariantCPtr other) const
00256 {
00257 return equals(other.object());
00258 }
00259
00260 template<typename T, ShDataType DT>
00261 bool ShDataVariant<T, DT>::isTrue() const
00262 {
00263 for(const_iterator I = begin(); I != end(); ++I) {
00264 if(!shDataTypeIsPositive((*I))) return false;
00265 }
00266 return true;
00267 }
00268
00269 template<typename T, ShDataType DT>
00270 void* ShDataVariant<T, DT>::array()
00271 {
00272 return m_begin;
00273 }
00274
00275 template<typename T, ShDataType DT>
00276 const void* ShDataVariant<T, DT>::array() const
00277 {
00278 return m_begin;
00279 }
00280
00281 template<typename T, ShDataType DT>
00282 typename ShDataVariant<T, DT>::DataType& ShDataVariant<T, DT>::operator[](int index)
00283 {
00284 return m_begin[index];
00285 }
00286
00287 template<typename T, ShDataType DT>
00288 const typename ShDataVariant<T, DT>::DataType& ShDataVariant<T, DT>::operator[](int index) const
00289 {
00290 return m_begin[index];
00291 }
00292
00293 template<typename T, ShDataType DT>
00294 typename ShDataVariant<T, DT>::iterator ShDataVariant<T, DT>::begin() {
00295 return m_begin;
00296 }
00297
00298 template<typename T, ShDataType DT>
00299 typename ShDataVariant<T, DT>::iterator ShDataVariant<T, DT>::end() {
00300 return m_end;
00301 }
00302
00303 template<typename T, ShDataType DT>
00304 typename ShDataVariant<T, DT>::const_iterator ShDataVariant<T, DT>::begin() const {
00305 return m_begin;
00306 }
00307
00308 template<typename T, ShDataType DT>
00309 typename ShDataVariant<T, DT>::const_iterator ShDataVariant<T, DT>::end() const {
00310 return m_end;
00311 }
00312
00313 template<typename T, ShDataType DT>
00314 std::string ShDataVariant<T, DT>::encode() const {
00315 if(size() < 1) return "";
00316
00317 std::ostringstream out;
00318 out << size();
00319 for(const_iterator I = m_begin; I != m_end; ++I) {
00320 out << "," << *I;
00321 }
00322 return out.str();
00323 }
00324 template<typename T, ShDataType DT>
00325 std::string ShDataVariant<T, DT>::encode(int index, int repeats) const
00326 {
00327 std::ostringstream out;
00328 out << repeats;
00329 for(int i = 0; i < repeats; ++i) {
00330 out << ", " << m_begin[index];
00331 }
00332 return out.str();
00333 }
00334
00335 template<typename T, ShDataType DT>
00336 std::string ShDataVariant<T, DT>::encode(bool neg, const ShSwizzle &swizzle) const
00337 {
00338 std::ostringstream out;
00339 out << swizzle.size();
00340 for(int i = 0; i < swizzle.size(); ++i) {
00341 out << ", " << m_begin[swizzle[i]];
00342 }
00343 return out.str();
00344 }
00345
00346
00347 template<typename T, ShDataType DT>
00348 std::string ShDataVariant<T, DT>::encodeArray() const {
00349 if(size() < 1) return "";
00350
00351 std::ostringstream out;
00352 for(const_iterator I = m_begin; I != m_end; ++I) {
00353 if(I != m_begin) out << ", ";
00354 out << *I;
00355 }
00356 return out.str();
00357 }
00358
00359 template<typename T, ShDataType DT>
00360 void ShDataVariant<T, DT>::alloc(int N) {
00361
00362 m_begin = new DataType[N];
00363 m_end = m_begin + N;
00364 }
00365
00366 #ifdef SH_USE_MEMORY_POOL
00367 template<typename T, ShDataType DT>
00368 void* ShDataVariant<T, DT>::operator new(std::size_t size)
00369 {
00370 if (size != sizeof(ShDataVariant)) return ::operator new(size);
00371 if (!m_pool) {
00372 m_pool = new ShPool(sizeof(ShDataVariant), 32768);
00373 }
00374 return m_pool->alloc();
00375 }
00376
00377 template<typename T, ShDataType DT>
00378 void ShDataVariant<T, DT>::operator delete(void* ptr, std::size_t size)
00379 {
00380 if(size != sizeof(ShDataVariant)) {
00381 SH_DEBUG_PRINT("delete size does not match " << size << " " << sizeof(ShDataVariant));
00382 }
00383 if(!m_pool) shError( ShException( "Deleting from memory pool without an m_pool." ) );
00384 m_pool->free(ptr);
00385 }
00386 #endif
00387
00388 template<typename T, ShDataType DT>
00389 ShPointer<ShDataVariant<T, DT> > variant_cast(ShVariantPtr c)
00390 {
00391 return shref_dynamic_cast<ShDataVariant<T, DT> >(c);
00392 }
00393
00394 template<typename T, ShDataType DT>
00395 ShPointer<const ShDataVariant<T, DT> > variant_cast(ShVariantCPtr c)
00396 {
00397 return shref_dynamic_cast<const ShDataVariant<T, DT> >(c);
00398 }
00399
00400 template<typename T, ShDataType DT>
00401 ShDataVariant<T, DT>* variant_cast(ShVariant* c)
00402 {
00403 return dynamic_cast<ShDataVariant<T, DT>*>(c);
00404 }
00405
00406 template<typename T, ShDataType DT>
00407 const ShDataVariant<T, DT>* variant_cast(const ShVariant* c)
00408 {
00409 return dynamic_cast<const ShDataVariant<T, DT>*>(c);
00410 }
00411
00412 template<typename T, ShDataType DT>
00413 ShPointer<ShDataVariant<T, DT> > variant_convert(ShVariantCPtr c)
00414 {
00415 ShDataVariant<T, DT>* result = new ShDataVariant<T, DT>(c->size());
00416 ShCastManager::instance()->doCast(result, c.object());
00417 return result;
00418 }
00419
00420 }
00421 #endif