参数解析
Dimension MeasureStringToDimensionWithUnit(const std::string& value, bool& useDefaultUnit,
DimensionUnit defaultUnit = DimensionUnit::PX, float defaultValue = 0.0f, bool isCalc = false)
{
errno = 0;
if (std::strcmp(value.c_str(), "auto") == 0) {
return Dimension(defaultValue, DimensionUnit::AUTO);
}
char* pEnd = nullptr;
double result = std::strtod(value.c_str(), &pEnd);
if (pEnd == value.c_str() || errno == ERANGE) {
useDefaultUnit = true;
return Dimension(defaultValue, defaultUnit);
}
if (pEnd != nullptr) {
if (std::strcmp(pEnd, "%") == 0) {
// Parse percent, transfer from [0, 100] to [0, 1]
return Dimension(result / 100.0, DimensionUnit::PERCENT);
}
if (std::strcmp(pEnd, "px") == 0) {
return Dimension(result, DimensionUnit::PX);
}
if (std::strcmp(pEnd, "vp") == 0) {
return Dimension(result, DimensionUnit::VP);
}
if (std::strcmp(pEnd, "fp") == 0) {
return Dimension(result, DimensionUnit::FP);
}
if (std::strcmp(pEnd, "lpx") == 0) {
return Dimension(result, DimensionUnit::LPX);
}
if ((std::strcmp(pEnd, "\0") == 0) && isCalc) {
return Dimension(result, DimensionUnit::NONE);
}
if (isCalc) {
return Dimension(result, DimensionUnit::INVALID);
}
}
useDefaultUnit = true;
return Dimension(result, defaultUnit);
}
这个 C++ 函数 MeasureStringToDimensionWithUnit 解析一个字符串 value,将其转换为 Dimension 结构体,并确定它的单位 (DimensionUnit)。
参数解析
const std::string& value
需要解析的字符串,例如 "50px"、"20%"、"auto"。
bool& useDefaultUnit
如果解析失败,则设为 true,表示需要使用默认单位。
DimensionUnit defaultUnit = DimensionUnit::PX
默认单位,默认为 PX(像素)。
float defaultValue = 0.0f
如果解析失败,返回该默认值。
bool isCalc = false
处理 calc() 计算表达式的情况。
代码逻辑分析
- 处理 "auto" 值
if (std::strcmp(value.c_str(), "auto") == 0) {
return Dimension(defaultValue, DimensionUnit::AUTO);
}
如果 value 是 "auto",返回 Dimension(defaultValue, AUTO)。
2. 将字符串转换为 double 类型
char* pEnd = nullptr;
double result = std::strtod(value.c_str(), &pEnd);
- std::strtod 用于将字符串转换为 double,pEnd 指向转换结束后的位置。
- 如果转换失败或数值超出范围:
if (pEnd == value.c_str() || errno == ERANGE) {
useDefaultUnit = true;
return Dimension(defaultValue, defaultUnit);
}
- 解析失败时,返回默认值和默认单位。
- 解析单位
如果 pEnd 不为空,则检查它是否是合法的单位:
if (pEnd != nullptr) {
if (std::strcmp(pEnd, "%") == 0) {
return Dimension(result / 100.0, DimensionUnit::PERCENT);
}
if (std::strcmp(pEnd, "px") == 0) {
return Dimension(result, DimensionUnit::PX);
}
if (std::strcmp(pEnd, "vp") == 0) {
return Dimension(result, DimensionUnit::VP);
}
if (std::strcmp(pEnd, "fp") == 0) {
return Dimension(result, DimensionUnit::FP);
}
if (std::strcmp(pEnd, "lpx") == 0) {
return Dimension(result, DimensionUnit::LPX);
}
- 支持的单位:
- % -> 百分比(会除以 100)
- px -> 像素
- vp -> 视口单位
- fp -> 可扩展单位
- lpx -> 逻辑像素单位
- 处理 calc() 计算模式
if ((std::strcmp(pEnd, "\0") == 0) && isCalc) {
return Dimension(result, DimensionUnit::NONE);
}
if (isCalc) {
return Dimension(result, DimensionUnit::INVALID);
}
如果 isCalc 为 true:
- 且没有单位(pEnd 是空字符串 "\0"),则返回 NONE。
- 其他情况返回 INVALID。
- 解析失败,使用默认单位
useDefaultUnit = true;
return Dimension(result, defaultUnit);
如果所有条件都不符合,返回默认单位。
总结
- "auto" 特殊处理。
- 解析数值部分,失败则返回默认值。
- 检查后缀单位(%、px、vp、fp、lpx)。
- calc() 模式特殊处理。
- 默认返回 defaultUnit(解析失败时)。
bool SetButtonDimension(
const ArkUI_Float32* dimensionArray, // 尺寸数据数组
uint32_t offset, // 数组中的偏移量
const size_t dataCount, // 数组的总大小
std::optional<CalcDimension>& optDimension // 输出:解析后的尺寸
)
dimensionArray:存储尺寸值的浮点型数组。
offset:当前 dimension 数据块的起始索引。
dataCount:数组的总大小(用于边界检查)。
optDimension:输出参数,存储解析出的 CalcDimension,如果解析失败则为空。
dimensionArray = { 1, 50.0, 2, 0, 0, 0, 1, 25.0, 1 }
└─┬──┘ └──┬┘ └──────────┬──────┘
标志 数值 单位
offset + 0:是否有值(1 表示有,0 表示无)。
offset + 1:尺寸的实际数值(50.0)。
offset + 2:尺寸单位(2 可能表示 PX)。