// -*- C++ -*-

#if !defined(__array_PackedArrayOfArrays_ipp__)
#error This file is an implementation detail of the class PackedArrayOfArrays.
#endif

namespace array {


// Construct from a container of containers.
template<typename _T>
template<typename _Container>
inline
PackedArrayOfArrays<_T>::
PackedArrayOfArrays(const _Container& cOfC) :
   Base(),
   _delimiters(1) {
   _delimiters[0] = 0;
   typedef typename _Container::const_iterator ArrayIter;
   typedef typename _Container::value_type::const_iterator ElementIter;
   for (ArrayIter i = cOfC.begin(); i != cOfC.end(); ++i) {
      pushArray();
      for (ElementIter j = i->begin(); j != i->end(); ++j) {
         push_back(*j);
      }
   }
}


template<typename _T>
template<typename SizeForwardIter, typename ValueForwardIter>
inline
PackedArrayOfArrays<_T>::
PackedArrayOfArrays(SizeForwardIter sizesBeginning, SizeForwardIter sizesEnd,
                    ValueForwardIter valuesBeginning,
                    ValueForwardIter valuesEnd) :
   Base(valuesBeginning, valuesEnd),
   _delimiters(1) {
   _delimiters[0] = 0;
   std::partial_sum(sizesBeginning, sizesEnd, std::back_inserter(_delimiters));
}


template<typename _T>
template<typename SizeForwardIter>
inline
void
PackedArrayOfArrays<_T>::
rebuild(SizeForwardIter sizesBeginning, SizeForwardIter sizesEnd) {
   _delimiters.resize(1);
   _delimiters[0] = 0;
   std::partial_sum(sizesBeginning, sizesEnd, std::back_inserter(_delimiters));
   Base::resize(_delimiters.back());
}


template<typename _T>
inline
void
PackedArrayOfArrays<_T>::
put(std::ostream& out) const {
   out << numArrays() << " " << size() << '\n';
   for (typename Base::size_type n = 0; n != numArrays(); ++n) {
      out << size(n) << '\n';
      std::copy(begin(n), end(n),
                std::ostream_iterator<typename Base::value_type>(out, " "));
      out << '\n';
   }
}

template<typename _T>
inline
void
PackedArrayOfArrays<_T>::
get(std::istream& in) {
   std::size_t numberOfArrays, numberOfElements, sz;
   in >> numberOfArrays >> numberOfElements;
   Base::resize(numberOfElements);
   _delimiters.resize(numberOfArrays + 1);

   _delimiters[0] = 0;
   for (typename Base::size_type n = 0; n != numberOfArrays; ++n) {
      in >> sz;
      _delimiters[n + 1] = _delimiters[n] + sz;
      for (typename Base::size_type m = 0; m != sz; ++m) {
         in >> operator()(n, m);
      }
   }
}

} // namespace array
