mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2024-11-25 23:17:28 +00:00
Macros: Add test and improve speed
Space macros out utilize cache locality ensure no lost functionality
This commit is contained in:
parent
51e0deb7c6
commit
a704d840dc
@ -1,6 +1,5 @@
|
|||||||
#define GENERATE_ENUM_STRINGS // Start string generation
|
#define GENERATE_ENUM_STRINGS // Start string generation
|
||||||
|
|
||||||
#include <map>
|
|
||||||
#include "eGameMessageType.h"
|
#include "eGameMessageType.h"
|
||||||
#include "eWorldMessageType.h"
|
#include "eWorldMessageType.h"
|
||||||
|
|
||||||
|
@ -2,54 +2,61 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#undef DECL_ENUM_ELEMENT
|
#ifndef __STRINGIFYENUMS__H__
|
||||||
#undef BEGIN_ENUM
|
#define __STRINGIFYENUMS__H__
|
||||||
#undef END_ENUM
|
|
||||||
|
|
||||||
#ifndef GENERATE_ENUM_STRINGS
|
# undef DECL_ENUM_ELEMENT
|
||||||
|
# undef BEGIN_ENUM
|
||||||
|
# undef END_ENUM
|
||||||
|
|
||||||
#define DECLARE_ENUM_ELEMENT(element) element,
|
# ifndef GENERATE_ENUM_STRINGS
|
||||||
#define BEGIN_ENUM(ENUM_NAME, TYPE) typedef enum class tag##ENUM_NAME : TYPE {
|
|
||||||
#define BEGIN_ENUM_INT(ENUM_NAME) BEGIN_ENUM(ENUM_NAME, int)
|
|
||||||
#define END_ENUM(ENUM_NAME) } ENUM_NAME; const char* ENUM_NAME##_as_string(enum tag##ENUM_NAME index);
|
|
||||||
|
|
||||||
#define DECLARE_ENUM_ELEMENT_WITH_VALUE(element, value) element = value,
|
# define DECLARE_ENUM_ELEMENT(element) element,
|
||||||
#define BEGIN_ENUM_WITH_VALUES(ENUM_NAME, TYPE) BEGIN_ENUM(ENUM_NAME, TYPE)
|
# define BEGIN_ENUM(ENUM_NAME, TYPE) typedef enum class tag##ENUM_NAME : TYPE {
|
||||||
#define BEGIN_ENUM_WITH_VALUES_INT(ENUM_NAME) BEGIN_ENUM(ENUM_NAME, int)
|
# define BEGIN_ENUM_INT(ENUM_NAME) BEGIN_ENUM(ENUM_NAME, int)
|
||||||
#define END_ENUM_WITH_VALUES(ENUM_NAME, TYPE) END_ENUM(ENUM_NAME)
|
# define END_ENUM(ENUM_NAME) } ENUM_NAME; const char* ENUM_NAME##_as_string(enum tag##ENUM_NAME index);
|
||||||
|
|
||||||
#else
|
# define DECLARE_ENUM_ELEMENT_WITH_VALUE(element, value) element = value,
|
||||||
#define NO_VALUE "<none>"
|
|
||||||
|
|
||||||
#define DECLARE_ENUM_ELEMENT(element) #element,
|
# define BEGIN_ENUM_WITH_VALUES(ENUM_NAME, TYPE) BEGIN_ENUM(ENUM_NAME, TYPE)
|
||||||
|
# define BEGIN_ENUM_WITH_VALUES_INT(ENUM_NAME) BEGIN_ENUM(ENUM_NAME, int)
|
||||||
|
# define END_ENUM_WITH_VALUES(ENUM_NAME, TYPE) END_ENUM(ENUM_NAME)
|
||||||
|
|
||||||
#define BEGIN_ENUM(ENUM_NAME, TYPE) enum class tag##ENUM_NAME : TYPE;\
|
# else // GENERATE_ENUM_STRINGS
|
||||||
|
# define NO_VALUE "<none>"
|
||||||
|
|
||||||
|
# define DECLARE_ENUM_ELEMENT(element) #element,
|
||||||
|
|
||||||
|
# define BEGIN_ENUM(ENUM_NAME, TYPE) enum class tag##ENUM_NAME : TYPE;\
|
||||||
const char* ENUM_NAME##_as_string(enum tag##ENUM_NAME value) {\
|
const char* ENUM_NAME##_as_string(enum tag##ENUM_NAME value) {\
|
||||||
std::size_t index = static_cast<std::size_t>(value);\
|
std::size_t index = static_cast<std::size_t>(value);\
|
||||||
static const char* s_##ENUM_NAME[] = {
|
static const char* s_##ENUM_NAME[] = {
|
||||||
|
|
||||||
#define BEGIN_ENUM_INT(ENUM_NAME) BEGIN_ENUM(ENUM_NAME, int)
|
# define BEGIN_ENUM_INT(ENUM_NAME) BEGIN_ENUM(ENUM_NAME, int)
|
||||||
|
|
||||||
#define END_ENUM(ENUM_NAME) };\
|
# define END_ENUM(ENUM_NAME) };\
|
||||||
static const std::size_t s_##ENUM_NAME_len = sizeof(s_##ENUM_NAME)/sizeof(const char*);\
|
static const std::size_t s_##ENUM_NAME_len = sizeof(s_##ENUM_NAME)/sizeof(const char*);\
|
||||||
if(index >=0 && index < s_##ENUM_NAME_len)\
|
if(index >=0 && index < s_##ENUM_NAME_len)\
|
||||||
return s_##ENUM_NAME[index]; \
|
return s_##ENUM_NAME[index]; \
|
||||||
return NO_VALUE;\
|
return NO_VALUE;\
|
||||||
}
|
}
|
||||||
|
|
||||||
#define DECLARE_ENUM_ELEMENT_WITH_VALUE(element, value) {value, #element},
|
# define DECLARE_ENUM_ELEMENT_WITH_VALUE(element, value) {value, #element},
|
||||||
|
|
||||||
#define BEGIN_ENUM_WITH_VALUES(ENUM_NAME, TYPE) enum class tag##ENUM_NAME : TYPE;\
|
# define BEGIN_ENUM_WITH_VALUES(ENUM_NAME, TYPE) enum class tag##ENUM_NAME : TYPE;\
|
||||||
const char* ENUM_NAME##_as_string(enum tag##ENUM_NAME value) {\
|
const char* ENUM_NAME##_as_string(enum tag##ENUM_NAME value) {\
|
||||||
std::map<TYPE, const char*> sv = {
|
static std::vector<std::pair<TYPE, const char*>> sv = {
|
||||||
|
|
||||||
#define BEGIN_ENUM_WITH_VALUES_INT(ENUM_NAME) BEGIN_ENUM_WITH_VALUES(ENUM_NAME, int)
|
# define BEGIN_ENUM_WITH_VALUES_INT(ENUM_NAME) BEGIN_ENUM_WITH_VALUES(ENUM_NAME, int)
|
||||||
|
|
||||||
#define END_ENUM_WITH_VALUES(ENUM_NAME, TYPE) };\
|
# define END_ENUM_WITH_VALUES(ENUM_NAME, TYPE) };\
|
||||||
auto it = sv.find(static_cast<TYPE>(value));\
|
static bool sorted = false;\
|
||||||
if (it != sv.end())\
|
if (!sorted) std::sort(sv.begin(), sv.end(), [&](const std::pair<TYPE, const char*>& lhs, const std::pair<TYPE, const char*>& rhs) { return lhs.first < rhs.first; });\
|
||||||
return it->second;\
|
sorted = true;\
|
||||||
return NO_VALUE;\
|
const auto it = std::lower_bound(sv.begin(), sv.end(), static_cast<TYPE>(value), [&](const std::pair<TYPE, const char*>& lhs, const TYPE rhs) { return lhs.first < rhs; });\
|
||||||
|
return it != sv.end() ? it->second : NO_VALUE;\
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
# endif // GENERATE_ENUM_STRINGS
|
||||||
|
|
||||||
|
#endif //!__STRINGIFYENUMS__H__
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
set(DGAMETEST_SOURCES
|
set(DGAMETEST_SOURCES
|
||||||
"GameDependencies.cpp"
|
"GameDependencies.cpp"
|
||||||
|
"MacroStringifyTests.cpp"
|
||||||
)
|
)
|
||||||
|
|
||||||
add_subdirectory(dComponentsTests)
|
add_subdirectory(dComponentsTests)
|
||||||
|
60
tests/dGameTests/MacroStringifyTests.cpp
Normal file
60
tests/dGameTests/MacroStringifyTests.cpp
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
#include "Logger.h"
|
||||||
|
#include "Game.h"
|
||||||
|
#include "eWorldMessageType.h"
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
|
#define funny(y, z) LOG("%s %s", eWorldMessageType_as_string(static_cast<eWorldMessageType>(y)), #z); ASSERT_EQ(eWorldMessageType_as_string(static_cast<eWorldMessageType>(y)), #z);
|
||||||
|
#define funny_invalid(y) LOG("%s", eWorldMessageType_as_string(static_cast<eWorldMessageType>(y))); ASSERT_EQ(eWorldMessageType_as_string(static_cast<eWorldMessageType>(y)), "<none>");
|
||||||
|
|
||||||
|
TEST(StringifiedMacroTest, eWorldMessageTypeMacroTest) {
|
||||||
|
Game::logger = new Logger("./MacroTest.log", true, true);
|
||||||
|
funny(1, VALIDATION);
|
||||||
|
funny(2, CHARACTER_LIST_REQUEST);
|
||||||
|
funny(3, CHARACTER_CREATE_REQUEST);
|
||||||
|
funny(4, LOGIN_REQUEST);
|
||||||
|
funny(5, GAME_MSG);
|
||||||
|
funny(6, CHARACTER_DELETE_REQUEST);
|
||||||
|
funny(7, CHARACTER_RENAME_REQUEST);
|
||||||
|
funny(8, HAPPY_FLOWER_MODE_NOTIFY);
|
||||||
|
funny(9, SLASH_RELOAD_MAP);
|
||||||
|
funny(10, SLASH_PUSH_MAP_REQUEST);
|
||||||
|
funny(11, SLASH_PUSH_MAP);
|
||||||
|
funny(12, SLASH_PULL_MAP);
|
||||||
|
funny(13, LOCK_MAP_REQUEST);
|
||||||
|
funny(14, GENERAL_CHAT_MESSAGE);
|
||||||
|
funny(15, HTTP_MONITOR_INFO_REQUEST);
|
||||||
|
funny(16, SLASH_DEBUG_SCRIPTS);
|
||||||
|
funny(17, MODELS_CLEAR);
|
||||||
|
funny(18, EXHIBIT_INSERT_MODEL);
|
||||||
|
funny(19, LEVEL_LOAD_COMPLETE);
|
||||||
|
funny(20, TMP_GUILD_CREATE);
|
||||||
|
funny(21, ROUTE_PACKET);
|
||||||
|
funny(22, POSITION_UPDATE);
|
||||||
|
funny(23, MAIL);
|
||||||
|
funny(24, WORD_CHECK);
|
||||||
|
funny(25, STRING_CHECK);
|
||||||
|
funny(26, GET_PLAYERS_IN_ZONE);
|
||||||
|
funny(27, REQUEST_UGC_MANIFEST_INFO);
|
||||||
|
funny(28, BLUEPRINT_GET_ALL_DATA_REQUEST);
|
||||||
|
funny(29, CANCEL_MAP_QUEUE);
|
||||||
|
funny(30, HANDLE_FUNNESS);
|
||||||
|
funny(31, FAKE_PRG_CSR_MESSAGE);
|
||||||
|
funny(32, REQUEST_FREE_TRIAL_REFRESH);
|
||||||
|
funny(33, GM_SET_FREE_TRIAL_STATUS);
|
||||||
|
funny(91, UI_HELP_TOP_5);
|
||||||
|
funny_invalid(123);
|
||||||
|
|
||||||
|
auto begin = std::chrono::high_resolution_clock::now();
|
||||||
|
for (int i = 0; i < 10000000; ++i) {
|
||||||
|
volatile auto f = eWorldMessageType_as_string(static_cast<eWorldMessageType>(i));
|
||||||
|
|
||||||
|
// To ensure the compiler doesn't optimize out the call, I print it at random intervals
|
||||||
|
if (rand() % 100000 == 0) LOG("%i, %s", i, f);
|
||||||
|
}
|
||||||
|
auto end = std::chrono::high_resolution_clock::now();
|
||||||
|
LOG("Time: %lld", std::chrono::duration_cast<std::chrono::microseconds>(end - begin).count());
|
||||||
|
|
||||||
|
delete Game::logger;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user