godot/core/string/ustring.cpp

/**************************************************************************/
/*  ustring.cpp                                                           */
/**************************************************************************/
/*                         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.                 */
/**************************************************************************/

#include "ustring.h"

#include "core/crypto/crypto_core.h"
#include "core/math/color.h"
#include "core/math/math_funcs.h"
#include "core/os/memory.h"
#include "core/string/print_string.h"
#include "core/string/string_name.h"
#include "core/string/translation_server.h"
#include "core/string/ucaps.h"
#include "core/variant/variant.h"
#include "core/version_generated.gen.h"

#include <stdio.h>
#include <stdlib.h>
#include <cstdint>

#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS
#endif

#if defined(MINGW_ENABLED) || defined(_MSC_VER)
#define snprintf
#endif

static const int MAX_DECIMALS =;

static _FORCE_INLINE_ char32_t lower_case(char32_t c) {}

const char CharString::_null =;
const char16_t Char16String::_null =;
const char32_t String::_null =;
const char32_t String::_replacement_char =;

bool select_word(const String &p_s, int p_col, int &r_beg, int &r_end) {}

/*************************************************************************/
/*  Char16String                                                         */
/*************************************************************************/

bool Char16String::operator<(const Char16String &p_right) const {}

Char16String &Char16String::operator+=(char16_t p_char) {}

void Char16String::operator=(const char16_t *p_cstr) {}

const char16_t *Char16String::get_data() const {}

void Char16String::copy_from(const char16_t *p_cstr) {}

/*************************************************************************/
/*  CharString                                                           */
/*************************************************************************/

bool CharString::operator<(const CharString &p_right) const {}

bool CharString::operator==(const CharString &p_right) const {}

CharString &CharString::operator+=(char p_char) {}

void CharString::operator=(const char *p_cstr) {}

const char *CharString::get_data() const {}

void CharString::copy_from(const char *p_cstr) {}

/*************************************************************************/
/*  String                                                               */
/*************************************************************************/

Error String::parse_url(String &r_scheme, String &r_host, int &r_port, String &r_path) const {}

void String::copy_from(const char *p_cstr) {}

void String::copy_from(const char *p_cstr, const int p_clip_to) {}

void String::copy_from(const wchar_t *p_cstr) {}

void String::copy_from(const wchar_t *p_cstr, const int p_clip_to) {}

void String::copy_from(const char32_t &p_char) {}

void String::copy_from(const char32_t *p_cstr) {}

void String::copy_from(const char32_t *p_cstr, const int p_clip_to) {}

// assumes the following have already been validated:
// p_char != nullptr
// p_length > 0
// p_length <= p_char strlen
void String::copy_from_unchecked(const char32_t *p_char, const int p_length) {}

void String::operator=(const char *p_str) {}

void String::operator=(const char32_t *p_str) {}

void String::operator=(const wchar_t *p_str) {}

String String::operator+(const String &p_str) const {}

String String::operator+(char32_t p_char) const {}

String operator+(const char *p_chr, const String &p_str) {}

String operator+(const wchar_t *p_chr, const String &p_str) {}

String operator+(char32_t p_chr, const String &p_str) {}

String &String::operator+=(const String &p_str) {}

String &String::operator+=(const char *p_str) {}

String &String::operator+=(const wchar_t *p_str) {}

String &String::operator+=(const char32_t *p_str) {}

String &String::operator+=(char32_t p_char) {}

bool String::operator==(const char *p_str) const {}

bool String::operator==(const wchar_t *p_str) const {}

bool String::operator==(const char32_t *p_str) const {}

bool String::operator==(const String &p_str) const {}

bool String::operator==(const StrRange &p_str_range) const {}

bool operator==(const char *p_chr, const String &p_str) {}

bool operator==(const wchar_t *p_chr, const String &p_str) {}

bool operator!=(const char *p_chr, const String &p_str) {}

bool operator!=(const wchar_t *p_chr, const String &p_str) {}

bool String::operator!=(const char *p_str) const {}

bool String::operator!=(const wchar_t *p_str) const {}

bool String::operator!=(const char32_t *p_str) const {}

bool String::operator!=(const String &p_str) const {}

bool String::operator<=(const String &p_str) const {}

bool String::operator>(const String &p_str) const {}

bool String::operator>=(const String &p_str) const {}

bool String::operator<(const char *p_str) const {}

bool String::operator<(const wchar_t *p_str) const {}

bool String::operator<(const char32_t *p_str) const {}

bool String::operator<(const String &p_str) const {}

signed char String::nocasecmp_to(const String &p_str) const {}

signed char String::casecmp_to(const String &p_str) const {}

static _FORCE_INLINE_ signed char natural_cmp_common(const char32_t *&r_this_str, const char32_t *&r_that_str) {}

static _FORCE_INLINE_ signed char naturalcasecmp_to_base(const char32_t *p_this_str, const char32_t *p_that_str) {}

signed char String::naturalcasecmp_to(const String &p_str) const {}

static _FORCE_INLINE_ signed char naturalnocasecmp_to_base(const char32_t *p_this_str, const char32_t *p_that_str) {}

signed char String::naturalnocasecmp_to(const String &p_str) const {}

static _FORCE_INLINE_ signed char file_cmp_common(const char32_t *&r_this_str, const char32_t *&r_that_str) {}

signed char String::filecasecmp_to(const String &p_str) const {}

signed char String::filenocasecmp_to(const String &p_str) const {}

const char32_t *String::get_data() const {}

String String::_camelcase_to_underscore() const {}

String String::capitalize() const {}

String String::to_camel_case() const {}

String String::to_pascal_case() const {}

String String::to_snake_case() const {}

String String::get_with_code_lines() const {}

int String::get_slice_count(const String &p_splitter) const {}

int String::get_slice_count(const char *p_splitter) const {}

String String::get_slice(const String &p_splitter, int p_slice) const {}

String String::get_slice(const char *p_splitter, int p_slice) const {}

String String::get_slicec(char32_t p_splitter, int p_slice) const {}

Vector<String> String::split_spaces() const {}

Vector<String> String::split(const String &p_splitter, bool p_allow_empty, int p_maxsplit) const {}

Vector<String> String::split(const char *p_splitter, bool p_allow_empty, int p_maxsplit) const {}

Vector<String> String::rsplit(const String &p_splitter, bool p_allow_empty, int p_maxsplit) const {}

Vector<String> String::rsplit(const char *p_splitter, bool p_allow_empty, int p_maxsplit) const {}

Vector<double> String::split_floats(const String &p_splitter, bool p_allow_empty) const {}

Vector<float> String::split_floats_mk(const Vector<String> &p_splitters, bool p_allow_empty) const {}

Vector<int> String::split_ints(const String &p_splitter, bool p_allow_empty) const {}

Vector<int> String::split_ints_mk(const Vector<String> &p_splitters, bool p_allow_empty) const {}

String String::join(const Vector<String> &parts) const {}

char32_t String::char_uppercase(char32_t p_char) {}

char32_t String::char_lowercase(char32_t p_char) {}

String String::to_upper() const {}

String String::to_lower() const {}

String String::chr(char32_t p_char) {}

String String::num(double p_num, int p_decimals) {}

String String::num_int64(int64_t p_num, int base, bool capitalize_hex) {}

String String::num_uint64(uint64_t p_num, int base, bool capitalize_hex) {}

String String::num_real(double p_num, bool p_trailing) {}

String String::num_scientific(double p_num) {}

String String::md5(const uint8_t *p_md5) {}

String String::hex_encode_buffer(const uint8_t *p_buffer, int p_len) {}

Vector<uint8_t> String::hex_decode() const {}

void String::print_unicode_error(const String &p_message, bool p_critical) const {}

CharString String::ascii(bool p_allow_extended) const {}

String String::utf8(const char *p_utf8, int p_len) {}

Error String::parse_utf8(const char *p_utf8, int p_len, bool p_skip_cr) {}

CharString String::utf8() const {}

String String::utf16(const char16_t *p_utf16, int p_len) {}

Error String::parse_utf16(const char16_t *p_utf16, int p_len, bool p_default_little_endian) {}

Char16String String::utf16() const {}

String::String(const char *p_str) {}

String::String(const wchar_t *p_str) {}

String::String(const char32_t *p_str) {}

String::String(const char *p_str, int p_clip_to_len) {}

String::String(const wchar_t *p_str, int p_clip_to_len) {}

String::String(const char32_t *p_str, int p_clip_to_len) {}

String::String(const StrRange &p_range) {}

int64_t String::hex_to_int() const {}

int64_t String::bin_to_int() const {}

int64_t String::to_int() const {}

int64_t String::to_int(const char *p_str, int p_len) {}

int64_t String::to_int(const wchar_t *p_str, int p_len) {}

bool String::is_numeric() const {}

template <typename C>
static double built_in_strtod(
		/* A decimal ASCII floating-point number,
		 * optionally preceded by white space. Must
		 * have form "-I.FE-X", where I is the integer
		 * part of the mantissa, F is the fractional
		 * part of the mantissa, and X is the
		 * exponent. Either of the signs may be "+",
		 * "-", or omitted. Either I or F may be
		 * omitted, or both. The decimal point isn't
		 * necessary unless F is present. The "E" may
		 * actually be an "e". E and X may both be
		 * omitted (but not just one). */
		const C *string,
		/* If non-nullptr, store terminating Cacter's
		 * address here. */
		C **endPtr = nullptr) {}

#define READING_SIGN
#define READING_INT
#define READING_DEC
#define READING_EXP
#define READING_DONE

double String::to_float(const char *p_str) {}

double String::to_float(const char32_t *p_str, const char32_t **r_end) {}

double String::to_float(const wchar_t *p_str, const wchar_t **r_end) {}

uint32_t String::num_characters(int64_t p_int) {}

int64_t String::to_int(const char32_t *p_str, int p_len, bool p_clamp) {}

double String::to_float() const {}

uint32_t String::hash(const char *p_cstr) {}

uint32_t String::hash(const char *p_cstr, int p_len) {}

uint32_t String::hash(const wchar_t *p_cstr, int p_len) {}

uint32_t String::hash(const wchar_t *p_cstr) {}

uint32_t String::hash(const char32_t *p_cstr, int p_len) {}

uint32_t String::hash(const char32_t *p_cstr) {}

uint32_t String::hash() const {}

uint64_t String::hash64() const {}

String String::md5_text() const {}

String String::sha1_text() const {}

String String::sha256_text() const {}

Vector<uint8_t> String::md5_buffer() const {}

Vector<uint8_t> String::sha1_buffer() const {}

Vector<uint8_t> String::sha256_buffer() const {}

String String::insert(int p_at_pos, const String &p_string) const {}

String String::erase(int p_pos, int p_chars) const {}

String String::substr(int p_from, int p_chars) const {}

int String::find(const String &p_str, int p_from) const {}

int String::find(const char *p_str, int p_from) const {}

int String::find_char(const char32_t &p_char, int p_from) const {}

int String::findmk(const Vector<String> &p_keys, int p_from, int *r_key) const {}

int String::findn(const String &p_str, int p_from) const {}

int String::findn(const char *p_str, int p_from) const {}

int String::rfind(const String &p_str, int p_from) const {}

int String::rfind(const char *p_str, int p_from) const {}

int String::rfindn(const String &p_str, int p_from) const {}

int String::rfindn(const char *p_str, int p_from) const {}

bool String::ends_with(const String &p_string) const {}

bool String::ends_with(const char *p_string) const {}

bool String::begins_with(const String &p_string) const {}

bool String::begins_with(const char *p_string) const {}

bool String::is_enclosed_in(const String &p_string) const {}

bool String::is_subsequence_of(const String &p_string) const {}

bool String::is_subsequence_ofn(const String &p_string) const {}

bool String::is_quoted() const {}

int String::_count(const String &p_string, int p_from, int p_to, bool p_case_insensitive) const {}

int String::_count(const char *p_string, int p_from, int p_to, bool p_case_insensitive) const {}

int String::count(const String &p_string, int p_from, int p_to) const {}

int String::count(const char *p_string, int p_from, int p_to) const {}

int String::countn(const String &p_string, int p_from, int p_to) const {}

int String::countn(const char *p_string, int p_from, int p_to) const {}

bool String::_base_is_subsequence_of(const String &p_string, bool case_insensitive) const {}

Vector<String> String::bigrams() const {}

// Similarity according to Sorensen-Dice coefficient
float String::similarity(const String &p_string) const {}

static bool _wildcard_match(const char32_t *p_pattern, const char32_t *p_string, bool p_case_sensitive) {}

bool String::match(const String &p_wildcard) const {}

bool String::matchn(const String &p_wildcard) const {}

String String::format(const Variant &values, const String &placeholder) const {}

static String _replace_common(const String &p_this, const String &p_key, const String &p_with, bool p_case_insensitive) {}

static String _replace_common(const String &p_this, char const *p_key, char const *p_with, bool p_case_insensitive) {}

String String::replace(const String &p_key, const String &p_with) const {}

String String::replace(const char *p_key, const char *p_with) const {}

String String::replace_first(const String &p_key, const String &p_with) const {}

String String::replace_first(const char *p_key, const char *p_with) const {}

String String::replacen(const String &p_key, const String &p_with) const {}

String String::replacen(const char *p_key, const char *p_with) const {}

String String::repeat(int p_count) const {}

String String::reverse() const {}

String String::left(int p_len) const {}

String String::right(int p_len) const {}

char32_t String::unicode_at(int p_idx) const {}

String String::indent(const String &p_prefix) const {}

String String::dedent() const {}

String String::strip_edges(bool left, bool right) const {}

String String::strip_escapes() const {}

String String::lstrip(const String &p_chars) const {}

String String::rstrip(const String &p_chars) const {}

bool String::is_network_share_path() const {}

String String::simplify_path() const {}

static int _humanize_digits(int p_num) {}

String String::humanize_size(uint64_t p_size) {}

bool String::is_absolute_path() const {}

String String::validate_ascii_identifier() const {}

bool String::is_valid_ascii_identifier() const {}

bool String::is_valid_unicode_identifier() const {}

bool String::is_valid_string() const {}

String String::uri_encode() const {}

String String::uri_decode() const {}

String String::c_unescape() const {}

String String::c_escape() const {}

String String::c_escape_multiline() const {}

String String::json_escape() const {}

String String::xml_escape(bool p_escape_quotes) const {}

static _FORCE_INLINE_ int _xml_unescape(const char32_t *p_src, int p_src_len, char32_t *p_dst) {}

String String::xml_unescape() const {}

String String::pad_decimals(int p_digits) const {}

String String::pad_zeros(int p_digits) const {}

String String::trim_prefix(const String &p_prefix) const {}

String String::trim_prefix(const char *p_prefix) const {}

String String::trim_suffix(const String &p_suffix) const {}

String String::trim_suffix(const char *p_suffix) const {}

bool String::is_valid_int() const {}

bool String::is_valid_hex_number(bool p_with_prefix) const {}

bool String::is_valid_float() const {}

String String::path_to_file(const String &p_path) const {}

String String::path_to(const String &p_path) const {}

bool String::is_valid_html_color() const {}

// Changes made to the set of invalid filename characters must also be reflected in the String documentation for is_valid_filename.
static const char *invalid_filename_characters =;

bool String::is_valid_filename() const {}

String String::validate_filename() const {}

bool String::is_valid_ip_address() const {}

bool String::is_resource_file() const {}

bool String::is_relative_path() const {}

String String::get_base_dir() const {}

String String::get_file() const {}

String String::get_extension() const {}

String String::path_join(const String &p_file) const {}

String String::property_name_encode() const {}

// Changes made to the set of invalid characters must also be reflected in the String documentation.

static const char32_t invalid_node_name_characters[] =;

String String::get_invalid_node_name_characters(bool p_allow_internal) {}

String String::validate_node_name() const {}

String String::get_basename() const {}

String itos(int64_t p_val) {}

String uitos(uint64_t p_val) {}

String rtos(double p_val) {}

String rtoss(double p_val) {}

// Right-pad with a character.
String String::rpad(int min_length, const String &character) const {}

// Left-pad with a character.
String String::lpad(int min_length, const String &character) const {}

// sprintf is implemented in GDScript via:
//   "fish %s pie" % "frog"
//   "fish %s %d pie" % ["frog", 12]
// In case of an error, the string returned is the error description and "error" is true.
String String::sprintf(const Array &values, bool *error) const {}

String String::quote(const String &quotechar) const {}

String String::unquote() const {}

Vector<uint8_t> String::to_ascii_buffer() const {}

Vector<uint8_t> String::to_utf8_buffer() const {}

Vector<uint8_t> String::to_utf16_buffer() const {}

Vector<uint8_t> String::to_utf32_buffer() const {}

Vector<uint8_t> String::to_wchar_buffer() const {}

#ifdef TOOLS_ENABLED
/**
 * "Tools TRanslate". Performs string replacement for internationalization
 * within the editor. A translation context can optionally be specified to
 * disambiguate between identical source strings in translations. When
 * placeholders are desired, use `vformat(TTR("Example: %s"), some_string)`.
 * If a string mentions a quantity (and may therefore need a dynamic plural form),
 * use `TTRN()` instead of `TTR()`.
 *
 * NOTE: Only use `TTR()` in editor-only code (typically within the `editor/` folder).
 * For translations that can be supplied by exported projects, use `RTR()` instead.
 */
String TTR(const String &p_text, const String &p_context) {}

/**
 * "Tools TRanslate for N items". Performs string replacement for
 * internationalization within the editor. A translation context can optionally
 * be specified to disambiguate between identical source strings in
 * translations. Use `TTR()` if the string doesn't need dynamic plural form.
 * When placeholders are desired, use
 * `vformat(TTRN("%d item", "%d items", some_integer), some_integer)`.
 * The placeholder must be present in both strings to avoid run-time warnings in `vformat()`.
 *
 * NOTE: Only use `TTRN()` in editor-only code (typically within the `editor/` folder).
 * For translations that can be supplied by exported projects, use `RTRN()` instead.
 */
String TTRN(const String &p_text, const String &p_text_plural, int p_n, const String &p_context) {}

/**
 * "Docs TRanslate". Used for the editor class reference documentation,
 * handling descriptions extracted from the XML.
 * It also replaces `$DOCS_URL` with the actual URL to the documentation's branch,
 * to allow dehardcoding it in the XML and doing proper substitutions everywhere.
 */
String DTR(const String &p_text, const String &p_context) {}

/**
 * "Docs TRanslate for N items". Used for the editor class reference documentation
 * (with support for plurals), handling descriptions extracted from the XML.
 * It also replaces `$DOCS_URL` with the actual URL to the documentation's branch,
 * to allow dehardcoding it in the XML and doing proper substitutions everywhere.
 */
String DTRN(const String &p_text, const String &p_text_plural, int p_n, const String &p_context) {}
#endif

/**
 * "Run-time TRanslate". Performs string replacement for internationalization
 * without the editor. A translation context can optionally be specified to
 * disambiguate between identical source strings in translations. When
 * placeholders are desired, use `vformat(RTR("Example: %s"), some_string)`.
 * If a string mentions a quantity (and may therefore need a dynamic plural form),
 * use `RTRN()` instead of `RTR()`.
 *
 * NOTE: Do not use `RTR()` in editor-only code (typically within the `editor/`
 * folder). For editor translations, use `TTR()` instead.
 */
String RTR(const String &p_text, const String &p_context) {}

/**
 * "Run-time TRanslate for N items". Performs string replacement for
 * internationalization without the editor. A translation context can optionally
 * be specified to disambiguate between identical source strings in translations.
 * Use `RTR()` if the string doesn't need dynamic plural form. When placeholders
 * are desired, use `vformat(RTRN("%d item", "%d items", some_integer), some_integer)`.
 * The placeholder must be present in both strings to avoid run-time warnings in `vformat()`.
 *
 * NOTE: Do not use `RTRN()` in editor-only code (typically within the `editor/`
 * folder). For editor translations, use `TTRN()` instead.
 */
String RTRN(const String &p_text, const String &p_text_plural, int p_n, const String &p_context) {}