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