summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/util/strformat.h
diff options
context:
space:
mode:
author Vas Crabb <vas@vastheman.com>2020-12-18 15:54:52 +1100
committer Vas Crabb <vas@vastheman.com>2020-12-18 15:54:52 +1100
commit1df245cb99882892678216c3d0c6e243611d627c (patch)
treea8f3563a74d58755f4a82d4cbfc2406cf79543b3 /src/lib/util/strformat.h
parentff9c1a0ca91f925e5c23b22a92a53c83f9f655ba (diff)
More Lua engine clean-up and documentation, resulting in core cleanup.
More Lua interface cleanup, additional properties and methods, and documentation migration/expansion. Emulated switch inputs can have "not" codes applied to host input axis directions. It works the same way as host switch inputs - push twice for a "not" prefix. Input polling helpers no longer need to store state in the input device items. There’s less leakage, and less chance of things interfering with each other. Allow snapshot view options to be configured through the internal UI via the video options menu. Made video options menus place initial focus on the currently selected view item. Removed some crud from the menu base class. Fixed the description of the "snapview" option. The value to get raw screen pixels was changed to "native" a long time ago but the description was never updated. Re-arranged the Golden Poker button lamps so that the 6-button layouts for Jolli Witch and Wild Witch make sense. In 6-button mode, the hold buttons double as bonus game and bet buttons, but the lamp outputs don't change. The simplest way to deal with this without requiring the user to switch views or using layout scripting is to place the dedicated buttons directly below the hold buttons that correspond to them. Removed some software list data that was redundantly copied into device_image_interface (m_supported was never even set, so it didn't even work), and made crc() work better (previously it wasn't recalculuated after unloading and loading another image). Made strformat.h and devcb.h play nicer with C++17 and pre-standard C++20. Format precision now correctly limits the length of string views. Confirmed that strformat.{h,cpp} works with pre-standard C++20 support in GCC 9. Removed an auto_alloc from cpu/arm7.
Diffstat (limited to 'src/lib/util/strformat.h')
-rw-r--r--src/lib/util/strformat.h119
1 files changed, 58 insertions, 61 deletions
diff --git a/src/lib/util/strformat.h b/src/lib/util/strformat.h
index 2ed90669284..0ce57606436 100644
--- a/src/lib/util/strformat.h
+++ b/src/lib/util/strformat.h
@@ -106,11 +106,12 @@
The format string type can be a pointer to a NUL-terminated string,
an array containing a NUL-terminated or non-terminated string, or a
STL contiguous container holding a string (e.g. std::string,
- std::vector or std::array). Note that NUL characters characters are
- only treated as terminators for pointers and arrays, they are
- treated as normal characters for other containers. A non-contiguous
- container (e.g. std::list or std::deque) will result in undesirable
- behaviour likely culminating in a crash.
+ std::string_view, std::vector or std::array). Note that NUL
+ characters characters are only treated as terminators for pointers
+ and arrays, they are treated as normal characters for other
+ containers. Using a non-contiguous container (e.g. std::list or
+ std::deque) will result in undesirable behaviour likely culminating
+ in a crash.
The value type of the format string and the character type of the
output stream/string need to match. You can't use a wchar_t format
@@ -184,6 +185,7 @@
#include <locale>
#include <sstream>
#include <string>
+#include <string_view>
#include <type_traits>
#include <utility>
@@ -576,10 +578,16 @@ template <typename Stream, typename T>
class format_output
{
private:
+ template <typename U> struct string_semantics
+ { static constexpr bool value = false; };
+ template <typename CharT, typename Traits, typename Allocator> struct string_semantics<std::basic_string<CharT, Traits, Allocator> >
+ { static constexpr bool value = true; };
+ template <typename CharT, typename Traits> struct string_semantics<std::basic_string_view<CharT, Traits> >
+ { static constexpr bool value = true; };
template <typename U> struct signed_integer_semantics
- { static constexpr bool value = std::is_integral<U>::value && std::is_signed<U>::value; };
+ { static constexpr bool value = std::is_integral_v<U>&& std::is_signed_v<U>; };
template <typename U> struct unsigned_integer_semantics
- { static constexpr bool value = std::is_integral<U>::value && !std::is_signed<U>::value; };
+ { static constexpr bool value = std::is_integral_v<U>&& !std::is_signed_v<U>; };
static void apply_signed(Stream &str, char16_t const &value)
{
@@ -590,19 +598,14 @@ private:
str << std::make_signed_t<std::uint_least32_t>(std::uint_least32_t(value));
}
template <typename U>
- static std::enable_if_t<std::is_same<std::make_signed_t<U>, std::make_signed_t<char> >::value> apply_signed(Stream &str, U const &value)
- {
- str << int(std::make_signed_t<U>(value));
- }
- template <typename U>
- static std::enable_if_t<!std::is_same<std::make_signed_t<U>, std::make_signed_t<char> >::value && signed_integer_semantics<U>::value> apply_signed(Stream &str, U const &value)
- {
- str << value;
- }
- template <typename U>
- static std::enable_if_t<!std::is_same<std::make_signed_t<U>, std::make_signed_t<char> >::value && unsigned_integer_semantics<U>::value> apply_signed(Stream &str, U const &value)
+ static std::enable_if_t<std::is_same_v<std::make_signed_t<U>, std::make_signed_t<char> > || std::is_integral_v<U> > apply_signed(Stream &str, U const &value)
{
- str << std::make_signed_t<U>(value);
+ if constexpr (std::is_same_v<std::make_signed_t<U>, std::make_signed_t<char> >)
+ str << int(std::make_signed_t<U>(value));
+ else if constexpr (std::is_signed_v<U>)
+ str << value;
+ else
+ str << std::make_signed_t<U>(value);
}
static void apply_unsigned(Stream &str, char16_t const &value)
@@ -614,26 +617,49 @@ private:
str << std::uint_least32_t(value);
}
template <typename U>
- static std::enable_if_t<std::is_same<std::make_unsigned_t<U>, std::make_unsigned_t<char> >::value> apply_unsigned(Stream &str, U const &value)
- {
- str << unsigned(std::make_unsigned_t<U>(value));
- }
- template <typename U>
- static std::enable_if_t<!std::is_same<std::make_unsigned_t<U>, std::make_unsigned_t<char> >::value && signed_integer_semantics<U>::value> apply_unsigned(Stream &str, U const &value)
+ static std::enable_if_t<std::is_same_v<std::make_unsigned_t<U>, std::make_unsigned_t<char> > || std::is_integral_v<U> > apply_unsigned(Stream &str, U const &value)
{
- str << std::make_unsigned_t<U>(value);
- }
- template <typename U>
- static std::enable_if_t<!std::is_same<std::make_unsigned_t<U>, std::make_unsigned_t<char> >::value && unsigned_integer_semantics<U>::value> apply_unsigned(Stream &str, U const &value)
- {
- str << value;
+ if constexpr (std::is_same_v<std::make_unsigned_t<U>, std::make_unsigned_t<char> >)
+ str << unsigned(std::make_unsigned_t<U>(value));
+ else if constexpr (std::is_signed_v<U>)
+ str << std::make_unsigned_t<U>(value);
+ else
+ str << value;
}
public:
template <typename U>
static void apply(Stream &str, format_flags const &flags, U const &value)
{
- if constexpr (signed_integer_semantics<U>::value)
+ if constexpr (string_semantics<U>::value)
+ {
+ int const precision(flags.get_precision());
+ if ((0 <= precision) && (value.size() > unsigned(precision)))
+ {
+ if constexpr (std::is_same_v<typename U::value_type, typename Stream::char_type>)
+ {
+ unsigned width(flags.get_field_width());
+ bool const pad(unsigned(precision) < width);
+ typename Stream::fmtflags const adjust(str.flags() & Stream::adjustfield);
+ if (!pad || (Stream::left == adjust)) str.write(&*value.begin(), unsigned(precision));
+ if (pad)
+ {
+ for (width -= precision; 0U < width; --width) str.put(str.fill());
+ if (Stream::left != adjust) str.write(&*value.begin(), unsigned(precision));
+ }
+ str.width(0);
+ }
+ else
+ {
+ str << value.substr(0, unsigned(precision));
+ }
+ }
+ else
+ {
+ str << value;
+ }
+ }
+ else if constexpr (signed_integer_semantics<U>::value)
{
switch (flags.get_conversion())
{
@@ -833,35 +859,6 @@ public:
str << value;
}
}
- template <typename CharT, typename Traits, typename Allocator>
- static void apply(Stream &str, format_flags const &flags, std::basic_string<CharT, Traits, Allocator> const &value)
- {
- int const precision(flags.get_precision());
- if ((0 <= precision) && (value.size() > unsigned(precision)))
- {
- if constexpr (std::is_same_v<CharT, typename Stream::char_type>)
- {
- unsigned width(flags.get_field_width());
- bool const pad(unsigned(precision) < width);
- typename Stream::fmtflags const adjust(str.flags() & Stream::adjustfield);
- if (!pad || (Stream::left == adjust)) str.write(&*value.begin(), unsigned(precision));
- if (pad)
- {
- for (width -= precision; 0U < width; --width) str.put(str.fill());
- if (Stream::left != adjust) str.write(&*value.begin(), unsigned(precision));
- }
- str.width(0);
- }
- else
- {
- str << value.substr(0, unsigned(precision));
- }
- }
- else
- {
- str << value;
- }
- }
};
template <typename Stream, typename T>