diff --git a/src/catacharset.cpp b/src/catacharset.cpp index d3018825249dd..e0a4288281505 100644 --- a/src/catacharset.cpp +++ b/src/catacharset.cpp @@ -415,21 +415,31 @@ std::u32string utf8_to_utf32( const std::string_view str ) std::vector utf8_display_split( const std::string &s ) { std::vector result; - std::string current_glyph; + std::vector parts; + utf8_display_split_into( s, parts ); + result.reserve( parts.size() ); + for( std::string_view part : parts ) { + result.emplace_back( part ); + } + return result; +} + +void utf8_display_split_into( const std::string &s, std::vector &result ) +{ const char *pos = s.c_str(); + const char *glyph_begin = pos; + const char *glyph_end = pos; int len = s.length(); while( len > 0 ) { - const char *old_pos = pos; const uint32_t ch = UTF8_getch( &pos, &len ); const int width = mk_wcwidth( ch ); - if( width > 0 && !current_glyph.empty() ) { - result.push_back( current_glyph ); - current_glyph.clear(); + if( width > 0 && glyph_begin != glyph_end ) { + result.push_back( std::string_view( glyph_begin, std::distance( glyph_begin, glyph_end ) ) ); + glyph_begin = glyph_end; } - current_glyph += std::string( old_pos, pos ); + glyph_end = pos; } - result.push_back( current_glyph ); - return result; + result.push_back( std::string_view( glyph_begin, std::distance( glyph_begin, glyph_end ) ) ); } int center_text_pos( const char *text, int start_pos, int end_pos ) diff --git a/src/catacharset.h b/src/catacharset.h index c93e3f7401bf3..a12432f930bc2 100644 --- a/src/catacharset.h +++ b/src/catacharset.h @@ -59,6 +59,7 @@ std::u32string utf8_to_utf32( std::string_view str ); // Split the given string into displayed characters. Each element of the returned vector // contains one 'regular' codepoint and all subsequent combining characters. std::vector utf8_display_split( const std::string & ); +void utf8_display_split_into( const std::string &, std::vector & ); /** * UTF8-Wrapper over std::string. diff --git a/src/mapgen.cpp b/src/mapgen.cpp index 442ec509449f3..ed8b070fe1915 100644 --- a/src/mapgen.cpp +++ b/src/mapgen.cpp @@ -4491,10 +4491,10 @@ bool mapgen_function_json_base::setup_common( const JsonObject &jo ) } for( int c = m_offset.y; c < expected_dim.y; c++ ) { const std::string row = parray.get_string( c ); - std::vector row_keys; - for( const std::string &key : utf8_display_split( row ) ) { - row_keys.emplace_back( key ); - } + static std::vector row_keys; + row_keys.clear(); + row_keys.reserve( total_size.x ); + utf8_display_split_into( row, row_keys ); if( row_keys.size() < static_cast( expected_dim.x ) ) { parray.throw_error( string_format( " format: row %d must have at least %d columns, not %d", @@ -4507,7 +4507,7 @@ bool mapgen_function_json_base::setup_common( const JsonObject &jo ) } for( int i = m_offset.x; i < expected_dim.x; i++ ) { const point p = point( i, c ) - m_offset; - const map_key key = row_keys[i]; + const map_key key{ std::string( row_keys[i] ) }; const auto iter_ter = keys_with_terrain.find( key ); const auto fpi = format_placings.find( key );