2014-02-09 22:10:30 -03:00
/**************************************************************************/
/* ustring.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
2018-01-05 00:50:27 +01:00
2020-08-05 09:25:28 +03:00
# pragma once
2014-02-09 22:10:30 -03:00
2022-09-26 13:03:44 +02:00
// Note: _GODOT suffix added to header guard to avoid conflict with ICU header.
2025-02-20 08:40:46 -06:00
# include "core/string/char_utils.h" // IWYU pragma: export
2020-11-07 19:33:38 -03:00
# include "core/templates/cowdata.h"
# include "core/templates/vector.h"
2018-09-11 18:13:45 +02:00
# include "core/typedefs.h"
2020-11-07 19:33:38 -03:00
# include "core/variant/array.h"
2014-02-09 22:10:30 -03:00
2024-10-22 17:08:05 -05:00
class String ;
template < typename T >
class CharStringT ;
2024-12-07 02:28:43 +01:00
/*************************************************************************/
/* Utility Functions */
/*************************************************************************/
// Not defined by std.
// strlen equivalent function for char16_t * arguments.
constexpr size_t strlen ( const char16_t * p_str ) {
const char16_t * ptr = p_str ;
while ( * ptr ! = 0 ) {
+ + ptr ;
}
return ptr - p_str ;
}
// strlen equivalent function for char32_t * arguments.
constexpr size_t strlen ( const char32_t * p_str ) {
const char32_t * ptr = p_str ;
while ( * ptr ! = 0 ) {
+ + ptr ;
}
return ptr - p_str ;
}
// strlen equivalent function for wchar_t * arguments; depends on the platform.
2025-03-30 22:33:21 +02:00
constexpr size_t strlen ( const wchar_t * p_str ) {
2024-12-07 02:28:43 +01:00
// Use static_cast twice because reinterpret_cast is not allowed in constexpr
# ifdef WINDOWS_ENABLED
// wchar_t is 16-bit
2025-03-30 22:33:21 +02:00
return strlen ( static_cast < const char16_t * > ( static_cast < const void * > ( p_str ) ) ) ;
2024-12-07 02:28:43 +01:00
# else
// wchar_t is 32-bit
2025-03-30 22:33:21 +02:00
return strlen ( static_cast < const char32_t * > ( static_cast < const void * > ( p_str ) ) ) ;
2024-12-07 02:28:43 +01:00
# endif
}
2025-03-30 22:33:21 +02:00
// strnlen equivalent function for char16_t * arguments.
constexpr size_t strnlen ( const char16_t * p_str , size_t p_clip_to_len ) {
size_t len = 0 ;
2024-12-07 02:28:43 +01:00
while ( len < p_clip_to_len & & * ( p_str + + ) ! = 0 ) {
len + + ;
}
return len ;
}
2025-03-30 22:33:21 +02:00
// strnlen equivalent function for char32_t * arguments.
constexpr size_t strnlen ( const char32_t * p_str , size_t p_clip_to_len ) {
size_t len = 0 ;
2024-12-07 02:28:43 +01:00
while ( len < p_clip_to_len & & * ( p_str + + ) ! = 0 ) {
len + + ;
}
return len ;
}
2025-03-30 22:33:21 +02:00
// strnlen equivalent function for wchar_t * arguments; depends on the platform.
constexpr size_t strnlen ( const wchar_t * p_str , size_t p_clip_to_len ) {
// Use static_cast twice because reinterpret_cast is not allowed in constexpr
# ifdef WINDOWS_ENABLED
// wchar_t is 16-bit
return strnlen ( static_cast < const char16_t * > ( static_cast < const void * > ( p_str ) ) , p_clip_to_len ) ;
# else
// wchar_t is 32-bit
return strnlen ( static_cast < const char32_t * > ( static_cast < const void * > ( p_str ) ) , p_clip_to_len ) ;
# endif
}
2024-10-22 17:08:05 -05:00
template < typename L , typename R >
constexpr int64_t str_compare ( const L * l_ptr , const R * r_ptr ) {
while ( true ) {
const char32_t l = * l_ptr ;
const char32_t r = * r_ptr ;
if ( l = = 0 | | l ! = r ) {
return static_cast < int64_t > ( l ) - static_cast < int64_t > ( r ) ;
}
l_ptr + + ;
r_ptr + + ;
}
}
2020-07-27 13:43:20 +03:00
/*************************************************************************/
/* CharProxy */
/*************************************************************************/
2018-12-16 00:44:18 +00:00
template < typename T >
2024-06-23 12:28:04 -05:00
class [[nodiscard]] CharProxy {
2024-10-22 17:08:05 -05:00
friend String ;
friend CharStringT < T > ;
2018-12-16 00:44:18 +00:00
const int _index ;
CowData < T > & _cowdata ;
2024-10-22 17:08:05 -05:00
static constexpr T _null = 0 ;
2018-12-16 00:44:18 +00:00
2021-09-30 23:02:41 +02:00
_FORCE_INLINE_ CharProxy ( const int & p_index , CowData < T > & p_cowdata ) :
2018-12-16 00:44:18 +00:00
_index ( p_index ) ,
2021-09-30 23:02:41 +02:00
_cowdata ( p_cowdata ) { }
2018-12-16 00:44:18 +00:00
public :
2021-09-30 23:02:41 +02:00
_FORCE_INLINE_ CharProxy ( const CharProxy < T > & p_other ) :
_index ( p_other . _index ) ,
_cowdata ( p_other . _cowdata ) { }
2018-12-16 00:44:18 +00:00
_FORCE_INLINE_ operator T ( ) const {
2020-05-14 16:41:43 +02:00
if ( unlikely ( _index = = _cowdata . size ( ) ) ) {
2019-01-04 16:01:54 +00:00
return _null ;
2020-05-14 16:41:43 +02:00
}
2019-01-04 16:01:54 +00:00
2018-12-16 00:44:18 +00:00
return _cowdata . get ( _index ) ;
}
_FORCE_INLINE_ const T * operator & ( ) const {
return _cowdata . ptr ( ) + _index ;
}
2021-09-30 23:02:41 +02:00
_FORCE_INLINE_ void operator = ( const T & p_other ) const {
_cowdata . set ( _index , p_other ) ;
2018-12-16 00:44:18 +00:00
}
2021-09-30 23:02:41 +02:00
_FORCE_INLINE_ void operator = ( const CharProxy < T > & p_other ) const {
_cowdata . set ( _index , p_other . operator T ( ) ) ;
2018-12-16 00:44:18 +00:00
}
} ;
2020-07-27 13:43:20 +03:00
/*************************************************************************/
2024-10-22 17:08:05 -05:00
/* CharStringT */
2020-07-27 13:43:20 +03:00
/*************************************************************************/
2024-10-22 17:08:05 -05:00
template < typename T >
2024-06-23 12:28:04 -05:00
class [[nodiscard]] CharStringT {
2024-10-22 17:08:05 -05:00
CowData < T > _cowdata ;
static constexpr T _null = 0 ;
2020-07-27 13:43:20 +03:00
public :
2024-10-22 17:08:05 -05:00
_FORCE_INLINE_ T * ptrw ( ) { return _cowdata . ptrw ( ) ; }
_FORCE_INLINE_ const T * ptr ( ) const { return _cowdata . ptr ( ) ; }
2025-05-30 09:25:21 +02:00
_FORCE_INLINE_ const T * get_data ( ) const { return ptr ( ) ? ptr ( ) : & _null ; }
2020-07-27 13:43:20 +03:00
_FORCE_INLINE_ int size ( ) const { return _cowdata . size ( ) ; }
2025-05-30 09:25:21 +02:00
_FORCE_INLINE_ int length ( ) const { return ptr ( ) ? size ( ) - 1 : 0 ; }
_FORCE_INLINE_ bool is_empty ( ) const { return length ( ) = = 0 ; }
2025-01-16 19:48:50 +01:00
2024-10-22 17:08:05 -05:00
_FORCE_INLINE_ operator Span < T > ( ) const { return Span ( ptr ( ) , length ( ) ) ; }
_FORCE_INLINE_ Span < T > span ( ) const { return Span ( ptr ( ) , length ( ) ) ; }
2025-01-16 19:48:50 +01:00
2025-05-28 20:33:21 +02:00
/// Resizes the string. The given size must include the null terminator.
/// New characters are not initialized, and should be set by the caller.
_FORCE_INLINE_ Error resize_uninitialized ( int64_t p_size ) { return _cowdata . template resize < false > ( p_size ) ; }
2020-07-27 13:43:20 +03:00
2024-10-22 17:08:05 -05:00
_FORCE_INLINE_ T get ( int p_index ) const { return _cowdata . get ( p_index ) ; }
_FORCE_INLINE_ void set ( int p_index , const T & p_elem ) { _cowdata . set ( p_index , p_elem ) ; }
_FORCE_INLINE_ const T & operator [ ] ( int p_index ) const {
2020-07-27 13:43:20 +03:00
if ( unlikely ( p_index = = _cowdata . size ( ) ) ) {
return _null ;
}
return _cowdata . get ( p_index ) ;
}
2024-10-22 17:08:05 -05:00
_FORCE_INLINE_ CharProxy < T > operator [ ] ( int p_index ) { return CharProxy < T > ( p_index , _cowdata ) ; }
2020-07-27 13:43:20 +03:00
2024-10-22 17:08:05 -05:00
_FORCE_INLINE_ CharStringT ( ) = default ;
_FORCE_INLINE_ CharStringT ( const CharStringT & p_str ) = default ;
_FORCE_INLINE_ CharStringT ( CharStringT & & p_str ) = default ;
_FORCE_INLINE_ void operator = ( const CharStringT & p_str ) { _cowdata = p_str . _cowdata ; }
_FORCE_INLINE_ void operator = ( CharStringT & & p_str ) { _cowdata = std : : move ( p_str . _cowdata ) ; }
_FORCE_INLINE_ CharStringT ( const T * p_cstr ) { copy_from ( p_cstr ) ; }
_FORCE_INLINE_ void operator = ( const T * p_cstr ) { copy_from ( p_cstr ) ; }
2020-07-27 13:43:20 +03:00
2024-10-22 17:08:05 -05:00
_FORCE_INLINE_ bool operator = = ( const CharStringT < T > & p_other ) const {
if ( length ( ) ! = p_other . length ( ) ) {
return false ;
}
return memcmp ( ptr ( ) , p_other . ptr ( ) , length ( ) * sizeof ( T ) ) = = 0 ;
}
_FORCE_INLINE_ bool operator ! = ( const CharStringT < T > & p_other ) const { return ! ( * this = = p_other ) ; }
_FORCE_INLINE_ bool operator < ( const CharStringT < T > & p_other ) const {
if ( length ( ) = = 0 ) {
return p_other . length ( ) ! = 0 ;
}
return str_compare ( get_data ( ) , p_other . get_data ( ) ) < 0 ;
}
_FORCE_INLINE_ CharStringT < T > & operator + = ( T p_char ) {
const int lhs_len = length ( ) ;
2025-05-28 20:33:21 +02:00
resize_uninitialized ( lhs_len + 2 ) ;
2020-07-27 13:43:20 +03:00
2024-10-22 17:08:05 -05:00
T * dst = ptrw ( ) ;
dst [ lhs_len ] = p_char ;
dst [ lhs_len + 1 ] = _null ;
2020-07-27 13:43:20 +03:00
2024-10-22 17:08:05 -05:00
return * this ;
}
2020-07-27 13:43:20 +03:00
2024-10-22 17:08:05 -05:00
protected :
void copy_from ( const T * p_cstr ) {
if ( ! p_cstr ) {
2025-05-28 20:33:21 +02:00
resize_uninitialized ( 0 ) ;
2024-10-22 17:08:05 -05:00
return ;
}
2025-01-16 19:48:50 +01:00
2024-10-22 17:08:05 -05:00
size_t len = strlen ( p_cstr ) ;
if ( len = = 0 ) {
2025-05-28 20:33:21 +02:00
resize_uninitialized ( 0 ) ;
2024-10-22 17:08:05 -05:00
return ;
}
2025-01-16 19:48:50 +01:00
2025-05-28 20:33:21 +02:00
Error err = resize_uninitialized ( + + len ) ; // include terminating null char.
2018-07-25 03:11:03 +02:00
2024-10-22 17:08:05 -05:00
ERR_FAIL_COND_MSG ( err ! = OK , " Failed to copy C-string. " ) ;
2019-01-04 16:01:54 +00:00
2024-10-22 17:08:05 -05:00
memcpy ( ptrw ( ) , p_cstr , len * sizeof ( T ) ) ;
2019-01-04 16:01:54 +00:00
}
2024-10-22 17:08:05 -05:00
} ;
2018-07-25 03:11:03 +02:00
2024-10-22 17:08:05 -05:00
template < typename T >
struct is_zero_constructible < CharStringT < T > > : std : : true_type { } ;
2019-03-12 12:57:22 +00:00
2024-10-22 17:08:05 -05:00
using CharString = CharStringT < char > ;
using Char16String = CharStringT < char16_t > ;
2014-02-09 22:10:30 -03:00
2020-07-27 13:43:20 +03:00
/*************************************************************************/
/* String */
/*************************************************************************/
2016-06-19 00:05:23 +02:00
2024-06-23 12:28:04 -05:00
class [[nodiscard]] String {
2020-07-27 13:43:20 +03:00
CowData < char32_t > _cowdata ;
2024-10-22 17:08:05 -05:00
static constexpr char32_t _null = 0 ;
static constexpr char32_t _replacement_char = 0xfffd ;
2014-02-09 22:10:30 -03:00
2024-12-07 02:28:43 +01:00
// Known-length copy.
void copy_from_unchecked ( const char32_t * p_char , int p_length ) ;
// NULL-terminated c string copy - automatically parse the string to find the length.
2025-03-24 12:25:48 +01:00
void append_latin1 ( const char * p_cstr ) {
append_latin1 ( Span ( p_cstr , p_cstr ? strlen ( p_cstr ) : 0 ) ) ;
2024-12-07 02:28:43 +01:00
}
2025-03-24 12:25:48 +01:00
void append_utf32 ( const char32_t * p_cstr ) {
append_utf32 ( Span ( p_cstr , p_cstr ? strlen ( p_cstr ) : 0 ) ) ;
2024-12-07 02:28:43 +01:00
}
2020-07-27 13:43:20 +03:00
2024-12-07 02:28:43 +01:00
// wchar_t copy_from depends on the platform.
2025-03-24 12:25:48 +01:00
void append_wstring ( const Span < wchar_t > & p_cstr ) {
2024-12-07 02:28:43 +01:00
# ifdef WINDOWS_ENABLED
// wchar_t is 16-bit, parse as UTF-16
2025-03-24 12:25:48 +01:00
append_utf16 ( ( const char16_t * ) p_cstr . ptr ( ) , p_cstr . size ( ) ) ;
2024-12-07 02:28:43 +01:00
# else
// wchar_t is 32-bit, copy directly
2025-03-24 12:25:48 +01:00
append_utf32 ( ( Span < char32_t > & ) p_cstr ) ;
2024-12-07 02:28:43 +01:00
# endif
}
2025-03-24 12:25:48 +01:00
void append_wstring ( const wchar_t * p_cstr ) {
2024-12-07 02:28:43 +01:00
# ifdef WINDOWS_ENABLED
// wchar_t is 16-bit, parse as UTF-16
2025-03-24 12:25:48 +01:00
append_utf16 ( ( const char16_t * ) p_cstr ) ;
2024-12-07 02:28:43 +01:00
# else
// wchar_t is 32-bit, copy directly
2025-03-24 12:25:48 +01:00
append_utf32 ( ( const char32_t * ) p_cstr ) ;
2024-12-07 02:28:43 +01:00
# endif
}
2020-07-27 13:43:20 +03:00
2016-06-12 00:25:01 -03:00
bool _base_is_subsequence_of ( const String & p_string , bool case_insensitive ) const ;
2019-01-18 11:29:28 +03:00
int _count ( const String & p_string , int p_from , int p_to , bool p_case_insensitive ) const ;
2023-11-02 15:15:48 -04:00
int _count ( const char * p_string , int p_from , int p_to , bool p_case_insensitive ) const ;
2024-07-28 21:32:28 +02:00
String _separate_compound_words ( ) const ;
2014-02-09 22:10:30 -03:00
public :
enum {
npos = - 1 ///<for "some" compatibility with std::string (npos is a huge value in std::string)
} ;
2020-07-27 13:43:20 +03:00
_FORCE_INLINE_ char32_t * ptrw ( ) { return _cowdata . ptrw ( ) ; }
_FORCE_INLINE_ const char32_t * ptr ( ) const { return _cowdata . ptr ( ) ; }
2025-05-30 09:25:21 +02:00
_FORCE_INLINE_ const char32_t * get_data ( ) const { return ptr ( ) ? ptr ( ) : & _null ; }
2025-01-16 19:48:50 +01:00
_FORCE_INLINE_ int size ( ) const { return _cowdata . size ( ) ; }
2025-05-30 09:25:21 +02:00
_FORCE_INLINE_ int length ( ) const { return ptr ( ) ? size ( ) - 1 : 0 ; }
_FORCE_INLINE_ bool is_empty ( ) const { return length ( ) = = 0 ; }
2025-01-16 19:48:50 +01:00
_FORCE_INLINE_ operator Span < char32_t > ( ) const { return Span ( ptr ( ) , length ( ) ) ; }
_FORCE_INLINE_ Span < char32_t > span ( ) const { return Span ( ptr ( ) , length ( ) ) ; }
2018-07-25 03:11:03 +02:00
2021-07-03 16:17:03 -06:00
void remove_at ( int p_index ) { _cowdata . remove_at ( p_index ) ; }
2018-07-25 03:11:03 +02:00
2025-05-28 20:33:21 +02:00
_FORCE_INLINE_ void clear ( ) { resize_uninitialized ( 0 ) ; }
2018-07-25 03:11:03 +02:00
2020-07-27 13:43:20 +03:00
_FORCE_INLINE_ char32_t get ( int p_index ) const { return _cowdata . get ( p_index ) ; }
_FORCE_INLINE_ void set ( int p_index , const char32_t & p_elem ) { _cowdata . set ( p_index , p_elem ) ; }
2025-05-28 20:33:21 +02:00
/// Resizes the string. The given size must include the null terminator.
/// New characters are not initialized, and should be set by the caller.
Error resize_uninitialized ( int64_t p_size ) { return _cowdata . resize < false > ( p_size ) ; }
2018-12-16 00:44:18 +00:00
2020-07-27 13:43:20 +03:00
_FORCE_INLINE_ const char32_t & operator [ ] ( int p_index ) const {
2020-05-14 16:41:43 +02:00
if ( unlikely ( p_index = = _cowdata . size ( ) ) ) {
2019-01-04 16:01:54 +00:00
return _null ;
2020-05-14 16:41:43 +02:00
}
2019-01-04 16:01:54 +00:00
return _cowdata . get ( p_index ) ;
}
2020-07-27 13:43:20 +03:00
_FORCE_INLINE_ CharProxy < char32_t > operator [ ] ( int p_index ) { return CharProxy < char32_t > ( p_index , _cowdata ) ; }
2018-07-25 03:11:03 +02:00
2024-12-07 02:28:43 +01:00
/* Compatibility Operators */
2014-02-09 22:10:30 -03:00
bool operator = = ( const String & p_str ) const ;
bool operator ! = ( const String & p_str ) const ;
String operator + ( const String & p_str ) const ;
2025-03-15 16:55:49 +01:00
String operator + ( const char * p_char ) const ;
String operator + ( const wchar_t * p_char ) const ;
String operator + ( const char32_t * p_char ) const ;
2022-02-13 14:41:29 +02:00
String operator + ( char32_t p_char ) const ;
2014-02-09 22:10:30 -03:00
String & operator + = ( const String & ) ;
2020-07-27 13:43:20 +03:00
String & operator + = ( char32_t p_char ) ;
2014-02-09 22:10:30 -03:00
String & operator + = ( const char * p_str ) ;
2020-07-27 13:43:20 +03:00
String & operator + = ( const wchar_t * p_str ) ;
String & operator + = ( const char32_t * p_str ) ;
2014-02-09 22:10:30 -03:00
bool operator = = ( const char * p_str ) const ;
2020-07-27 13:43:20 +03:00
bool operator = = ( const wchar_t * p_str ) const ;
bool operator = = ( const char32_t * p_str ) const ;
2025-01-16 19:48:50 +01:00
bool operator = = ( const Span < char32_t > & p_str_range ) const ;
2020-07-27 13:43:20 +03:00
2014-02-09 22:10:30 -03:00
bool operator ! = ( const char * p_str ) const ;
2020-07-27 13:43:20 +03:00
bool operator ! = ( const wchar_t * p_str ) const ;
bool operator ! = ( const char32_t * p_str ) const ;
bool operator < ( const char32_t * p_str ) const ;
2014-02-09 22:10:30 -03:00
bool operator < ( const char * p_str ) const ;
2020-07-27 13:43:20 +03:00
bool operator < ( const wchar_t * p_str ) const ;
2017-12-11 23:38:07 +01:00
bool operator < ( const String & p_str ) const ;
bool operator < = ( const String & p_str ) const ;
2020-11-04 23:01:55 -03:00
bool operator > ( const String & p_str ) const ;
bool operator > = ( const String & p_str ) const ;
2014-02-09 22:10:30 -03:00
signed char casecmp_to ( const String & p_str ) const ;
signed char nocasecmp_to ( const String & p_str ) const ;
2023-05-04 20:32:45 +02:00
signed char naturalcasecmp_to ( const String & p_str ) const ;
2017-05-11 20:07:59 +01:00
signed char naturalnocasecmp_to ( const String & p_str ) const ;
2024-02-02 16:50:23 +01:00
// Special sorting for file names. Names starting with `_` are put before all others except those starting with `.`, otherwise natural comparison is used.
signed char filecasecmp_to ( const String & p_str ) const ;
signed char filenocasecmp_to ( const String & p_str ) const ;
2014-02-09 22:10:30 -03:00
2020-07-27 13:43:20 +03:00
bool is_valid_string ( ) const ;
2022-07-05 15:18:29 +03:00
/* debug, error messages */
void print_unicode_error ( const String & p_message , bool p_critical = false ) const ;
2014-02-09 22:10:30 -03:00
/* complex helpers */
2019-05-03 14:21:04 +02:00
String substr ( int p_from , int p_chars = - 1 ) const ;
2017-12-11 23:38:07 +01:00
int find ( const String & p_str , int p_from = 0 ) const ; ///< return <0 if failed
2019-01-07 17:02:55 +00:00
int find ( const char * p_str , int p_from = 0 ) const ; ///< return <0 if failed
2024-10-10 23:50:50 -07:00
int find_char ( char32_t p_char , int p_from = 0 ) const ; ///< return <0 if failed
2017-12-11 23:38:07 +01:00
int findn ( const String & p_str , int p_from = 0 ) const ; ///< return <0 if failed, case insensitive
2023-11-02 15:15:48 -04:00
int findn ( const char * p_str , int p_from = 0 ) const ; ///< return <0 if failed
2017-12-11 23:38:07 +01:00
int rfind ( const String & p_str , int p_from = - 1 ) const ; ///< return <0 if failed
2023-11-02 15:15:48 -04:00
int rfind ( const char * p_str , int p_from = - 1 ) const ; ///< return <0 if failed
2024-10-10 23:50:50 -07:00
int rfind_char ( char32_t p_char , int p_from = - 1 ) const ; ///< return <0 if failed
2017-12-11 23:38:07 +01:00
int rfindn ( const String & p_str , int p_from = - 1 ) const ; ///< return <0 if failed, case insensitive
2023-11-02 15:15:48 -04:00
int rfindn ( const char * p_str , int p_from = - 1 ) const ; ///< return <0 if failed
2020-04-02 01:20:12 +02:00
int findmk ( const Vector < String > & p_keys , int p_from = 0 , int * r_key = nullptr ) const ; ///< return <0 if failed
2014-02-09 22:10:30 -03:00
bool match ( const String & p_wildcard ) const ;
bool matchn ( const String & p_wildcard ) const ;
bool begins_with ( const String & p_string ) const ;
2016-03-09 00:00:52 +01:00
bool begins_with ( const char * p_string ) const ;
2014-02-09 22:10:30 -03:00
bool ends_with ( const String & p_string ) const ;
2023-11-02 15:15:48 -04:00
bool ends_with ( const char * p_string ) const ;
2017-10-28 23:46:20 +02:00
bool is_enclosed_in ( const String & p_string ) const ;
2016-06-12 00:25:01 -03:00
bool is_subsequence_of ( const String & p_string ) const ;
2022-01-26 18:03:56 -05:00
bool is_subsequence_ofn ( const String & p_string ) const ;
2017-10-28 23:46:20 +02:00
bool is_quoted ( ) const ;
2024-10-10 23:50:50 -07:00
bool is_lowercase ( ) const ;
2016-06-13 14:06:03 -03:00
Vector < String > bigrams ( ) const ;
float similarity ( const String & p_string ) const ;
2023-11-02 13:36:57 -04:00
String format ( const Variant & values , const String & placeholder = " {_} " ) const ;
2017-12-11 23:38:07 +01:00
String replace_first ( const String & p_key , const String & p_with ) const ;
2023-11-02 15:15:48 -04:00
String replace_first ( const char * p_key , const char * p_with ) const ;
2017-12-11 23:38:07 +01:00
String replace ( const String & p_key , const String & p_with ) const ;
String replace ( const char * p_key , const char * p_with ) const ;
2024-05-28 12:15:00 +02:00
String replace_char ( char32_t p_key , char32_t p_with ) const ;
String replace_chars ( const String & p_keys , char32_t p_with ) const ;
String replace_chars ( const char * p_keys , char32_t p_with ) const ;
2017-12-11 23:38:07 +01:00
String replacen ( const String & p_key , const String & p_with ) const ;
2023-11-02 15:15:48 -04:00
String replacen ( const char * p_key , const char * p_with ) const ;
2019-09-01 23:49:55 -04:00
String repeat ( int p_count ) const ;
2023-06-21 20:40:48 +03:00
String reverse ( ) const ;
2017-12-11 23:38:07 +01:00
String insert ( int p_at_pos , const String & p_string ) const ;
2023-03-30 15:45:45 +02:00
String erase ( int p_pos , int p_chars = 1 ) const ;
2024-05-28 12:55:07 +02:00
String remove_char ( char32_t p_what ) const ;
String remove_chars ( const String & p_chars ) const ;
String remove_chars ( const char * p_chars ) const ;
2014-02-09 22:10:30 -03:00
String pad_decimals ( int p_digits ) const ;
String pad_zeros ( int p_digits ) const ;
2018-04-13 17:40:27 +03:00
String trim_prefix ( const String & p_prefix ) const ;
2023-11-02 15:15:48 -04:00
String trim_prefix ( const char * p_prefix ) const ;
2018-04-13 17:40:27 +03:00
String trim_suffix ( const String & p_suffix ) const ;
2023-11-02 15:15:48 -04:00
String trim_suffix ( const char * p_suffix ) const ;
2015-02-01 18:42:36 +00:00
String lpad ( int min_length , const String & character = " " ) const ;
String rpad ( int min_length , const String & character = " " ) const ;
2015-02-19 15:45:49 +00:00
String sprintf ( const Array & values , bool * error ) const ;
2023-11-02 13:36:57 -04:00
String quote ( const String & quotechar = " \" " ) const ;
2017-10-28 23:46:20 +02:00
String unquote ( ) const ;
2014-02-09 22:10:30 -03:00
static String num ( double p_num , int p_decimals = - 1 ) ;
static String num_scientific ( double p_num ) ;
2024-11-01 02:02:09 -07:00
static String num_scientific ( float p_num ) ;
2021-02-25 09:54:50 -05:00
static String num_real ( double p_num , bool p_trailing = true ) ;
2024-03-26 17:04:14 +01:00
static String num_real ( float p_num , bool p_trailing = true ) ;
2015-02-01 18:42:36 +00:00
static String num_int64 ( int64_t p_num , int base = 10 , bool capitalize_hex = false ) ;
2018-02-22 13:13:51 +01:00
static String num_uint64 ( uint64_t p_num , int base = 10 , bool capitalize_hex = false ) ;
2024-12-12 14:09:47 +01:00
static String chr ( char32_t p_char ) {
String string ;
2025-03-24 12:25:48 +01:00
string . append_utf32 ( Span ( & p_char , 1 ) ) ;
2024-12-12 14:09:47 +01:00
return string ;
}
2014-02-09 22:10:30 -03:00
static String md5 ( const uint8_t * p_md5 ) ;
2016-06-17 10:55:16 +03:00
static String hex_encode_buffer ( const uint8_t * p_buffer , int p_len ) ;
2023-03-06 10:17:33 +07:00
Vector < uint8_t > hex_decode ( ) const ;
2014-02-09 22:10:30 -03:00
bool is_numeric ( ) const ;
2020-07-27 13:43:20 +03:00
double to_float ( ) const ;
2021-01-28 07:39:05 -05:00
int64_t hex_to_int ( ) const ;
int64_t bin_to_int ( ) const ;
2020-05-13 05:31:51 -04:00
int64_t to_int ( ) const ;
2020-07-27 13:43:20 +03:00
2020-06-03 00:04:04 -04:00
static int64_t to_int ( const char * p_str , int p_len = - 1 ) ;
2020-07-27 13:43:20 +03:00
static int64_t to_int ( const wchar_t * p_str , int p_len = - 1 ) ;
static int64_t to_int ( const char32_t * p_str , int p_len = - 1 , bool p_clamp = false ) ;
2020-07-24 14:07:57 -04:00
static double to_float ( const char * p_str ) ;
2020-07-27 13:43:20 +03:00
static double to_float ( const wchar_t * p_str , const wchar_t * * r_end = nullptr ) ;
static double to_float ( const char32_t * p_str , const char32_t * * r_end = nullptr ) ;
2023-04-06 17:54:56 +02:00
static uint32_t num_characters ( int64_t p_int ) ;
2020-07-27 13:43:20 +03:00
2014-02-09 22:10:30 -03:00
String capitalize ( ) const ;
2022-08-30 12:36:24 +03:00
String to_camel_case ( ) const ;
String to_pascal_case ( ) const ;
String to_snake_case ( ) const ;
2024-07-28 21:32:28 +02:00
String to_kebab_case ( ) const ;
2014-02-09 22:10:30 -03:00
2019-06-15 23:45:24 -03:00
String get_with_code_lines ( ) const ;
2023-11-02 13:36:57 -04:00
int get_slice_count ( const String & p_splitter ) const ;
2023-11-02 15:15:48 -04:00
int get_slice_count ( const char * p_splitter ) const ;
2023-11-02 13:36:57 -04:00
String get_slice ( const String & p_splitter , int p_slice ) const ;
2023-11-02 15:15:48 -04:00
String get_slice ( const char * p_splitter , int p_slice ) const ;
2020-07-27 13:43:20 +03:00
String get_slicec ( char32_t p_splitter , int p_slice ) const ;
2014-02-09 22:10:30 -03:00
2022-08-12 16:21:15 +02:00
Vector < String > split ( const String & p_splitter = " " , bool p_allow_empty = true , int p_maxsplit = 0 ) const ;
2023-11-02 15:15:48 -04:00
Vector < String > split ( const char * p_splitter = " " , bool p_allow_empty = true , int p_maxsplit = 0 ) const ;
2022-08-12 16:21:15 +02:00
Vector < String > rsplit ( const String & p_splitter = " " , bool p_allow_empty = true , int p_maxsplit = 0 ) const ;
2023-11-02 15:15:48 -04:00
Vector < String > rsplit ( const char * p_splitter = " " , bool p_allow_empty = true , int p_maxsplit = 0 ) const ;
2025-03-08 11:56:40 -05:00
Vector < String > split_spaces ( int p_maxsplit = 0 ) const ;
2022-11-20 12:29:50 +01:00
Vector < double > split_floats ( const String & p_splitter , bool p_allow_empty = true ) const ;
2014-02-09 22:10:30 -03:00
Vector < float > split_floats_mk ( const Vector < String > & p_splitters , bool p_allow_empty = true ) const ;
Vector < int > split_ints ( const String & p_splitter , bool p_allow_empty = true ) const ;
Vector < int > split_ints_mk ( const Vector < String > & p_splitters , bool p_allow_empty = true ) const ;
2024-01-08 22:36:19 -03:00
String join ( const Vector < String > & parts ) const ;
2017-10-02 22:01:43 +07:00
2020-07-27 13:43:20 +03:00
static char32_t char_uppercase ( char32_t p_char ) ;
static char32_t char_lowercase ( char32_t p_char ) ;
2014-02-09 22:10:30 -03:00
String to_upper ( ) const ;
String to_lower ( ) const ;
2019-01-18 11:29:28 +03:00
int count ( const String & p_string , int p_from = 0 , int p_to = 0 ) const ;
2023-11-02 15:15:48 -04:00
int count ( const char * p_string , int p_from = 0 , int p_to = 0 ) const ;
2019-01-18 11:29:28 +03:00
int countn ( const String & p_string , int p_from = 0 , int p_to = 0 ) const ;
2023-11-02 15:15:48 -04:00
int countn ( const char * p_string , int p_from = 0 , int p_to = 0 ) const ;
2019-01-18 11:29:28 +03:00
2022-06-12 10:45:58 +08:00
String left ( int p_len ) const ;
String right ( int p_len ) const ;
2021-12-15 23:01:06 +08:00
String indent ( const String & p_prefix ) const ;
2017-10-11 16:27:54 +08:00
String dedent ( ) const ;
2016-05-11 09:22:59 +02:00
String strip_edges ( bool left = true , bool right = true ) const ;
2014-02-09 22:10:30 -03:00
String strip_escapes ( ) const ;
2018-07-25 03:11:03 +02:00
String lstrip ( const String & p_chars ) const ;
String rstrip ( const String & p_chars ) const ;
2017-01-14 00:51:09 -03:00
String get_extension ( ) const ;
String get_basename ( ) const ;
2025-02-24 23:52:33 +01:00
String path_join ( const String & p_path ) const ;
2020-11-23 14:47:11 +03:00
char32_t unicode_at ( int p_idx ) const ;
2014-02-09 22:10:30 -03:00
CharString ascii ( bool p_allow_extended = false ) const ;
2025-03-08 00:01:27 +01:00
// Parse an ascii string.
// If any character is > 127, an error will be logged, and 0xfffd will be inserted.
2025-03-24 12:25:48 +01:00
Error append_ascii ( const Span < char > & p_range ) ;
2025-01-16 19:48:50 +01:00
static String ascii ( const Span < char > & p_range ) {
2025-03-08 00:01:27 +01:00
String s ;
2025-03-24 12:25:48 +01:00
s . append_ascii ( p_range ) ;
2025-03-08 00:01:27 +01:00
return s ;
}
2025-01-09 16:14:10 +01:00
CharString latin1 ( ) const { return ascii ( true ) ; }
2025-03-24 12:25:48 +01:00
void append_latin1 ( const Span < char > & p_cstr ) ;
2025-01-09 16:14:10 +01:00
static String latin1 ( const Span < char > & p_string ) {
String string ;
2025-03-24 12:25:48 +01:00
string . append_latin1 ( p_string ) ;
2025-01-09 16:14:10 +01:00
return string ;
}
2025-03-08 00:01:27 +01:00
2025-03-21 16:42:23 +02:00
CharString utf8 ( Vector < uint8_t > * r_ch_length_map = nullptr ) const ;
2025-03-24 12:25:48 +01:00
Error append_utf8 ( const char * p_utf8 , int p_len = - 1 , bool p_skip_cr = false ) ;
Error append_utf8 ( const Span < char > & p_range , bool p_skip_cr = false ) {
return append_utf8 ( p_range . ptr ( ) , p_range . size ( ) , p_skip_cr ) ;
2025-01-08 16:29:00 +01:00
}
2025-01-09 17:13:06 +01:00
static String utf8 ( const char * p_utf8 , int p_len = - 1 ) {
String ret ;
ret . append_utf8 ( p_utf8 , p_len ) ;
return ret ;
}
2025-01-16 19:48:50 +01:00
static String utf8 ( const Span < char > & p_range ) { return utf8 ( p_range . ptr ( ) , p_range . size ( ) ) ; }
2016-03-09 00:00:52 +01:00
2020-07-27 13:43:20 +03:00
Char16String utf16 ( ) const ;
2025-03-24 12:25:48 +01:00
Error append_utf16 ( const char16_t * p_utf16 , int p_len = - 1 , bool p_default_little_endian = true ) ;
Error append_utf16 ( const Span < char16_t > p_range , bool p_skip_cr = false ) {
return append_utf16 ( p_range . ptr ( ) , p_range . size ( ) , p_skip_cr ) ;
2025-01-08 16:29:00 +01:00
}
2025-01-09 17:13:06 +01:00
static String utf16 ( const char16_t * p_utf16 , int p_len = - 1 ) {
String ret ;
ret . append_utf16 ( p_utf16 , p_len ) ;
return ret ;
}
2025-01-16 19:48:50 +01:00
static String utf16 ( const Span < char16_t > & p_range ) { return utf16 ( p_range . ptr ( ) , p_range . size ( ) ) ; }
2020-07-27 13:43:20 +03:00
2025-03-24 12:25:48 +01:00
void append_utf32 ( const Span < char32_t > & p_cstr ) ;
2025-03-14 16:54:44 +01:00
static String utf32 ( const Span < char32_t > & p_span ) {
String string ;
2025-03-24 12:25:48 +01:00
string . append_utf32 ( p_span ) ;
2025-03-14 16:54:44 +01:00
return string ;
}
2025-01-09 16:14:10 +01:00
2020-07-27 13:43:20 +03:00
static uint32_t hash ( const char32_t * p_cstr , int p_len ) ; /* hash the string */
static uint32_t hash ( const char32_t * p_cstr ) ; /* hash the string */
static uint32_t hash ( const wchar_t * p_cstr , int p_len ) ; /* hash the string */
static uint32_t hash ( const wchar_t * p_cstr ) ; /* hash the string */
2014-02-09 22:10:30 -03:00
static uint32_t hash ( const char * p_cstr , int p_len ) ; /* hash the string */
static uint32_t hash ( const char * p_cstr ) ; /* hash the string */
uint32_t hash ( ) const ; /* hash the string */
2016-03-09 00:00:52 +01:00
uint64_t hash64 ( ) const ; /* hash the string */
2014-03-13 22:57:24 -03:00
String md5_text ( ) const ;
2019-07-02 16:07:02 +02:00
String sha1_text ( ) const ;
2016-06-17 10:55:16 +03:00
String sha256_text ( ) const ;
2014-08-01 22:10:38 -03:00
Vector < uint8_t > md5_buffer ( ) const ;
2019-07-02 16:07:02 +02:00
Vector < uint8_t > sha1_buffer ( ) const ;
2016-06-23 13:57:45 -03:00
Vector < uint8_t > sha256_buffer ( ) const ;
2014-08-01 22:10:38 -03:00
2022-02-03 21:48:38 +05:45
_FORCE_INLINE_ bool contains ( const char * p_str ) const { return find ( p_str ) ! = - 1 ; }
_FORCE_INLINE_ bool contains ( const String & p_str ) const { return find ( p_str ) ! = - 1 ; }
2024-12-05 17:56:08 +01:00
_FORCE_INLINE_ bool contains_char ( char32_t p_chr ) const { return find_char ( p_chr ) ! = - 1 ; }
2024-05-06 10:26:10 +02:00
_FORCE_INLINE_ bool containsn ( const char * p_str ) const { return findn ( p_str ) ! = - 1 ; }
_FORCE_INLINE_ bool containsn ( const String & p_str ) const { return findn ( p_str ) ! = - 1 ; }
2014-02-09 22:10:30 -03:00
// path functions
2021-06-03 15:41:22 +02:00
bool is_absolute_path ( ) const ;
2021-08-29 19:43:47 -04:00
bool is_relative_path ( ) const ;
2014-02-09 22:10:30 -03:00
bool is_resource_file ( ) const ;
String path_to ( const String & p_path ) const ;
String path_to_file ( const String & p_path ) const ;
String get_base_dir ( ) const ;
String get_file ( ) const ;
2019-10-04 14:35:01 +03:00
static String humanize_size ( uint64_t p_size ) ;
2014-02-09 22:10:30 -03:00
String simplify_path ( ) const ;
2022-01-24 13:12:46 +02:00
bool is_network_share_path ( ) const ;
2014-02-09 22:10:30 -03:00
String xml_escape ( bool p_escape_quotes = false ) const ;
String xml_unescape ( ) const ;
2020-11-29 22:43:38 -05:00
String uri_encode ( ) const ;
String uri_decode ( ) const ;
2025-04-07 22:49:57 +03:00
String uri_file_decode ( ) const ;
2014-02-09 22:10:30 -03:00
String c_escape ( ) const ;
2017-01-16 18:03:38 +01:00
String c_escape_multiline ( ) const ;
2014-02-09 22:10:30 -03:00
String c_unescape ( ) const ;
2016-01-10 15:01:06 -03:00
String json_escape ( ) const ;
2024-05-22 10:22:50 +08:00
Error parse_url ( String & r_scheme , String & r_host , int & r_port , String & r_path , String & r_fragment ) const ;
2016-03-09 00:00:52 +01:00
2019-12-20 10:03:15 +08:00
String property_name_encode ( ) const ;
2021-01-28 12:48:12 -08:00
// node functions
2023-11-09 15:37:08 +01:00
static String get_invalid_node_name_characters ( bool p_allow_internal = false ) ;
2021-01-28 12:48:12 -08:00
String validate_node_name ( ) const ;
2024-08-23 14:30:51 +08:00
String validate_ascii_identifier ( ) const ;
2024-09-22 19:31:58 +08:00
String validate_unicode_identifier ( ) const ;
2022-07-18 17:58:27 -07:00
String validate_filename ( ) const ;
2021-01-28 12:48:12 -08:00
2024-08-23 14:30:51 +08:00
bool is_valid_ascii_identifier ( ) const ;
bool is_valid_unicode_identifier ( ) const ;
2021-06-16 10:24:34 -06:00
bool is_valid_int ( ) const ;
2014-02-09 22:10:30 -03:00
bool is_valid_float ( ) const ;
2016-10-20 09:58:00 -03:00
bool is_valid_hex_number ( bool p_with_prefix ) const ;
2014-02-09 22:10:30 -03:00
bool is_valid_html_color ( ) const ;
bool is_valid_ip_address ( ) const ;
2019-04-08 19:18:03 -03:00
bool is_valid_filename ( ) const ;
2014-02-09 22:10:30 -03:00
2024-08-23 14:30:51 +08:00
// Use `is_valid_ascii_identifier()` instead. Kept for compatibility.
bool is_valid_identifier ( ) const { return is_valid_ascii_identifier ( ) ; }
2014-02-09 22:10:30 -03:00
/**
* The constructors must not depend on other overloads
*/
2018-07-25 03:11:03 +02:00
_FORCE_INLINE_ String ( ) { }
2024-12-20 13:22:46 +01:00
_FORCE_INLINE_ String ( const String & p_str ) = default ;
_FORCE_INLINE_ String ( String & & p_str ) = default ;
2025-01-25 13:58:50 +08:00
# ifdef SIZE_EXTRA
_NO_INLINE_ ~ String ( ) { }
# endif
2024-12-20 13:22:46 +01:00
_FORCE_INLINE_ void operator = ( const String & p_str ) { _cowdata = p_str . _cowdata ; }
2024-12-10 13:39:42 +01:00
_FORCE_INLINE_ void operator = ( String & & p_str ) { _cowdata = std : : move ( p_str . _cowdata ) ; }
2018-07-25 03:11:03 +02:00
2020-10-13 15:59:37 -03:00
Vector < uint8_t > to_ascii_buffer ( ) const ;
Vector < uint8_t > to_utf8_buffer ( ) const ;
Vector < uint8_t > to_utf16_buffer ( ) const ;
Vector < uint8_t > to_utf32_buffer ( ) const ;
2023-02-13 16:18:12 +02:00
Vector < uint8_t > to_wchar_buffer ( ) const ;
2024-09-13 09:19:26 +03:00
Vector < uint8_t > to_multibyte_char_buffer ( const String & p_encoding = String ( ) ) const ;
2020-10-13 15:59:37 -03:00
2024-12-07 02:28:43 +01:00
// Constructors for NULL terminated C strings.
String ( const char * p_cstr ) {
2025-03-24 12:25:48 +01:00
append_latin1 ( p_cstr ) ;
2024-12-07 02:28:43 +01:00
}
String ( const wchar_t * p_cstr ) {
2025-03-24 12:25:48 +01:00
append_wstring ( p_cstr ) ;
2024-12-07 02:28:43 +01:00
}
String ( const char32_t * p_cstr ) {
2025-03-24 12:25:48 +01:00
append_utf32 ( p_cstr ) ;
2024-12-07 02:28:43 +01:00
}
// Copy assignment for NULL terminated C strings.
void operator = ( const char * p_cstr ) {
2025-03-24 12:25:48 +01:00
clear ( ) ;
append_latin1 ( p_cstr ) ;
2024-12-07 02:28:43 +01:00
}
void operator = ( const wchar_t * p_cstr ) {
2025-03-24 12:25:48 +01:00
clear ( ) ;
append_wstring ( p_cstr ) ;
2024-12-07 02:28:43 +01:00
}
void operator = ( const char32_t * p_cstr ) {
2025-03-24 12:25:48 +01:00
clear ( ) ;
append_utf32 ( p_cstr ) ;
2024-12-07 02:28:43 +01:00
}
2014-02-09 22:10:30 -03:00
} ;
2025-03-07 13:16:32 +01:00
// Zero-constructing String initializes _cowdata.ptr() to nullptr and thus empty.
template < >
struct is_zero_constructible < String > : std : : true_type { } ;
2014-02-09 22:10:30 -03:00
bool operator = = ( const char * p_chr , const String & p_str ) ;
2020-07-27 13:43:20 +03:00
bool operator = = ( const wchar_t * p_chr , const String & p_str ) ;
2020-11-04 23:01:55 -03:00
bool operator ! = ( const char * p_chr , const String & p_str ) ;
bool operator ! = ( const wchar_t * p_chr , const String & p_str ) ;
2014-02-09 22:10:30 -03:00
String operator + ( const char * p_chr , const String & p_str ) ;
2020-07-27 13:43:20 +03:00
String operator + ( const wchar_t * p_chr , const String & p_str ) ;
String operator + ( char32_t p_chr , const String & p_str ) ;
2014-02-09 22:10:30 -03:00
String itos ( int64_t p_val ) ;
2019-11-01 16:16:31 +01:00
String uitos ( uint64_t p_val ) ;
2014-02-09 22:10:30 -03:00
String rtos ( double p_val ) ;
String rtoss ( double p_val ) ; //scientific version
struct NoCaseComparator {
bool operator ( ) ( const String & p_a , const String & p_b ) const {
return p_a . nocasecmp_to ( p_b ) < 0 ;
}
} ;
2017-05-11 20:07:59 +01:00
struct NaturalNoCaseComparator {
bool operator ( ) ( const String & p_a , const String & p_b ) const {
return p_a . naturalnocasecmp_to ( p_b ) < 0 ;
}
} ;
2024-02-02 16:50:23 +01:00
struct FileNoCaseComparator {
bool operator ( ) ( const String & p_a , const String & p_b ) const {
return p_a . filenocasecmp_to ( p_b ) < 0 ;
}
} ;
2014-02-09 22:10:30 -03:00
/* end of namespace */
2020-03-18 18:34:36 +01:00
// Tool translate (TTR and variants) for the editor UI,
// and doc translate for the class reference (DTR).
2016-05-17 18:27:15 -03:00
# ifdef TOOLS_ENABLED
2020-03-18 18:34:36 +01:00
// Gets parsed.
2020-07-16 10:52:06 +02:00
String TTR ( const String & p_text , const String & p_context = " " ) ;
String TTRN ( const String & p_text , const String & p_text_plural , int p_n , const String & p_context = " " ) ;
String DTR ( const String & p_text , const String & p_context = " " ) ;
String DTRN ( const String & p_text , const String & p_text_plural , int p_n , const String & p_context = " " ) ;
2020-03-18 18:34:36 +01:00
// Use for C strings.
2019-06-16 21:57:34 +02:00
# define TTRC(m_value) (m_value)
2020-03-18 18:34:36 +01:00
// Use to avoid parsing (for use later with C strings).
2019-04-08 19:18:03 -03:00
# define TTRGET(m_value) TTR(m_value)
2014-02-09 22:10:30 -03:00
2016-05-17 18:27:15 -03:00
# else
2019-04-08 19:18:03 -03:00
# define TTRC(m_value) (m_value)
2019-06-16 21:57:34 +02:00
# define TTRGET(m_value) (m_value)
2016-05-17 18:27:15 -03:00
# endif
2022-05-19 14:08:47 +08:00
// Use this to mark property names for editor translation.
// Often for dynamic properties defined in _get_property_list().
// Property names defined directly inside EDITOR_DEF, GLOBAL_DEF, and ADD_PROPERTY macros don't need this.
# define PNAME(m_value) (m_value)
// Similar to PNAME, but to mark groups, i.e. properties with PROPERTY_USAGE_GROUP.
// Groups defined directly inside ADD_GROUP macros don't need this.
// The arguments are the same as ADD_GROUP. m_prefix is only used for extraction.
# define GNAME(m_value, m_prefix) (m_value)
2020-03-18 18:34:36 +01:00
// Runtime translate for the public node API.
2020-07-16 10:52:06 +02:00
String RTR ( const String & p_text , const String & p_context = " " ) ;
String RTRN ( const String & p_text , const String & p_text_plural , int p_n , const String & p_context = " " ) ;
2016-05-17 18:27:15 -03:00
2023-12-15 20:56:06 -03:00
/**
* " Extractable TRanslate " . Used for strings that can appear inside an exported
* project ( such as the ones in nodes like ` FileDialog ` ) , which are made possible
* to add in the POT generator . A translation context can optionally be specified
* to disambiguate between identical source strings in translations .
* When placeholders are desired , use vformat ( ETR ( " Example: %s " ) , some_string ) ` .
* If a string mentions a quantity ( and may therefore need a dynamic plural form ) ,
* use ` ETRN ( ) ` instead of ` ETR ( ) ` .
*
* NOTE : This function is for string extraction only , and will just return the
* string it was given . The translation itself should be done internally by nodes
* with ` atr ( ) ` instead .
*/
_FORCE_INLINE_ String ETR ( const String & p_text , const String & p_context = " " ) {
return p_text ;
}
/**
* " Extractable TRanslate for N items " . Used for strings that can appear inside an
* exported project ( such as the ones in nodes like ` FileDialog ` ) , which are made
* possible to add in the POT generator . A translation context can optionally be
* specified to disambiguate between identical source strings in translations .
* Use ` ETR ( ) ` if the string doesn ' t need dynamic plural form . When placeholders
* are desired , use ` vformat ( ETRN ( " %d item " , " %d items " , some_integer ) , some_integer ) ` .
* The placeholder must be present in both strings to avoid run - time warnings in ` vformat ( ) ` .
*
* NOTE : This function is for string extraction only , and will just return the
* string it was given . The translation itself should be done internally by nodes
* with ` atr ( ) ` instead .
*/
_FORCE_INLINE_ String ETRN ( const String & p_text , const String & p_text_plural , int p_n , const String & p_context = " " ) {
if ( p_n = = 1 ) {
return p_text ;
}
return p_text_plural ;
}
2017-12-23 09:59:54 +01:00
bool select_word ( const String & p_s , int p_col , int & r_beg , int & r_end ) ;
2020-11-10 18:31:33 -03:00
template < typename . . . P >
_FORCE_INLINE_ Vector < String > sarray ( P . . . p_args ) {
2025-05-15 22:17:12 +08:00
return Vector < String > ( { String ( p_args ) . . . } ) ;
2020-11-10 18:31:33 -03:00
}