Godot 4 源码分析 - 增加格式化字符串功能

这篇具有很好参考价值的文章主要介绍了Godot 4 源码分析 - 增加格式化字符串功能。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Godot 4的主要字符串类型为String,已经设计得比较完善了,但有一个问题,格式化这块没怎么考虑。

String中有一个format函数,但这个函数只有两个参数,这咋用?

String String::format(const Variant &values, String placeholder) const {
	String new_string = String(this->ptr());

	if (values.get_type() == Variant::ARRAY) {
		Array values_arr = values;

		for (int i = 0; i < values_arr.size(); i++) {
			String i_as_str = String::num_int64(i);

			if (values_arr[i].get_type() == Variant::ARRAY) { //Array in Array structure [["name","RobotGuy"],[0,"godot"],["strength",9000.91]]
				Array value_arr = values_arr[i];

				if (value_arr.size() == 2) {
					Variant v_key = value_arr[0];
					String key = v_key;

					Variant v_val = value_arr[1];
					String val = v_val;

					new_string = new_string.replace(placeholder.replace("_", key), val);
				} else {
					ERR_PRINT(String("STRING.format Inner Array size != 2 ").ascii().get_data());
				}
			} else { //Array structure ["RobotGuy","Logis","rookie"]
				Variant v_val = values_arr[i];
				String val = v_val;

				if (placeholder.find("_") > -1) {
					new_string = new_string.replace(placeholder.replace("_", i_as_str), val);
				} else {
					new_string = new_string.replace_first(placeholder, val);
				}
			}
		}
	} else if (values.get_type() == Variant::DICTIONARY) {
		Dictionary d = values;
		List<Variant> keys;
		d.get_key_list(&keys);

		for (const Variant &key : keys) {
			new_string = new_string.replace(placeholder.replace("_", key), d[key]);
		}
	} else {
		ERR_PRINT(String("Invalid type: use Array or Dictionary.").ascii().get_data());
	}

	return new_string;
}

查找使用例子,都是这种效果

Godot 4 源码分析 - 增加格式化字符串功能,godot,python,windows

一看就懵。哪里有之前用的带%s %d...之类的格式化用得舒服。

动手实现一个

template <typename... Args>
static std::string str_format(const std::string &format, Args... args) {
	auto size_buf = std::snprintf(nullptr, 0, format.c_str(), args...) + 1;
	std::unique_ptr<char[]> buf(new (std::nothrow) char[size_buf]);

	if (!buf)
		return std::string("");

	std::snprintf(buf.get(), size_buf, format.c_str(), args...);
	return std::string(buf.get(), buf.get() + size_buf - 1);
}

template <typename... Args>
static String str_format(const std::u32string &format, Args... args) {
	auto size_buf = std::snprintf(nullptr, 0, TDrString::Convert_u32String_stdString(format).c_str(), args...) + 1;
	std::unique_ptr<char[]> buf(new (std::nothrow) char[size_buf]);

	if (!buf)
		return String(U"");

	std::string strFormat = TDrString::Convert_u32String_stdString(format);
	std::snprintf(buf.get(), size_buf, strFormat.c_str(), args...);
	std::string str(buf.get(), buf.get() + size_buf - 1);
	return String(str);
}

提供std::string与String两种格式化效果。之后使用方式:

cofs << U"ERROR" << str_format(U"函数 [%s] 调用失败:参数个数不匹配,形参 [%d] 个,实参 [%d]个", drFunCall.GetHint().c_str(), it->arguments.size(), drFunCall.arguments.size());

顺便再在网上转下,发现fmt库的评价不错。直接拉下来GitHub - fmtlib/fmt: A modern formatting library加入到源码中,可以使用

不过fmt的使用方式是{},有点新鲜,貌似与C++ 20兼容,那就先用上

fmt::format("[{}.Read] > 解析数据{}", prefixType, hint.utf8().ptr());

直接支持中文。

这个过程中发现一个小问题:std::string没法直接转成String,String类提供了一堆构造函数,但就是没有std::string

	String(const char *p_str);
	String(const wchar_t *p_str);
	String(const char32_t *p_str);
	String(const char *p_str, int p_clip_to_len);
	String(const wchar_t *p_str, int p_clip_to_len);
	String(const char32_t *p_str, int p_clip_to_len);
	String(const StrRange &p_range);

顺手增加String与std::string互相转化的逻辑:

头文件:
	String(const std::string &str);
	operator std::string();

源文件:
String::String(const std::string &str) {
	std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
	std::wstring formatted_wstring = converter.from_bytes(str);
	copy_from(formatted_wstring.c_str());
}		

String::operator std::string() {
	std::string utf8;
    const char32_t * utf32 = ptr();
	for (char32_t c : utf32) {
		if (c <= 0x7F) {
			utf8.push_back(static_cast<char>(c));
		} else if (c <= 0x7FF) {
			utf8.push_back(static_cast<char>((c >> 6) | 0xC0));
			utf8.push_back(static_cast<char>((c & 0x3F) | 0x80));
		} else if (c <= 0xFFFF) {
			utf8.push_back(static_cast<char>((c >> 12) | 0xE0));
			utf8.push_back(static_cast<char>(((c >> 6) & 0x3F) | 0x80));
			utf8.push_back(static_cast<char>((c & 0x3F) | 0x80));
		} else if (c <= 0x10FFFF) {
			utf8.push_back(static_cast<char>((c >> 18) | 0xF0));
			utf8.push_back(static_cast<char>(((c >> 12) & 0x3F) | 0x80));
			utf8.push_back(static_cast<char>(((c >> 6) & 0x3F) | 0x80));
			utf8.push_back(static_cast<char>((c & 0x3F) | 0x80));
		} else {
			throw std::invalid_argument("Invalid UTF-32 character.");
		}
	}
	return utf8;
}

这就方便了许多。

比如,要将Variant 转为 std::string,直接一路火花带闪电

Variant v;
...
std::string str = v.operator String().operator std::string();

其实还有更简单的用法,不过在代码提示与自动完成情况下,这样写代码更为舒爽。文章来源地址https://www.toymoban.com/news/detail-628462.html

到了这里,关于Godot 4 源码分析 - 增加格式化字符串功能的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Python入门篇】——Python基础语法(字符串格式化,表达式格式化和数据输入)

    作者简介: 辭七七,目前大一,正在学习C/C++,Java,Python等 作者主页: 七七的个人主页 文章收录专栏: Python入门,本专栏主要内容为Python的基础语法,Python中的选择循环语句,Python函数,Python的数据容器等。 欢迎大家点赞 👍 收藏 ⭐ 加关注哦!💖💖 目前通过%符号占位

    2024年02月05日
    浏览(46)
  • Python 的字符串格式化指南

    Python 中控制字符串格式通常有三种形式: % 占位符(格式化符) str.format() 函数 f-string 内嵌式 Python 最先开始格式化字符串是用 %,但它的致命缺点是支持的类型有限制,只支持 int,str,double 这三种类型,从而导致其他所有类型只能转换(强制转换)为这几个类型,还有如果

    2024年02月08日
    浏览(47)
  • 浅谈非栈上格式化字符串

    这里先浅分析修改返回地址的两种打法,分别是\\\"诸葛连弩\\\"和”四马分肥“ 本文例题 以陕西省赛easy_printf为主 简单看一看程序 需要先过一个判断然后进入vuln 进入后 有一个13次的循环 可以让我们操作 第一步 肯定要先leak出栈地址 程序基地址和libc基地址 第二步 修改ret地址

    2024年02月14日
    浏览(45)
  • 格式化字符串你都懂了吗

    今天跟大家聊聊字 符串的格式化 这部分内容。乍一听“ 格式化 ”这三个字,有的初学者可能会懵:难道这是要清空字符串的节奏? 其实不是的,恰恰相反,格式化字符串是为了让字符串变的更美观、更灵活。接下来就给大家详细介绍格式化字符串的概念以及具体用法。 格

    2024年02月04日
    浏览(45)
  • Python字符串格式化 (%操作符)

    在许多编程语言中都包含有格式化字符串的功能,比如C和Fortran语言中的格式化输入输出。在Python中内置有对字符串进行格式化的操作符是\\\"%\\\"。 模板 格式化字符串时,Python使用一个字符串作为模板。模板中有格式符,这些格式符为真实值预留位置,并说明真实数值应该呈现的

    2024年02月14日
    浏览(43)
  • Python 用户输入和字符串格式化指南

    Python 允许用户输入数据。这意味着我们可以向用户询问输入。在 Python 3.6 中,使用 input() 方法来获取用户输入。在 Python 2.7 中,使用 raw_input() 方法来获取用户输入。以下示例要求用户输入用户名,并在输入用户名后将其打印在屏幕上: Python 3.6: Python 2.7: 为了确保字符串按预

    2024年02月05日
    浏览(67)
  • 格式化字符串走过的坑 pwn109

    格式化字符串走过的坑 pwn109 今天做的一道题有一个坑我调试半天终于打通了,格式化字符串的坑,确实不少,东西也比较多容易忘记,怎么说呢,功夫在平时,经验少了 老规矩先看一下保护 Full RELRO意味着got不能修改也就是不能通过格式化字符串漏洞来改got表,但是nx保护关

    2024年04月08日
    浏览(49)
  • vmware 16增加硬盘容量并在Ubuntu 18.04上边格式化并挂载

    参考了《增加 VM虚拟机硬盘容量》 《Linux学习之分区挂载》中有给VMWare 16虚拟机添加一块硬盘的内容,需要先参考添加硬盘。 sudo mkfs.ext4 /dev/sda4 给 /dev/sda4 进行 ext4 格式化。 sudo mkdir /mountsda4 新建一个挂载目录。 sudo mount -t ext4 /dev/sda4 /mountsda4 将 /dev/sda4 挂载到 /mountsda4 。 d

    2024年02月09日
    浏览(43)
  • Java工具类——json字符串格式化处理

    在我们拿到一团未经格式化的json字符串时,非常不方便查看,比如这样 因此随手写了个工具类用来格式化json。注意,原json字符串必须语法无误,并且不包含换行、空格、缩进等,否则会保留下来。 ok废话不多说上代码 运行后效果

    2024年01月17日
    浏览(46)
  • Pandas中的字符串和时间转换与格式化

    Pandas 提供了若干个函数来格式化时间。 其中,最常用的是 to_datetime() 函数。 可以使用 to_datetime() 函数将一个字符串解析为时间,并指定字符串的格式。例如: 输出: 还可以使用 strftime() 函数将时间格式化为字符串。例如: 输出: 如果想要格式化某一列中的时间,可以使用

    2024年02月04日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包