SNC_io_parser<EW>::SNC_io_parser(std::ostream& os, SNC_structure& W,
                                 bool sort, bool reduce_) :
  Base(W), in(std::cin), out(os),
  FI(W.halffacets_begin(),W.halffacets_end(),'F'),
  CI(W.volumes_begin(),W.volumes_end(),'C'),
  SEI(W.shalfedges_begin(),W.shalfedges_end(),'e'),
  SLI(W.shalfloops_begin(),W.shalfloops_end(),'l'),
  SFI(W.sfaces_begin(),W.sfaces_end(),'f'),
  vn(W.number_of_vertices()),
  en(W.number_of_halfedges()),
  fn(W.number_of_halffacets()),
  cn(W.number_of_volumes()),
  sen(W.number_of_shalfedges()),
  sln(W.number_of_shalfloops()),
  sfn(W.number_of_sfaces())
{
  verbose = (get_mode(out) != CGAL::IO::ASCII &&
             get_mode(out) != CGAL::IO::BINARY);
  sorted = sort;
  reduce = reduce_;
  reduce = reduce && this->is_extended_kernel() && this->is_bounded();
  sorted = sorted || reduce;

  Vertex_iterator vi;
  CGAL_forall_vertices(vi, *this->sncp()) {
    VL.push_back(vi);
    if(sorted) {
      vi->point() = normalized(vi->point());
      if(vi->has_shalfloop() &&
         sort_sloops<SNC_structure>(*this->sncp())(vi->shalfloop()->twin(),
                                                   vi->shalfloop()))
        vi->shalfloop() = vi->shalfloop()->twin();
    }
  }
  if(sorted) {
    VL.sort(sort_vertices<SNC_structure>(*this->sncp()));
  }
  if(reduce)
    for(int k=0; k<4; k++){
      VL.pop_front(); VL.pop_back();
    }
  int i = 0;
  typename std::list<Vertex_iterator>::iterator vl;
  for(vl = VL.begin(); vl != VL.end(); vl++)
    VI[*vl] = i++;

  SM_decorator SD;
  Halfedge_iterator ei;
  CGAL_forall_halfedges(ei, *this->sncp()) {
    EL.push_back(ei);
    if(sorted) {
      //      std::cerr << ei->point() << " | " << normalized(ei->point()) << " |";
      ei->point() = normalized(ei->point());
      //      std::cerr << ei->point() << std::endl;
      sort_sedges<SNC_structure> sortSE(*this->sncp());
      SHalfedge_handle new_outedge = ei->out_sedge();
      SHalfedge_around_svertex_circulator cb(new_outedge), ce(cb);
      CGAL_For_all(cb,ce) {
        if(cb != new_outedge && sortSE(cb,new_outedge))
          new_outedge = cb;
      }
      ei->out_sedge() = new_outedge;
    }
  }
  if(sorted) EL.sort(sort_edges<SNC_structure>(*this->sncp()));
  if(reduce)
    for(int k=0; k<12; k++){
      EL.pop_front(); EL.pop_back();
    }
  i = 0;
  typename std::list<Halfedge_iterator>::iterator el;
  for(el = EL.begin(); el != EL.end(); el++)
    EI[*el] = i++;

  Halffacet_iterator fi;
  CGAL_forall_halffacets(fi, *this->sncp()){
    if(sorted) {
      sort_sedges<SNC_structure> sortSE(*this->sncp());
      Halffacet_cycle_iterator fc;
      for(fc = fi->facet_cycles_begin();
          fc != fi->facet_cycles_end(); ++fc) {
        if(fc.is_shalfedge()) {
          SHalfedge_handle se(fc);
          if(this->sncp()->is_boundary_object(se))
            this->sncp()->undef_boundary_item(se);
          SHalfedge_around_facet_circulator sfc(fc), send(sfc);
          CGAL_For_all(sfc, send) {
            if(sortSE(sfc, se))
              se = sfc;
          }
          this->sncp()->store_boundary_item(se,fc);
          *fc = make_object(se);
        }
      }
      fi->plane() = normalized(fi->plane());
      fi->boundary_entry_objects().sort(sort_facet_cycle_entries<Base>((Base) *this));
    }
    FL.push_back(fi);
  }
  if(sorted) FL.sort(sort_facets<SNC_structure>(*this->sncp()));
  if(reduce) {
    for(int k=0; k<6; k++){
      FL.pop_front();
      FL.pop_back();
    }
  }
  i = 0;
  typename std::list<Halffacet_iterator>::iterator fl;
  for(fl = FL.begin(); fl != FL.end(); fl++)
    FI[*fl] = i++;

  SHalfedge_iterator sei;
  CGAL_forall_shalfedges(sei, *this->sncp()) {
    SEL.push_back(sei);
    if(sorted)
      sei->circle() = normalized(sei->circle());
  }
  if(sorted) SEL.sort(sort_sedges<SNC_structure>(*this->sncp()));
  if(reduce)
    for(int k=0; k<24; k++){
      SEL.pop_front(); SEL.pop_back();
    }
  i = 0;
  typename std::list<SHalfedge_iterator>::iterator sel;
  for(sel = SEL.begin(); sel != SEL.end(); sel++)
    SEI[*sel] = i++;

  SHalfloop_iterator sli;
  CGAL_forall_shalfloops(sli, *this->sncp()) {
    SLL.push_back(sli);
    if(sorted)
      sli->circle() = normalized(sli->circle());
  }
  if(sorted) SLL.sort(sort_sloops<SNC_structure>(*this->sncp()));
  i = 0;
  typename std::list<SHalfloop_iterator>::iterator sll;
  for(sll = SLL.begin(); sll != SLL.end(); sll++)
    SLI[*sll] = i++;

  SFace_iterator sfi;
  CGAL_forall_sfaces(sfi, *this->sncp()) {
    if(sorted) {
      SFace_cycle_iterator fc;
      CGAL_forall_sface_cycles_of(fc, sfi) {
        if(fc.is_shalfedge()) {
          SHalfedge_handle se(fc);
          if(this->sncp()->is_sm_boundary_object(se))
            this->sncp()->undef_sm_boundary_item(se);
          SHalfedge_around_sface_circulator cb(se), ce(cb);
          CGAL_For_all(cb,ce) {
            if(cb->source() != se->source()) {
              if(lexicographically_xyz_smaller(cb->source()->twin()->source()->point(),
                                               se->source()->twin()->source()->point()))
                se = cb;
            }
            else
              if(lexicographically_xyz_smaller(cb->twin()->source()->twin()->source()->point(),
                                               se->twin()->source()->twin()->source()->point()))
                se = cb;
          }
          this->sncp()->store_sm_boundary_item(se,fc);
          *fc = make_object(se);
        }
      }
      sfi->boundary_entry_objects().sort(sort_sface_cycle_entries<Base>((Base) *this));
    }
    SFL.push_back(sfi);
  }
  if(sorted) SFL.sort(sort_sfaces<SNC_structure>(*this->sncp()));
  if(reduce)
    for(int k=0; k<8; k++){
      SFL.pop_front(); SFL.pop_back();
    }
  i = 0;
  typename std::list<SFace_iterator>::iterator sfl;
  for(sfl = SFL.begin(); sfl != SFL.end(); sfl++)
    SFI[*sfl] = i++;

  Volume_iterator ci;
  CGAL::Unique_hash_map<SFace_handle,bool> Done(false);
  find_minimal_sface_of_shell<SNC_structure> findMinSF(*this->sncp(),Done);
  CGAL_forall_volumes(ci, *this->sncp()) {
    if(sorted) {
      Shell_entry_iterator it;
      CGAL_forall_shells_of(it,ci) {
        findMinSF.minimal_sface() = SFace_handle(it);
        visit_shell_objects(SFace_handle(it),findMinSF);
        *it = make_object(findMinSF.minimal_sface());
      }
      ci->shell_entry_objects().sort(sort_shell_entries<Base>((Base)*this));
    }
    CL.push_back(ci);
  }

  if(sorted) CL.sort(sort_volumes<SNC_structure>(*this->sncp()));
  if(reduce)
    CL.pop_front();
  i = 0;
  typename std::list<Volume_iterator>::iterator cl;
  for(cl = CL.begin(); cl != CL.end(); cl++)
    CI[*cl] = i++;

  VI[W.vertices_end()]=-2;
  EI[W.halfedges_end()]=-2;
  FI[W.halffacets_end()]=-2;
  CI[W.volumes_end()]=-2;
  SEI[W.shalfedges_end()]=-2;
  SLI[W.shalfloops_end()]=-2;
  SFI[W.sfaces_end()]=-2;
}