add hex literal and tests
This commit is contained in:
parent
a841ef876f
commit
44dd56542a
|
@ -8,7 +8,8 @@ SUBDIRS = \
|
||||||
tools \
|
tools \
|
||||||
support \
|
support \
|
||||||
examples \
|
examples \
|
||||||
playground
|
playground \
|
||||||
|
tests
|
||||||
|
|
||||||
OTHER_FILES = \
|
OTHER_FILES = \
|
||||||
doc/Doxyfile \
|
doc/Doxyfile \
|
||||||
|
@ -25,3 +26,4 @@ tools.depends = src
|
||||||
support.depends = src skins
|
support.depends = src skins
|
||||||
examples.depends = tools support skins qmlexport
|
examples.depends = tools support skins qmlexport
|
||||||
playground.depends = tools support skins qmlexport
|
playground.depends = tools support skins qmlexport
|
||||||
|
tests.depends = src
|
||||||
|
|
|
@ -333,9 +333,52 @@ namespace QskRgb
|
||||||
|
|
||||||
namespace literals
|
namespace literals
|
||||||
{
|
{
|
||||||
|
template< QRgb V >
|
||||||
|
constexpr QRgb parse_hex_literal_h()
|
||||||
|
{
|
||||||
|
return V;
|
||||||
|
}
|
||||||
|
|
||||||
|
template< QRgb V, char C, char... Cs >
|
||||||
|
constexpr QRgb parse_hex_literal_h()
|
||||||
|
{
|
||||||
|
constexpr auto is_0_9 = C >= '0' && C <= '9';
|
||||||
|
constexpr auto is_a_f = C >= 'a' && C <= 'f';
|
||||||
|
constexpr auto is_A_F = C >= 'A' && C <= 'F';
|
||||||
|
|
||||||
|
static_assert( is_0_9 || is_a_f || is_A_F, "invalid hex character" );
|
||||||
|
|
||||||
|
if constexpr ( is_0_9 )
|
||||||
|
{
|
||||||
|
return parse_hex_literal_h< ( V << 4 ) | ( C - '0' ), Cs... >();
|
||||||
|
}
|
||||||
|
if constexpr ( is_a_f )
|
||||||
|
{
|
||||||
|
return parse_hex_literal_h< ( V << 4 ) | ( C - 'a' + 10 ), Cs... >();
|
||||||
|
}
|
||||||
|
if constexpr ( is_A_F )
|
||||||
|
{
|
||||||
|
return parse_hex_literal_h< ( V << 4 ) | ( C - 'A' + 10 ), Cs... >();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template< char C, char... Cs >
|
||||||
|
constexpr QRgb parse_hex_literal_x()
|
||||||
|
{
|
||||||
|
static_assert( C == 'x', "invalid hex prefix character" );
|
||||||
|
return parse_hex_literal_h< 0, Cs... >();
|
||||||
|
}
|
||||||
|
|
||||||
|
template< char C, char... Cs >
|
||||||
|
constexpr QRgb parse_hex_literal_0()
|
||||||
|
{
|
||||||
|
static_assert( C == '0', "invalid hex prefix character" );
|
||||||
|
return parse_hex_literal_x< Cs... >();
|
||||||
|
}
|
||||||
|
|
||||||
namespace qrgb
|
namespace qrgb
|
||||||
{
|
{
|
||||||
// converts a hex string from '#RRGGBB[AA]' to '0x[AA]RRGGBB' integer
|
// converts a hex string from '#RRGGBB[AA]' to '0xAARRGGBB' integer
|
||||||
QSK_EXPORT constexpr QRgb operator""_rgba(
|
QSK_EXPORT constexpr QRgb operator""_rgba(
|
||||||
const char* const str, const size_t len ) noexcept
|
const char* const str, const size_t len ) noexcept
|
||||||
{
|
{
|
||||||
|
@ -348,7 +391,7 @@ namespace QskRgb
|
||||||
return qRgba( r, g, b, a );
|
return qRgba( r, g, b, a );
|
||||||
}
|
}
|
||||||
|
|
||||||
// converts a hex string from '#[AA]RRGGBB' to '0x[AA]RRGGBB' integer
|
// converts a hex string from '#[AA]RRGGBB' to '0xAARRGGBB' integer
|
||||||
QSK_EXPORT constexpr QRgb operator""_argb(
|
QSK_EXPORT constexpr QRgb operator""_argb(
|
||||||
const char* const str, const size_t len ) noexcept
|
const char* const str, const size_t len ) noexcept
|
||||||
{
|
{
|
||||||
|
@ -361,14 +404,82 @@ namespace QskRgb
|
||||||
return qRgba( r, g, b, a );
|
return qRgba( r, g, b, a );
|
||||||
}
|
}
|
||||||
|
|
||||||
#define QSK_CHECK_CONSTEXPR_LITERAL 1
|
// converts a hex literal from '0xRRGGBB[AA]' to '0xAARRGGBB' integer
|
||||||
#ifdef QSK_CHECK_CONSTEXPR_LITERAL
|
template< char... Cs >
|
||||||
|
constexpr QRgb operator""_rgba()
|
||||||
|
{
|
||||||
|
constexpr auto rrggbb = 8;
|
||||||
|
constexpr auto rrggbbaa = 10;
|
||||||
|
static_assert( sizeof...( Cs ) == rrggbb || sizeof...( Cs ) == rrggbbaa,
|
||||||
|
"invalid color literal length" );
|
||||||
|
constexpr auto rgba = parse_hex_literal_0< Cs... >();
|
||||||
|
if constexpr ( sizeof...( Cs ) == rrggbb )
|
||||||
|
{
|
||||||
|
const auto r = ( rgba >> ( 4 * 4 ) ) & 0xFF;
|
||||||
|
const auto g = ( rgba >> ( 2 * 4 ) ) & 0xFF;
|
||||||
|
const auto b = ( rgba >> ( 0 * 4 ) ) & 0xFF;
|
||||||
|
const auto a = 0xFF;
|
||||||
|
return qRgba( r, g, b, a );
|
||||||
|
}
|
||||||
|
if constexpr ( sizeof...( Cs ) == rrggbbaa )
|
||||||
|
{
|
||||||
|
const auto r = ( rgba >> ( 6 * 4 ) ) & 0xFF;
|
||||||
|
const auto g = ( rgba >> ( 4 * 4 ) ) & 0xFF;
|
||||||
|
const auto b = ( rgba >> ( 2 * 4 ) ) & 0xFF;
|
||||||
|
const auto a = ( rgba >> ( 0 * 4 ) ) & 0xFF;
|
||||||
|
return qRgba( r, g, b, a );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// converts a hex literal from '0x[AA]RRGGBB' to '0xAARRGGBB' integer
|
||||||
|
template< char... Cs >
|
||||||
|
constexpr QRgb operator""_argb()
|
||||||
|
{
|
||||||
|
constexpr auto rrggbb = 8;
|
||||||
|
constexpr auto aarrggbb = 10;
|
||||||
|
static_assert( sizeof...( Cs ) == rrggbb || sizeof...( Cs ) == aarrggbb,
|
||||||
|
"invalid color literal length" );
|
||||||
|
constexpr auto rgba = parse_hex_literal_0< Cs... >();
|
||||||
|
if constexpr ( sizeof...( Cs ) == rrggbb )
|
||||||
|
{
|
||||||
|
const auto r = ( rgba >> ( 4 * 4 ) ) & 0xFF;
|
||||||
|
const auto g = ( rgba >> ( 2 * 4 ) ) & 0xFF;
|
||||||
|
const auto b = ( rgba >> ( 0 * 4 ) ) & 0xFF;
|
||||||
|
const auto a = 0xFF;
|
||||||
|
return qRgba( r, g, b, a );
|
||||||
|
}
|
||||||
|
if constexpr ( sizeof...( Cs ) == aarrggbb )
|
||||||
|
{
|
||||||
|
const auto r = ( rgba >> ( 4 * 4 ) ) & 0xFF;
|
||||||
|
const auto g = ( rgba >> ( 2 * 4 ) ) & 0xFF;
|
||||||
|
const auto b = ( rgba >> ( 0 * 4 ) ) & 0xFF;
|
||||||
|
const auto a = ( rgba >> ( 6 * 4 ) ) & 0xFF;
|
||||||
|
return qRgba( r, g, b, a );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define QSK_REQUIRE_CONSTEXPR_LITERAL 1
|
||||||
|
#ifdef QSK_REQUIRE_CONSTEXPR_LITERAL
|
||||||
|
// RGBA hex string to QRgb with defaulted alpha = 0xFF
|
||||||
static_assert( "#123456"_rgba == 0xFF123456, "not constexpr" );
|
static_assert( "#123456"_rgba == 0xFF123456, "not constexpr" );
|
||||||
static_assert( "#123456"_argb == 0xFF123456, "not constexpr" );
|
static_assert( "#123456"_argb == 0xFF123456, "not constexpr" );
|
||||||
|
|
||||||
|
// ARGB hex string to QRgb with defaulted alpha = 0xFF
|
||||||
static_assert( "#AA112233"_argb == 0xAA112233, "not constexpr" );
|
static_assert( "#AA112233"_argb == 0xAA112233, "not constexpr" );
|
||||||
static_assert( "#112233AA"_rgba == 0xAA112233, "not constexpr" );
|
static_assert( "#112233AA"_rgba == 0xAA112233, "not constexpr" );
|
||||||
#endif
|
|
||||||
|
|
||||||
|
// RGBA hex literal to QRgb with defaulted alpha = 0xFF
|
||||||
|
static_assert( 0x112233_rgba == 0xFF112233, "" );
|
||||||
|
static_assert( 0xaabbcc_rgba == 0xFFAABBCC, "" );
|
||||||
|
static_assert( 0xAABBCC_rgba == 0xFFAABBCC, "" );
|
||||||
|
static_assert( 0x112233aa_rgba == 0xaa112233, "" );
|
||||||
|
|
||||||
|
// ARGB hex literal to QRgb with defaulted alpha = 0xFF
|
||||||
|
static_assert( 0x112233_argb == 0xFF112233, "" );
|
||||||
|
static_assert( 0xaabbcc_argb == 0xFFAABBCC, "" );
|
||||||
|
static_assert( 0xAABBCC_argb == 0xFFAABBCC, "" );
|
||||||
|
static_assert( 0x112233aa_argb == 0x112233aa, "" );
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace color
|
namespace color
|
||||||
|
@ -398,6 +509,60 @@ namespace QskRgb
|
||||||
const auto color = QColor{ r, g, b, a };
|
const auto color = QColor{ r, g, b, a };
|
||||||
return color;
|
return color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// converts a hex literal from '0xRRGGBB[AA]' to a QColor
|
||||||
|
template< char... Cs >
|
||||||
|
constexpr QColor operator""_rgba()
|
||||||
|
{
|
||||||
|
constexpr auto rrggbb = 8;
|
||||||
|
constexpr auto rrggbbaa = 10;
|
||||||
|
static_assert( sizeof...( Cs ) == rrggbb || sizeof...( Cs ) == rrggbbaa,
|
||||||
|
"invalid color literal length" );
|
||||||
|
constexpr auto rgba = parse_hex_literal_0< Cs... >();
|
||||||
|
if constexpr ( sizeof...( Cs ) == rrggbb )
|
||||||
|
{
|
||||||
|
const auto r = ( rgba >> ( 4 * 4 ) ) & 0xFF;
|
||||||
|
const auto g = ( rgba >> ( 2 * 4 ) ) & 0xFF;
|
||||||
|
const auto b = ( rgba >> ( 0 * 4 ) ) & 0xFF;
|
||||||
|
const auto a = 0xFF;
|
||||||
|
return { r, g, b, a };
|
||||||
|
}
|
||||||
|
if constexpr ( sizeof...( Cs ) == rrggbbaa )
|
||||||
|
{
|
||||||
|
const auto r = ( rgba >> ( 6 * 4 ) ) & 0xFF;
|
||||||
|
const auto g = ( rgba >> ( 4 * 4 ) ) & 0xFF;
|
||||||
|
const auto b = ( rgba >> ( 2 * 4 ) ) & 0xFF;
|
||||||
|
const auto a = ( rgba >> ( 0 * 4 ) ) & 0xFF;
|
||||||
|
return { r, g, b, a };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// converts a hex literal from '0x[AA]RRGGBB' to a QColor
|
||||||
|
template< char... Cs >
|
||||||
|
constexpr QColor operator""_argb()
|
||||||
|
{
|
||||||
|
constexpr auto rrggbb = 8;
|
||||||
|
constexpr auto aarrggbb = 10;
|
||||||
|
static_assert( sizeof...( Cs ) == rrggbb || sizeof...( Cs ) == aarrggbb,
|
||||||
|
"invalid color literal length" );
|
||||||
|
constexpr auto rgba = parse_hex_literal_0< Cs... >();
|
||||||
|
if constexpr ( sizeof...( Cs ) == rrggbb )
|
||||||
|
{
|
||||||
|
const auto r = ( rgba >> ( 4 * 4 ) ) & 0xFF;
|
||||||
|
const auto g = ( rgba >> ( 2 * 4 ) ) & 0xFF;
|
||||||
|
const auto b = ( rgba >> ( 0 * 4 ) ) & 0xFF;
|
||||||
|
const auto a = 0xFF;
|
||||||
|
return { r, g, b, a };
|
||||||
|
}
|
||||||
|
if constexpr ( sizeof...( Cs ) == aarrggbb )
|
||||||
|
{
|
||||||
|
const auto r = ( rgba >> ( 4 * 4 ) ) & 0xFF;
|
||||||
|
const auto g = ( rgba >> ( 2 * 4 ) ) & 0xFF;
|
||||||
|
const auto b = ( rgba >> ( 0 * 4 ) ) & 0xFF;
|
||||||
|
const auto a = ( rgba >> ( 6 * 4 ) ) & 0xFF;
|
||||||
|
return { r, g, b, a };
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,109 @@
|
||||||
|
#include "test_QskRgbLiterals.h"
|
||||||
|
#include <QTest>
|
||||||
|
#include <QskRgbValue.h>
|
||||||
|
|
||||||
|
void QskRgbLiterals::parsing_data()
|
||||||
|
{
|
||||||
|
QTest::addColumn< QString >( "text" );
|
||||||
|
QTest::addColumn< QRgb >( "expected" );
|
||||||
|
|
||||||
|
QTest::newRow( "" ) << "" << ( QRgb ) 0;
|
||||||
|
QTest::newRow( "#" ) << "#" << ( QRgb ) 0;
|
||||||
|
QTest::newRow( "#1" ) << "#1" << ( QRgb ) 0x1;
|
||||||
|
QTest::newRow( "#12" ) << "#12" << ( QRgb ) 0x12;
|
||||||
|
QTest::newRow( "#123" ) << "#123" << ( QRgb ) 0x123;
|
||||||
|
QTest::newRow( "#1234" ) << "#1234" << ( QRgb ) 0x1234;
|
||||||
|
QTest::newRow( "#12345" ) << "#12345" << ( QRgb ) 0x12345;
|
||||||
|
QTest::newRow( "#123456" ) << "#123456" << ( QRgb ) 0x123456;
|
||||||
|
QTest::newRow( "#1234567" ) << "#1234567" << ( QRgb ) 0x1234567;
|
||||||
|
QTest::newRow( "#12345678" ) << "#12345678" << ( QRgb ) 0x12345678;
|
||||||
|
QTest::newRow( "#123456789" ) << "#123456789" << ( QRgb ) 0x23456789;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QskRgbLiterals::parsing()
|
||||||
|
{
|
||||||
|
QFETCH( QString, text );
|
||||||
|
QFETCH( QRgb, expected );
|
||||||
|
|
||||||
|
const auto actual = text.toStdString();
|
||||||
|
QCOMPARE( QskRgb::fromHexString( actual.c_str(), actual.size() ), expected );
|
||||||
|
}
|
||||||
|
|
||||||
|
void QskRgbLiterals::qrgbLiterals_data()
|
||||||
|
{
|
||||||
|
QTest::addColumn< QRgb >( "actual" );
|
||||||
|
QTest::addColumn< QRgb >( "expected" );
|
||||||
|
|
||||||
|
using namespace QskRgb::literals::qrgb;
|
||||||
|
|
||||||
|
QTest::newRow( "\"#123456\"_rgba" ) << "#123456"_rgba << ( QRgb ) 0xFF123456;
|
||||||
|
QTest::newRow( "\"#123456\"_argb" ) << "#123456"_argb << ( QRgb ) 0xFF123456;
|
||||||
|
|
||||||
|
QTest::newRow( "\"#AA112233\"_argb" ) << "#AA112233"_argb << ( QRgb ) 0xAA112233;
|
||||||
|
QTest::newRow( "\"#112233AA\"_rgba" ) << "#112233AA"_rgba << ( QRgb ) 0xAA112233;
|
||||||
|
|
||||||
|
QTest::newRow( "0x112233_rgba" ) << 0x112233_rgba << ( QRgb ) 0xFF112233;
|
||||||
|
QTest::newRow( "0xaabbcc_rgba" ) << 0xaabbcc_rgba << ( QRgb ) 0xFFAABBCC;
|
||||||
|
QTest::newRow( "0xAABBCC_rgba" ) << 0xAABBCC_rgba << ( QRgb ) 0xFFAABBCC;
|
||||||
|
QTest::newRow( "0x112233aa_rgba" ) << 0x112233aa_rgba << ( QRgb ) 0xaa112233;
|
||||||
|
|
||||||
|
QTest::newRow( "0x112233_argb" ) << 0x112233_argb << ( QRgb ) 0xFF112233;
|
||||||
|
QTest::newRow( "0xaabbcc_argb" ) << 0xaabbcc_argb << ( QRgb ) 0xFFAABBCC;
|
||||||
|
QTest::newRow( "0xAABBCC_argb" ) << 0xAABBCC_argb << ( QRgb ) 0xFFAABBCC;
|
||||||
|
QTest::newRow( "0x112233aa_argb" ) << 0x112233aa_argb << ( QRgb ) 0x112233aa;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QskRgbLiterals::qrgbLiterals()
|
||||||
|
{
|
||||||
|
using namespace QskRgb::literals::qrgb;
|
||||||
|
|
||||||
|
#ifdef QSK_REQUIRE_CONSTEXPR_LITERAL
|
||||||
|
static_assert( "#123456"_rgba == 0xFF123456, "not constexpr" );
|
||||||
|
static_assert( "#123456"_argb == 0xFF123456, "not constexpr" );
|
||||||
|
|
||||||
|
static_assert( "#AA112233"_argb == 0xAA112233, "not constexpr" );
|
||||||
|
static_assert( "#112233AA"_rgba == 0xAA112233, "not constexpr" );
|
||||||
|
|
||||||
|
static_assert( 0x112233_rgba == 0xFF112233, "not constexpr" );
|
||||||
|
static_assert( 0xaabbcc_rgba == 0xFFAABBCC, "not constexpr" );
|
||||||
|
static_assert( 0xAABBCC_rgba == 0xFFAABBCC, "not constexpr" );
|
||||||
|
static_assert( 0x112233aa_rgba == 0xaa112233, "not constexpr" );
|
||||||
|
|
||||||
|
static_assert( 0x112233_argb == 0xFF112233, "not constexpr" );
|
||||||
|
static_assert( 0xaabbcc_argb == 0xFFAABBCC, "not constexpr" );
|
||||||
|
static_assert( 0xAABBCC_argb == 0xFFAABBCC, "not constexpr" );
|
||||||
|
static_assert( 0x112233aa_argb == 0x112233aa, "not constexpr" );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
QFETCH( QRgb, actual );
|
||||||
|
QFETCH( QRgb, expected );
|
||||||
|
QCOMPARE( actual, expected );
|
||||||
|
}
|
||||||
|
|
||||||
|
void QskRgbLiterals::colorLiterals_data()
|
||||||
|
{
|
||||||
|
QTest::addColumn< QColor >( "actual" );
|
||||||
|
QTest::addColumn< QColor >( "expected" );
|
||||||
|
|
||||||
|
using namespace QskRgb::literals::color;
|
||||||
|
QTest::newRow( "\"#112233\"_rgba" ) << "#112233"_rgba << QColor::fromRgb( 0x11, 0x22, 0x33 );
|
||||||
|
QTest::newRow( "\"#112233\"_argb" ) << "#112233"_argb << QColor::fromRgb( 0x11, 0x22, 0x33 );
|
||||||
|
QTest::newRow( "\"#112233AA\"_rgba" )
|
||||||
|
<< "#112233AA"_rgba << QColor::fromRgb( 0x11, 0x22, 0x33, 0xAA );
|
||||||
|
QTest::newRow( "\"#112233AA\"_argb" )
|
||||||
|
<< "#112233AA"_argb << QColor::fromRgb( 0x22, 0x33, 0xAA, 0x11 );
|
||||||
|
|
||||||
|
QTest::newRow( "0x112233_rgba" ) << 0x112233_rgba << QColor::fromRgb( 0x11, 0x22, 0x33 );
|
||||||
|
QTest::newRow( "0x112233_argb" ) << 0x112233_argb << QColor::fromRgb( 0x11, 0x22, 0x33 );
|
||||||
|
QTest::newRow( "0x112233AA_rgba" )
|
||||||
|
<< 0x112233AA_rgba << QColor::fromRgb( 0x11, 0x22, 0x33, 0xAA );
|
||||||
|
QTest::newRow( "0x112233AA_argb" )
|
||||||
|
<< 0x112233AA_argb << QColor::fromRgb( 0x22, 0x33, 0xAA, 0x11 );
|
||||||
|
}
|
||||||
|
|
||||||
|
void QskRgbLiterals::colorLiterals()
|
||||||
|
{
|
||||||
|
QFETCH( QColor, actual );
|
||||||
|
QFETCH( QColor, expected );
|
||||||
|
QCOMPARE( actual, expected );
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
class QskRgbLiterals final : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
private Q_SLOTS:
|
||||||
|
void parsing_data();
|
||||||
|
void parsing();
|
||||||
|
void qrgbLiterals_data();
|
||||||
|
void qrgbLiterals();
|
||||||
|
void colorLiterals_data();
|
||||||
|
void colorLiterals();
|
||||||
|
};
|
|
@ -0,0 +1,12 @@
|
||||||
|
QT += testlib
|
||||||
|
CONFIG += testcase
|
||||||
|
CONFIG += no_testcase_installs
|
||||||
|
CONFIG += qskinny
|
||||||
|
|
||||||
|
HEADERS += \
|
||||||
|
tests_main.h \
|
||||||
|
test_QskRgbLiterals.h \
|
||||||
|
|
||||||
|
SOURCES += \
|
||||||
|
tests_main.cpp \
|
||||||
|
test_QskRgbLiterals.cpp \
|
|
@ -0,0 +1,4 @@
|
||||||
|
#include "test_QskRgbLiterals.h"
|
||||||
|
#include <QTest>
|
||||||
|
|
||||||
|
QTEST_APPLESS_MAIN( QskRgbLiterals )
|
Loading…
Reference in New Issue