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(void *data, int N, 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)
00100 : m_managed(true)
00101 {
00102 alloc(swizzle.size());
00103 for(int i = 0; i < swizzle.size(); ++i) {
00104 m_begin[i] = other[swizzle[i]];
00105 }
00106 if(neg) negate();
00107 }
00108
00109 template<typename T, ShDataType DT>
00110 ShDataVariant<T, DT>::~ShDataVariant()
00111 {
00112 if(m_managed) delete[] m_begin;
00113 }
00114
00115 template<typename T, ShDataType DT>
00116 ShValueType ShDataVariant<T, DT>::valueType() const {
00117 return value_type;
00118 }
00119
00120 template<typename T, ShDataType DT>
00121 ShDataType ShDataVariant<T, DT>::dataType() const {
00122 return DT;
00123 }
00124
00125 template<typename T, ShDataType DT>
00126 bool ShDataVariant<T, DT>::typeMatches(
00127 ShValueType valueType, ShDataType dataType) const {
00128 return (valueType == value_type) && (dataType == DT);
00129 }
00130
00131
00132 template<typename T, ShDataType DT>
00133 const char* ShDataVariant<T, DT>::typeName() const {
00134 return ShStorageTypeInfo<T>::name;
00135 }
00136
00137 template<typename T, ShDataType DT>
00138 int ShDataVariant<T, DT>::size() const
00139 {
00140 return m_end - m_begin;
00141 }
00142
00143 template<typename T, ShDataType DT>
00144 int ShDataVariant<T, DT>::datasize() const
00145 {
00146 return sizeof(DataType);
00147 }
00148
00149 template<typename T, ShDataType DT>
00150 bool ShDataVariant<T, DT>::managed() const
00151 {
00152 return m_managed;
00153 }
00154
00155 template<typename T, ShDataType DT>
00156 void ShDataVariant<T, DT>::negate()
00157 {
00158 transform(m_begin, m_end, m_begin, std::negate<DataType>());
00159 }
00160
00161 template<typename T, ShDataType DT>
00162 void ShDataVariant<T, DT>::set(const ShVariant* other)
00163 {
00164 SH_DEBUG_ASSERT(other->size() == size());
00165
00166 CPtrType cast_other = variant_cast<T, DT>(other);
00167 if(cast_other) {
00168 std::copy(cast_other->begin(), cast_other->end(), begin());
00169 } else {
00170 ShCastManager::instance()->doCast(this, other);
00171 }
00172 }
00173
00174 template<typename T, ShDataType DT>
00175 void ShDataVariant<T, DT>::set(ShVariantCPtr other)
00176 {
00177 set(other.object());
00178 }
00179
00180 template<typename T, ShDataType DT>
00181 void ShDataVariant<T, DT>::set(const ShVariant* other, int index)
00182 {
00183 SH_DEBUG_ASSERT(other->size() == 1);
00184 CPtrType cast_other = variant_cast<T, DT>(other);
00185 if(cast_other) {
00186 m_begin[index] = (*cast_other)[0];
00187 } else {
00188
00189 ShDataVariant *temp = new ShDataVariant(m_begin + index, 1, false);
00190 ShCastManager::instance()->doCast(temp, other);
00191 delete temp;
00192 }
00193 }
00194
00195 template<typename T, ShDataType DT>
00196 void ShDataVariant<T, DT>::set(ShVariantCPtr other, int index)
00197 {
00198 set(other.object(), index);
00199 }
00200
00201 template<typename T, ShDataType DT>
00202 void ShDataVariant<T, DT>::set(const ShVariant* other, bool neg, const ShSwizzle &writemask)
00203 {
00204 int wmsize = writemask.size();
00205 SH_DEBUG_ASSERT(wmsize == other->size());
00206
00207 if(writemask.identity() && (wmsize == size())) {
00208 set(other);
00209 if(neg) negate();
00210 return;
00211 }
00212
00213
00214 CPtrType cast_other = variant_cast<T, DT>(other);
00215 if(cast_other) {
00216 for(int i = 0; i < wmsize; ++i) {
00217 m_begin[writemask[i]] = (*cast_other)[i];
00218 }
00219 if(neg) negate();
00220 } else {
00221
00222 ShDataVariant *temp = new ShDataVariant(wmsize);
00223 ShCastManager::instance()->doCast(temp, other);
00224 for(int i = 0; i < wmsize; ++i) {
00225 m_begin[writemask[i]] = neg ? -(*temp)[i] : (*temp)[i];
00226 }
00227 delete temp;
00228 }
00229 }
00230
00231 template<typename T, ShDataType DT>
00232 void ShDataVariant<T, DT>::set(ShVariantCPtr other, bool neg, const ShSwizzle &writemask)
00233 {
00234 set(other.object(), neg, writemask);
00235 }
00236
00237 template<typename T, ShDataType DT>
00238 ShVariantPtr ShDataVariant<T, DT>::get() const
00239 {
00240 return new ShDataVariant<T, DT>(*this);
00241 }
00242
00243 template<typename T, ShDataType DT>
00244 ShVariantPtr ShDataVariant<T, DT>::get(int index) const
00245 {
00246 return new ShDataVariant<T, DT>(1, m_begin[index]);
00247 }
00248
00249 template<typename T, ShDataType DT>
00250 ShVariantPtr ShDataVariant<T, DT>::get(bool neg, const ShSwizzle &swizzle) const
00251 {
00252 return new ShDataVariant<T, DT>(*this, neg, swizzle);
00253 }
00254
00255
00256 template<typename T, ShDataType DT>
00257 bool ShDataVariant<T, DT>::equals(const ShVariant* other) const
00258 {
00259 if(!other || (size() != other->size())
00260 || !other->typeMatches(valueType(), dataType())) return false;
00261
00262 const ShDataVariant* castOther = variant_cast<T, DT>(other);
00263 const_iterator I, J;
00264 I = m_begin;
00265 J = castOther->begin();
00266 for(;I != m_end; ++I, ++J) {
00267 if(!shDataTypeEqual((*I), (*J))) return false;
00268 }
00269 return true;
00270 }
00271
00272 template<typename T, ShDataType DT>
00273 bool ShDataVariant<T, DT>::equals(ShVariantCPtr other) const
00274 {
00275 return equals(other.object());
00276 }
00277
00278 template<typename T, ShDataType DT>
00279 bool ShDataVariant<T, DT>::isTrue() const
00280 {
00281 for(const_iterator I = begin(); I != end(); ++I) {
00282 if(!shDataTypeIsPositive((*I))) return false;
00283 }
00284 return true;
00285 }
00286
00287 template<typename T, ShDataType DT>
00288 void* ShDataVariant<T, DT>::array()
00289 {
00290 return m_begin;
00291 }
00292
00293 template<typename T, ShDataType DT>
00294 const void* ShDataVariant<T, DT>::array() const
00295 {
00296 return m_begin;
00297 }
00298
00299 template<typename T, ShDataType DT>
00300 typename ShDataVariant<T, DT>::DataType& ShDataVariant<T, DT>::operator[](int index)
00301 {
00302 return m_begin[index];
00303 }
00304
00305 template<typename T, ShDataType DT>
00306 const typename ShDataVariant<T, DT>::DataType& ShDataVariant<T, DT>::operator[](int index) const
00307 {
00308 return m_begin[index];
00309 }
00310
00311 template<typename T, ShDataType DT>
00312 typename ShDataVariant<T, DT>::iterator ShDataVariant<T, DT>::begin() {
00313 return m_begin;
00314 }
00315
00316 template<typename T, ShDataType DT>
00317 typename ShDataVariant<T, DT>::iterator ShDataVariant<T, DT>::end() {
00318 return m_end;
00319 }
00320
00321 template<typename T, ShDataType DT>
00322 typename ShDataVariant<T, DT>::const_iterator ShDataVariant<T, DT>::begin() const {
00323 return m_begin;
00324 }
00325
00326 template<typename T, ShDataType DT>
00327 typename ShDataVariant<T, DT>::const_iterator ShDataVariant<T, DT>::end() const {
00328 return m_end;
00329 }
00330
00331 template<typename T, ShDataType DT>
00332 std::string ShDataVariant<T, DT>::encode() const {
00333 if(size() < 1) return "";
00334
00335 std::ostringstream out;
00336 out << size();
00337 for(const_iterator I = m_begin; I != m_end; ++I) {
00338 out << "," << *I;
00339 }
00340 return out.str();
00341 }
00342 template<typename T, ShDataType DT>
00343 std::string ShDataVariant<T, DT>::encode(int index, int repeats) const
00344 {
00345 std::ostringstream out;
00346 out << repeats;
00347 for(int i = 0; i < repeats; ++i) {
00348 out << ", " << m_begin[index];
00349 }
00350 return out.str();
00351 }
00352
00353 template<typename T, ShDataType DT>
00354 std::string ShDataVariant<T, DT>::encode(bool neg, const ShSwizzle &swizzle) const
00355 {
00356 std::ostringstream out;
00357 out << swizzle.size();
00358 for(int i = 0; i < swizzle.size(); ++i) {
00359 out << ", " << m_begin[swizzle[i]];
00360 }
00361 return out.str();
00362 }
00363
00364 template<typename T, ShDataType DT>
00365 std::string ShDataVariant<T, DT>::encodeArray() const {
00366 if(size() < 1) return "";
00367
00368 std::ostringstream out;
00369 for(const_iterator I = m_begin; I != m_end; ++I) {
00370 if(I != m_begin) out << ", ";
00371 out << *I;
00372 }
00373 return out.str();
00374 }
00375
00376 template<typename T, ShDataType DT>
00377 void ShDataVariant<T, DT>::alloc(int N) {
00378
00379 m_begin = new DataType[N];
00380 m_end = m_begin + N;
00381 }
00382
00383 #ifdef SH_USE_MEMORY_POOL
00384 template<typename T, ShDataType DT>
00385 void* ShDataVariant<T, DT>::operator new(std::size_t size)
00386 {
00387 if (size != sizeof(ShDataVariant)) return ::operator new(size);
00388 if (!m_pool) {
00389 m_pool = new ShPool(sizeof(ShDataVariant), 32768);
00390 }
00391 return m_pool->alloc();
00392 }
00393
00394 template<typename T, ShDataType DT>
00395 void ShDataVariant<T, DT>::operator delete(void* ptr, std::size_t size)
00396 {
00397 if(size != sizeof(ShDataVariant)) {
00398 SH_DEBUG_PRINT("delete size does not match " << size << " " << sizeof(ShDataVariant));
00399 }
00400 if(!m_pool) shError( ShException( "Deleting from memory pool without an m_pool." ) );
00401 m_pool->free(ptr);
00402 }
00403 #endif
00404
00405 template<typename T, ShDataType DT>
00406 ShPointer<ShDataVariant<T, DT> > variant_cast(ShVariantPtr c)
00407 {
00408 return shref_dynamic_cast<ShDataVariant<T, DT> >(c);
00409 }
00410
00411 template<typename T, ShDataType DT>
00412 ShPointer<const ShDataVariant<T, DT> > variant_cast(ShVariantCPtr c)
00413 {
00414 return shref_dynamic_cast<const ShDataVariant<T, DT> >(c);
00415 }
00416
00417 template<typename T, ShDataType DT>
00418 ShDataVariant<T, DT>* variant_cast(ShVariant* c)
00419 {
00420 return dynamic_cast<ShDataVariant<T, DT>*>(c);
00421 }
00422
00423 template<typename T, ShDataType DT>
00424 const ShDataVariant<T, DT>* variant_cast(const ShVariant* c)
00425 {
00426 return dynamic_cast<const ShDataVariant<T, DT>*>(c);
00427 }
00428
00429 template<typename T, ShDataType DT>
00430 ShPointer<ShDataVariant<T, DT> > variant_convert(ShVariantCPtr c)
00431 {
00432 ShDataVariant<T, DT>* result = new ShDataVariant<T, DT>(c->size());
00433 result->set(c);
00434 return result;
00435 }
00436
00437 }
00438 #endif