| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | /**************************************************************************/ | 
					
						
							| 
									
										
										
										
											2019-02-12 13:30:56 +01:00
										 |  |  | /*  string_name.h                                                         */ | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | /**************************************************************************/ | 
					
						
							|  |  |  | /*                         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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-12 13:30:56 +01:00
										 |  |  | #ifndef STRING_NAME_H
 | 
					
						
							|  |  |  | #define STRING_NAME_H
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-11 18:13:45 +02:00
										 |  |  | #include "core/os/mutex.h"
 | 
					
						
							| 
									
										
										
										
											2020-11-07 19:33:38 -03:00
										 |  |  | #include "core/string/ustring.h"
 | 
					
						
							|  |  |  | #include "core/templates/safe_refcount.h"
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-16 12:23:32 +02:00
										 |  |  | #define UNIQUE_NODE_PREFIX "%"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-20 17:35:34 +01:00
										 |  |  | class Main; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | struct StaticCString { | 
					
						
							|  |  |  | 	const char *ptr; | 
					
						
							|  |  |  | 	static StaticCString create(const char *p_ptr); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class StringName { | 
					
						
							|  |  |  | 	enum { | 
					
						
							| 
									
										
										
										
											2021-07-17 18:22:52 -03:00
										 |  |  | 		STRING_TABLE_BITS = 16, | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		STRING_TABLE_LEN = 1 << STRING_TABLE_BITS, | 
					
						
							|  |  |  | 		STRING_TABLE_MASK = STRING_TABLE_LEN - 1 | 
					
						
							|  |  |  | 	}; | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	struct _Data { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		SafeRefCount refcount; | 
					
						
							| 
									
										
										
										
											2021-07-17 18:22:52 -03:00
										 |  |  | 		SafeNumeric<uint32_t> static_count; | 
					
						
							| 
									
										
										
										
											2020-05-12 17:01:17 +02:00
										 |  |  | 		const char *cname = nullptr; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		String name; | 
					
						
							| 
									
										
										
										
											2021-07-20 17:01:18 -03:00
										 |  |  | #ifdef DEBUG_ENABLED
 | 
					
						
							|  |  |  | 		uint32_t debug_references = 0; | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		String get_name() const { return cname ? String(cname) : name; } | 
					
						
							| 
									
										
										
										
											2024-05-30 13:24:48 -07:00
										 |  |  | 		bool operator==(const String &p_name) const; | 
					
						
							|  |  |  | 		bool operator!=(const String &p_name) const; | 
					
						
							|  |  |  | 		bool operator==(const char *p_name) const; | 
					
						
							|  |  |  | 		bool operator!=(const char *p_name) const; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-12 17:01:17 +02:00
										 |  |  | 		int idx = 0; | 
					
						
							|  |  |  | 		uint32_t hash = 0; | 
					
						
							|  |  |  | 		_Data *prev = nullptr; | 
					
						
							|  |  |  | 		_Data *next = nullptr; | 
					
						
							|  |  |  | 		_Data() {} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	}; | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-23 01:53:02 +02:00
										 |  |  | 	static inline _Data *_table[STRING_TABLE_LEN]; | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-12 17:01:17 +02:00
										 |  |  | 	_Data *_data = nullptr; | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	void unref(); | 
					
						
							|  |  |  | 	friend void register_core_types(); | 
					
						
							|  |  |  | 	friend void unregister_core_types(); | 
					
						
							| 
									
										
										
										
											2020-07-20 17:35:34 +01:00
										 |  |  | 	friend class Main; | 
					
						
							| 
									
										
										
										
											2024-07-23 01:53:02 +02:00
										 |  |  | 	static inline Mutex mutex; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	static void setup(); | 
					
						
							|  |  |  | 	static void cleanup(); | 
					
						
							| 
									
										
										
										
											2024-07-23 01:53:02 +02:00
										 |  |  | 	static inline bool configured = false; | 
					
						
							| 
									
										
										
										
											2021-07-20 17:01:18 -03:00
										 |  |  | #ifdef DEBUG_ENABLED
 | 
					
						
							|  |  |  | 	struct DebugSortReferences { | 
					
						
							|  |  |  | 		bool operator()(const _Data *p_left, const _Data *p_right) const { | 
					
						
							|  |  |  | 			return p_left->debug_references > p_right->debug_references; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-23 01:53:02 +02:00
										 |  |  | 	static inline bool debug_stringname = false; | 
					
						
							| 
									
										
										
										
											2021-07-20 17:01:18 -03:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	StringName(_Data *p_data) { _data = p_data; } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | public: | 
					
						
							| 
									
										
										
										
											2020-12-15 12:04:21 +00:00
										 |  |  | 	operator const void *() const { return (_data && (_data->cname || !_data->name.is_empty())) ? (void *)1 : nullptr; } | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	bool operator==(const String &p_name) const; | 
					
						
							|  |  |  | 	bool operator==(const char *p_name) const; | 
					
						
							|  |  |  | 	bool operator!=(const String &p_name) const; | 
					
						
							| 
									
										
										
										
											2022-12-20 17:22:44 +03:00
										 |  |  | 	bool operator!=(const char *p_name) const; | 
					
						
							| 
									
										
										
										
											2022-04-16 12:23:32 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-30 13:24:48 -07:00
										 |  |  | 	char32_t operator[](int p_index) const; | 
					
						
							|  |  |  | 	int length() const; | 
					
						
							|  |  |  | 	bool is_empty() const; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-16 12:23:32 +02:00
										 |  |  | 	_FORCE_INLINE_ bool is_node_unique_name() const { | 
					
						
							|  |  |  | 		if (!_data) { | 
					
						
							|  |  |  | 			return false; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (_data->cname != nullptr) { | 
					
						
							|  |  |  | 			return (char32_t)_data->cname[0] == (char32_t)UNIQUE_NODE_PREFIX[0]; | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			return (char32_t)_data->name[0] == (char32_t)UNIQUE_NODE_PREFIX[0]; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	_FORCE_INLINE_ bool operator<(const StringName &p_name) const { | 
					
						
							|  |  |  | 		return _data < p_name._data; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2023-05-18 13:25:40 +02:00
										 |  |  | 	_FORCE_INLINE_ bool operator<=(const StringName &p_name) const { | 
					
						
							|  |  |  | 		return _data <= p_name._data; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	_FORCE_INLINE_ bool operator>(const StringName &p_name) const { | 
					
						
							|  |  |  | 		return _data > p_name._data; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	_FORCE_INLINE_ bool operator>=(const StringName &p_name) const { | 
					
						
							|  |  |  | 		return _data >= p_name._data; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	_FORCE_INLINE_ bool operator==(const StringName &p_name) const { | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 		// the real magic of all this mess happens here.
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		// this is why path comparisons are very fast
 | 
					
						
							|  |  |  | 		return _data == p_name._data; | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	_FORCE_INLINE_ uint32_t hash() const { | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 		if (_data) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 			return _data->hash; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 			return 0; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-09-05 18:07:13 +02:00
										 |  |  | 	_FORCE_INLINE_ const void *data_unique_pointer() const { | 
					
						
							|  |  |  | 		return (void *)_data; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	bool operator!=(const StringName &p_name) const; | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-29 00:29:49 -03:00
										 |  |  | 	_FORCE_INLINE_ operator String() const { | 
					
						
							|  |  |  | 		if (_data) { | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 			if (_data->cname) { | 
					
						
							| 
									
										
										
										
											2015-06-29 00:29:49 -03:00
										 |  |  | 				return String(_data->cname); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 			} else { | 
					
						
							| 
									
										
										
										
											2015-06-29 00:29:49 -03:00
										 |  |  | 				return _data->name; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2015-06-29 00:29:49 -03:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return String(); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	static StringName search(const char *p_name); | 
					
						
							| 
									
										
										
										
											2020-07-27 13:43:20 +03:00
										 |  |  | 	static StringName search(const char32_t *p_name); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	static StringName search(const String &p_name); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	struct AlphCompare { | 
					
						
							|  |  |  | 		_FORCE_INLINE_ bool operator()(const StringName &l, const StringName &r) const { | 
					
						
							| 
									
										
										
										
											2017-12-16 15:31:30 +01:00
										 |  |  | 			const char *l_cname = l._data ? l._data->cname : ""; | 
					
						
							|  |  |  | 			const char *r_cname = r._data ? r._data->cname : ""; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (l_cname) { | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 				if (r_cname) { | 
					
						
							| 
									
										
										
										
											2017-12-16 15:31:30 +01:00
										 |  |  | 					return is_str_less(l_cname, r_cname); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 				} else { | 
					
						
							| 
									
										
										
										
											2017-12-16 15:31:30 +01:00
										 |  |  | 					return is_str_less(l_cname, r._data->name.ptr()); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2017-12-16 15:31:30 +01:00
										 |  |  | 			} else { | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 				if (r_cname) { | 
					
						
							| 
									
										
										
										
											2017-12-16 15:31:30 +01:00
										 |  |  | 					return is_str_less(l._data->name.ptr(), r_cname); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 				} else { | 
					
						
							| 
									
										
										
										
											2017-12-16 15:31:30 +01:00
										 |  |  | 					return is_str_less(l._data->name.ptr(), r._data->name.ptr()); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2017-12-16 15:31:30 +01:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-30 13:24:48 -07:00
										 |  |  | 	StringName &operator=(const StringName &p_name); | 
					
						
							| 
									
										
										
										
											2021-07-17 18:22:52 -03:00
										 |  |  | 	StringName(const char *p_name, bool p_static = false); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	StringName(const StringName &p_name); | 
					
						
							| 
									
										
										
										
											2021-07-17 18:22:52 -03:00
										 |  |  | 	StringName(const String &p_name, bool p_static = false); | 
					
						
							|  |  |  | 	StringName(const StaticCString &p_static_string, bool p_static = false); | 
					
						
							| 
									
										
										
										
											2020-05-12 17:01:17 +02:00
										 |  |  | 	StringName() {} | 
					
						
							| 
									
										
										
										
											2023-04-07 23:32:37 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	static void assign_static_unique_class_name(StringName *ptr, const char *p_name); | 
					
						
							| 
									
										
										
										
											2021-07-17 18:22:52 -03:00
										 |  |  | 	_FORCE_INLINE_ ~StringName() { | 
					
						
							|  |  |  | 		if (likely(configured) && _data) { //only free if configured
 | 
					
						
							|  |  |  | 			unref(); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-07-20 17:01:18 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | #ifdef DEBUG_ENABLED
 | 
					
						
							|  |  |  | 	static void set_debug_stringnames(bool p_enable) { debug_stringname = p_enable; } | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-04 23:01:55 -03:00
										 |  |  | bool operator==(const String &p_name, const StringName &p_string_name); | 
					
						
							|  |  |  | bool operator!=(const String &p_name, const StringName &p_string_name); | 
					
						
							|  |  |  | bool operator==(const char *p_name, const StringName &p_string_name); | 
					
						
							|  |  |  | bool operator!=(const char *p_name, const StringName &p_string_name); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-17 18:22:52 -03:00
										 |  |  | StringName _scs_create(const char *p_chr, bool p_static = false); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-08 08:55:20 +01:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * The SNAME macro is used to speed up StringName creation, as it allows caching it after the first usage in a very efficient way. | 
					
						
							|  |  |  |  * It should NOT be used everywhere, but instead in places where high performance is required and the creation of a StringName | 
					
						
							|  |  |  |  * can be costly. Places where it should be used are: | 
					
						
							|  |  |  |  * - Control::get_theme_*(<name> and Window::get_theme_*(<name> functions. | 
					
						
							|  |  |  |  * - emit_signal(<name>,..) function | 
					
						
							|  |  |  |  * - call_deferred(<name>,..) function | 
					
						
							| 
									
										
										
										
											2022-02-10 12:00:11 +01:00
										 |  |  |  * - Comparisons to a StringName in overridden _set and _get methods. | 
					
						
							| 
									
										
										
										
											2022-02-08 08:55:20 +01:00
										 |  |  |  * | 
					
						
							|  |  |  |  * Use in places that can be called hundreds of times per frame (or more) is recommended, but this situation is very rare. If in doubt, do not use. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-19 19:25:15 +02:00
										 |  |  | #define SNAME(m_arg) ([]() -> const StringName & { static StringName sname = _scs_create(m_arg, true); return sname; })()
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-12 13:30:56 +01:00
										 |  |  | #endif // STRING_NAME_H
 |