34 namespace StringWrapImp
38 std::string_view prefix_first ;
39 std::string_view prefix_other ;
40 std::size_t width_first ;
41 std::size_t width_other ;
42 bool preserve_spaces ;
47 WordWrapper( std::ostream & , Config ) ;
48 void emit(
const std::string & word , std::size_t newlines ,
const std::string & prespace ) ;
51 ~WordWrapper() = default ;
52 WordWrapper(
const WordWrapper & ) = delete ;
53 WordWrapper( WordWrapper && ) = delete ;
54 WordWrapper & operator=(
const WordWrapper & ) = delete ;
55 WordWrapper & operator=( WordWrapper && ) = delete ;
58 std::string_view prefix()
const ;
61 std::size_t m_lines {0U} ;
62 std::size_t m_w {0U} ;
63 std::ostream & m_out ;
66 void wrapImp( std::istream & , WordWrapper & ) ;
72G::StringWrapImp::WordWrapper::WordWrapper( std::ostream & out , Config config ) :
78std::string_view G::StringWrapImp::WordWrapper::prefix()
const
80 return m_lines ? m_config.prefix_other : m_config.prefix_first ;
83void G::StringWrapImp::WordWrapper::emit(
const std::string & word , std::size_t newlines ,
const std::string & prespace )
86 std::size_t wordsize = StringWrap::wordsize( word ) ;
87 std::size_t spacesize = m_config.preserve_spaces ? prespace.size() : 1U ;
88 std::size_t width = ( newlines || m_lines > 1 ) ? m_config.width_other : m_config.width_first ;
89 bool start_new_line = newlines || m_w == 0 || (m_w+spacesize+wordsize) > width ;
93 bool first_line = m_w == 0 ;
94 for( std::size_t i = 1U ; i < newlines ; i++ )
96 m_out << (first_line?
"":
"\n") << prefix() ;
98 m_w = prefix().size() ;
103 m_out << (first_line?
"":
"\n") << prefix() << word ;
104 m_w = prefix().size() + wordsize ;
109 if( m_config.preserve_spaces )
110 m_out << (prespace.empty()?std::string(1U,
' '):prespace) << word ;
112 m_out <<
" " << word ;
113 m_w += (spacesize+wordsize) ;
120 const std::string & prefix_first ,
const std::string & prefix_other ,
121 std::size_t width_first , std::size_t width_other ,
122 bool preserve_spaces )
124 StringWrapImp::Config config {
127 width_first , width_other?width_other:width_first ,
131 std::ostringstream out ;
132 StringWrapImp::WordWrapper wrapper( out , config ) ;
134 imembuf buf( text_in.data() , text_in.size() ) ;
135 std::istream in( &buf ) ;
137 StringWrapImp::wrapImp( in , wrapper ) ;
142void G::StringWrapImp::wrapImp( std::istream & in , WordWrapper & ww )
146 std::size_t newlines = 0U ;
147 std::string prespace ;
151 if( c ==
' ' || c ==
'\n' )
156 ww.emit( word , newlines , prespace ) ;
170 prespace.append( 1U , c ) ;
175 word.append( 1U , c ) ;
180 ww.emit( word , newlines , prespace ) ;
186 const unsigned char * p =
reinterpret_cast<const unsigned char*
>( s.data() ) ;
187 std::size_t n = s.size() ;
188 std::size_t result = 0U ;
190 for( std::size_t i = 0U ; i < n ; i += d , p += d )
193 if( ( p[0] & 0x80U ) == 0U )
197 else if( ( p[0] & 0xE0U ) == 0xC0U && (i+1U) < n &&
198 ( p[1] & 0xC0 ) == 0x80U )
202 else if( ( p[0] & 0xF0U ) == 0xE0U && (i+2U) < n &&
203 ( p[1] & 0xC0 ) == 0x80U &&
204 ( p[2] & 0xC0 ) == 0x80U )
208 else if( ( p[0] & 0xF8U ) == 0xF0U && (i+3U) < n &&
209 ( p[1] & 0xC0 ) == 0x80U &&
210 ( p[2] & 0xC0 ) == 0x80U &&
211 ( p[3] & 0xC0 ) == 0x80U )
static std::size_t wordsize(const std::string &)
Returns the number of characters in UTF-8 text.
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)
Does word-wrapping of UTF-8 text.
An input streambuf that takes its data from a fixed-size const buffer.