mirror of
https://foundry.openuru.org/gitblit/r/CWE-ou-minkata.git
synced 2025-07-18 11:19:10 +00:00
Add better documentation, and fix some floating point flag stuff
This commit is contained in:
2
Doxyfile
2
Doxyfile
@ -1588,7 +1588,7 @@ INCLUDE_FILE_PATTERNS =
|
|||||||
# undefined via #undef or recursively expanded use the := operator
|
# undefined via #undef or recursively expanded use the := operator
|
||||||
# instead of the = operator.
|
# instead of the = operator.
|
||||||
|
|
||||||
PREDEFINED =
|
PREDEFINED = BUILDING_DOXYGEN
|
||||||
|
|
||||||
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
|
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
|
||||||
# this tag can be used to specify a list of macro names that should be expanded.
|
# this tag can be used to specify a list of macro names that should be expanded.
|
||||||
|
@ -50,7 +50,7 @@ Mead, WA 99021
|
|||||||
|
|
||||||
namespace plFormat_Private
|
namespace plFormat_Private
|
||||||
{
|
{
|
||||||
static const char *_scanNextFormat(IFormatDataObject &data)
|
static const char *_scanNextFormat(_IFormatDataObject &data)
|
||||||
{
|
{
|
||||||
hsAssert(data.fFormatStr, "Passed a null format string!");
|
hsAssert(data.fFormatStr, "Passed a null format string!");
|
||||||
|
|
||||||
@ -64,7 +64,7 @@ namespace plFormat_Private
|
|||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _fetchPrefixChunk(IFormatDataObject &data)
|
static void _fetchPrefixChunk(_IFormatDataObject &data)
|
||||||
{
|
{
|
||||||
do {
|
do {
|
||||||
const char *next = _scanNextFormat(data);
|
const char *next = _scanNextFormat(data);
|
||||||
@ -81,7 +81,7 @@ namespace plFormat_Private
|
|||||||
} while (0);
|
} while (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
FormatSpec FetchNextFormat(IFormatDataObject &data)
|
FormatSpec _FetchNextFormat(_IFormatDataObject &data)
|
||||||
{
|
{
|
||||||
_fetchPrefixChunk(data);
|
_fetchPrefixChunk(data);
|
||||||
hsAssert(*data.fFormatStr == '{', "Too many actual parameters for format string");
|
hsAssert(*data.fFormatStr == '{', "Too many actual parameters for format string");
|
||||||
@ -135,13 +135,13 @@ namespace plFormat_Private
|
|||||||
spec.fDigitClass = kDigitChar;
|
spec.fDigitClass = kDigitChar;
|
||||||
break;
|
break;
|
||||||
case 'f':
|
case 'f':
|
||||||
spec.fFloatClass = kFloatF;
|
spec.fFloatClass = kFloatFixed;
|
||||||
break;
|
|
||||||
case 'g':
|
|
||||||
spec.fFloatClass = kFloatG;
|
|
||||||
break;
|
break;
|
||||||
case 'e':
|
case 'e':
|
||||||
spec.fFloatClass = kFloatE;
|
spec.fFloatClass = kFloatExp;
|
||||||
|
break;
|
||||||
|
case 'E':
|
||||||
|
spec.fFloatClass = kFloatExpUpper;
|
||||||
break;
|
break;
|
||||||
case '0': case '1': case '2': case '3': case '4':
|
case '0': case '1': case '2': case '3': case '4':
|
||||||
case '5': case '6': case '7': case '8': case '9':
|
case '5': case '6': case '7': case '8': case '9':
|
||||||
@ -166,7 +166,7 @@ namespace plFormat_Private
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
plString _IFormat(plFormat_Private::IFormatDataObject &data)
|
plString _IFormat(plFormat_Private::_IFormatDataObject &data)
|
||||||
{
|
{
|
||||||
_fetchPrefixChunk(data);
|
_fetchPrefixChunk(data);
|
||||||
hsAssert(*data.fFormatStr == 0, "Not enough actual parameters for format string");
|
hsAssert(*data.fFormatStr == 0, "Not enough actual parameters for format string");
|
||||||
|
@ -47,85 +47,105 @@ Mead, WA 99021
|
|||||||
#include <list>
|
#include <list>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
/* (TODO: Make this table doxygen-friendly)
|
#ifdef BUILDING_DOXYGEN // Doxygen doesn't appear to support variadic templates yet
|
||||||
|
/** Format a string using type-safe arguments
|
||||||
|
* \param format The format string -- see below for details
|
||||||
*
|
*
|
||||||
* FORMAT SPECIFICATION
|
* Character Sequence | Description
|
||||||
|
* ------------------ | -----------
|
||||||
|
* `{}` | Format a value (using defaults)
|
||||||
|
* `{{` | Escape for a single '{' char
|
||||||
|
* `{options}` | Format a value, with the specified options (see below)
|
||||||
*
|
*
|
||||||
* {} - format a value (defaults)
|
* Formatting Options
|
||||||
* {{ - Escape for a single '{' char
|
* ------------------
|
||||||
* {options} - Format a value, with the specified options (see below)
|
|
||||||
*
|
*
|
||||||
* Options:
|
* Format Option | Description
|
||||||
* < - Align left
|
* ------------- | -----------
|
||||||
* > - Align right
|
* `<` | Align left
|
||||||
* NNN - Pad to NNN characters (minimum - can be more)
|
* `>` | Align right
|
||||||
* + - Show a '+' char for positive signed values (decimal only)
|
* `NNN` | Pad to NNN characters (minimum - can be more)
|
||||||
* _C - Use C as the pad character (only '\001'..'\177' supported for now)
|
* `+` | Show a '+' char for positive signed values (decimal only)
|
||||||
* x - Hex (lower-case)
|
* `_C` | Use C as the pad character (only '\001'..'\177' supported for now)
|
||||||
* X - Hex (upper-case)
|
* `x` | Hex (lower-case)
|
||||||
* o - Octal
|
* `X` | Hex (upper-case)
|
||||||
* b - Binary
|
* `o` | Octal
|
||||||
* d - Decimal (default) -- when used with char types, outputs a
|
* `b` | Binary
|
||||||
* number instead of the UTF representation of the char
|
* `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)
|
* `c` | UTF character (default for character types)
|
||||||
* FFF.EEE - Use FFF.EEE floating point precision
|
* `FFF.EEE` | Use FFF.EEE floating point precision
|
||||||
* f - Use 'f' format for floating point numbers
|
* `f` | Fixed floating point format (ddd.ddd)
|
||||||
* g - Use 'g' format for floating point numbers
|
* `e` | Exponent notation for floating point (d.ddde[+/-]dd)
|
||||||
* e - Use 'e' format for floating point numbers
|
* `E` | Same as 'e' format, but with upper case E (d.dddE[+/-]dd)
|
||||||
*/
|
*/
|
||||||
|
plString plFormat(const char *format, ...);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
// For internal use by plFormat and its helper function
|
|
||||||
namespace plFormat_Private
|
namespace plFormat_Private
|
||||||
{
|
{
|
||||||
enum Alignment : unsigned char
|
enum Alignment : unsigned char
|
||||||
{
|
{
|
||||||
kAlignDefault, kAlignLeft, kAlignRight
|
kAlignDefault, /**< Left for strings, right for numbers */
|
||||||
|
kAlignLeft, /**< Left alignment */
|
||||||
|
kAlignRight /**< Right alignment */
|
||||||
};
|
};
|
||||||
|
|
||||||
enum DigitClass : unsigned char
|
enum DigitClass : unsigned char
|
||||||
{
|
{
|
||||||
kDigitDefault, kDigitDec, kDigitDecAlwaysSigned,
|
kDigitDefault, /**< Default digit formatting */
|
||||||
kDigitHex, kDigitHexUpper, kDigitOct, kDigitBin, kDigitChar
|
kDigitDec, /**< Format as decimal integer */
|
||||||
|
kDigitDecAlwaysSigned, /**< Same as `kDigitDec`, but include a '+' for positive numbers too */
|
||||||
|
kDigitHex, /**< Hex integer (assume unsigned) */
|
||||||
|
kDigitHexUpper, /**< Hex integer with upper-case digits */
|
||||||
|
kDigitOct, /**< Octal integer (assume unsigned) */
|
||||||
|
kDigitBin, /**< Binary integer (assume unsigned) */
|
||||||
|
kDigitChar /**< Single unicode character (as UTF-8) */
|
||||||
};
|
};
|
||||||
|
|
||||||
enum FloatClass : unsigned char
|
enum FloatClass : unsigned char
|
||||||
{
|
{
|
||||||
kFloatDefault, kFloatE, kFloatF, kFloatG
|
kFloatDefault, /**< Use Fixed or Exp format depending on value */
|
||||||
|
kFloatFixed, /**< Use Fixed notation (ddd.ddd) */
|
||||||
|
kFloatExp, /**< Use Exp notation (d.ddde[+/-]dd) */
|
||||||
|
kFloatExpUpper /**< Same as `kFloatExp`, but with an upper-case E */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Represents a parsed format tag, for use in formatter implementations. */
|
||||||
struct FormatSpec
|
struct FormatSpec
|
||||||
{
|
{
|
||||||
int fPrecisionLeft = 0; // Also used for padding
|
int fPrecisionLeft = 0; /**< Requested padding and/or precision */
|
||||||
int fPrecisionRight = 0;
|
int fPrecisionRight = 0; /**< Requested precision after the . for floating-point */
|
||||||
|
|
||||||
char fPadChar = 0;
|
char fPadChar = 0; /**< Explicit padding char (default is space) */
|
||||||
Alignment fAlignment = kAlignDefault;
|
Alignment fAlignment = kAlignDefault; /**< Requested pad alignment */
|
||||||
DigitClass fDigitClass = kDigitDefault;
|
DigitClass fDigitClass = kDigitDefault; /**< Requested int formatting */
|
||||||
FloatClass fFloatClass = kFloatDefault;
|
FloatClass fFloatClass = kFloatDefault; /**< Requested float formatting */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct IFormatDataObject
|
// These need to be publically visible for the macros below, but shouldn't
|
||||||
|
// be used directly outside of plFormat and its macros
|
||||||
|
struct _IFormatDataObject
|
||||||
{
|
{
|
||||||
const char *fFormatStr;
|
const char *fFormatStr;
|
||||||
std::list<plStringBuffer<char>> fOutput;
|
std::list<plStringBuffer<char>> fOutput;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern FormatSpec FetchNextFormat(IFormatDataObject &data);
|
extern FormatSpec _FetchNextFormat(_IFormatDataObject &data);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fun fact: You can add your own formatters by declaring
|
/** Declare a formattable type for `plFormat`.
|
||||||
// PL_FORMAT_TYPE(mytype) in a header, and
|
* \sa PL_FORMAT_IMPL()
|
||||||
// PL_FORMAT_IMPL(mytype) { ... } in a source file
|
*/
|
||||||
|
|
||||||
#define PL_FORMAT_TYPE(_type) \
|
#define PL_FORMAT_TYPE(_type) \
|
||||||
extern plStringBuffer<char> _impl_plFormat_DataHandler( \
|
extern plStringBuffer<char> _impl_plFormat_DataHandler( \
|
||||||
const plFormat_Private::FormatSpec &format, _type value); \
|
const plFormat_Private::FormatSpec &format, _type value); \
|
||||||
namespace plFormat_Private \
|
namespace plFormat_Private \
|
||||||
{ \
|
{ \
|
||||||
template <typename... _Args> \
|
template <typename... _Args> \
|
||||||
plString _IFormat(IFormatDataObject &data, _type value, _Args... args) \
|
plString _IFormat(_IFormatDataObject &data, _type value, _Args... args) \
|
||||||
{ \
|
{ \
|
||||||
plFormat_Private::FormatSpec format = plFormat_Private::FetchNextFormat(data); \
|
plFormat_Private::FormatSpec format = plFormat_Private::_FetchNextFormat(data); \
|
||||||
data.fOutput.push_back(_impl_plFormat_DataHandler(format, value)); \
|
data.fOutput.push_back(_impl_plFormat_DataHandler(format, value)); \
|
||||||
return _IFormat(data, args...); \
|
return _IFormat(data, args...); \
|
||||||
} \
|
} \
|
||||||
@ -133,17 +153,41 @@ namespace plFormat_Private
|
|||||||
template <typename... _Args> \
|
template <typename... _Args> \
|
||||||
plString plFormat(const char *fmt_str, _type value, _Args... args) \
|
plString plFormat(const char *fmt_str, _type value, _Args... args) \
|
||||||
{ \
|
{ \
|
||||||
plFormat_Private::IFormatDataObject data; \
|
plFormat_Private::_IFormatDataObject data; \
|
||||||
data.fFormatStr = fmt_str; \
|
data.fFormatStr = fmt_str; \
|
||||||
plFormat_Private::FormatSpec format = plFormat_Private::FetchNextFormat(data); \
|
plFormat_Private::FormatSpec format = plFormat_Private::_FetchNextFormat(data); \
|
||||||
data.fOutput.push_back(_impl_plFormat_DataHandler(format, value)); \
|
data.fOutput.push_back(_impl_plFormat_DataHandler(format, value)); \
|
||||||
return plFormat_Private::_IFormat(data, args...); \
|
return plFormat_Private::_IFormat(data, args...); \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Provide the implementation for a formattable type for `plFormat`.
|
||||||
|
* \sa PL_FORMAT_TYPE(), PL_FORMAT_FORWARD()
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
*
|
||||||
|
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
* PL_FORMAT_IMPL(const MyType &)
|
||||||
|
* {
|
||||||
|
* return plFormat("MyType[data={},count={}]", value.data, value.count);
|
||||||
|
* }
|
||||||
|
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
*/
|
||||||
#define PL_FORMAT_IMPL(_type) \
|
#define PL_FORMAT_IMPL(_type) \
|
||||||
plStringBuffer<char> _impl_plFormat_DataHandler( \
|
plStringBuffer<char> _impl_plFormat_DataHandler( \
|
||||||
const plFormat_Private::FormatSpec &format, _type value)
|
const plFormat_Private::FormatSpec &format, _type value)
|
||||||
|
|
||||||
|
/** Shortcut to call another `PL_FORMAT_IMPL` formatter.
|
||||||
|
* \sa PL_FORMAT_IMPL()
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
*
|
||||||
|
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
* PL_FORMAT_IMPL(const MyType &)
|
||||||
|
* {
|
||||||
|
* return PL_FORMAT_FORWARD(format, value.ToString());
|
||||||
|
* }
|
||||||
|
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
*/
|
||||||
#define PL_FORMAT_FORWARD(format, fwd_value) \
|
#define PL_FORMAT_FORWARD(format, fwd_value) \
|
||||||
_impl_plFormat_DataHandler((format), (fwd_value))
|
_impl_plFormat_DataHandler((format), (fwd_value))
|
||||||
|
|
||||||
@ -174,10 +218,10 @@ PL_FORMAT_TYPE(const std::wstring &)
|
|||||||
// To use other formats, don't pass us a bool directly...
|
// To use other formats, don't pass us a bool directly...
|
||||||
PL_FORMAT_TYPE(bool)
|
PL_FORMAT_TYPE(bool)
|
||||||
|
|
||||||
// End of the chain -- emits the last piece (if any) and builds the final string
|
|
||||||
namespace plFormat_Private
|
namespace plFormat_Private
|
||||||
{
|
{
|
||||||
plString _IFormat(IFormatDataObject &data);
|
// End of the chain -- emits the last piece (if any) and builds the final string
|
||||||
|
plString _IFormat(_IFormatDataObject &data);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // plFormat_Defined
|
#endif // plFormat_Defined
|
||||||
|
Reference in New Issue
Block a user