@ -182,16 +182,8 @@ void ScriptText::_TextParamError(std::string msg)
}
}
}
}
void ScriptText : : _GetEncodedText ( std : : back_insert_iterator < std : : string > & output , int & param_count , StringIDList & seen_ids )
void ScriptText : : _GetEncodedText ParamsTraditional ( std : : back_insert_iterator < std : : string > & output , int & param_count , StringIDList & seen_ids , const std : : string & name )
{
{
const std : : string & name = GetGameStringName ( this - > string ) ;
if ( std : : find ( seen_ids . begin ( ) , seen_ids . end ( ) , this - > string ) ! = seen_ids . end ( ) ) throw Script_FatalError ( fmt : : format ( " {}: Circular reference detected " , name ) ) ;
seen_ids . push_back ( this - > string ) ;
Utf8Encode ( output , SCC_ENCODED ) ;
fmt : : format_to ( output , " {:X} " , this - > string ) ;
auto write_param_fallback = [ & ] ( int idx ) {
auto write_param_fallback = [ & ] ( int idx ) {
if ( std : : holds_alternative < ScriptTextRef > ( this - > param [ idx ] ) ) {
if ( std : : holds_alternative < ScriptTextRef > ( this - > param [ idx ] ) ) {
int count = 1 ; // 1 because the string id is included in consumed parameters
int count = 1 ; // 1 because the string id is included in consumed parameters
@ -210,9 +202,6 @@ void ScriptText::_GetEncodedText(std::back_insert_iterator<std::string> &output,
const StringParams & params = GetGameStringParams ( this - > string ) ;
const StringParams & params = GetGameStringParams ( this - > string ) ;
int cur_idx = 0 ;
int cur_idx = 0 ;
int prev_string = - 1 ;
int prev_idx = - 1 ;
int prev_count = - 1 ;
for ( const StringParam & cur_param : params ) {
for ( const StringParam & cur_param : params ) {
if ( cur_idx > = this - > paramc ) {
if ( cur_idx > = this - > paramc ) {
@ -220,107 +209,132 @@ void ScriptText::_GetEncodedText(std::back_insert_iterator<std::string> &output,
break ;
break ;
}
}
if ( this - > GetActiveInstance ( ) - > IsTextParamMismatchAllowed ( ) ) {
switch ( cur_param . type ) {
switch ( cur_param . type ) {
case StringParam : : RAW_STRING :
case StringParam : : RAW_STRING :
if ( ! std : : holds_alternative < std : : string > ( this - > param [ cur_idx ] ) ) {
if ( ! std : : holds_alternative < std : : string > ( this - > param [ cur_idx ] ) ) {
this - > _TextParamError ( fmt : : format ( " {}: Parameter {} expects a raw string " , name , cur_idx ) ) ;
this - > _TextParamError ( fmt : : format ( " {}: Parameter {} expects a raw string " , name , cur_idx ) ) ;
write_param_fallback ( cur_idx + + ) ;
break ;
}
fmt : : format_to ( output , " : \" {} \" " , std : : get < std : : string > ( this - > param [ cur_idx + + ] ) ) ;
param_count + + ;
break ;
case StringParam : : STRING : {
if ( ! std : : holds_alternative < ScriptTextRef > ( this - > param [ cur_idx ] ) ) {
this - > _TextParamError ( fmt : : format ( " {}: Parameter {} expects a substring " , name , cur_idx ) ) ;
write_param_fallback ( cur_idx + + ) ;
break ;
}
int count = 1 ; // 1 because the string id is included in consumed parameters
fmt : : format_to ( output , " : " ) ;
std : : get < ScriptTextRef > ( this - > param [ cur_idx + + ] ) - > _GetEncodedText ( output , count , seen_ids ) ;
if ( count ! = cur_param . consumes ) {
this - > _TextParamError ( fmt : : format ( " {}: Parameter {} substring consumes {}, but expected {} to be consumed " , name , cur_idx , count - 1 , cur_param . consumes - 1 ) ) ;
}
param_count + = count ;
break ;
}
default :
if ( cur_idx + cur_param . consumes > this - > paramc ) {
this - > _TextParamError ( fmt : : format ( " {}: Not enough parameters " , name ) ) ;
}
for ( int i = 0 ; i < cur_param . consumes & & cur_idx < this - > paramc ; i + + ) {
if ( ! std : : holds_alternative < SQInteger > ( this - > param [ cur_idx ] ) ) {
this - > _TextParamError ( fmt : : format ( " {}: Parameter {} expects an integer " , name , cur_idx ) ) ;
write_param_fallback ( cur_idx + + ) ;
write_param_fallback ( cur_idx + + ) ;
break ;
continue ;
}
}
fmt : : format_to ( output , " : \" {} \" " , std : : get < std : : string > ( this - > param [ cur_idx + + ] ) ) ;
fmt : : format_to ( output , " : {:X }" , std : : get < SQInteger > ( this - > param [ cur_idx + + ] ) ) ;
param_count + + ;
param_count + + ;
}
break ;
}
}
for ( int i = cur_idx ; i < this - > paramc ; i + + ) {
write_param_fallback ( i ) ;
}
}
void ScriptText : : _GetEncodedText ( std : : back_insert_iterator < std : : string > & output , int & param_count , StringIDList & seen_ids )
{
const std : : string & name = GetGameStringName ( this - > string ) ;
if ( std : : find ( seen_ids . begin ( ) , seen_ids . end ( ) , this - > string ) ! = seen_ids . end ( ) ) throw Script_FatalError ( fmt : : format ( " {}: Circular reference detected " , name ) ) ;
seen_ids . push_back ( this - > string ) ;
Utf8Encode ( output , SCC_ENCODED ) ;
fmt : : format_to ( output , " {:X} " , this - > string ) ;
if ( this - > GetActiveInstance ( ) - > IsTextParamMismatchAllowed ( ) ) {
this - > _GetEncodedTextParamsTraditional ( output , param_count , seen_ids , name ) ;
seen_ids . pop_back ( ) ;
return ;
}
const StringParams & params = GetGameStringParams ( this - > string ) ;
int cur_idx = 0 ;
int prev_string = - 1 ;
int prev_idx = - 1 ;
int prev_count = - 1 ;
for ( const StringParam & cur_param : params ) {
if ( cur_idx > = this - > paramc ) throw Script_FatalError ( fmt : : format ( " {}: Not enough parameters " , name ) ) ;
if ( prev_string ! = - 1 ) {
/* The previous substring added more parameters than expected, means we will consume them but can't properly validate them. */
for ( int i = 0 ; i < cur_param . consumes ; i + + ) {
if ( prev_idx < prev_count ) {
ScriptLog : : Warning ( fmt : : format ( " {}: Parameter {} uses parameter {} from substring {} and cannot be validated " , name , param_count + i , prev_idx + + , prev_string ) ) ;
} else {
/* No more extra parameters, assume SQInteger are expected. */
if ( cur_idx > = this - > paramc ) throw Script_FatalError ( fmt : : format ( " {}: Not enough parameters " , name ) ) ;
if ( ! std : : holds_alternative < SQInteger > ( this - > param [ cur_idx ] ) ) throw Script_FatalError ( fmt : : format ( " {}: Parameter {} expects an integer " , name , param_count + i ) ) ;
fmt : : format_to ( output , " :{:X} " , std : : get < SQInteger > ( this - > param [ cur_idx + + ] ) ) ;
}
}
if ( prev_idx = = prev_count ) {
/* Re-enable validation. */
prev_string = - 1 ;
}
} else {
switch ( cur_param . type ) {
case StringParam : : RAW_STRING :
if ( ! std : : holds_alternative < std : : string > ( this - > param [ cur_idx ] ) ) throw Script_FatalError ( fmt : : format ( " {}: Parameter {} expects a raw string " , name , param_count ) ) ;
fmt : : format_to ( output , " : \" {} \" " , std : : get < std : : string > ( this - > param [ cur_idx + + ] ) ) ;
break ;
break ;
case StringParam : : STRING : {
case StringParam : : STRING : {
if ( ! std : : holds_alternative < ScriptTextRef > ( this - > param [ cur_idx ] ) ) {
if ( ! std : : holds_alternative < ScriptTextRef > ( this - > param [ cur_idx ] ) ) throw Script_FatalError ( fmt : : format ( " {}: Parameter {} expects a substring " , name , param_count ) ) ;
this - > _TextParamError ( fmt : : format ( " {}: Parameter {} expects a substring " , name , cur_idx ) ) ;
int count = 0 ;
write_param_fallback ( cur_idx + + ) ;
break ;
}
int count = 1 ; // 1 because the string id is included in consumed parameters
fmt : : format_to ( output , " : " ) ;
fmt : : format_to ( output , " : " ) ;
std : : get < ScriptTextRef > ( this - > param [ cur_idx + + ] ) - > _GetEncodedText ( output , count , seen_ids ) ;
std : : get < ScriptTextRef > ( this - > param [ cur_idx + + ] ) - > _GetEncodedText ( output , count , seen_ids ) ;
if ( count ! = cur_param . consumes ) {
if ( + + count ! = cur_param . consumes ) {
this - > _TextParamError ( fmt : : format ( " {}: Parameter {} substring consumes {}, but expected {} to be consumed " , name , cur_idx , count - 1 , cur_param . consumes - 1 ) ) ;
ScriptLog : : Error ( fmt : : format ( " {}: Parameter {} substring consumes {}, but expected {} to be consumed " , name , param_count , count - 1 , cur_param . consumes - 1 ) ) ;
/* Fill missing params if needed. */
for ( int i = count ; i < cur_param . consumes ; i + + ) fmt : : format_to ( output , " :0 " ) ;
/* Disable validation for the extra params if any. */
if ( count > cur_param . consumes ) {
prev_string = param_count ;
prev_idx = cur_param . consumes - 1 ;
prev_count = count - 1 ;
}
}
}
param_count + = count ;
break ;
break ;
}
}
default :
default :
if ( cur_idx + cur_param . consumes > this - > paramc ) {
if ( cur_idx + cur_param . consumes > this - > paramc ) throw Script_FatalError ( fmt : : format ( " {}: Not enough parameters " , name ) ) ;
this - > _TextParamError ( fmt : : format ( " {}: Not enough parameters " , name ) ) ;
for ( int i = 0 ; i < cur_param . consumes ; i + + ) {
}
for ( int i = 0 ; i < cur_param . consumes & & cur_idx < this - > paramc ; i + + ) {
if ( ! std : : holds_alternative < SQInteger > ( this - > param [ cur_idx ] ) ) {
this - > _TextParamError ( fmt : : format ( " {}: Parameter {} expects an integer " , name , cur_idx ) ) ;
write_param_fallback ( cur_idx + + ) ;
continue ;
}
fmt : : format_to ( output , " :{:X} " , std : : get < SQInteger > ( this - > param [ cur_idx + + ] ) ) ;
param_count + + ;
}
break ;
}
} else {
if ( prev_string ! = - 1 ) {
/* The previous substring added more parameters than expected, means we will consume them but can't properly validate them. */
for ( int i = 0 ; i < cur_param . consumes ; i + + ) {
if ( prev_idx < prev_count ) {
ScriptLog : : Warning ( fmt : : format ( " {}: Parameter {} uses parameter {} from substring {} and cannot be validated " , name , param_count + i , prev_idx + + , prev_string ) ) ;
} else {
/* No more extra parameters, assume SQInteger are expected. */
if ( cur_idx > = this - > paramc ) throw Script_FatalError ( fmt : : format ( " {}: Not enough parameters " , name ) ) ;
if ( ! std : : holds_alternative < SQInteger > ( this - > param [ cur_idx ] ) ) throw Script_FatalError ( fmt : : format ( " {}: Parameter {} expects an integer " , name , param_count + i ) ) ;
if ( ! std : : holds_alternative < SQInteger > ( this - > param [ cur_idx ] ) ) throw Script_FatalError ( fmt : : format ( " {}: Parameter {} expects an integer " , name , param_count + i ) ) ;
fmt : : format_to ( output , " :{:X} " , std : : get < SQInteger > ( this - > param [ cur_idx + + ] ) ) ;
fmt : : format_to ( output , " :{:X} " , std : : get < SQInteger > ( this - > param [ cur_idx + + ] ) ) ;
}
}
}
if ( prev_idx = = prev_count ) {
/* Re-enable validation. */
prev_string = - 1 ;
}
} else {
switch ( cur_param . type ) {
case StringParam : : RAW_STRING :
if ( ! std : : holds_alternative < std : : string > ( this - > param [ cur_idx ] ) ) throw Script_FatalError ( fmt : : format ( " {}: Parameter {} expects a raw string " , name , param_count ) ) ;
fmt : : format_to ( output , " : \" {} \" " , std : : get < std : : string > ( this - > param [ cur_idx + + ] ) ) ;
break ;
case StringParam : : STRING : {
if ( ! std : : holds_alternative < ScriptTextRef > ( this - > param [ cur_idx ] ) ) throw Script_FatalError ( fmt : : format ( " {}: Parameter {} expects a substring " , name , param_count ) ) ;
int count = 0 ;
fmt : : format_to ( output , " : " ) ;
std : : get < ScriptTextRef > ( this - > param [ cur_idx + + ] ) - > _GetEncodedText ( output , count , seen_ids ) ;
if ( + + count ! = cur_param . consumes ) {
ScriptLog : : Error ( fmt : : format ( " {}: Parameter {} substring consumes {}, but expected {} to be consumed " , name , param_count , count - 1 , cur_param . consumes - 1 ) ) ;
/* Fill missing params if needed. */
for ( int i = count ; i < cur_param . consumes ; i + + ) fmt : : format_to ( output , " :0 " ) ;
/* Disable validation for the extra params if any. */
if ( count > cur_param . consumes ) {
prev_string = param_count ;
prev_idx = cur_param . consumes - 1 ;
prev_count = count - 1 ;
}
}
break ;
}
default :
if ( cur_idx + cur_param . consumes > this - > paramc ) throw Script_FatalError ( fmt : : format ( " {}: Not enough parameters " , name ) ) ;
for ( int i = 0 ; i < cur_param . consumes ; i + + ) {
if ( ! std : : holds_alternative < SQInteger > ( this - > param [ cur_idx ] ) ) throw Script_FatalError ( fmt : : format ( " {}: Parameter {} expects an integer " , name , param_count + i ) ) ;
fmt : : format_to ( output , " :{:X} " , std : : get < SQInteger > ( this - > param [ cur_idx + + ] ) ) ;
}
}
}
}
}
}
}
if ( this - > GetActiveInstance ( ) - > IsTextParamMismatchAllowed ( ) ) {
param_count + = cur_param . consumes ;
for ( int i = cur_idx ; i < this - > paramc ; i + + ) {
write_param_fallback ( i ) ;
}
}
}
seen_ids . pop_back ( ) ;
seen_ids . pop_back ( ) ;