mirror of
https://foundry.openuru.org/gitblit/r/CWE-ou-minkata.git
synced 2025-07-18 11:19:10 +00:00
Merge pull request #431 from zrax/plFormat_float
Add float and double support to plFormat
This commit is contained in:
@ -556,9 +556,9 @@ plString plFileSystem::ConvertFileSize(uint64_t size)
|
||||
float decimal = static_cast<float>(last_div) / 1024.f;
|
||||
// Kilobytes are so small that we only care about whole numbers
|
||||
if (i < 1)
|
||||
return plString::Format("%.0f %s", decimal, labels[i]);
|
||||
return plFormat("{.0f} {}", decimal, labels[i]);
|
||||
else
|
||||
return plString::Format("%.2f %s", decimal, labels[i]);
|
||||
return plFormat("{.2f} {}", decimal, labels[i]);
|
||||
}
|
||||
last_div = my_div;
|
||||
}
|
||||
|
@ -147,7 +147,7 @@ namespace plFormat_Private
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
{
|
||||
char *end = nullptr;
|
||||
spec.fPrecisionLeft = strtol(ptr, &end, 10);
|
||||
spec.fMinimumLength = strtol(ptr, &end, 10);
|
||||
ptr = end - 1;
|
||||
}
|
||||
break;
|
||||
@ -155,7 +155,7 @@ namespace plFormat_Private
|
||||
{
|
||||
hsAssert(*(ptr + 1), "Unterminated format specifier");
|
||||
char *end = nullptr;
|
||||
spec.fPrecisionRight = strtol(ptr + 1, &end, 10);
|
||||
spec.fPrecision = strtol(ptr + 1, &end, 10);
|
||||
ptr = end - 1;
|
||||
}
|
||||
break;
|
||||
@ -227,16 +227,16 @@ static plStringBuffer<char> _formatNumeric(const plFormat_Private::FormatSpec &f
|
||||
max = 1;
|
||||
|
||||
plStringBuffer<char> buffer;
|
||||
if (format.fPrecisionLeft > max) {
|
||||
char *output = buffer.CreateWritableBuffer(format.fPrecisionLeft);
|
||||
memset(output, pad, format.fPrecisionLeft);
|
||||
if (format.fMinimumLength > max) {
|
||||
char *output = buffer.CreateWritableBuffer(format.fMinimumLength);
|
||||
memset(output, pad, format.fMinimumLength);
|
||||
if (format.fAlignment == plFormat_Private::kAlignLeft) {
|
||||
_IFormatNumeric_Impl<_IType>(output + max, value, radix, upperCase);
|
||||
} else {
|
||||
_IFormatNumeric_Impl<_IType>(output + format.fPrecisionLeft,
|
||||
_IFormatNumeric_Impl<_IType>(output + format.fMinimumLength,
|
||||
value, radix, upperCase);
|
||||
}
|
||||
output[format.fPrecisionLeft] = 0;
|
||||
output[format.fMinimumLength] = 0;
|
||||
} else {
|
||||
char *output = buffer.CreateWritableBuffer(max);
|
||||
_IFormatNumeric_Impl<_IType>(output + max, value, radix, upperCase);
|
||||
@ -268,21 +268,21 @@ static plStringBuffer<char> _formatDecimal(const plFormat_Private::FormatSpec &f
|
||||
|
||||
plStringBuffer<char> buffer;
|
||||
char *output;
|
||||
if (format.fPrecisionLeft > max) {
|
||||
output = buffer.CreateWritableBuffer(format.fPrecisionLeft);
|
||||
memset(output, pad, format.fPrecisionLeft);
|
||||
if (format.fMinimumLength > max) {
|
||||
output = buffer.CreateWritableBuffer(format.fMinimumLength);
|
||||
memset(output, pad, format.fMinimumLength);
|
||||
if (format.fAlignment == plFormat_Private::kAlignLeft)
|
||||
_IFormatNumeric_Impl<_IType>(output + max, abs, 10);
|
||||
else
|
||||
_IFormatNumeric_Impl<_IType>(output + format.fPrecisionLeft, abs, 10);
|
||||
output[format.fPrecisionLeft] = 0;
|
||||
_IFormatNumeric_Impl<_IType>(output + format.fMinimumLength, abs, 10);
|
||||
output[format.fMinimumLength] = 0;
|
||||
} else {
|
||||
output = buffer.CreateWritableBuffer(max);
|
||||
_IFormatNumeric_Impl<_IType>(output + max, abs, 10);
|
||||
output[max] = 0;
|
||||
}
|
||||
|
||||
int signPos = format.fPrecisionLeft - static_cast<int>(max);
|
||||
int signPos = format.fPrecision - static_cast<int>(max);
|
||||
if (signPos < 0)
|
||||
signPos = 0;
|
||||
|
||||
@ -296,7 +296,7 @@ static plStringBuffer<char> _formatDecimal(const plFormat_Private::FormatSpec &f
|
||||
|
||||
static plStringBuffer<char> _formatChar(const plFormat_Private::FormatSpec &format, int ch)
|
||||
{
|
||||
hsAssert(format.fPrecisionLeft == 0 && format.fPadChar == 0,
|
||||
hsAssert(format.fMinimumLength == 0 && format.fPadChar == 0,
|
||||
"Char formatting does not currently support padding");
|
||||
|
||||
// Don't need to nul-terminate this, since plStringBuffer's constructor fixes it
|
||||
@ -392,6 +392,60 @@ _PL_FORMAT_IMPL_INT_TYPE(long, unsigned long)
|
||||
_PL_FORMAT_IMPL_INT_TYPE(int64_t, uint64_t)
|
||||
#endif
|
||||
|
||||
PL_FORMAT_IMPL(float)
|
||||
{
|
||||
return PL_FORMAT_FORWARD(format, double(value));
|
||||
}
|
||||
|
||||
PL_FORMAT_IMPL(double)
|
||||
{
|
||||
char pad = format.fPadChar ? format.fPadChar : ' ';
|
||||
|
||||
// Cheating a bit here -- just pass it along to cstdio
|
||||
char format_buffer[32];
|
||||
size_t end = 0;
|
||||
|
||||
format_buffer[end++] = '%';
|
||||
if (format.fPrecision) {
|
||||
int count = snprintf(format_buffer + end, arrsize(format_buffer) - end,
|
||||
".%d", format.fPrecision);
|
||||
|
||||
// Ensure one more space (excluding \0) is available for the format specifier
|
||||
hsAssert(count > 0 && count + end + 2 < arrsize(format_buffer),
|
||||
"Not enough space for format string");
|
||||
end += count;
|
||||
}
|
||||
|
||||
format_buffer[end++] =
|
||||
(format.fFloatClass == plFormat_Private::kFloatExp) ? 'e' :
|
||||
(format.fFloatClass == plFormat_Private::kFloatExpUpper) ? 'E' :
|
||||
(format.fFloatClass == plFormat_Private::kFloatFixed) ? 'f' : 'g';
|
||||
format_buffer[end] = 0;
|
||||
|
||||
int format_size = snprintf(nullptr, 0, format_buffer, value);
|
||||
hsAssert(format_size > 0, "Your libc doesn't support reporting format size");
|
||||
plStringBuffer<char> out_buffer;
|
||||
char *output;
|
||||
|
||||
if (format.fMinimumLength > format_size) {
|
||||
output = out_buffer.CreateWritableBuffer(format.fMinimumLength);
|
||||
memset(output, pad, format.fMinimumLength);
|
||||
if (format.fAlignment == plFormat_Private::kAlignLeft) {
|
||||
snprintf(output, format_size + 1, format_buffer, value);
|
||||
output[format_size] = pad; // snprintf overwrites this
|
||||
output[format.fMinimumLength] = 0;
|
||||
} else {
|
||||
snprintf(output + (format.fMinimumLength - format_size), format_size + 1,
|
||||
format_buffer, value);
|
||||
}
|
||||
} else {
|
||||
output = out_buffer.CreateWritableBuffer(format_size);
|
||||
snprintf(output, format_size + 1, format_buffer, value);
|
||||
}
|
||||
|
||||
return out_buffer;
|
||||
}
|
||||
|
||||
PL_FORMAT_IMPL(char)
|
||||
{
|
||||
/* Note: The use of unsigned here is not a typo -- we only format decimal
|
||||
@ -445,18 +499,18 @@ static plStringBuffer<char> _formatString(const plFormat_Private::FormatSpec &fo
|
||||
{
|
||||
char pad = format.fPadChar ? format.fPadChar : ' ';
|
||||
|
||||
if (format.fPrecisionLeft > value.GetSize()) {
|
||||
if (format.fMinimumLength > value.GetSize()) {
|
||||
plStringBuffer<char> buf;
|
||||
char *output = buf.CreateWritableBuffer(format.fPrecisionLeft);
|
||||
memset(output, pad, format.fPrecisionLeft);
|
||||
char *output = buf.CreateWritableBuffer(format.fMinimumLength);
|
||||
memset(output, pad, format.fMinimumLength);
|
||||
if (format.fAlignment == plFormat_Private::kAlignRight) {
|
||||
memcpy(output + (format.fPrecisionLeft - value.GetSize()),
|
||||
memcpy(output + (format.fMinimumLength - value.GetSize()),
|
||||
value.GetData(), value.GetSize());
|
||||
} else {
|
||||
memcpy(output, value.GetData(), value.GetSize());
|
||||
}
|
||||
|
||||
output[format.fPrecisionLeft] = 0;
|
||||
output[format.fMinimumLength] = 0;
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
@ -73,7 +73,7 @@ Mead, WA 99021
|
||||
* `b` | Binary
|
||||
* `d` | Decimal (default) -- when used with char types, outputs a number instead of the UTF representation of the char
|
||||
* `c` | UTF character (default for character types)
|
||||
* `FFF.EEE` | Use FFF.EEE floating point precision
|
||||
* `.EEE` | Use EEE digits of floating point precision
|
||||
* `f` | Fixed floating point format (ddd.ddd)
|
||||
* `e` | Exponent notation for floating point (d.ddde[+/-]dd)
|
||||
* `E` | Same as 'e' format, but with upper case E (d.dddE[+/-]dd)
|
||||
@ -114,8 +114,8 @@ namespace plFormat_Private
|
||||
/** Represents a parsed format tag, for use in formatter implementations. */
|
||||
struct FormatSpec
|
||||
{
|
||||
int fPrecisionLeft = 0; /**< Requested padding and/or precision */
|
||||
int fPrecisionRight = 0; /**< Requested precision after the . for floating-point */
|
||||
int fMinimumLength = 0; /**< Requested minimum padding length */
|
||||
int fPrecision = 0; /**< Requested precision for floating-point */
|
||||
|
||||
char fPadChar = 0; /**< Explicit padding char (default is space) */
|
||||
Alignment fAlignment = kAlignDefault; /**< Requested pad alignment */
|
||||
@ -192,6 +192,10 @@ namespace plFormat_Private
|
||||
PL_FORMAT_TYPE(int64_t)
|
||||
PL_FORMAT_TYPE(uint64_t)
|
||||
#endif
|
||||
|
||||
PL_FORMAT_TYPE(float)
|
||||
PL_FORMAT_TYPE(double)
|
||||
|
||||
PL_FORMAT_TYPE(const char *)
|
||||
PL_FORMAT_TYPE(const wchar_t *)
|
||||
PL_FORMAT_TYPE(const plString &)
|
||||
@ -203,9 +207,6 @@ namespace plFormat_Private
|
||||
PL_FORMAT_TYPE(const std::string &)
|
||||
PL_FORMAT_TYPE(const std::wstring &)
|
||||
|
||||
// TODO: Implement floating point types (float, double). They're harder
|
||||
// than the others, so I'll get around to them later >.>
|
||||
|
||||
// Formats as "true" or "false", following normal string formatting rules.
|
||||
// To use other formats, don't pass us a bool directly...
|
||||
PL_FORMAT_TYPE(bool)
|
||||
|
@ -257,10 +257,10 @@ static bool DumpSpecificMsgInfo(plMessage* msg, plString& info)
|
||||
PrintKIType(kGZFlashUpdate); // flash an update without saving (for animation of GZFill in)
|
||||
PrintKIType(kNoCommand);
|
||||
|
||||
info = plString::Format("Type: %s Str: %s User: %s(%d) Delay: %f Int: %d",
|
||||
info = plFormat("Type: {} Str: {} User: {}({}) Delay: {} Int: {}",
|
||||
typeName,
|
||||
kiMsg->GetString().c_str("(nil)"),
|
||||
kiMsg->GetUser().c_str("(nil)"),
|
||||
kiMsg->GetString(),
|
||||
kiMsg->GetUser(),
|
||||
kiMsg->GetPlayerID(),
|
||||
kiMsg->GetDelay(),
|
||||
kiMsg->GetIntValue());
|
||||
|
@ -1566,7 +1566,7 @@ void cyMisc::FogSetDefExp2(float end, float density)
|
||||
void cyMisc::SetClearColor(float red, float green, float blue)
|
||||
{
|
||||
// do this command via the console to keep the maxplugins from barfing
|
||||
plString command = plString::Format("Graphics.Renderer.SetClearColor %f %f %f", red, green, blue);
|
||||
plString command = plFormat("Graphics.Renderer.SetClearColor {f} {f} {f}", red, green, blue);
|
||||
|
||||
// create message to send to the console
|
||||
plControlEventMsg* pMsg = new plControlEventMsg;
|
||||
|
@ -563,17 +563,17 @@ bool plAvTaskSeek::IUpdateObjective(plArmatureMod *avatar)
|
||||
// ----------
|
||||
void plAvTaskSeek::DumpDebug(const char *name, int &x, int&y, int lineHeight, plDebugText &debugTxt)
|
||||
{
|
||||
debugTxt.DrawString(x, y, plString::Format("duration: %.2f pos: (%.3f, %.3f, %.3f) goalPos: (%.3f, %.3f, %.3f) ",
|
||||
debugTxt.DrawString(x, y, plFormat("duration: {.2f} pos: ({.3f}, {.3f}, {.3f}) goalPos: ({.3f}, {.3f}, {.3f}) ",
|
||||
hsTimer::GetSysSeconds() - fStartTime,
|
||||
fPosition.fX, fPosition.fY, fPosition.fZ, fSeekPos.fX, fSeekPos.fY, fSeekPos.fZ));
|
||||
y += lineHeight;
|
||||
|
||||
debugTxt.DrawString(x, y, plString::Format("positioning: %d rotating %d goalVec: (%.3f, %.3f, %.3f) dist: %.3f angFwd: %.3f angRt: %.3f",
|
||||
debugTxt.DrawString(x, y, plFormat("positioning: {} rotating {} goalVec: ({.3f}, {.3f}, {.3f}) dist: {.3f} angFwd: {.3f} angRt: {.3f}",
|
||||
fStillPositioning, fStillRotating, fGoalVec.fX, fGoalVec.fY, fGoalVec.fZ,
|
||||
fDistance, fAngForward, fAngRight));
|
||||
y += lineHeight;
|
||||
|
||||
debugTxt.DrawString(x, y, plString::Format(" distFwd: %.3f distRt: %.3f shufRange: %.3f sidAngle: %.3f sidRange: %.3f, fMinWalk: %.3f",
|
||||
debugTxt.DrawString(x, y, plFormat(" distFwd: {.3f} distRt: {.3f} shufRange: {.3f} sidAngle: {.3f} sidRange: {.3f}, fMinWalk: {.3f}",
|
||||
fDistForward, fDistRight, fShuffleRange, fMaxSidleAngle, fMaxSidleRange, fMinFwdAngle));
|
||||
y += lineHeight;
|
||||
}
|
||||
@ -583,17 +583,17 @@ void plAvTaskSeek::DumpToAvatarLog(plArmatureMod *avatar)
|
||||
plStatusLog *log = plAvatarMgr::GetInstance()->GetLog();
|
||||
log->AddLine(avatar->GetMoveKeyString().c_str());
|
||||
|
||||
log->AddLine(plString::Format(" duration: %.2f pos: (%.3f, %.3f, %.3f) goalPos: (%.3f, %.3f, %.3f) ",
|
||||
log->AddLine(plFormat(" duration: {.2f} pos: ({.3f}, {.3f}, {.3f}) goalPos: ({.3f}, {.3f}, {.3f}) ",
|
||||
hsTimer::GetSysSeconds() - fStartTime,
|
||||
fPosition.fX, fPosition.fY, fPosition.fZ,
|
||||
fSeekPos.fX, fSeekPos.fY, fSeekPos.fZ).c_str());
|
||||
|
||||
log->AddLine(plString::Format(" positioning: %d rotating %d goalVec: (%.3f, %.3f, %.3f) dist: %.3f angFwd: %.3f angRt: %.3f",
|
||||
log->AddLine(plFormat(" positioning: {} rotating {} goalVec: ({.3f}, {.3f}, {.3f}) dist: {.3f} angFwd: {.3f} angRt: {.3f}",
|
||||
fStillPositioning, fStillRotating,
|
||||
fGoalVec.fX, fGoalVec.fY, fGoalVec.fZ,
|
||||
fDistance, fAngForward, fAngRight).c_str());
|
||||
|
||||
log->AddLine(plString::Format(" distFwd: %.3f distRt: %.3f shufRange: %.3f sidAngle: %.3f sidRange: %.3f, fMinWalk: %.3f",
|
||||
log->AddLine(plFormat(" distFwd: {.3f} distRt: {.3f} shufRange: {.3f} sidAngle: {.3f} sidRange: {.3f}, fMinWalk: {.3f}",
|
||||
fDistForward, fDistRight, fShuffleRange,
|
||||
fMaxSidleAngle, fMaxSidleRange, fMinFwdAngle).c_str());
|
||||
}
|
||||
|
Reference in New Issue
Block a user