Path: blob/master/modules/mono/utils/naming_utils.cpp
10279 views
/**************************************************************************/1/* naming_utils.cpp */2/**************************************************************************/3/* This file is part of: */4/* GODOT ENGINE */5/* https://godotengine.org */6/**************************************************************************/7/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */8/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */9/* */10/* Permission is hereby granted, free of charge, to any person obtaining */11/* a copy of this software and associated documentation files (the */12/* "Software"), to deal in the Software without restriction, including */13/* without limitation the rights to use, copy, modify, merge, publish, */14/* distribute, sublicense, and/or sell copies of the Software, and to */15/* permit persons to whom the Software is furnished to do so, subject to */16/* the following conditions: */17/* */18/* The above copyright notice and this permission notice shall be */19/* included in all copies or substantial portions of the Software. */20/* */21/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */22/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */23/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */24/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */25/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */26/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */27/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */28/**************************************************************************/2930#include "naming_utils.h"3132#include "core/string/ucaps.h"33#include "core/templates/hash_map.h"3435HashMap<String, String> _create_hashmap_from_vector(Vector<Pair<String, String>> vector) {36HashMap<String, String> hashmap = HashMap<String, String>(vector.size());37for (const Pair<String, String> &pair : vector) {38hashmap.insert(pair.first, pair.second);39}40return hashmap;41}4243// Hardcoded collection of PascalCase name conversions.44const HashMap<String, String> pascal_case_name_overrides = _create_hashmap_from_vector({45{ "BitMap", "Bitmap" },46{ "JSONRPC", "JsonRpc" },47{ "Object", "GodotObject" },48{ "OpenXRIPBinding", "OpenXRIPBinding" },49{ "SkeletonModification2DCCDIK", "SkeletonModification2DCcdik" },50{ "SkeletonModification2DFABRIK", "SkeletonModification2DFabrik" },51{ "SkeletonModification3DCCDIK", "SkeletonModification3DCcdik" },52{ "SkeletonModification3DFABRIK", "SkeletonModification3DFabrik" },53{ "System", "System_" },54{ "Thread", "GodotThread" },55});5657// Hardcoded collection of PascalCase part conversions.58const HashMap<String, String> pascal_case_part_overrides = _create_hashmap_from_vector({59{ "AA", "AA" }, // Anti Aliasing60{ "AO", "AO" }, // Ambient Occlusion61{ "FILENAME", "FileName" },62{ "FADEIN", "FadeIn" },63{ "FADEOUT", "FadeOut" },64{ "FX", "FX" },65{ "GI", "GI" }, // Global Illumination66{ "GZIP", "GZip" },67{ "HBOX", "HBox" }, // Horizontal Box68{ "ID", "Id" },69{ "IO", "IO" }, // Input/Output70{ "IP", "IP" }, // Internet Protocol71{ "IV", "IV" }, // Initialization Vector72{ "MACOS", "MacOS" },73{ "NODEPATH", "NodePath" },74{ "SPIRV", "SpirV" },75{ "STDIN", "StdIn" },76{ "STDOUT", "StdOut" },77{ "USERNAME", "UserName" },78{ "UV", "UV" },79{ "UV2", "UV2" },80{ "VBOX", "VBox" }, // Vertical Box81{ "WHITESPACE", "WhiteSpace" },82{ "WM", "WM" },83{ "XR", "XR" },84{ "XRAPI", "XRApi" },85});8687String _get_pascal_case_part_override(String p_part, bool p_input_is_upper = true) {88if (!p_input_is_upper) {89for (int i = 0; i < p_part.length(); i++) {90p_part[i] = _find_upper(p_part[i]);91}92}9394if (pascal_case_part_overrides.has(p_part)) {95return pascal_case_part_overrides.get(p_part);96}9798return String();99}100101Vector<String> _split_pascal_case(const String &p_identifier) {102Vector<String> parts;103int current_part_start = 0;104bool prev_was_upper = is_ascii_upper_case(p_identifier[0]);105for (int i = 1; i < p_identifier.length(); i++) {106if (prev_was_upper) {107if (is_digit(p_identifier[i]) || is_ascii_lower_case(p_identifier[i])) {108if (!is_digit(p_identifier[i])) {109// These conditions only apply when the separator is not a digit.110if (i - current_part_start == 1) {111// Upper character was only the beginning of a word.112prev_was_upper = false;113continue;114}115if (i != p_identifier.length()) {116// If this is not the last character, the last uppercase117// character is the start of the next word.118i--;119}120}121if (i - current_part_start > 0) {122parts.append(p_identifier.substr(current_part_start, i - current_part_start));123current_part_start = i;124prev_was_upper = false;125}126}127} else {128if (is_digit(p_identifier[i]) || is_ascii_upper_case(p_identifier[i])) {129parts.append(p_identifier.substr(current_part_start, i - current_part_start));130current_part_start = i;131prev_was_upper = true;132}133}134}135136// Add the rest of the identifier as the last part.137if (current_part_start != p_identifier.length()) {138parts.append(p_identifier.substr(current_part_start));139}140141return parts;142}143144String pascal_to_pascal_case(const String &p_identifier) {145if (p_identifier.length() == 0) {146return p_identifier;147}148149if (p_identifier.length() <= 2) {150return p_identifier.to_upper();151}152153if (pascal_case_name_overrides.has(p_identifier)) {154// Use hardcoded value for the identifier.155return pascal_case_name_overrides.get(p_identifier);156}157158Vector<String> parts = _split_pascal_case(p_identifier);159160String ret;161162for (String &part : parts) {163String part_override = _get_pascal_case_part_override(part);164if (!part_override.is_empty()) {165// Use hardcoded value for part.166ret += part_override;167continue;168}169170if (part.length() <= 2 && part.to_upper() == part) {171// Acronym of length 1 or 2.172for (int j = 0; j < part.length(); j++) {173part[j] = _find_upper(part[j]);174}175ret += part;176continue;177}178179part[0] = _find_upper(part[0]);180for (int i = 1; i < part.length(); i++) {181if (is_digit(part[i - 1])) {182// Use uppercase after digits.183part[i] = _find_upper(part[i]);184continue;185}186187part[i] = _find_lower(part[i]);188}189ret += part;190}191192return ret;193}194195String snake_to_pascal_case(const String &p_identifier, bool p_input_is_upper) {196String ret;197Vector<String> parts = p_identifier.split("_", true);198199for (int i = 0; i < parts.size(); i++) {200String part = parts[i];201202String part_override = _get_pascal_case_part_override(part, p_input_is_upper);203if (!part_override.is_empty()) {204// Use hardcoded value for part.205ret += part_override;206continue;207}208209if (!part.is_empty()) {210part[0] = _find_upper(part[0]);211for (int j = 1; j < part.length(); j++) {212if (is_digit(part[j - 1])) {213// Use uppercase after digits.214part[j] = _find_upper(part[j]);215continue;216}217218if (p_input_is_upper) {219part[j] = _find_lower(part[j]);220}221}222ret += part;223} else {224if (i == 0 || i == (parts.size() - 1)) {225// Preserve underscores at the beginning and end226ret += "_";227} else {228// Preserve contiguous underscores229if (parts[i - 1].length()) {230ret += "__";231} else {232ret += "_";233}234}235}236}237238return ret;239}240241String snake_to_camel_case(const String &p_identifier, bool p_input_is_upper) {242String ret;243Vector<String> parts = p_identifier.split("_", true);244245for (int i = 0; i < parts.size(); i++) {246String part = parts[i];247248String part_override = _get_pascal_case_part_override(part, p_input_is_upper);249if (!part_override.is_empty()) {250// Use hardcoded value for part.251if (i == 0) {252part_override[0] = _find_lower(part_override[0]);253}254ret += part_override;255continue;256}257258if (!part.is_empty()) {259if (i == 0) {260part[0] = _find_lower(part[0]);261} else {262part[0] = _find_upper(part[0]);263}264for (int j = 1; j < part.length(); j++) {265if (is_digit(part[j - 1])) {266// Use uppercase after digits.267part[j] = _find_upper(part[j]);268continue;269}270271if (p_input_is_upper) {272part[j] = _find_lower(part[j]);273}274}275ret += part;276} else {277if (i == 0 || i == (parts.size() - 1)) {278// Preserve underscores at the beginning and end279ret += "_";280} else {281// Preserve contiguous underscores282if (parts[i - 1].length()) {283ret += "__";284} else {285ret += "_";286}287}288}289}290291return ret;292}293294295