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