Fixes Haiku performance issues.

This commit is contained in:
Martín Lucas Golini
2024-10-20 04:09:20 -03:00
parent 2bb66d2e40
commit 66002c3db8
23 changed files with 135 additions and 69 deletions

View File

@@ -1,16 +1,19 @@
#ifndef EE_STRING_HPP
#define EE_STRING_HPP
#include <charconv>
#include <cstdlib>
#include <cstring>
#include <eepp/config.hpp>
#include <eepp/core/utf.hpp>
#include <limits>
#include <locale>
#include <sstream>
#include <string>
#include <string_view>
#include <vector>
#include <eepp/config.hpp>
#include <eepp/core/utf.hpp>
namespace EE {
template <typename T> struct FormatArg {
@@ -342,19 +345,41 @@ class EE_API String {
const std::string& prepend = "", size_t digitsAfterComma = 2 );
/** Converts from a string to type */
template <class T>
static bool fromString( T& t, const std::string& s,
std::ios_base& ( *f )( std::ios_base& ) = std::dec ) {
std::istringstream iss( s );
return !( iss >> f >> t ).fail();
template <typename T> static bool fromString( T& t, const std::string& s, int base = 10 ) {
const char* begin = s.data();
const char* end = s.data() + s.size();
if constexpr ( std::is_integral_v<T> && std::is_signed_v<T> ) {
long long value = 0;
std::from_chars_result result = std::from_chars( begin, end, value, base );
if ( result.ec == std::errc{} && result.ptr == end &&
value >= std::numeric_limits<T>::min() &&
value <= std::numeric_limits<T>::max() ) {
t = static_cast<T>( value );
return true;
}
return false;
} else if constexpr ( std::is_integral_v<T> && std::is_unsigned_v<T> ) {
unsigned long long value = 0;
std::from_chars_result result = std::from_chars( begin, end, value, base );
if ( result.ec == std::errc{} && result.ptr == end &&
value <= std::numeric_limits<T>::max() ) {
t = static_cast<T>( value );
return true;
}
return false;
} else if constexpr ( std::is_same_v<T, float> || std::is_same_v<T, double> ) {
std::from_chars_result result = std::from_chars( begin, end, t );
bool res = result.ec == std::errc{} && result.ptr == end;
return res;
} else {
static_assert( false, "String::fromString not implemented for this type" );
}
}
/** Converts from a String to type */
template <class T>
static bool fromString( T& t, const String& s,
std::ios_base& ( *f )( std::ios_base& ) = std::dec ) {
std::istringstream iss( s.toUtf8() );
return !( iss >> f >> t ).fail();
template <typename T> static bool fromString( T& t, const String& s, int base = 10 ) {
return fromString( t, s.toUtf8(), base );
}
template <typename... Args>

View File

@@ -78,6 +78,10 @@ class EE_API PixelDensity {
static Float toDpFromStringI( const std::string& str );
static Float toPxFromString( const std::string& str );
static Float toPxFromStringI( const std::string& str );
protected:
static Float sPixelDensity;
};

View File

@@ -77,7 +77,7 @@ class EE_API StyleSheetProperty {
template <typename Type> Type asType( Type defaultValue ) const {
Type val = defaultValue;
return String::fromString<Type>( val, mValue ) ? val : defaultValue;
return String::fromString( val, mValue ) ? val : defaultValue;
}
int asInt( int defaultValue = 0 ) const;

View File

@@ -6,7 +6,6 @@
#include <eepp/core/utf.hpp>
#include <iostream>
#include <iterator>
#include <limits>
#include <random>
#include <thirdparty/utf8cpp/utf8.h>
@@ -351,7 +350,7 @@ String String::unescape( const String& str ) {
}
if ( buffer.size() >= len ) {
Uint32 value;
if ( String::fromString( value, buffer, std::hex ) )
if ( String::fromString( value, buffer, 16 ) )
output.push_back( value );
}
}
@@ -370,7 +369,7 @@ String String::unescape( const String& str ) {
}
if ( buffer.size() == len ) {
Uint32 value;
if ( String::fromString( value, buffer, std::hex ) )
if ( String::fromString( value, buffer, 16 ) )
output.push_back( value );
}
}
@@ -396,7 +395,7 @@ String String::unescape( const String& str ) {
}
if ( buffer.size() <= 3 ) {
Uint32 value;
if ( String::fromString( value, buffer, std::oct ) )
if ( String::fromString( value, buffer, 8 ) )
output.push_back( value );
}
break;

View File

@@ -161,7 +161,7 @@ Float PixelDensity::toDpFromString( const std::string& str ) {
if ( !num.empty() ) {
Float val = 0;
bool res = String::fromString<Float>( val, num );
bool res = String::fromString( val, num );
if ( res ) {
if ( unit == "dp" || unit == "dip" ) {
@@ -181,4 +181,38 @@ Float PixelDensity::toDpFromStringI( const std::string& str ) {
return (Int32)toDpFromString( str );
}
Float PixelDensity::toPxFromString( const std::string& str ) {
std::string num;
std::string unit;
for ( std::size_t i = 0; i < str.size(); i++ ) {
if ( String::isNumber( str[i], true ) || ( '-' == str[i] && i == 0 ) ||
( '+' == str[i] && i == 0 ) ) {
num += str[i];
} else {
unit = str.substr( i );
break;
}
}
if ( !num.empty() ) {
Float val = 0;
bool res = String::fromString( val, num );
if ( res ) {
if ( unit == "dp" || unit == "dip" ) {
return dpToPx( val );
} else {
return val;
}
}
}
return 0;
}
Float PixelDensity::toPxFromStringI( const std::string& str ) {
return (Int32)toPxFromString( str );
}
}} // namespace EE::Graphics

View File

@@ -35,10 +35,10 @@ ios_size HttpStreamChunked::write( const char* data, ios_size size ) {
if ( lenEnd != std::string::npos ) {
std::string::size_type firstCharPos = lenEnd + 2;
unsigned long length;
std::size_t length;
// Get the length of the chunk
bool res = String::fromString( length, mChunkBuffer.substr( 0, lenEnd ), std::hex );
bool res = String::fromString( length, mChunkBuffer.substr( 0, lenEnd ), 16 );
// If the length is solved...
if ( res ) {
@@ -75,7 +75,7 @@ ios_size HttpStreamChunked::write( const char* data, ios_size size ) {
if ( lenEnd != std::string::npos ) {
bool res = String::fromString(
length, mChunkBuffer.substr( 0, lenEnd ), std::hex );
length, mChunkBuffer.substr( 0, lenEnd ), 16 );
if ( res && length > 0 ) {
retry = true;

View File

@@ -642,7 +642,7 @@ void URI::parseHostAndPort( std::string::const_iterator& it,
if ( !port.empty() ) {
int nport = 0;
if ( String::fromString<int>( nport, port ) && nport > 0 && nport < 65536 ) {
if ( String::fromString( nport, port ) && nport > 0 && nport < 65536 ) {
mPort = (unsigned short)nport;
} else {
return; // throw SyntaxException("bad or invalid port number", port);

View File

@@ -521,7 +521,7 @@ Color Color::fromString( std::string str ) {
for ( int i = 0; i < 3; i++ ) {
Float val = 0;
if ( String::fromString<Float>( val, functionString.getParameters().at( i ) ) ) {
if ( String::fromString( val, functionString.getParameters().at( i ) ) ) {
switch ( i ) {
case 0:
color.r = static_cast<Uint8>( eemax( eemin( 255.f, val ), 0.f ) );
@@ -542,7 +542,7 @@ Color Color::fromString( std::string str ) {
Float val = 255;
if ( functionString.getParameters().size() >= 4 ) {
if ( String::fromString<Float>( val, functionString.getParameters().at( 3 ) ) ) {
if ( String::fromString( val, functionString.getParameters().at( 3 ) ) ) {
color.a = static_cast<Uint8>( eemax( eemin( 1.f, val ), 0.f ) * 255.f + 0.5f );
} else {
return Color::Transparent;
@@ -558,7 +558,7 @@ Color Color::fromString( std::string str ) {
// Allow creating rgba( #AABBCC, 0.5 )
Color color( Color::fromString( functionString.getParameters()[0] ) );
Float val = 255;
if ( String::fromString<Float>( val, functionString.getParameters().at( 1 ) ) )
if ( String::fromString( val, functionString.getParameters().at( 1 ) ) )
color.a = static_cast<Uint8>( eemax( eemin( 1.f, val ), 0.f ) * 255.f + 0.5f );
return color;
@@ -575,7 +575,7 @@ Color Color::fromString( std::string str ) {
Float hueVal, saturationVal, lightnessVal;
int hueIntVal;
if ( String::fromString<int>( hueIntVal, functionString.getParameters().at( 0 ) ) &&
if ( String::fromString( hueIntVal, functionString.getParameters().at( 0 ) ) &&
hueIntVal >= 0 && hueIntVal <= 360 ) {
hueVal = hueIntVal / 360.f;
} else {
@@ -585,7 +585,7 @@ Color Color::fromString( std::string str ) {
Float saturationFloatVal;
std::string saturationString( functionString.getParameters().at( 1 ) );
String::replaceAll( saturationString, "%", "" );
if ( String::fromString<Float>( saturationFloatVal, saturationString ) &&
if ( String::fromString( saturationFloatVal, saturationString ) &&
saturationFloatVal >= 0 && saturationFloatVal <= 100 ) {
saturationVal = saturationFloatVal / 100.f;
} else {
@@ -595,7 +595,7 @@ Color Color::fromString( std::string str ) {
Float lightnessFloatVal;
std::string lightnessString( functionString.getParameters().at( 2 ) );
String::replaceAll( lightnessString, "%", "" );
if ( String::fromString<Float>( lightnessFloatVal, lightnessString ) &&
if ( String::fromString( lightnessFloatVal, lightnessString ) &&
lightnessFloatVal >= 0 && lightnessFloatVal <= 100 ) {
lightnessVal = lightnessFloatVal / 100.f;
} else {
@@ -605,7 +605,7 @@ Color Color::fromString( std::string str ) {
Float alphaVal = 1;
if ( functionString.getParameters().size() >= 4 ) {
if ( String::fromString<Float>( alphaVal,
if ( String::fromString( alphaVal,
functionString.getParameters().at( 3 ) ) ) {
alphaVal = eemax( eemin( 1.f, alphaVal ), 0.f );
} else {
@@ -632,7 +632,7 @@ Color Color::fromString( std::string str ) {
Float hueVal, saturationVal, valueVal;
int hueIntVal;
if ( String::fromString<int>( hueIntVal, functionString.getParameters().at( 0 ) ) &&
if ( String::fromString( hueIntVal, functionString.getParameters().at( 0 ) ) &&
hueIntVal >= 0 && hueIntVal <= 360 ) {
hueVal = hueIntVal;
} else {
@@ -642,7 +642,7 @@ Color Color::fromString( std::string str ) {
Float saturationFloatVal;
std::string saturationString( functionString.getParameters().at( 1 ) );
String::replaceAll( saturationString, "%", "" );
if ( String::fromString<Float>( saturationFloatVal, saturationString ) &&
if ( String::fromString( saturationFloatVal, saturationString ) &&
saturationFloatVal >= 0 && saturationFloatVal <= 100 ) {
saturationVal = saturationFloatVal / 100.f;
} else {
@@ -652,7 +652,7 @@ Color Color::fromString( std::string str ) {
Float valueFloatVal;
std::string valueString( functionString.getParameters().at( 2 ) );
String::replaceAll( valueString, "%", "" );
if ( String::fromString<Float>( valueFloatVal, valueString ) && valueFloatVal >= 0 &&
if ( String::fromString( valueFloatVal, valueString ) && valueFloatVal >= 0 &&
valueFloatVal <= 100 ) {
valueVal = valueFloatVal / 100.f;
} else {
@@ -662,7 +662,7 @@ Color Color::fromString( std::string str ) {
Float alphaVal = 1;
if ( functionString.getParameters().size() >= 4 ) {
if ( String::fromString<Float>( alphaVal,
if ( String::fromString( alphaVal,
functionString.getParameters().at( 3 ) ) ) {
alphaVal = eemax( eemin( 1.f, alphaVal ), 0.f );
} else {

View File

@@ -172,7 +172,7 @@ void DrawableImageParser::registerBaseParsers() {
} else {
int intVal = 0;
if ( String::fromString( intVal, param ) ) {
if ( PixelDensity::toPxFromStringI( param ) ) {
drawable->setCorners( intVal );
}
}
@@ -362,7 +362,7 @@ void DrawableImageParser::registerBaseParsers() {
if ( !unicodeChar.empty() )
codePoint = unicodeChar[0];
} else if ( String::startsWith( buffer, "0x" ) ) {
if ( String::fromString( value, buffer, std::hex ) )
if ( String::fromString( value, buffer, 16 ) )
codePoint = value;
} else if ( String::fromString( value, buffer ) ) {
codePoint = value;

View File

@@ -317,7 +317,7 @@ StyleSheetLength StyleSheetLength::fromString( const std::string& str, const Flo
if ( !num.empty() ) {
Float val = 0;
if ( String::fromString<Float>( val, num ) )
if ( String::fromString( val, num ) )
length.setValue( val, unitFromString( unit ) );
}

View File

@@ -328,8 +328,8 @@ static OriginPoint toOriginPoint( std::string val ) {
Float x = 0;
Float y = 0;
bool Res1 = String::fromString<Float>( x, String::trim( parts[0] ) );
bool Res2 = String::fromString<Float>( y, String::trim( parts[1] ) );
bool Res1 = String::fromString( x, String::trim( parts[0] ) );
bool Res2 = String::fromString( y, String::trim( parts[1] ) );
if ( Res1 && Res2 ) {
return OriginPoint( x, y );
@@ -407,16 +407,16 @@ Vector2f StyleSheetProperty::asVector2f( const Vector2f& defaultValue ) const {
Float val;
vector.x =
String::fromString<Float>( val, String::trim( xySplit[0] ) ) ? val : defaultValue.x;
String::fromString( val, String::trim( xySplit[0] ) ) ? val : defaultValue.x;
vector.y =
String::fromString<Float>( val, String::trim( xySplit[1] ) ) ? val : defaultValue.y;
String::fromString( val, String::trim( xySplit[1] ) ) ? val : defaultValue.y;
return vector;
} else if ( xySplit.size() == 1 ) {
Float val;
vector.x = vector.y =
String::fromString<Float>( val, xySplit[0] ) ? val : defaultValue.x;
String::fromString( val, xySplit[0] ) ? val : defaultValue.x;
return vector;
}
@@ -434,15 +434,15 @@ Vector2i StyleSheetProperty::asVector2i( const Vector2i& defaultValue ) const {
int val;
vector.x =
String::fromString<int>( val, String::trim( xySplit[0] ) ) ? val : defaultValue.x;
String::fromString( val, String::trim( xySplit[0] ) ) ? val : defaultValue.x;
vector.y =
String::fromString<int>( val, String::trim( xySplit[1] ) ) ? val : defaultValue.y;
String::fromString( val, String::trim( xySplit[1] ) ) ? val : defaultValue.y;
return vector;
} else if ( xySplit.size() == 1 ) {
int val;
vector.x = vector.y = String::fromString<int>( val, xySplit[0] ) ? val : defaultValue.x;
vector.x = vector.y = String::fromString( val, xySplit[0] ) ? val : defaultValue.x;
return vector;
}

View File

@@ -638,7 +638,7 @@ StructuralSelector StyleSheetSpecification::getStructuralSelector( const std::st
if ( nIndex == std::string::npos ) {
// The equation is 0n + b. So a = 0, and we only have to parse b.
a = 0;
if ( String::fromString( t, parameters ) ) {
if ( String::isNumber( parameters ) && String::fromString( t, parameters ) ) {
b = t;
} else {
return StructuralSelector( it->second, 0, 0, FunctionString::parse( name ) );

View File

@@ -161,8 +161,8 @@ void TextureAtlasNew::textureAtlasSave( const Event* Event ) {
if ( !FileSystem::isDirectory( FPath ) ) {
Int32 w = 0, h = 0, b;
bool Res1 = String::fromString<Int32>( w, mComboWidth->getText() );
bool Res2 = String::fromString<Int32>( h, mComboHeight->getText() );
bool Res1 = String::fromString( w, mComboWidth->getText() );
bool Res2 = String::fromString( h, mComboHeight->getText() );
b = static_cast<Int32>( mPixelSpace->getValue() );
Texture::Filter textureFilter = mTextureFilter->getText() == "Nearest"
? Texture::Filter::Nearest

View File

@@ -621,7 +621,7 @@ void UIConsole::cmdShowCursor( const std::vector<String>& params ) {
if ( params.size() >= 2 ) {
Int32 tInt = 0;
bool Res = String::fromString<Int32>( tInt, params[1] );
bool Res = String::fromString( tInt, params[1] );
if ( Res && ( tInt == 0 || tInt == 1 ) ) {
getUISceneNode()->getWindow()->getCursorManager()->setVisible( 0 != tInt );
@@ -636,7 +636,7 @@ void UIConsole::cmdFrameLimit( const std::vector<String>& params ) {
if ( params.size() >= 2 ) {
Int32 tInt = 0;
bool Res = String::fromString<Int32>( tInt, params[1] );
bool Res = String::fromString( tInt, params[1] );
if ( Res && ( tInt >= 0 && tInt <= 10000 ) ) {
getUISceneNode()->getWindow()->setFrameRateLimit( tInt );
@@ -687,7 +687,7 @@ void UIConsole::cmdGrep( const std::vector<String>& params ) {
void UIConsole::cmdSetGamma( const std::vector<String>& params ) {
if ( params.size() >= 2 ) {
Float tFloat = 0.f;
bool Res = String::fromString<Float>( tFloat, params[1] );
bool Res = String::fromString( tFloat, params[1] );
if ( Res && ( tFloat > 0.1f && tFloat <= 10.0f ) ) {
getUISceneNode()->getWindow()->setGamma( tFloat, tFloat, tFloat );
@@ -702,7 +702,7 @@ void UIConsole::cmdSetVolume( const std::vector<String>& params ) {
if ( params.size() >= 2 ) {
Float tFloat = 0.f;
bool Res = String::fromString<Float>( tFloat, params[1] );
bool Res = String::fromString( tFloat, params[1] );
if ( Res && ( tFloat >= 0.0f && tFloat <= 100.0f ) ) {
EE::Audio::Listener::setGlobalVolume( tFloat );
@@ -775,7 +775,7 @@ void UIConsole::cmdShowFps( const std::vector<String>& params ) {
if ( params.size() >= 2 ) {
Int32 tInt = 0;
bool res = String::fromString<Int32>( tInt, params[1] );
bool res = String::fromString( tInt, params[1] );
if ( res && ( tInt == 0 || tInt == 1 ) ) {
mShowFps = 0 != tInt;

View File

@@ -632,7 +632,7 @@ bool UIMenu::applyProperty( const StyleSheetProperty& attribute ) {
switch ( attribute.getPropertyDefinition()->getPropertyId() ) {
case PropertyId::MinIconSize:
setIconMinimumSize( attribute.asSizei() );
setIconMinimumSize( attribute.asDpDimensionSizei() );
break;
default:
return UIWidget::applyProperty( attribute );

View File

@@ -628,7 +628,7 @@ bool UIPushButton::applyProperty( const StyleSheetProperty& attribute ) {
break;
}
case PropertyId::MinIconSize:
setIconMinimumSize( attribute.asSizei() );
setIconMinimumSize( attribute.asDpDimensionSizei() );
break;
case PropertyId::TextAlign: {
std::string align = String::toLower( attribute.value() );

View File

@@ -891,7 +891,7 @@ void UISceneNode::loadGlyphIcon( const StyleSheetStyleVector& styles ) {
std::string buffer( glyphProp.asString() );
Uint32 value;
if ( String::startsWith( buffer, "0x" ) ) {
if ( String::fromString( value, buffer, std::hex ) )
if ( String::fromString( value, buffer, 16 ) )
codePoint = value;
} else if ( String::fromString( value, buffer ) ) {
codePoint = value;

View File

@@ -194,7 +194,7 @@ void UISpinBox::onBufferChange( const Event* ) {
if ( pos != mInput->getText().size() - 1 )
mInput->setText( mInput->getText().substr( 0, mInput->getText().size() - 1 ) );
} else {
bool res = String::fromString<double>( val, mInput->getText() );
bool res = String::fromString( val, mInput->getText() );
if ( res && val != mValue )
setValue( val );
}

View File

@@ -104,10 +104,10 @@ UITheme* UITheme::loadFromTextureAtlas( UITheme* tTheme, Graphics::TextureAtlas*
int l = 0, t = 0, r = 0, b = 0;
if ( srcRect.size() == 4 ) {
String::fromString<int>( l, srcRect[0] );
String::fromString<int>( t, srcRect[1] );
String::fromString<int>( r, srcRect[2] );
String::fromString<int>( b, srcRect[3] );
String::fromString( l, srcRect[0] );
String::fromString( t, srcRect[1] );
String::fromString( r, srcRect[2] );
String::fromString( b, srcRect[3] );
}
std::string skinName( elemNameFromSkin( nameParts ) );
@@ -203,10 +203,10 @@ UITheme* UITheme::loadFromDirectroy( UITheme* tTheme, const std::string& Path,
int l = 0, t = 0, r = 0, b = 0;
if ( srcRect.size() == 4 ) {
String::fromString<int>( l, srcRect[0] );
String::fromString<int>( t, srcRect[1] );
String::fromString<int>( r, srcRect[2] );
String::fromString<int>( b, srcRect[3] );
String::fromString( l, srcRect[0] );
String::fromString( t, srcRect[1] );
String::fromString( r, srcRect[2] );
String::fromString( b, srcRect[3] );
}
std::string skinName( elemNameFromSkin( nameParts ) );

View File

@@ -277,7 +277,7 @@ WindowSettings Engine::createWindowSettings( IniFile* ini, std::string iniKeyNam
pixelDensity = currentDisplay->getPixelDensity();
} else {
float pd = 1;
bool res = String::fromString<float>( pd, pixelDensityStr );
bool res = String::fromString( pd, pixelDensityStr );
if ( res )
pixelDensity = pd;

View File

@@ -1329,7 +1329,7 @@ void EETest::cmdSetPartsNum( const std::vector<String>& params ) {
if ( params.size() >= 2 ) {
Int32 tInt = 0;
bool Res = String::fromString<Int32>( tInt, params[1] );
bool Res = String::fromString( tInt, params[1] );
if ( Res && ( tInt >= 0 && tInt <= 100000 ) ) {
PS[2].create( ParticleEffect::WormHole, tInt, TN[5],

View File

@@ -1902,7 +1902,7 @@ void LSPClientServer::readStdOut( const char* bytes, size_t n ) {
break;
}
index += strlen( CONTENT_LENGTH_HEADER );
index += std::strlen( CONTENT_LENGTH_HEADER );
auto endindex = buffer.find( "\r\n", index );
auto msgstart = buffer.find( "\r\n\r\n", index );
if ( endindex == std::string::npos || msgstart == std::string::npos )
@@ -1910,7 +1910,10 @@ void LSPClientServer::readStdOut( const char* bytes, size_t n ) {
msgstart += 4;
int length = 0;
bool ok = String::fromString( length, buffer.substr( index, endindex - index ) );
std::string lengthStr( buffer.substr( index, endindex - index ) );
String::trimInPlace( lengthStr );
bool ok = String::fromString( length, lengthStr );
// FIXME perhaps detect if no reply for some time
// then again possibly better left to user to restart in such case
if ( !ok ) {

View File

@@ -56,7 +56,8 @@ bool StatusBuildOutputController::searchFindAndAddStatusResult(
continue;
}
std::string subtxt = text.substr( matches[i].start, matches[i].end );
std::string subtxt =
text.substr( matches[i].start, matches[i].end - matches[i].start );
if ( pattern.config.patternOrder.message == i ) {
auto nl = subtxt.find_first_of( '\n' );
if ( nl == std::string::npos ) {