44
55#pragma once
66
7+ #include " gl/attributes/force_inline.hpp"
78#include " gl/constants.hpp"
89#include " gl/graph_traits.hpp"
910#include " gl/impl/impl_tags.hpp"
11+ #include " gl/io/graph_fmt_traits.hpp"
1012#include " gl/io/options.hpp"
1113#include " gl/io/stream_options_manipulator.hpp"
1214#include " gl/util/ranges.hpp"
@@ -633,22 +635,17 @@ class graph final {
633635 friend std::ostream& operator <<(std::ostream& os, const graph& g) {
634636 using io::detail::option_bit;
635637
636- if (io::is_option_set (os, option_bit::specification_fmt)) {
637- g._gsf_write (os);
638- return os;
639- }
638+ if (io::is_option_set (os, option_bit::specification_fmt))
639+ return g._gsf_write (os);
640640
641641 if (io::is_option_set (os, option_bit::verbose))
642- g._verbose_write (os);
642+ return g._verbose_write (os);
643643 else
644- g._concise_write (os);
645-
646- return os;
644+ return g._concise_write (os);
647645 }
648646
649- friend inline std::istream& operator >>(std::istream& is, graph& g) {
650- g._gsf_read (is);
651- return is;
647+ friend gl_attr_force_inline std::istream& operator >>(std::istream& is, graph& g) {
648+ return g._gsf_read (is);
652649 }
653650
654651 // --- friend declarations ---
@@ -663,6 +660,8 @@ class graph final {
663660 friend struct detail ::to_impl;
664661
665662private:
663+ using fmt_traits = io::detail::graph_fmt_traits<directional_tag>;
664+
666665 graph (const graph& other)
667666 : _n_vertices{other._n_vertices }, _n_edges{other._n_edges }, _impl{other._impl } {
668667 // Deep copy vertex properties
@@ -682,11 +681,7 @@ class graph final {
682681 }
683682 }
684683
685- [[nodiscard]] static constexpr std::string _directed_type_str () {
686- return traits::c_directed_edge<edge_type> ? " directed" : " undirected" ;
687- }
688-
689- // --- graph element verification methods ---
684+ // --- element validation ---
690685
691686 gl_attr_force_inline void _verify_vertex_id (const id_type vertex_id) const {
692687 if (not this ->has_vertex (vertex_id))
@@ -704,7 +699,7 @@ class graph final {
704699 ));
705700 }
706701
707- // --- vertex methods ---
702+ // --- vertex modifiers ---
708703
709704 void _remove_vertex_impl (const id_type vertex_id) {
710705 const auto removed_edge_ids = this ->_impl .remove_vertex (vertex_id);
@@ -721,35 +716,37 @@ class graph final {
721716 }
722717 }
723718
724- // --- io methods ---
725-
726- void _verbose_write (std::ostream& os) const {
727- os << std::format (
728- " type: {}\n number of vertices: {}\n number of edges: {}\n vertices:\n " ,
729- _directed_type_str (),
730- this ->order (),
731- this ->size ()
732- );
719+ // --- I/O utility ---
733720
721+ std::ostream& _verbose_write (std::ostream& os) const {
722+ os << " type: " << fmt_traits::type << " , |V| = " << this ->order ()
723+ << " , |E| = " << this ->size () << ' \n ' ;
734724 for (const auto & vertex : this ->vertices ()) {
735- os << " - " << vertex << " \n incident edges :\n " ;
725+ os << " - " << vertex << " \n " << fmt_traits::out_edges << " :\n " ;
736726 for (const auto & edge : this ->out_edges (vertex.id ()))
737727 os << " \t - " << edge << ' \n ' ;
738728 }
729+ return os;
739730 }
740731
741- void _concise_write (std::ostream& os) const {
742- os << std::format ( " {} {} {} \n " , _directed_type_str (), this -> order (), this -> size ()) ;
732+ std::ostream& _concise_write (std::ostream& os) const {
733+ using io::detail::option_bit ;
743734
744- for (const auto & vertex : this ->vertices ()) {
745- os << " - " << vertex << " :" ;
746- for (const auto & edge : this ->out_edges (vertex.id ()))
747- os << ' ' << edge;
735+ for (const auto & src : this ->vertices ()) {
736+ os << src << " :" ;
737+ for (const auto & edge : this ->out_edges (src.id ())) {
738+ os << ' ' << edge.other (src.id ());
739+ if constexpr (traits::c_writable<edge_properties_type>)
740+ if (io::is_option_set (os, option_bit::with_connection_properties))
741+ os << ' [' << edge.properties () << ' ]' ;
742+ }
748743 os << ' \n ' ;
749744 }
745+
746+ return os;
750747 }
751748
752- void _gsf_write (std::ostream& os) const {
749+ std::ostream& _gsf_write (std::ostream& os) const {
753750 using io::detail::option_bit;
754751
755752 const bool with_vertex_properties =
@@ -767,12 +764,12 @@ class graph final {
767764 static_cast <int >(with_edge_properties)
768765 );
769766
770- if constexpr (traits::c_writable<typename vertex_type::properties_type >)
767+ if constexpr (traits::c_writable<vertex_properties_type >)
771768 if (with_vertex_properties)
772769 for (const auto & vertex : this ->vertices ())
773770 os << vertex.properties () << ' \n ' ;
774771
775- if constexpr (traits::c_writable<typename edge_type::properties_type >) {
772+ if constexpr (traits::c_writable<edge_properties_type >) {
776773 if (with_edge_properties) {
777774 const auto print_out_edges = [this , &os](const id_type vertex_id) {
778775 for (const auto & edge : this ->out_edges (vertex_id)) {
@@ -786,7 +783,7 @@ class graph final {
786783 for (const auto vertex_id : this ->vertex_ids ())
787784 print_out_edges (vertex_id);
788785
789- return ;
786+ return os ;
790787 }
791788 }
792789
@@ -800,16 +797,18 @@ class graph final {
800797
801798 for (const auto vertex_id : this ->vertex_ids ())
802799 print_out_edges (vertex_id);
800+
801+ return os;
803802 }
804803
805- void _gsf_read (std::istream& is) {
804+ std::istream& _gsf_read (std::istream& is) {
806805 bool directed;
807806 is >> directed;
808807
809808 if (directed != traits::c_directed_edge<edge_type>)
810809 throw std::ios_base::failure (std::format (
811810 " Invalid graph specification: directional tag does not match - should be {}" ,
812- _directed_type_str ()
811+ fmt_traits::type
813812 ));
814813
815814 // read initial graph parameters
@@ -866,6 +865,8 @@ class graph final {
866865 this ->add_edge (source_id, target_id);
867866 }
868867 }
868+
869+ return is;
869870 }
870871
871872 size_type _n_vertices = 0uz;
0 commit comments