39 std::size_t width_first ;
40 std::size_t width_other ;
41 bool preserve_spaces ;
48 void emit(
const std::string & word , std::size_t newlines ,
const std::string & prespace ) ;
61 std::size_t m_lines {0U} ;
62 std::size_t m_w {0U} ;
63 std::ostream & m_out ;
65 const std::locale & m_loc ;
70G::StringWrap::WordWrapper::WordWrapper( std::ostream & out ,
Config config ,
const std::locale & loc ) :
79 return m_lines ? m_config.prefix_other : m_config.prefix_first ;
82void G::StringWrap::WordWrapper::emit(
const std::string & word , std::size_t newlines ,
const std::string & prespace )
86 std::size_t spacesize = m_config.preserve_spaces ? prespace.size() : 1U ;
87 std::size_t width = ( newlines || m_lines > 1 ) ? m_config.width_other : m_config.width_first ;
88 bool start_new_line = newlines || m_w == 0 || (m_w+spacesize+
wordsize) > width ;
92 bool first_line = m_w == 0 ;
93 for( std::size_t i = 1U ; i < newlines ; i++ )
95 m_out << (first_line?
"":
"\n") << prefix() ;
97 m_w = prefix().size() ;
102 m_out << (first_line?
"":
"\n") << prefix() << word ;
108 if( m_config.preserve_spaces )
109 m_out << (prespace.empty()?std::string(1U,
' '):prespace) << word ;
111 m_out <<
" " << word ;
119 const std::string & prefix_first ,
const std::string & prefix_other ,
120 std::size_t width_first , std::size_t width_other ,
121 bool preserve_spaces ,
const std::locale & loc )
126 width_first , width_other?width_other:width_first ,
130 std::ostringstream out ;
133 imembuf buf( text_in.data() , text_in.size() ) ;
134 std::istream in( &buf ) ;
137 wrap( in , wrapper ) ;
145 const auto & cctype = std::use_facet<std::ctype<char>>( in.getloc() ) ;
147 std::size_t newlines = 0U ;
148 std::string prespace ;
152 if( cctype.is( std::ctype_base::space , c ) )
157 ww.emit( word , newlines , prespace ) ;
171 prespace.append( 1U , c ) ;
176 word.append( 1U , c ) ;
181 ww.emit( word , newlines , prespace ) ;
189 return std::locale( std::setlocale(LC_CTYPE,
nullptr) ) ;
191 catch( std::exception & )
193 return std::locale::classic() ;
212 const auto & codecvt = std::use_facet<std::codecvt<char32_t,char,std::mbstate_t>>( loc ) ;
213 std::vector<char32_t> warray( s.size() ) ;
214 std::mbstate_t state {} ;
215 const char * cnext = nullptr ;
216 char32_t * wnext = nullptr ;
217 auto rc = codecvt.in( state ,
218 s.data() , s.end() , cnext ,
219 &warray[0] , &warray[0]+warray.size() , wnext ) ;
220 std::size_t din = cnext ? std::distance( s.data() , cnext ) : 0U ;
221 std::size_t dout = wnext ? std::distance( &warray[0] , wnext ) : 0U ;
222 return ( rc == std::codecvt_base::ok && din == s.size() && dout ) ? dout : s.size() ;
224 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 like c++17's std::string_view.
Private implementation structure for G::StringWrap.