35 std::size_t width_first ;
36 std::size_t width_other ;
37 bool preserve_spaces ;
44 void emit(
const std::string & word , std::size_t newlines ,
const std::string & prespace ) ;
57 std::size_t m_lines {0U} ;
58 std::size_t m_w {0U} ;
59 std::ostream & m_out ;
61 const std::locale & m_loc ;
66G::StringWrap::WordWrapper::WordWrapper( std::ostream & out ,
Config config ,
const std::locale & loc ) :
75 return m_lines ? m_config.prefix_other : m_config.prefix_first ;
78void G::StringWrap::WordWrapper::emit(
const std::string & word , std::size_t newlines ,
const std::string & prespace )
82 std::size_t spacesize = m_config.preserve_spaces ? prespace.size() : 1U ;
83 std::size_t width = ( newlines || m_lines > 1 ) ? m_config.width_other : m_config.width_first ;
84 bool start_new_line = newlines || m_w == 0 || (m_w+spacesize+
wordsize) > width ;
88 bool first_line = m_w == 0 ;
89 for( std::size_t i = 1U ; i < newlines ; i++ )
91 m_out << (first_line?
"":
"\n") << prefix() ;
93 m_w = prefix().size() ;
98 m_out << (first_line?
"":
"\n") << prefix() << word ;
104 if( m_config.preserve_spaces )
105 m_out << (prespace.empty()?std::string(1U,
' '):prespace) << word ;
107 m_out <<
" " << word ;
115 const std::string & prefix_first ,
const std::string & prefix_other ,
116 std::size_t width_first , std::size_t width_other ,
117 bool preserve_spaces ,
const std::locale & loc )
120 { prefix_first.data() , prefix_first.size() } ,
121 { prefix_other.data() , prefix_other.size() } ,
122 width_first , width_other?width_other:width_first ,
126 std::ostringstream out ;
129 imembuf buf( text_in.data() , text_in.size() ) ;
130 std::istream in( &buf ) ;
133 wrap( in , wrapper ) ;
141 const auto & cctype = std::use_facet<std::ctype<char>>( in.getloc() ) ;
143 std::size_t newlines = 0U ;
144 std::string prespace ;
148 if( cctype.is( std::ctype_base::space , c ) )
153 ww.emit( word , newlines , prespace ) ;
167 prespace.append( 1U , c ) ;
172 word.append( 1U , c ) ;
177 ww.emit( word , newlines , prespace ) ;
185 return std::locale( std::setlocale(LC_CTYPE,
nullptr) ) ;
187 catch( std::exception & )
189 return std::locale::classic() ;
208 const auto & codecvt = std::use_facet<std::codecvt<char32_t,char,std::mbstate_t>>( loc ) ;
209 std::vector<char32_t> warray( s.size() ) ;
210 std::mbstate_t state {} ;
211 const char * cnext = nullptr ;
212 char32_t * wnext = nullptr ;
213 auto rc = codecvt.in( state ,
214 s.data() , s.end() , cnext ,
215 &warray[0] , &warray[0]+warray.size() , wnext ) ;
216 std::size_t din = cnext ? std::distance( s.data() , cnext ) : 0U ;
217 std::size_t dout = wnext ? std::distance( &warray[0] , wnext ) : 0U ;
218 return ( rc == std::codecvt_base::ok && din == s.size() && dout ) ? dout : s.size() ;
220 catch( std::exception & )
Private implementation structure for G::StringWrap.
static std::locale defaultLocale()
Returns a locale with at least the CTYPE and codecvt facets initialised according to the C locale's C...
static std::size_t wordsize(const std::string &mbcs, const std::locale &)
Returns the number of wide characters after converting the input string using the locale's codecvt fa...
static std::string wrap(const std::string &text, const std::string &prefix_first, const std::string &prefix_other, std::size_t width_first=70U, std::size_t width_other=0U, bool preserve_spaces=false, const std::locale &=defaultLocale())
Does word-wrapping.
An input streambuf that takes its data from a fixed-size const buffer.
A class template like c++17's std::basic_string_view.
Private implementation structure for G::StringWrap.