// Copyright (c) 2009 INRIA Sophia-Antipolis (France). // All rights reserved. // // This file is part of CGAL (www.cgal.org). // // $URL: https://github.com/CGAL/cgal/blob/v5.2/Mesh_3/include/CGAL/internal/Mesh_3/indices_management.h $ // $Id: indices_management.h 9a0f310 2020-07-29T16:40:48+02:00 Laurent Rineau // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // Author(s) : Stéphane Tayeb // //****************************************************************************** // File Description : // // //****************************************************************************** #ifndef CGAL_INTERNAL_MESH_3_INDICES_MANAGEMENT_H #define CGAL_INTERNAL_MESH_3_INDICES_MANAGEMENT_H #include #include #include #include #include #include #include #include #include namespace CGAL { namespace Mesh_3 { namespace internal { // ----------------------------------- // Index_generator // Don't use boost::variant if types are the same type // ----------------------------------- template < typename Subdomain_index, typename Surface_patch_index > struct Index_generator { typedef boost::variant Index; typedef Index type; }; template < typename T > struct Index_generator { typedef T Index; typedef Index type; }; template ::value> struct Indices_tuple_generator { using type = std::tuple; }; template struct Indices_tuple_generator { using type = std::tuple; }; template using Indices_tuple_t = typename Indices_tuple_generator::type; // Nasty meta-programming to get a boost::variant of four types that // may not be all different. template struct seq1 { typedef T0 type; }; template struct seq2 { typedef boost::variant type; }; template struct seq3 { typedef boost::variant type; }; template struct seq4 { typedef boost::variant type; }; template struct insert; template struct insert, U> { typedef seq2 type; }; template struct insert, V> { typedef seq3 type; }; template struct insert, W> { typedef seq4 type; }; template struct insert, T> { typedef seq1 type; }; template struct insert, T> { typedef seq2 type; }; template struct insert, U> { typedef seq2 type; }; template struct insert, T> { typedef seq3 type; }; template struct insert, U> { typedef seq3 type; }; template struct insert, V> { typedef seq3 type; }; template < typename Subdomain_index, typename Surface_patch_index, typename Curves_index, typename Corner_index> struct Index_generator_with_features { typedef typename insert< typename insert< typename insert, Surface_patch_index >::type, Curves_index >::type, Corner_index>::type seq; typedef typename seq::type Index; typedef Index type; }; template < typename T> struct Index_generator_with_features { typedef T Index; typedef Index type; }; template const T& get_index(const Boost_variant& x, typename boost::disable_if >::type * = 0) { return boost::get(x); } template const T& get_index(const T& x) { return x; } template ::value> struct Read_mesh_domain_index { // here we have has_feature==true typedef Mesh_domain MT; // was named "mesh traits" previously typename Mesh_domain::Index operator()(int dimension, std::istream& is) const { switch(dimension) { case 0: typename MT::Corner_index ci; if(is_ascii(is)) is >> ci; else CGAL::read(is, ci); return ci; break; case 1: typename MT::Curve_index si; if(is_ascii(is)) is >> si; else CGAL::read(is, si); return si; break; default: return Read_mesh_domain_index()(dimension, is); } } }; // end template partial specialization // Read_mesh_domain_index template ::value> struct Write_mesh_domain_index { // here we have has_feature==true typedef Mesh_domain MT; // was named "mesh traits" previously typedef typename MT::Corner_index Ci; typedef typename MT::Curve_index Si; void operator()(std::ostream& os, int dimension, const typename Mesh_domain::Index& index) const { switch(dimension) { case 0: { const Ci& ci = get_index(index); if(is_ascii(os)) os << oformat(ci); else CGAL::write(os, ci); } break; case 1: { const Si& si = get_index(index); if(is_ascii(os)) os << oformat(si); else CGAL::write(os, si); } break; default: Write_mesh_domain_index()(os, dimension, index); } } }; // end template partial specialization // Write_mesh_domain_index template struct Read_mesh_domain_index { // here we have has_feature==false typedef Mesh_domain MT; // was named "mesh traits" previously typename Mesh_domain::Index operator()(int dimension, std::istream& is) const { switch(dimension) { case 2: { typename MT::Surface_patch_index spi; if(is_ascii(is)) is >> iformat(spi); else CGAL::read(is, spi); return spi; } break; default: {// 3 typename MT::Subdomain_index di; if(is_ascii(is)) is >> iformat(di); else CGAL::read(is, di); return di; } break; } } }; // end template partial specialization // Read_mesh_domain_index template struct Write_mesh_domain_index { // here we have has_feature==false typedef Mesh_domain MT; // was named "mesh traits" previously typedef typename MT::Surface_patch_index Spi; typedef typename MT::Subdomain_index Di; void operator()(std::ostream& os, int dimension, const typename Mesh_domain::Index& index) const { switch(dimension) { case 2: { const Spi& spi = get_index(index); if(is_ascii(os)) os << oformat(spi); else CGAL::write(os, spi); } break; default: {// 3 const Di& di = get_index(index); if(is_ascii(os)) os << oformat(di); else CGAL::write(os, di); } break; } } }; // end template partial specialization // Write_mesh_domain_index template struct Read_write_index { void operator()(std::ostream& os, int, Index index) const { if(is_ascii(os)) os << oformat(index); else CGAL::write(os, index); } Index operator()(std::istream& is, int) const { Index index; if(is_ascii(is)) is >> iformat(index); else CGAL::read(is, index); return index; } }; struct Variant_write_visitor { std::ostream& os; template void operator()(T v) const { if(is_ascii(os)) os << CGAL::oformat(v); else CGAL::write(os, v); } }; template struct Variant_read_visitor { std::istream& is; Index& variant; template void operator()(T) const { T v; if(is_ascii(is)) is >> CGAL::iformat(v); else CGAL::read(is, v); variant = v; } }; template struct Read_write_index> { using Index = boost::variant; using index_seq = std::make_index_sequence::value>; template Index get_index(int dimension, std::index_sequence) const{ static const Index variants[] = { std::tuple_element_t{}... }; return variants[dimension < 0 ? 0 : 3-dimension]; } void operator()(std::ostream& os, int, Index index) const { Variant_write_visitor visitor{os}; apply_visitor(visitor, index); } Index operator()(std::istream& is, int dimension) const { Index index = get_index(dimension, index_seq{}); Variant_read_visitor visitor{is, index}; apply_visitor(visitor, index); return index; } }; } // end namespace internal } // end namespace Mesh_3 } // end namespace CGAL #endif // CGAL_INTERNAL_MESH_3_INDICES_MANAGEMENT_H