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;
}

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

一看就懵。哪里有之前用的带%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();

其实还有更简单的用法,不过在代码提示与自动完成情况下,这样写代码更为舒爽。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/26974.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

excel - left函数

介绍: left 函数用于从文本字符串的开头提取指定数量的字符。 用法: 它的语法如下&#xff1a; left(文本, 数量)参数介绍如下: 文本&#xff1a;要从中提取字符的文本字符串。数量&#xff1a;要提取的字符的数量。 举例: 以下是一个例子来说明 left 函数的使用方法。假…

Node.js-模块化理解及基本使用

模块化的定义 讲一个复杂的程序文件按照一定的规则拆分成多个独立的小文件&#xff0c;这些小文件就是小模块&#xff0c;这就是模块化。 每个小模块内部的数据是私有的&#xff0c;可以暴露内部数据给外部其他模块使用。 模块化优点 减少命名的冲突提高复用性提高可维护性按需…

快速排序和qsort函数详解详解qsort函数

&#x1f495;是非成败转头空&#xff0c;青山依旧在&#xff0c;几度夕阳红&#x1f495; 作者&#xff1a;Mylvzi 文章主要内容&#xff1a;快速排序和qsort函数详解 前言&#xff1a; 我们之前学习过冒泡排序&#xff0c;冒泡排序尽管很方便&#xff0c;但也存在一些局限性…

信创优选,国产开源。Solon v2.4.2 发布

Solon 是什么开源项目&#xff1f; 一个&#xff0c;Java 新的生态型应用开发框架。它从零开始构建&#xff0c;有自己的标准规范与开放生态&#xff08;历时五年&#xff0c;已有全球第二级别的生态规模&#xff09;。与其他框架相比&#xff0c;它解决了两个重要的痛点&…

Session与Cookie的区别(五)

储存状态的方式 小明的故事说完了&#xff0c;该来把上面这一段变成网络的实际案例了。其实在网络世界中问题也是一样的。 前面已经提到过我们会把状态存在 Cookie 里面&#xff0c;让 Request 之间能够变得有关联。 假设我们今天要来做一个会员系统&#xff0c;那我要怎么知道…

vue 列表|表格环境中的下拉菜单

elementui组件为vue提供了各式各样的ui组件&#xff0c;但均为各类最为基本的控件&#xff0c;没有提供业务级的使用案例&#xff0c;为此进行扩展补充。 vue-elementui 基本入门使用 一、下拉菜单 下拉菜单与html中的select控件有所差距&#xff0c;select为表单控件的一员页…

windows(iis)服务器部署安装wordpress(php)网站教程

该教程包含iis安装,php安装,mysql安装,php网站部署上线,windows服务部署php网站,只需要这一篇文章就够了。 该教程为iis服务器部署安装wordpress(php)网站教程,同样适用wordpress网站迁移。 配置要求 1、windows服务器安装iis windows服务器安装iis管理器 打开控制面…

项目中使用git vscode GitHubDesktopSetup-x64

一、使用git bash 1.使用git bash拉取gitee项目 1.在本地新建一个文件夹&#xff08;这个文件夹是用来存放从gitee上拉下来的项目的&#xff09; 2.在这个文件夹右键选择 git bash here 3.输入命令 git init (创建/初始化一个新的仓库) 4.输入命令 git remote add origin …

医学影像PACS临床信息系统源码

医学影像临床信息系统&#xff08;Picture Archiving and Communication Systems&#xff09;PACS是指从医疗影像设备中获得数字影像&#xff0c;利用高速网络进行存储、管理、传输的医疗影像信息管理系统。通过该系统&#xff0c;能实现影像数字化、无胶片化管理。 登记系统 …

配置Picgo图床之COS、OSS、Github图床

简介 PicGo是一款开源的图片上传和管理工具&#xff0c;它提供了简单易用的界面和丰富的功能&#xff0c;方便用户上传、管理和分享图片。 以下是PicGo的一些主要特点和功能&#xff1a; 图片上传&#xff1a;PicGo支持将本地图片快速上传到云存储服务&#xff0c;如七牛云、…

JVM 之 OopMap 和 RememberedSet

前几天看周志明的《深入 Java 虚拟机》&#xff0c;感觉对 OopMap 和 RememberedSet 的介绍&#xff0c;看起来不太容易理解清楚。今天查了一些资料&#xff0c;并结合自己的一些猜想&#xff0c;把对这两种数据结构的理解写出来。目的只是为了简单易懂&#xff0c;而且多有推测…

解决Vue+Element UI使用表单rules国际化时From表单验证信息不能实时更新

说明&#xff1a;该篇博客是博主一字一码编写的&#xff0c;实属不易&#xff0c;请尊重原创&#xff0c;谢谢大家&#xff01; 博主在工作之余开始进行自动化测试平台的开发&#xff0c;虽然已经996一个月了但是还是在使劲挤时间做这件事情&#xff0c;目前平台使用前端框架vu…

LangChain手记 Overview

整理并翻译自DeepLearning.AILangChain的官方课程&#xff1a;Overview 综述&#xff08;Overview&#xff09; LangChain是为大模型应用开发设计的开源框架 LangChain目前提供Python和JavaScript&#xff08;TypeScript&#xff09;两种语言的包 LangChain的主攻方向是聚合和…

扩散模型实战(三):扩散模型的应用

推荐阅读列表&#xff1a; 扩散模型实战&#xff08;一&#xff09;&#xff1a;基本原理介绍 扩散模型实战&#xff08;二&#xff09;&#xff1a;扩散模型的发展 扩散只是一种思想&#xff0c;扩散模型也并非固定的深度网络结构。除此之外&#xff0c;如果将扩散的思想融入…

MySQL 优化

问题描述 MySQL 的性能优化分为四个部分&#xff1a; 硬件和操作系统层面的优化架构设计层面的优化MySQL 程序配置优SQL 优化 一、硬件及操作系统层面优化 从硬件层面来说&#xff0c;影响 Mysql 性能的因素有&#xff0c;CPU、可用内存大小、磁盘读写速度、 网络带宽。 从操作…

docker solr-8.11.2安装部署

历史背景 现在solr官网仅能够下载到最新版本的安装包。并且支持docker。现在就用docker来部署一下 1、准备工作 docker环境部署&#xff08;这个自己百度一下哈&#xff0c;很简单两个命令就能解决&#xff09; yum -y install yum-utils yum -y install docker-ce 安装命令…

爬虫 学习HTML标签和元素的基本概念,了解网页的结构和内容

HTML&#xff08;Hypertext Markup Language&#xff09;是一种用于创建网页的标记语言&#xff0c;由一系列的标签组成。标签使用尖括号&#xff08;< 和 >&#xff09;包围&#xff0c;并且通常成对出现&#xff0c;一个是开始标签&#xff0c;一个是结束标签。 HTML文…

第7集丨Vue 江湖 —— 条件渲染

目录 一、v-show二、v-if2.1 基本使用2.2 条件渲染分组2.3 与 v-else-if、v-else 结合使用 三、v-if vs v-show四、测试案例 本节条件渲染所涉及到的指令有&#xff1a; v-showv-ifv-else-ifv-else 一、v-show 1. 用法&#xff1a; 语法: v-show" 表达式"&#xff…

FFmpeg 使用总结

FFmpeg 简介 FFmpeg的名称来自MPEG视频编码标准&#xff0c;前面的“FF”代表“Fast Forward”&#xff0c;FFmpeg是一套可以用来记录、转换数字音频、视频&#xff0c;并能将其转化为流的开源计算机程序。可以轻易地实现多种视频格式之间的相互转换。包括如下几个部分&#xf…

QT学习之旅 - Winsock入门

文章目录 服务端初始化为服务器创建套接字sockaddr和sockaddr_ininet_addrhtonl()、htons()、ntohl()、ntohs()四个函数htonl()函数htons()函数ntohs()函数ntohl()函数这些函数存在的意义(就是为了字节存放) 绑定getsockoptudp主函数处理 客户端 客户端和服务器应用程序的前几个…