1/*****************************************************************************/ 2/* Xdmf */ 3/* Extensible Data Model and Format */ 4/* */ 5/* Id : XdmfArray.tpp */ 6/* */ 7/* Author: */ 8/* Kenneth Leiter */ 9/* kenneth.leiter@arl.army.mil */ 10/* US Army Research Laboratory */ 11/* Aberdeen Proving Ground, MD */ 12/* */ 13/* Copyright @ 2011 US Army Research Laboratory */ 14/* All Rights Reserved */ 15/* See Copyright.txt for details */ 16/* */ 17/* This software is distributed WITHOUT ANY WARRANTY; without */ 18/* even the implied warranty of MERCHANTABILITY or FITNESS */ 19/* FOR A PARTICULAR PURPOSE. See the above copyright notice */ 20/* for more information. */ 21/* */ 22/*****************************************************************************/ 23 24#include <functional> 25#include <numeric> 26#include <sstream> 27#include "XdmfArray.hpp" 28 29template <typename T> 30class XdmfArray::GetValue : public boost::static_visitor<T> { 31public: 32 33 GetValue(const unsigned int index) : 34 mIndex(index) 35 { 36 } 37 38 T 39 operator()(const boost::blank &) const 40 { 41 return 0; 42 } 43 44 T 45 operator()(const shared_ptr<std::vector<std::string> > & array) const 46 { 47 return (T)atof(array->operator[](mIndex).c_str()); 48 } 49 50 template<typename U> 51 T 52 operator()(const shared_ptr<std::vector<U> > & array) const 53 { 54 return (T)array->operator[](mIndex); 55 } 56 57 template<typename U> 58 T 59 operator()(const boost::shared_array<const U> & array) const 60 { 61 return (T)array[mIndex]; 62 } 63 64private: 65 66 const unsigned int mIndex; 67}; 68 69template <> 70class XdmfArray::GetValue<std::string> : 71 public boost::static_visitor<std::string> { 72public: 73 74 GetValue(const unsigned int index) : 75 mIndex(index) 76 { 77 } 78 79 std::string 80 operator()(const boost::blank &) const 81 { 82 return ""; 83 } 84 85 std::string 86 operator()(const shared_ptr<std::vector<std::string> > & array) const 87 { 88 return array->operator[](mIndex); 89 } 90 91 template<typename U> 92 std::string 93 operator()(const shared_ptr<std::vector<U> > & array) const 94 { 95 std::stringstream value; 96 value << array->operator[](mIndex); 97 return value.str(); 98 } 99 100 std::string 101 operator()(const boost::shared_array<const std::string> & array) const 102 { 103 return array[mIndex]; 104 } 105 106 template<typename U> 107 std::string 108 operator()(const boost::shared_array<const U> & array) const 109 { 110 std::stringstream value; 111 value << array[mIndex]; 112 return value.str(); 113 } 114 115private: 116 117 const unsigned int mIndex; 118}; 119 120template <typename T> 121class XdmfArray::GetValues : public boost::static_visitor<void> { 122public: 123 124 GetValues(const unsigned int startIndex, 125 T * valuesPointer, 126 const unsigned int numValues, 127 const unsigned int arrayStride, 128 const unsigned int valuesStride) : 129 mStartIndex(startIndex), 130 mValuesPointer(valuesPointer), 131 mNumValues(numValues), 132 mArrayStride(arrayStride), 133 mValuesStride(valuesStride) 134 { 135 } 136 137 void 138 operator()(const boost::blank &) const 139 { 140 return; 141 } 142 143 void 144 operator()(const shared_ptr<std::vector<std::string> > & array) const 145 { 146 for(unsigned int i=0; i<mNumValues; ++i) { 147 mValuesPointer[i*mValuesStride] = 148 (T)atof(array->operator[](mStartIndex + i*mArrayStride).c_str()); 149 } 150 } 151 152 template<typename U> 153 void 154 operator()(const shared_ptr<std::vector<U> > & array) const 155 { 156 for(unsigned int i=0; i<mNumValues; ++i) { 157 mValuesPointer[i*mValuesStride] = 158 (T)array->operator[](mStartIndex + i*mArrayStride); 159 } 160 } 161 162 template<typename U> 163 void 164 operator()(const boost::shared_array<const U> & array) const 165 { 166 for(unsigned int i=0; i<mNumValues; ++i) { 167 mValuesPointer[i*mValuesStride] = (T)array[mStartIndex + i*mArrayStride]; 168 } 169 } 170 171private: 172 173 const unsigned int mStartIndex; 174 T * mValuesPointer; 175 const unsigned int mNumValues; 176 const unsigned int mArrayStride; 177 const unsigned int mValuesStride; 178}; 179 180template <> 181class XdmfArray::GetValues<std::string> : public boost::static_visitor<void> { 182public: 183 184 GetValues(const unsigned int startIndex, 185 std::string * valuesPointer, 186 const unsigned int numValues, 187 const unsigned int arrayStride, 188 const unsigned int valuesStride) : 189 mStartIndex(startIndex), 190 mValuesPointer(valuesPointer), 191 mNumValues(numValues), 192 mArrayStride(arrayStride), 193 mValuesStride(valuesStride) 194 { 195 } 196 197 void 198 operator()(const boost::blank &) const 199 { 200 return; 201 } 202 203 template<typename U> 204 void 205 operator()(const shared_ptr<std::vector<U> > & array) const 206 { 207 for(unsigned int i=0; i<mNumValues; ++i) { 208 std::stringstream value; 209 value << array->operator[](mStartIndex + i*mArrayStride); 210 mValuesPointer[i*mValuesStride] = value.str(); 211 } 212 } 213 214 template<typename U> 215 void 216 operator()(const boost::shared_array<const U> & array) const 217 { 218 for(unsigned int i=0; i<mNumValues; ++i) { 219 std::stringstream value; 220 value << array[mStartIndex + i*mArrayStride]; 221 mValuesPointer[i*mValuesStride] = value.str(); 222 } 223 } 224 225private: 226 227 const unsigned int mStartIndex; 228 std::string * mValuesPointer; 229 const unsigned int mNumValues; 230 const unsigned int mArrayStride; 231 const unsigned int mValuesStride; 232}; 233 234template <typename T> 235class XdmfArray::Insert : public boost::static_visitor<void> { 236public: 237 238 Insert(XdmfArray * const array, 239 const unsigned int startIndex, 240 const T * const valuesPointer, 241 const unsigned int numValues, 242 const unsigned int arrayStride, 243 const unsigned int valuesStride, 244 std::vector<unsigned int> & dimensions) : 245 mArray(array), 246 mStartIndex(startIndex), 247 mValuesPointer(valuesPointer), 248 mNumValues(numValues), 249 mArrayStride(arrayStride), 250 mValuesStride(valuesStride), 251 mDimensions(dimensions) 252 { 253 } 254 255 void 256 operator()(const boost::blank &) const 257 { 258 mArray->initialize<T>(); 259 boost::apply_visitor(*this, 260 mArray->mArray); 261 } 262 263 void 264 operator()(shared_ptr<std::vector<std::string> > & array) const 265 { 266 unsigned int size = mStartIndex + (mNumValues - 1) * mArrayStride + 1; 267 if(array->size() < size) { 268 array->resize(size); 269 mDimensions.clear(); 270 } 271 for(unsigned int i=0; i<mNumValues; ++i) { 272 std::stringstream value; 273 value << mValuesPointer[i*mValuesStride]; 274 array->operator[](mStartIndex + i*mArrayStride) = value.str(); 275 } 276 } 277 278 template<typename U> 279 void 280 operator()(shared_ptr<std::vector<U> > & array) const 281 { 282 unsigned int size = mStartIndex + (mNumValues - 1) * mArrayStride + 1; 283 if(array->size() < size) { 284 array->resize(size); 285 mDimensions.clear(); 286 } 287 for(unsigned int i=0; i<mNumValues; ++i) { 288 array->operator[](mStartIndex + i*mArrayStride) = 289 (U)mValuesPointer[i*mValuesStride]; 290 } 291 } 292 293 template<typename U> 294 void 295 operator()(boost::shared_array<const U> &) const 296 { 297 mArray->internalizeArrayPointer(); 298 boost::apply_visitor(*this, 299 mArray->mArray); 300 } 301 302private: 303 304 XdmfArray * const mArray; 305 const unsigned int mStartIndex; 306 const T * const mValuesPointer; 307 const unsigned int mNumValues; 308 const unsigned int mArrayStride; 309 const unsigned int mValuesStride; 310 std::vector<unsigned int> & mDimensions; 311}; 312 313template <> 314class XdmfArray::Insert<std::string> : public boost::static_visitor<void> { 315public: 316 317 Insert(XdmfArray * const array, 318 const unsigned int startIndex, 319 const std::string * const valuesPointer, 320 const unsigned int numValues, 321 const unsigned int arrayStride, 322 const unsigned int valuesStride, 323 std::vector<unsigned int> & dimensions) : 324 mArray(array), 325 mStartIndex(startIndex), 326 mValuesPointer(valuesPointer), 327 mNumValues(numValues), 328 mArrayStride(arrayStride), 329 mValuesStride(valuesStride), 330 mDimensions(dimensions) 331 { 332 } 333 334 void 335 operator()(const boost::blank &) const 336 { 337 mArray->initialize<std::string>(); 338 boost::apply_visitor(*this, 339 mArray->mArray); 340 } 341 342 void 343 operator()(shared_ptr<std::vector<std::string> > & array) const 344 { 345 unsigned int size = mStartIndex + (mNumValues - 1) * mArrayStride + 1; 346 if(array->size() < size) { 347 array->resize(size); 348 mDimensions.clear(); 349 } 350 for(unsigned int i=0; i<mNumValues; ++i) { 351 array->operator[](mStartIndex + i*mArrayStride) = 352 mValuesPointer[i*mValuesStride].c_str(); 353 } 354 } 355 356 template<typename U> 357 void 358 operator()(shared_ptr<std::vector<U> > & array) const 359 { 360 unsigned int size = mStartIndex + (mNumValues - 1) * mArrayStride + 1; 361 if(array->size() < size) { 362 array->resize(size); 363 mDimensions.clear(); 364 } 365 for(unsigned int i=0; i<mNumValues; ++i) { 366 array->operator[](mStartIndex + i*mArrayStride) = 367 (U)atof(mValuesPointer[i*mValuesStride].c_str()); 368 } 369 } 370 371 template<typename U> 372 void 373 operator()(boost::shared_array<const U> &) const 374 { 375 mArray->internalizeArrayPointer(); 376 boost::apply_visitor(*this, 377 mArray->mArray); 378 } 379 380private: 381 382 XdmfArray * const mArray; 383 const unsigned int mStartIndex; 384 const std::string * const mValuesPointer; 385 const unsigned int mNumValues; 386 const unsigned int mArrayStride; 387 const unsigned int mValuesStride; 388 std::vector<unsigned int> & mDimensions; 389}; 390 391template <typename T> 392class XdmfArray::PushBack : public boost::static_visitor<void> { 393public: 394 395 PushBack(const T & val, 396 XdmfArray * const array) : 397 mVal(val), 398 mArray(array) 399 { 400 } 401 402 void 403 operator()(const boost::blank &) const 404 { 405 mArray->initialize<T>(); 406 boost::apply_visitor(*this, 407 mArray->mArray); 408 } 409 410 void 411 operator()(shared_ptr<std::vector<std::string> > & array) const 412 { 413 std::stringstream value; 414 value << mVal; 415 array->push_back(value.str()); 416 mArray->mDimensions.clear(); 417 } 418 419 template<typename U> 420 void 421 operator()(shared_ptr<std::vector<U> > & array) const 422 { 423 array->push_back((U)mVal); 424 mArray->mDimensions.clear(); 425 } 426 427 template<typename U> 428 void 429 operator()(const boost::shared_array<const U> &) const 430 { 431 mArray->internalizeArrayPointer(); 432 boost::apply_visitor(*this, 433 mArray->mArray); 434 } 435 436private: 437 438 const T & mVal; 439 XdmfArray * const mArray; 440}; 441 442template <> 443class XdmfArray::PushBack<std::string> : public boost::static_visitor<void> { 444public: 445 446 PushBack(const std::string & val, 447 XdmfArray * const array) : 448 mVal(val), 449 mArray(array) 450 { 451 } 452 453 void 454 operator()(const boost::blank &) const 455 { 456 mArray->initialize<std::string>(); 457 boost::apply_visitor(*this, 458 mArray->mArray); 459 } 460 461 void 462 operator()(shared_ptr<std::vector<std::string> > & array) const 463 { 464 array->push_back(mVal); 465 mArray->mDimensions.clear(); 466 } 467 468 template<typename U> 469 void 470 operator()(shared_ptr<std::vector<U> > & array) const 471 { 472 array->push_back((U)atof(mVal.c_str())); 473 mArray->mDimensions.clear(); 474 } 475 476 template<typename U> 477 void 478 operator()(const boost::shared_array<const U> &) const 479 { 480 mArray->internalizeArrayPointer(); 481 boost::apply_visitor(*this, 482 mArray->mArray); 483 } 484 485private: 486 487 const std::string & mVal; 488 XdmfArray * const mArray; 489}; 490 491template <typename T> 492class XdmfArray::Resize : public boost::static_visitor<void> { 493public: 494 495 Resize(XdmfArray * const array, 496 const unsigned int numValues, 497 const T & val) : 498 mArray(array), 499 mNumValues(numValues), 500 mVal(val) 501 { 502 } 503 504 void 505 operator()(const boost::blank &) const 506 { 507 mArray->initialize<T>(); 508 boost::apply_visitor(*this, 509 mArray->mArray); 510 } 511 512 void 513 operator()(shared_ptr<std::vector<std::string> > & array) const 514 { 515 std::stringstream value; 516 value << mVal; 517 array->resize(mNumValues, value.str()); 518 mArray->mDimensions.clear(); 519 } 520 521 template<typename U> 522 void 523 operator()(shared_ptr<std::vector<U> > & array) const 524 { 525 array->resize(mNumValues, (U)mVal); 526 mArray->mDimensions.clear(); 527 } 528 529 template<typename U> 530 void 531 operator()(const boost::shared_array<const U> &) const 532 { 533 mArray->internalizeArrayPointer(); 534 boost::apply_visitor(*this, 535 mArray->mArray); 536 } 537 538private: 539 540 XdmfArray * mArray; 541 const unsigned int mNumValues; 542 const T & mVal; 543}; 544 545template <> 546class XdmfArray::Resize<std::string> : public boost::static_visitor<void> { 547public: 548 549 Resize(XdmfArray * const array, 550 const unsigned int numValues, 551 const std::string & val) : 552 mArray(array), 553 mNumValues(numValues), 554 mVal(val) 555 { 556 } 557 558 void 559 operator()(const boost::blank &) const 560 { 561 mArray->initialize<std::string>(); 562 boost::apply_visitor(*this, 563 mArray->mArray); 564 } 565 566 void 567 operator()(shared_ptr<std::vector<std::string> > & array) const 568 { 569 array->resize(mNumValues, mVal); 570 mArray->mDimensions.clear(); 571 } 572 573 template<typename U> 574 void 575 operator()(shared_ptr<std::vector<U> > & array) const 576 { 577 array->resize(mNumValues, (U)atof(mVal.c_str())); 578 mArray->mDimensions.clear(); 579 } 580 581 template<typename U> 582 void 583 operator()(const boost::shared_array<const U> &) const 584 { 585 mArray->internalizeArrayPointer(); 586 boost::apply_visitor(*this, 587 mArray->mArray); 588 } 589 590private: 591 592 XdmfArray * mArray; 593 const unsigned int mNumValues; 594 const std::string & mVal; 595}; 596 597struct XdmfArray::NullDeleter 598{ 599 void 600 operator()(void const *) const 601 { 602 } 603}; 604 605template <typename T> 606T 607XdmfArray::getValue(const unsigned int index) const 608{ 609 return boost::apply_visitor(GetValue<T>(index), 610 mArray); 611} 612 613template <typename T> 614void 615XdmfArray::getValues(const unsigned int startIndex, 616 T * const valuesPointer, 617 const unsigned int numValues, 618 const unsigned int arrayStride, 619 const unsigned int valuesStride) const 620{ 621 boost::apply_visitor(GetValues<T>(startIndex, 622 valuesPointer, 623 numValues, 624 arrayStride, 625 valuesStride), 626 mArray); 627} 628 629template <typename T> 630shared_ptr<std::vector<T> > 631XdmfArray::getValuesInternal() 632{ 633 this->internalizeArrayPointer(); 634 try { 635 shared_ptr<std::vector<T> > currArray = 636 boost::get<shared_ptr<std::vector<T> > >(mArray); 637 return currArray; 638 } 639 catch(const boost::bad_get & exception) { 640 return shared_ptr<std::vector<T> >(); 641 } 642} 643 644template <typename T> 645shared_ptr<std::vector<T> > 646XdmfArray::initialize(const unsigned int size) 647{ 648 // Set type of variant to type of pointer 649 shared_ptr<std::vector<T> > newArray(new std::vector<T>(size)); 650 if(mTmpReserveSize > 0) { 651 newArray->reserve(mTmpReserveSize); 652 mTmpReserveSize = 0; 653 } 654 mArray = newArray; 655 return newArray; 656} 657 658template <typename T> 659shared_ptr<std::vector<T> > 660XdmfArray::initialize(const std::vector<unsigned int> & dimensions) 661{ 662 mDimensions = dimensions; 663 const unsigned int size = static_cast<unsigned int>( 664 std::accumulate(dimensions.begin(), 665 dimensions.end(), 666 1, 667 std::multiplies<unsigned int>())); 668 return this->initialize<T>(size); 669} 670 671template<typename T> 672void 673XdmfArray::insert(const unsigned int index, 674 const T & value) 675{ 676 boost::apply_visitor(Insert<T>(this, 677 index, 678 &value, 679 1, 680 0, 681 0, 682 mDimensions), 683 mArray); 684} 685 686template <typename T> 687void 688XdmfArray::insert(const unsigned int startIndex, 689 const T * const valuesPointer, 690 const unsigned int numValues, 691 const unsigned int arrayStride, 692 const unsigned int valuesStride) 693{ 694 boost::apply_visitor(Insert<T>(this, 695 startIndex, 696 valuesPointer, 697 numValues, 698 arrayStride, 699 valuesStride, 700 mDimensions), 701 mArray); 702} 703 704template <typename T> 705void 706XdmfArray::pushBack(const T & value) 707{ 708 return boost::apply_visitor(PushBack<T>(value, 709 this), 710 mArray); 711} 712 713template<typename T> 714void 715XdmfArray::resize(const unsigned int numValues, 716 const T & value) 717{ 718 return boost::apply_visitor(Resize<T>(this, 719 numValues, 720 value), 721 mArray); 722 std::vector<unsigned int> newDimensions; 723 newDimensions.push_back(numValues); 724} 725 726template<typename T> 727void 728XdmfArray::resize(const std::vector<unsigned int> & dimensions, 729 const T & value) 730{ 731 const unsigned int size = static_cast<unsigned int>( 732 std::accumulate(dimensions.begin(), 733 dimensions.end(), 734 1, 735 std::multiplies<unsigned int>())); 736 this->resize(size, value); 737 mDimensions = dimensions; 738} 739 740template <typename T> 741void 742XdmfArray::setValuesInternal(const T * const arrayPointer, 743 const unsigned int numValues, 744 const bool transferOwnership) 745{ 746 // Remove contents of internal array. 747 if(transferOwnership) { 748 const boost::shared_array<const T> newArrayPointer(arrayPointer); 749 mArray = newArrayPointer; 750 } 751 else { 752 const boost::shared_array<const T> newArrayPointer(arrayPointer, 753 NullDeleter()); 754 mArray = newArrayPointer; 755 } 756 mArrayPointerNumValues = numValues; 757} 758 759template <typename T> 760void 761XdmfArray::setValuesInternal(std::vector<T> & array, 762 const bool transferOwnership) 763{ 764 if(transferOwnership) { 765 shared_ptr<std::vector<T> > newArray(&array); 766 mArray = newArray; 767 } 768 else { 769 shared_ptr<std::vector<T> > newArray(&array, NullDeleter()); 770 mArray = newArray; 771 } 772} 773 774template <typename T> 775void 776XdmfArray::setValuesInternal(const shared_ptr<std::vector<T> > array) 777{ 778 mArray = array; 779} 780 781template <typename T> 782bool 783XdmfArray::swap(std::vector<T> & array) 784{ 785 this->internalizeArrayPointer(); 786 if(!this->isInitialized()) { 787 this->initialize<T>(); 788 } 789 try { 790 shared_ptr<std::vector<T> > currArray = 791 boost::get<shared_ptr<std::vector<T> > >(mArray); 792 currArray->swap(array); 793 return true; 794 } 795 catch(const boost::bad_get & exception) { 796 return false; 797 } 798} 799 800template <typename T> 801bool 802XdmfArray::swap(const shared_ptr<std::vector<T> > array) 803{ 804 return this->swap(*array.get()); 805} 806