added alignment support to PhFormat

git-svn-id: svn://svn.code.sf.net/p/processhacker/code@3719 21ef857c-d57f-4fe0-8362-d861dc6d29cd
This commit is contained in:
wj32
2010-10-03 03:58:03 +00:00
parent d1c36b5bd4
commit 4e90ccc7d9
4 changed files with 215 additions and 44 deletions
+29 -12
View File
@@ -34,7 +34,9 @@ extern ULONG PhMaxSizeUnit;
#define SMALL_BUFFER_LENGTH (PHOBJ_SMALL_OBJECT_SIZE - FIELD_OFFSET(PH_STRING, Buffer) - sizeof(WCHAR))
#define BUFFER_SIZE 512
#define PHP_FORMAT_NEGATIVE 0x1000
#define PHP_FORMAT_NEGATIVE 0x1
#define PHP_FORMAT_POSITIVE 0x2
#define PHP_FORMAT_PAD 0x4
// Internal CRT routines needed for floating-point conversion
@@ -61,6 +63,31 @@ static WCHAR PhpFormatDecimalSeparator = '.';
static WCHAR PhpFormatThousandSeparator = ',';
static _locale_t PhpFormatUserLocale = NULL;
PPH_STRING PhpResizeFormatBuffer(
__in PPH_STRING String,
__inout PSIZE_T AllocatedLength,
__in SIZE_T UsedLength,
__in SIZE_T NeededLength
)
{
PPH_STRING newString;
SIZE_T allocatedLength;
allocatedLength = *AllocatedLength;
allocatedLength *= 2;
if (allocatedLength < UsedLength + NeededLength)
allocatedLength = UsedLength + NeededLength;
newString = PhCreateStringEx(NULL, allocatedLength);
memcpy(newString->Buffer, String->Buffer, UsedLength);
PhDereferenceObject(String);
*AllocatedLength = allocatedLength;
return newString;
}
PPH_STRING PhFormat(
__in PPH_FORMAT Format,
__in ULONG Count,
@@ -90,17 +117,7 @@ PPH_STRING PhFormat(
do { \
if (allocatedLength < usedLength + (NeededLength)) \
{ \
PPH_STRING newString; \
\
allocatedLength *= 2; \
\
if (allocatedLength < usedLength + (NeededLength)) \
allocatedLength = usedLength + (NeededLength); \
\
newString = PhCreateStringEx(NULL, allocatedLength); \
memcpy(newString->Buffer, string->Buffer, usedLength); \
PhDereferenceObject(string); \
string = newString; \
string = PhpResizeFormatBuffer(string, &allocatedLength, usedLength, (NeededLength)); \
buffer = string->Buffer + usedLength / sizeof(WCHAR); \
} \
} while (0)
+147 -20
View File
@@ -127,6 +127,8 @@
PWSTR temp; \
ULONG tempCount; \
ULONG r; \
ULONG preCount; \
ULONG padCount; \
\
radix = 10; \
if (((Format)->Type & FormatUseRadix) && (Format)->Radix >= 2 && (Format)->Radix <= 69) \
@@ -169,22 +171,42 @@
tempCount++; \
} \
\
preCount = 0; \
\
if (flags & PHP_FORMAT_NEGATIVE) \
{ \
*temp-- = '-'; \
tempCount++; \
} \
preCount++; \
else if ((Format)->Type & FormatPrefixSign) \
preCount++; \
\
if (((Format)->Type & FormatPadZeros) && !((Format)->Type & FormatGroupDigits)) \
{ \
*temp-- = '+'; \
tempCount++; \
if (preCount + tempCount < (Format)->Width) \
{ \
flags |= PHP_FORMAT_PAD; \
padCount = (Format)->Width - (preCount + tempCount); \
preCount += padCount; \
} \
} \
\
temp++; \
ENSURE_BUFFER(tempCount * sizeof(WCHAR)); \
ENSURE_BUFFER((preCount + tempCount) * sizeof(WCHAR)); \
if (OK_BUFFER) \
{ \
if (flags & PHP_FORMAT_NEGATIVE) \
*buffer++ = '-'; \
else if ((Format)->Type & FormatPrefixSign) \
*buffer++ = '+'; \
\
if (flags & PHP_FORMAT_PAD) \
{ \
wmemset(buffer, '0', padCount); \
buffer += padCount; \
} \
\
memcpy(buffer, temp, tempCount * sizeof(WCHAR)); \
ADVANCE_BUFFER(tempCount * sizeof(WCHAR)); \
buffer += tempCount; \
} \
usedLength += (preCount + tempCount) * sizeof(WCHAR); \
} while (0)
#ifdef _M_IX86
@@ -241,14 +263,15 @@ CommonInt64Format:
ULONG precision; \
DOUBLE value; \
CHAR c; \
PSTR temp; \
ULONG length; \
\
if ((Format)->Type & FormatUsePrecision) \
{ \
precision = (Format)->Precision; \
\
if (precision > BUFFER_SIZE - _CVTBUFSIZE) \
precision = BUFFER_SIZE - _CVTBUFSIZE; \
if (precision > BUFFER_SIZE - 1 - _CVTBUFSIZE) \
precision = BUFFER_SIZE - 1 - _CVTBUFSIZE; \
} \
else \
{ \
@@ -268,10 +291,11 @@ CommonInt64Format:
/* Use MS CRT routines to do the work. */ \
\
value = (Format)->u.Double; \
temp = (PSTR)tempBuffer + 1; /* leave one character so we can insert a prefix if needed */ \
_cfltcvt_l( \
&value, \
(PSTR)tempBuffer, \
sizeof(tempBuffer), \
temp, \
sizeof(tempBuffer) - 1, \
c, \
precision, \
!!((Format)->Type & FormatUpperCase), \
@@ -281,9 +305,20 @@ CommonInt64Format:
/* if (((Format)->Type & FormatForceDecimalPoint) && precision == 0) */ \
/* _forcdecpt_l(tempBufferAnsi, PhpFormatUserLocale); */ \
if ((Format)->Type & FormatCropZeros) \
_cropzeros_l((PSTR)tempBuffer, PhpFormatUserLocale); \
_cropzeros_l(temp, PhpFormatUserLocale); \
\
length = (ULONG)strlen((PSTR)tempBuffer); \
length = (ULONG)strlen(temp); \
\
if (temp[0] == '-') \
{ \
flags |= PHP_FORMAT_NEGATIVE; \
temp++; \
length--; \
} \
else if ((Format)->Type & FormatPrefixSign) \
{ \
flags |= PHP_FORMAT_POSITIVE; \
} \
\
if (((Format)->Type & FormatGroupDigits) && !((Format)->Type & (FormatStandardForm | FormatHexadecimalForm))) \
{ \
@@ -291,14 +326,15 @@ CommonInt64Format:
PSTR decimalPoint; \
ULONG wholeCount; \
ULONG sepsCount; \
ULONG ensureLength; \
ULONG copyCount; \
ULONG needsSep; \
\
/* Find the first non-digit character and assume that is the */ \
/* decimal point (or the end of the string). */ \
\
whole = (PSTR)tempBuffer; \
decimalPoint = (PSTR)tempBuffer; \
whole = temp; \
decimalPoint = temp; \
\
while ((UCHAR)(*decimalPoint - '0') < 10) \
decimalPoint++; \
@@ -306,20 +342,28 @@ CommonInt64Format:
/* Copy the characters to the output buffer, and at the same time */ \
/* insert the separators. */ \
\
wholeCount = (ULONG)(decimalPoint - (PSTR)tempBuffer); \
wholeCount = (ULONG)(decimalPoint - temp); \
\
if (wholeCount != 0) \
sepsCount = (wholeCount + 2) / 3 - 1; \
else \
sepsCount = 0; \
\
ENSURE_BUFFER((length + sepsCount) * sizeof(WCHAR)); \
ensureLength = (length + sepsCount) * sizeof(WCHAR); \
if (flags & (PHP_FORMAT_NEGATIVE | PHP_FORMAT_POSITIVE)) \
ensureLength += sizeof(WCHAR); \
ENSURE_BUFFER(ensureLength); \
\
copyCount = wholeCount; \
needsSep = (wholeCount + 2) % 3; \
\
if (OK_BUFFER) \
{ \
if (flags & PHP_FORMAT_NEGATIVE) \
*buffer++ = '-'; \
else if (flags & PHP_FORMAT_POSITIVE) \
*buffer++ = '+'; \
\
while (copyCount--) \
{ \
*buffer++ = *whole++; \
@@ -332,6 +376,8 @@ CommonInt64Format:
} \
} \
\
if (flags & (PHP_FORMAT_NEGATIVE | PHP_FORMAT_POSITIVE)) \
usedLength += sizeof(WCHAR); \
usedLength += (wholeCount + sepsCount) * sizeof(WCHAR); \
\
/* Copy the rest. */ \
@@ -351,16 +397,50 @@ CommonInt64Format:
} \
else \
{ \
SIZE_T preLength; \
SIZE_T padLength; \
\
/* Take care of the sign and zero padding. */ \
preLength = 0; \
\
if (flags & (PHP_FORMAT_NEGATIVE | PHP_FORMAT_POSITIVE)) \
preLength++; \
\
if ((Format)->Type & FormatPadZeros) \
{ \
if (preLength + length < (Format)->Width) \
{ \
flags |= PHP_FORMAT_PAD; \
padLength = (Format)->Width - (preLength + length); \
preLength += padLength; \
} \
} \
/* We don't need to group digits, so directly copy the characters */ \
/* to the output buffer. */ \
\
ENSURE_BUFFER(length * sizeof(WCHAR)); \
ENSURE_BUFFER((preLength + length) * sizeof(WCHAR)); \
\
if (OK_BUFFER) \
{ \
if (flags & PHP_FORMAT_NEGATIVE) \
*buffer++ = '-'; \
else if (flags & PHP_FORMAT_POSITIVE) \
*buffer++ = '+'; \
\
if (flags & PHP_FORMAT_PAD) \
{ \
wmemset(buffer, '0', padLength); \
buffer += padLength; \
} \
} \
\
usedLength += preLength * sizeof(WCHAR); \
\
if (!OK_BUFFER || NT_SUCCESS(RtlMultiByteToUnicodeN( \
buffer, \
length * sizeof(WCHAR), \
NULL, \
(PSTR)tempBuffer, \
(PSTR)temp, \
length \
))) \
{ \
@@ -370,6 +450,7 @@ CommonInt64Format:
} while (0)
case DoubleFormatType:
flags = 0;
COMMON_DOUBLE_FORMAT(format);
break;
@@ -412,7 +493,9 @@ CommonInt64Format:
doubleFormat.Type = DoubleFormatType | FormatUsePrecision | FormatCropZeros | FormatGroupDigits;
doubleFormat.Precision = 2;
doubleFormat.Width = 0; // stupid compiler
doubleFormat.u.Double = s;
flags = 0;
COMMON_DOUBLE_FORMAT(&doubleFormat);
ENSURE_BUFFER(sizeof(WCHAR) + PhpSizeUnitNamesCounted[i].Length);
@@ -428,5 +511,49 @@ CommonInt64Format:
ContinueLoop:
partLength = usedLength - partLength;
if (format->Type & (FormatLeftAlign | FormatRightAlign))
{
SIZE_T newLength;
SIZE_T addLength;
newLength = format->Width * sizeof(WCHAR);
// We only pad and never truncate.
if (partLength < newLength)
{
addLength = newLength - partLength;
ENSURE_BUFFER(addLength);
if (OK_BUFFER)
{
WCHAR pad;
if (format->Type & FormatUsePad)
pad = format->Pad;
else
pad = ' ';
if (format->Type & FormatLeftAlign)
{
// Left alignment is easy; we just fill the remaining space
// with the pad character.
wmemset(buffer, pad, addLength / sizeof(WCHAR));
}
else
{
PWSTR start;
// Right alignment is much slower and involves moving the
// text forward, then filling in the space before it.
start = buffer - partLength / sizeof(WCHAR);
memmove(start + addLength / sizeof(WCHAR), start, partLength);
wmemset(start, pad, addLength / sizeof(WCHAR));
}
}
ADVANCE_BUFFER(addLength);
}
}
}
}
+28 -10
View File
@@ -2999,26 +2999,44 @@ typedef enum _PH_FORMAT_TYPE
UIntPtrFormatType,
DoubleFormatType,
SizeFormatType,
FormatTypeMask = 0xff,
FormatTypeMask = 0x3f,
FormatUsePrecision = 0x100,
FormatUseWidth = 0x200,
FormatUseRadix = 0x400,
/** If not specified, for floating-point 6 is assumed **/
FormatUsePrecision = 0x40,
/** If not specified, ' ' is assumed */
FormatUsePad = 0x80,
/** If not specified, 10 is assumed */
FormatUseRadix = 0x100,
/** Reserved */
FormatUseReserved = 0x200,
// Floating-point flags
FormatStandardForm = 0x1000, // Use standard form instead of normal form
FormatHexadecimalForm = 0x2000, // Use hexadecimal form instead of normal form
FormatForceDecimalPoint = 0x4000, // Reserved
/** Use standard form instead of normal form */
FormatStandardForm = 0x1000,
/** Use hexadecimal form instead of normal form */
FormatHexadecimalForm = 0x2000,
/** Reserved */
FormatForceDecimalPoint = 0x4000,
/** Trailing zeros and possibly the decimal point are trimmed */
FormatCropZeros = 0x8000,
// Floating-point and integer flags
FormatGroupDigits = 0x10000, // Group digits (with floating-point, only works when in normal form)
FormatPrefixSign = 0x20000, // Always insert a prefix, '+' for positive and '-' for negative
/** Group digits (with floating-point, only works when in normal form) */
FormatGroupDigits = 0x10000,
/** Always insert a prefix, '+' for positive and '-' for negative */
FormatPrefixSign = 0x20000,
/** Pad left with zeros, taking into consideration the sign. Width must be specified.
* Format*Align cannot be used in conjunction with this flag. If FormatGroupDigits is specified,
* this flag is ignored. */
FormatPadZeros = 0x40000,
// General flags
/** Applies left alignment. Width must be specified. */
FormatLeftAlign = 0x80000000,
/** Applies right alignment. Width must be specified. */
FormatRightAlign = 0x40000000,
FormatUpperCase = 0x20000000 // Make characters uppercase (only available for some types)
/** Make characters uppercase (only available for some types) */
FormatUpperCase = 0x20000000
} PH_FORMAT_TYPE;
typedef struct _PH_FORMAT
+11 -2
View File
@@ -1426,10 +1426,19 @@ PPH_STRING PhGetFileVersionInfoString2(
)
{
WCHAR subBlock[65];
PH_FORMAT format[4];
_snwprintf(subBlock, 64, L"\\StringFileInfo\\%08X\\%s", LangCodePage, StringName);
PhInitFormatS(&format[0], L"\\StringFileInfo\\");
PhInitFormatX(&format[1], LangCodePage);
format[1].Type |= FormatPadZeros | FormatUpperCase;
format[1].Width = 8;
PhInitFormatC(&format[2], '\\');
PhInitFormatS(&format[3], StringName);
return PhGetFileVersionInfoString(VersionInfo, subBlock);
if (PhFormatToBuffer(format, 4, subBlock, sizeof(subBlock), NULL))
return PhGetFileVersionInfoString(VersionInfo, subBlock);
else
return NULL;
}
BOOLEAN PhInitializeImageVersionInfo(