From 4131022f6c8283d387f1cdc8f2f1e8df9375ea54 Mon Sep 17 00:00:00 2001 From: Shauren Date: Sun, 31 Mar 2024 19:32:39 +0200 Subject: Core/Entities: Make ObjectGuid formattable with fmt without using ToString() --- src/server/game/Entities/Object/ObjectGuid.cpp | 493 ++++++++++++++++++------- src/server/game/Entities/Object/ObjectGuid.h | 40 +- 2 files changed, 391 insertions(+), 142 deletions(-) (limited to 'src/server/game/Entities') diff --git a/src/server/game/Entities/Object/ObjectGuid.cpp b/src/server/game/Entities/Object/ObjectGuid.cpp index e443d0a13b4..2ac6a236094 100644 --- a/src/server/game/Entities/Object/ObjectGuid.cpp +++ b/src/server/game/Entities/Object/ObjectGuid.cpp @@ -23,6 +23,7 @@ #include "Realm.h" #include "Util.h" #include "World.h" +#include static_assert(sizeof(ObjectGuid) == sizeof(uint64) * 2, "ObjectGuid must be exactly 16 bytes"); @@ -31,54 +32,108 @@ namespace struct ObjectGuidInfo { std::string Names[AsUnderlyingType(HighGuid::Count)]; - std::string(ObjectGuidInfo::*ClientFormatFunction[AsUnderlyingType(HighGuid::Count)])(char const* typeName, ObjectGuid guid); - ObjectGuid(ObjectGuidInfo::*ClientParseFunction[AsUnderlyingType(HighGuid::Count)])(HighGuid type, char const* guidString); + fmt::appender(*ClientFormatFunction[AsUnderlyingType(HighGuid::Count)])(fmt::format_context& ctx, std::string const& typeName, ObjectGuid const& guid); + ObjectGuid(*ClientParseFunction[AsUnderlyingType(HighGuid::Count)])(HighGuid type, std::string_view guidString); - std::string Format(ObjectGuid guid) + static std::string Format(ObjectGuid const& guid) { - if (guid.GetHigh() >= HighGuid::Count) - return "Uniq-WOWGUID_TO_STRING_FAILED"; - - int32 type = AsUnderlyingType(guid.GetHigh()); - if (!ClientFormatFunction[type]) - return "Uniq-WOWGUID_TO_STRING_FAILED"; - - return (this->*ClientFormatFunction[type])(Names[type].c_str(), guid); + return Trinity::StringFormat("{}", guid); } - ObjectGuid Parse(std::string const& guidString) + ObjectGuid Parse(std::string_view guidString) const { std::size_t typeEnd = guidString.find('-'); if (typeEnd == std::string::npos) + { + if (guidString == "0000000000000000") + return ObjectGuid::Empty; return ObjectGuid::FromStringFailed; + } - int32 type = 0; - for (; type < AsUnderlyingType(HighGuid::Count); ++type) - { - if (Names[type].length() < typeEnd) - continue; + std::string_view typeStr = guidString.substr(0, typeEnd); + guidString.remove_prefix(typeEnd + 1); - if (guidString.compare(0, typeEnd, Names[type]) == 0) - break; + // find correct parser for type name + for (int32 type = 0; type < AsUnderlyingType(HighGuid::Count); ++type) + if (typeStr == Names[type]) + return ClientParseFunction[type](HighGuid(type), guidString); + + return ObjectGuid::FromStringFailed; + } + + struct FormatPadding { std::ptrdiff_t Value; constexpr operator std::ptrdiff_t() const { return Value; } }; + + template + static constexpr inline FormatPadding padding{ .Value = Width }; + static constexpr inline FormatPadding no_padding{ .Value = 0 }; + + struct FormatBase { int32 Value; constexpr operator int32() const { return Value; } }; + + static constexpr inline FormatBase dec{ 10 }; + static constexpr inline FormatBase hex{ 16 }; + + static fmt::appender AppendTypeName(fmt::format_context& ctx, std::string const& type) + { + return std::copy(type.begin(), type.end(), ctx.out()); + } + + template + static fmt::appender AppendComponent(fmt::format_context& ctx, uint64 component) + { + *ctx.out() = '-'; + + std::array buf; + auto [end, err] = std::to_chars(buf.data(), buf.data() + buf.size(), component, Base); + + ASSERT_NODEBUGINFO(err == std::errc(), "Failed to convert guid part to string"); + + if constexpr (Width != 0) + { + if (std::distance(buf.data(), end) < Width) + std::fill_n(ctx.out(), Width - std::distance(buf.data(), end), '0'); } - if (type >= AsUnderlyingType(HighGuid::Count)) - return ObjectGuid::FromStringFailed; + return std::transform(buf.data(), end, ctx.out(), charToUpper); + } - return (this->*ClientParseFunction[type])(HighGuid(type), &guidString[typeEnd + 1]); + static fmt::appender AppendComponent(fmt::format_context& ctx, std::string_view component) + { + *ctx.out() = '-'; + return std::copy(component.begin(), component.end(), ctx.out()); } - std::string FormatNull(char const*, ObjectGuid) + template + static bool ParseComponent(std::string_view& input, T* component) { - return "0000000000000000"; + auto [end, err] = std::from_chars(input.data(), input.data() + input.length(), *component, Base); + if (err != std::errc()) + return false; + + input.remove_prefix(end - input.data()); + if (!input.empty()) + { + if (input[0] != '-') + return false; + + input.remove_prefix(1); + } + + return true; + } + + static bool ParseDone(std::string_view const& sv) { return sv.empty(); } + + static fmt::appender FormatNull(fmt::format_context& ctx, std::string const& /*typeName*/, ObjectGuid const& /*guid*/) + { + return std::fill_n(ctx.out(), 16, '0'); } - ObjectGuid ParseNull(HighGuid, char const*) + static ObjectGuid ParseNull(HighGuid, std::string_view) { return ObjectGuid::Empty; } - std::string FormatUniq(char const* typeName, ObjectGuid guid) + static fmt::appender FormatUniq(fmt::format_context& ctx, std::string const& typeName, ObjectGuid const& guid) { constexpr char const* uniqNames[] = { @@ -105,13 +160,15 @@ namespace }; ObjectGuid::LowType id = guid.GetCounter(); - if (id >= std::size(uniqNames)) + if (id >= std::size(uniqNames) || !uniqNames[id]) id = 3; - return Trinity::StringFormat("{}-{}", typeName, uniqNames[id]); + ctx.advance_to(AppendTypeName(ctx, typeName)); + ctx.advance_to(AppendComponent(ctx, uniqNames[id])); + return ctx.out(); } - ObjectGuid ParseUniq(HighGuid /*type*/, char const* guidString) + static ObjectGuid ParseUniq(HighGuid /*type*/, std::string_view guidString) { constexpr char const* uniqNames[] = { @@ -132,7 +189,9 @@ namespace "WOWGUID_FAKE_MODERATOR", nullptr, nullptr, - "WOWGUID_UNIQUE_ACCOUNT_OBJ_INITIALIZATION" + "WOWGUID_UNIQUE_ACCOUNT_OBJ_INITIALIZATION", + nullptr, + "WOWGUID_PENDING_PERMANENT_CHARACTER_ASSIGNMENT" }; for (std::size_t id = 0; id < std::size(uniqNames); ++id) @@ -140,334 +199,480 @@ namespace if (!uniqNames[id]) continue; - if (strcmp(guidString, uniqNames[id]) == 0) + if (guidString == uniqNames[id]) return ObjectGuidFactory::CreateUniq(id); } return ObjectGuid::FromStringFailed; } - std::string FormatPlayer(char const* typeName, ObjectGuid guid) + static fmt::appender FormatPlayer(fmt::format_context& ctx, std::string const& typeName, ObjectGuid const& guid) { - return Trinity::StringFormat("{}-{}-{:08X}", typeName, guid.GetRealmId(), guid.GetRawValue(0)); + ctx.advance_to(AppendTypeName(ctx, typeName)); + ctx.advance_to(AppendComponent(ctx, guid.GetRealmId())); + ctx.advance_to(AppendComponent, hex>(ctx, guid.GetRawValue(0))); + return ctx.out(); } - ObjectGuid ParsePlayer(HighGuid /*type*/, char const* guidString) + static ObjectGuid ParsePlayer(HighGuid /*type*/, std::string_view guidString) { uint32 realmId = 0; uint64 dbId = UI64LIT(0); - if (std::sscanf(guidString, "%u-%08" SCNx64, &realmId, &dbId) != 2) + if (!ParseComponent(guidString, &realmId) + || !ParseComponent(guidString, &dbId) + || !ParseDone(guidString)) return ObjectGuid::FromStringFailed; return ObjectGuidFactory::CreatePlayer(realmId, dbId); } - std::string FormatItem(char const* typeName, ObjectGuid guid) + static fmt::appender FormatItem(fmt::format_context& ctx, std::string const& typeName, ObjectGuid const& guid) { - return Trinity::StringFormat("{}-{}-{}-{:016X}", typeName, guid.GetRealmId(), uint32(guid.GetRawValue(1) >> 18) & 0xFFFFFF, guid.GetRawValue(0)); + ctx.advance_to(AppendTypeName(ctx, typeName)); + ctx.advance_to(AppendComponent(ctx, guid.GetRealmId())); + ctx.advance_to(AppendComponent(ctx, guid.GetRawValue(1) >> 18 & 0xFFFFFF)); + ctx.advance_to(AppendComponent, hex>(ctx, guid.GetRawValue(0))); + return ctx.out(); } - ObjectGuid ParseItem(HighGuid /*type*/, char const* guidString) + static ObjectGuid ParseItem(HighGuid /*type*/, std::string_view guidString) { uint32 realmId = 0; uint32 arg1 = 0; uint64 dbId = UI64LIT(0); - if (std::sscanf(guidString, "%u-%u-%016" SCNx64, &realmId, &arg1, &dbId) != 3) + if (!ParseComponent(guidString, &realmId) + || !ParseComponent(guidString, &arg1) + || !ParseComponent(guidString, &dbId) + || !ParseDone(guidString)) return ObjectGuid::FromStringFailed; return ObjectGuidFactory::CreateItem(realmId, dbId); } - std::string FormatWorldObject(char const* typeName, ObjectGuid guid) + static fmt::appender FormatWorldObject(fmt::format_context& ctx, std::string const& typeName, ObjectGuid const& guid) { - return Trinity::StringFormat("{}-{}-{}-{}-{}-{}-{:010X}", typeName, guid.GetSubType(), guid.GetRealmId(), guid.GetMapId(), - uint32(guid.GetRawValue(0) >> 40) & 0xFFFFFF, guid.GetEntry(), guid.GetCounter()); + ctx.advance_to(AppendTypeName(ctx, typeName)); + ctx.advance_to(AppendComponent(ctx, guid.GetSubType())); + ctx.advance_to(AppendComponent(ctx, guid.GetRealmId())); + ctx.advance_to(AppendComponent(ctx, guid.GetMapId())); + ctx.advance_to(AppendComponent(ctx, guid.GetRawValue(0) >> 40 & 0xFFFFFF)); + ctx.advance_to(AppendComponent(ctx, guid.GetEntry())); + ctx.advance_to(AppendComponent, hex>(ctx, guid.GetCounter())); + return ctx.out(); } - ObjectGuid ParseWorldObject(HighGuid type, char const* guidString) + static ObjectGuid ParseWorldObject(HighGuid type, std::string_view guidString) { - uint32 subType = 0; + uint8 subType = 0; uint32 realmId = 0; - uint32 mapId = 0; + uint16 mapId = 0; uint32 serverId = 0; uint32 id = 0; uint64 counter = UI64LIT(0); - if (std::sscanf(guidString, "%u-%u-%u-%u-%u-%010" SCNx64, &subType, &realmId, &mapId, &serverId, &id, &counter) != 6) + + if (!ParseComponent(guidString, &subType) + || !ParseComponent(guidString, &realmId) + || !ParseComponent(guidString, &mapId) + || !ParseComponent(guidString, &serverId) + || !ParseComponent(guidString, &id) + || !ParseComponent(guidString, &counter) + || !ParseDone(guidString)) return ObjectGuid::FromStringFailed; return ObjectGuidFactory::CreateWorldObject(type, subType, realmId, mapId, serverId, id, counter); } - std::string FormatTransport(char const* typeName, ObjectGuid guid) + static fmt::appender FormatTransport(fmt::format_context& ctx, std::string const& typeName, ObjectGuid const& guid) { - return Trinity::StringFormat("{}-{}-{:016X}", typeName, uint32(guid.GetRawValue(1) >> 38) & 0xFFFFF, guid.GetRawValue(0)); + ctx.advance_to(AppendTypeName(ctx, typeName)); + ctx.advance_to(AppendComponent(ctx, guid.GetEntry())); + ctx.advance_to(AppendComponent, hex>(ctx, guid.GetRawValue(0))); + return ctx.out(); } - ObjectGuid ParseTransport(HighGuid type, char const* guidString) + static ObjectGuid ParseTransport(HighGuid type, std::string_view guidString) { uint32 id = 0; - uint64 counter = UI64LIT(0); + uint32 counter = 0; - if (std::sscanf(guidString, "%u-%016" SCNx64, &id, &counter) != 2) + if (!ParseComponent(guidString, &id) + || !ParseComponent(guidString, &counter) + || !ParseDone(guidString)) return ObjectGuid::FromStringFailed; return ObjectGuidFactory::CreateTransport(type, counter); } - std::string FormatClientActor(char const* typeName, ObjectGuid guid) + static fmt::appender FormatClientActor(fmt::format_context& ctx, std::string const& typeName, ObjectGuid const& guid) { - return Trinity::StringFormat("{}-{}-{}-{}", typeName, guid.GetRealmId(), uint32(guid.GetRawValue(1) >> 26) & 0xFFFFFF, uint32(guid.GetRawValue(0))); + ctx.advance_to(AppendTypeName(ctx, typeName)); + ctx.advance_to(AppendComponent(ctx, guid.GetRealmId())); + ctx.advance_to(AppendComponent(ctx, guid.GetRawValue(1) >> 26 & 0xFFFFFF)); + ctx.advance_to(AppendComponent(ctx, guid.GetRawValue(0) & 0xFFFFFFFF)); + return ctx.out(); } - ObjectGuid ParseClientActor(HighGuid /*type*/, char const* guidString) + static ObjectGuid ParseClientActor(HighGuid /*type*/, std::string_view guidString) { - uint32 ownerType = 0; - uint32 ownerId = 0; + uint16 ownerType = 0; + uint16 ownerId = 0; uint32 counter = 0; - if (std::sscanf(guidString, "%u-%u-%u", &ownerType, &ownerId, &counter) != 3) + if (!ParseComponent(guidString, &ownerType) + || !ParseComponent(guidString, &ownerId) + || !ParseComponent(guidString, &counter) + || !ParseDone(guidString)) return ObjectGuid::FromStringFailed; return ObjectGuidFactory::CreateClientActor(ownerType, ownerId, counter); } - std::string FormatChatChannel(char const* typeName, ObjectGuid guid) + static fmt::appender FormatChatChannel(fmt::format_context& ctx, std::string const& typeName, ObjectGuid const& guid) { uint32 builtIn = (guid.GetRawValue(1) >> 25) & 0x1; uint32 trade = (guid.GetRawValue(1) >> 24) & 0x1; uint32 zoneId = (guid.GetRawValue(1) >> 10) & 0x3FFF; uint32 factionGroupMask = (guid.GetRawValue(1) >> 4) & 0x3F; - return Trinity::StringFormat("{}-{}-{}-{}-{}-{}-{:08X}", typeName, guid.GetRealmId(), builtIn, trade, zoneId, factionGroupMask, guid.GetRawValue(0)); + + ctx.advance_to(AppendTypeName(ctx, typeName)); + ctx.advance_to(AppendComponent(ctx, guid.GetRealmId())); + ctx.advance_to(AppendComponent(ctx, builtIn)); + ctx.advance_to(AppendComponent(ctx, trade)); + ctx.advance_to(AppendComponent(ctx, zoneId)); + ctx.advance_to(AppendComponent(ctx, factionGroupMask)); + ctx.advance_to(AppendComponent, hex>(ctx, guid.GetRawValue(0))); + return ctx.out(); } - ObjectGuid ParseChatChannel(HighGuid /*type*/, char const* guidString) + static ObjectGuid ParseChatChannel(HighGuid /*type*/, std::string_view guidString) { uint32 realmId = 0; uint32 builtIn = 0; uint32 trade = 0; - uint32 zoneId = 0; - uint32 factionGroupMask = 0; + uint16 zoneId = 0; + uint8 factionGroupMask = 0; uint64 id = UI64LIT(0); - if (std::sscanf(guidString, "%u-%u-%u-%u-%u-%08" SCNx64, &realmId, &builtIn, &trade, &zoneId, &factionGroupMask, &id) != 6) + if (!ParseComponent(guidString, &realmId) + || !ParseComponent(guidString, &builtIn) + || !ParseComponent(guidString, &trade) + || !ParseComponent(guidString, &zoneId) + || !ParseComponent(guidString, &factionGroupMask) + || !ParseComponent(guidString, &id) + || !ParseDone(guidString)) return ObjectGuid::FromStringFailed; return ObjectGuidFactory::CreateChatChannel(realmId, builtIn != 0, trade != 0, zoneId, factionGroupMask, id); } - std::string FormatGlobal(char const* typeName, ObjectGuid guid) + static fmt::appender FormatGlobal(fmt::format_context& ctx, std::string const& typeName, ObjectGuid const& guid) { - return Trinity::StringFormat("{}-{}-{:012X}", typeName, guid.GetRawValue(1) & 0x3FFFFFFFFFFFFFF, guid.GetRawValue(0)); + ctx.advance_to(AppendTypeName(ctx, typeName)); + ctx.advance_to(AppendComponent(ctx, guid.GetRawValue(1) & 0x3FFFFFFFFFFFFFF)); + ctx.advance_to(AppendComponent, hex>(ctx, guid.GetRawValue(0))); + return ctx.out(); } - ObjectGuid ParseGlobal(HighGuid type, char const* guidString) + static ObjectGuid ParseGlobal(HighGuid type, std::string_view guidString) { uint64 dbIdHigh = UI64LIT(0); uint64 dbIdLow = UI64LIT(0); - if (std::sscanf(guidString, "%" SCNu64 "-%012" SCNx64, &dbIdHigh, &dbIdLow) != 2) + if (!ParseComponent(guidString, &dbIdHigh) + || !ParseComponent(guidString, &dbIdLow) + || !ParseDone(guidString)) return ObjectGuid::FromStringFailed; return ObjectGuidFactory::CreateGlobal(type, dbIdHigh, dbIdLow); } - std::string FormatGuild(char const* typeName, ObjectGuid guid) + static fmt::appender FormatGuild(fmt::format_context& ctx, std::string const& typeName, ObjectGuid const& guid) { - return Trinity::StringFormat("{}-{}-{:012X}", typeName, guid.GetRealmId(), guid.GetRawValue(0)); + ctx.advance_to(AppendTypeName(ctx, typeName)); + ctx.advance_to(AppendComponent(ctx, guid.GetRealmId())); + ctx.advance_to(AppendComponent, hex>(ctx, guid.GetRawValue(0))); + return ctx.out(); } - ObjectGuid ParseGuild(HighGuid type, char const* guidString) + static ObjectGuid ParseGuild(HighGuid type, std::string_view guidString) { uint32 realmId = 0; uint64 dbId = UI64LIT(0); - if (std::sscanf(guidString, "%u-%012" SCNx64, &realmId, &dbId) != 2) + if (!ParseComponent(guidString, &realmId) + || !ParseComponent(guidString, &dbId) + || !ParseDone(guidString)) return ObjectGuid::FromStringFailed; return ObjectGuidFactory::CreateGuild(type, realmId, dbId); } - std::string FormatMobileSession(char const* typeName, ObjectGuid guid) + static fmt::appender FormatMobileSession(fmt::format_context& ctx, std::string const& typeName, ObjectGuid const& guid) { - return Trinity::StringFormat("{}-{}-{}-{:08X}", typeName, guid.GetRealmId(), uint32(guid.GetRawValue(1) >> 33) & 0x1FF, guid.GetRawValue(0)); + ctx.advance_to(AppendTypeName(ctx, typeName)); + ctx.advance_to(AppendComponent(ctx, guid.GetRealmId())); + ctx.advance_to(AppendComponent(ctx, guid.GetRawValue(1) >> 33 & 0x1FF)); + ctx.advance_to(AppendComponent, hex>(ctx, guid.GetRawValue(0))); + return ctx.out(); } - ObjectGuid ParseMobileSession(HighGuid /*type*/, char const* guidString) + static ObjectGuid ParseMobileSession(HighGuid /*type*/, std::string_view guidString) { uint32 realmId = 0; - uint32 arg1 = 0; + uint16 arg1 = 0; uint64 counter = UI64LIT(0); - if (std::sscanf(guidString, "%u-%u-%08" SCNx64, &realmId, &arg1, &counter) != 3) + if (!ParseComponent(guidString, &realmId) + || !ParseComponent(guidString, &arg1) + || !ParseComponent(guidString, &counter) + || !ParseDone(guidString)) return ObjectGuid::FromStringFailed; return ObjectGuidFactory::CreateMobileSession(realmId, arg1, counter); } - std::string FormatWebObj(char const* typeName, ObjectGuid guid) + static fmt::appender FormatWebObj(fmt::format_context& ctx, std::string const& typeName, ObjectGuid const& guid) { - return Trinity::StringFormat("{}-{}-{}-{}-{:012X}", typeName, guid.GetRealmId(), uint32(guid.GetRawValue(1) >> 37) & 0x1F, - uint32(guid.GetRawValue(1) >> 35) & 0x3, guid.GetRawValue(0)); + ctx.advance_to(AppendTypeName(ctx, typeName)); + ctx.advance_to(AppendComponent(ctx, guid.GetRealmId())); + ctx.advance_to(AppendComponent(ctx, guid.GetRawValue(1) >> 37 & 0x1F)); + ctx.advance_to(AppendComponent(ctx, guid.GetRawValue(1) >> 35 & 0x3)); + ctx.advance_to(AppendComponent, hex>(ctx, guid.GetRawValue(0))); + return ctx.out(); } - ObjectGuid ParseWebObj(HighGuid /*type*/, char const* guidString) + static ObjectGuid ParseWebObj(HighGuid /*type*/, std::string_view guidString) { uint32 realmId = 0; - uint32 arg1 = 0; - uint32 arg2 = 0; + uint8 arg1 = 0; + uint8 arg2 = 0; uint64 counter = UI64LIT(0); - if (std::sscanf(guidString, "%u-%u-%u-%012" SCNx64, &realmId, &arg1, &arg2, &counter) != 4) + if (!ParseComponent(guidString, &realmId) + || !ParseComponent(guidString, &arg1) + || !ParseComponent(guidString, &arg2) + || !ParseComponent(guidString, &counter) + || !ParseDone(guidString)) return ObjectGuid::FromStringFailed; return ObjectGuidFactory::CreateWebObj(realmId, arg1, arg2, counter); } - std::string FormatLFGObject(char const* typeName, ObjectGuid guid) + static fmt::appender FormatLFGObject(fmt::format_context& ctx, std::string const& typeName, ObjectGuid const& guid) { - return Trinity::StringFormat("{}-{}-{}-{}-{}-{}-{}-{:06X}", typeName, uint32(guid.GetRawValue(1) >> 54) & 0xF, uint32(guid.GetRawValue(1) >> 50) & 0xF, - uint32(guid.GetRawValue(1) >> 46) & 0xF, uint32(guid.GetRawValue(1) >> 38) & 0xFF, uint32(guid.GetRawValue(1) >> 37) & 0x1, - uint32(guid.GetRawValue(1) >> 35) & 0x3, guid.GetRawValue(0)); + ctx.advance_to(AppendTypeName(ctx, typeName)); + ctx.advance_to(AppendComponent(ctx, guid.GetRawValue(1) >> 54 & 0xF)); + ctx.advance_to(AppendComponent(ctx, guid.GetRawValue(1) >> 50 & 0xF)); + ctx.advance_to(AppendComponent(ctx, guid.GetRawValue(1) >> 46 & 0xF)); + ctx.advance_to(AppendComponent(ctx, guid.GetRawValue(1) >> 38 & 0xFF)); + ctx.advance_to(AppendComponent(ctx, guid.GetRawValue(1) >> 37 & 0x1)); + ctx.advance_to(AppendComponent(ctx, guid.GetRawValue(1) >> 35 & 0x3)); + ctx.advance_to(AppendComponent, hex>(ctx, guid.GetRawValue(0))); + return ctx.out(); } - ObjectGuid ParseLFGObject(HighGuid /*type*/, char const* guidString) + static ObjectGuid ParseLFGObject(HighGuid /*type*/, std::string_view guidString) { - uint32 arg1 = 0; - uint32 arg2 = 0; - uint32 arg3 = 0; - uint32 arg4 = 0; - uint32 arg5 = 0; - uint32 arg6 = 0; + uint8 arg1 = 0; + uint8 arg2 = 0; + uint8 arg3 = 0; + uint8 arg4 = 0; + uint8 arg5 = 0; + uint8 arg6 = 0; uint64 counter = UI64LIT(0); - if (std::sscanf(guidString, "%u-%u-%u-%u-%u-%u-%06" SCNx64, &arg1, &arg2, &arg3, &arg4, &arg5, &arg6, &counter) != 7) + if (!ParseComponent(guidString, &arg1) + || !ParseComponent(guidString, &arg2) + || !ParseComponent(guidString, &arg3) + || !ParseComponent(guidString, &arg4) + || !ParseComponent(guidString, &arg5) + || !ParseComponent(guidString, &arg6) + || !ParseComponent(guidString, &counter) + || !ParseDone(guidString)) return ObjectGuid::FromStringFailed; return ObjectGuidFactory::CreateLFGObject(arg1, arg2, arg3, arg4, arg5 != 0, arg6, counter); } - std::string FormatLFGList(char const* typeName, ObjectGuid guid) + static fmt::appender FormatLFGList(fmt::format_context& ctx, std::string const& typeName, ObjectGuid const& guid) { - return Trinity::StringFormat("{}-{}-{:06X}", typeName, uint32(guid.GetRawValue(1) >> 54) & 0xF, guid.GetRawValue(0)); + ctx.advance_to(AppendTypeName(ctx, typeName)); + ctx.advance_to(AppendComponent(ctx, guid.GetRawValue(1) >> 54 & 0xF)); + ctx.advance_to(AppendComponent, hex>(ctx, guid.GetRawValue(0))); + return ctx.out(); } - ObjectGuid ParseLFGList(HighGuid /*type*/, char const* guidString) + static ObjectGuid ParseLFGList(HighGuid /*type*/, std::string_view guidString) { - uint32 arg1 = 0; + uint8 arg1 = 0; uint64 counter = UI64LIT(0); - if (std::sscanf(guidString, "%u-%06" SCNx64, &arg1, &counter) != 2) + if (!ParseComponent(guidString, &arg1) + || !ParseComponent(guidString, &counter) + || !ParseDone(guidString)) return ObjectGuid::FromStringFailed; return ObjectGuidFactory::CreateLFGList(arg1, counter); } - std::string FormatClient(char const* typeName, ObjectGuid guid) + static fmt::appender FormatClient(fmt::format_context& ctx, std::string const& typeName, ObjectGuid const& guid) { - return Trinity::StringFormat("{}-{}-{}-{:012X}", typeName, guid.GetRealmId(), uint32(guid.GetRawValue(1) >> 10) & 0xFFFFFFFF, guid.GetRawValue(0)); + ctx.advance_to(AppendTypeName(ctx, typeName)); + ctx.advance_to(AppendComponent(ctx, guid.GetRealmId())); + ctx.advance_to(AppendComponent(ctx, guid.GetRawValue(1) >> 10 & 0xFFFFFFFF)); + ctx.advance_to(AppendComponent, hex>(ctx, guid.GetRawValue(0))); + return ctx.out(); } - ObjectGuid ParseClient(HighGuid type, char const* guidString) + static ObjectGuid ParseClient(HighGuid type, std::string_view guidString) { uint32 realmId = 0; uint32 arg1 = 0; uint64 counter = UI64LIT(0); - if (std::sscanf(guidString, "%u-%u-%012" SCNx64, &realmId, &arg1, &counter) != 3) + if (!ParseComponent(guidString, &realmId) + || !ParseComponent(guidString, &arg1) + || !ParseComponent(guidString, &counter) + || !ParseDone(guidString)) return ObjectGuid::FromStringFailed; return ObjectGuidFactory::CreateClient(type, realmId, arg1, counter); } - std::string FormatClubFinder(char const* typeName, ObjectGuid guid) + static fmt::appender FormatClubFinder(fmt::format_context& ctx, std::string const& typeName, ObjectGuid const& guid) { uint32 type = uint32(guid.GetRawValue(1) >> 33) & 0xFF; uint32 clubFinderId = uint32(guid.GetRawValue(1)) & 0xFFFFFFFF; - if (type == 1) // guild - return Trinity::StringFormat("{}-{}-{}-{}-{}", typeName, type, clubFinderId, guid.GetRealmId(), guid.GetRawValue(0) /*guildId*/); - return Trinity::StringFormat("{}-{}-{}-{:016X}", typeName, type, clubFinderId, guid.GetRawValue(0) /*clubId*/); + ctx.advance_to(AppendTypeName(ctx, typeName)); + ctx.advance_to(AppendComponent(ctx, type)); + ctx.advance_to(AppendComponent(ctx, clubFinderId)); + switch (type) + { + case 0: // club + ctx.advance_to(AppendComponent, hex>(ctx, guid.GetRawValue(0))); // clubId + break; + case 1: // guild + ctx.advance_to(AppendComponent(ctx, guid.GetRealmId())); + ctx.advance_to(AppendComponent(ctx, guid.GetRawValue(0))); // guildId + break; + default: + break; + } + + return ctx.out(); } - ObjectGuid ParseClubFinder(HighGuid /*type*/, char const* guidString) + static ObjectGuid ParseClubFinder(HighGuid /*type*/, std::string_view guidString) { - uint32 type = 0; - uint32 consumed = 0; - - if (std::sscanf(guidString, "%u-%n", &type, &consumed) != 1) - return ObjectGuid::FromStringFailed; - + uint8 type = 0; uint32 clubFinderId = 0; uint32 realmId = 0; uint64 dbId = UI64LIT(0); + if (!ParseComponent(guidString, &type) + || !ParseComponent(guidString, &clubFinderId)) + return ObjectGuid::FromStringFailed; + switch (type) { case 0: // club - if (std::sscanf(guidString + consumed, "%u-%016" SCNx64, &clubFinderId, &dbId) != 2) + if (!ParseComponent(guidString, &dbId)) return ObjectGuid::FromStringFailed; break; case 1: // guild - if (std::sscanf(guidString + consumed, "%u-%u-%016" SCNx64, &clubFinderId, &realmId, &dbId) != 3) + if (!ParseComponent(guidString, &realmId) + || !ParseComponent(guidString, &dbId)) return ObjectGuid::FromStringFailed; break; default: return ObjectGuid::FromStringFailed; } + if (!ParseDone(guidString)) + return ObjectGuid::FromStringFailed; + return ObjectGuidFactory::CreateClubFinder(realmId, type, clubFinderId, dbId); } - std::string FormatToolsClient(char const* typeName, ObjectGuid guid) + static fmt::appender FormatToolsClient(fmt::format_context& ctx, std::string const& typeName, ObjectGuid const& guid) { - return Trinity::StringFormat("{}-{}-{}-{:010X}", typeName, guid.GetMapId(), uint32(guid.GetRawValue(0) >> 40) & 0xFFFFFF, guid.GetCounter()); + ctx.advance_to(AppendTypeName(ctx, typeName)); + ctx.advance_to(AppendComponent(ctx, guid.GetMapId())); + ctx.advance_to(AppendComponent(ctx, guid.GetRawValue(0) >> 40 & 0xFFFFFF)); + ctx.advance_to(AppendComponent, hex>(ctx, guid.GetCounter())); + return ctx.out(); } - ObjectGuid ParseToolsClient(HighGuid /*type*/, char const* guidString) + static ObjectGuid ParseToolsClient(HighGuid /*type*/, std::string_view guidString) { - uint32 mapId = 0; + uint16 mapId = 0; uint32 serverId = 0; uint64 counter = UI64LIT(0); - if (std::sscanf(guidString, "%u-%u-%010" SCNx64, &mapId, &serverId, &counter) != 3) + + if (!ParseComponent(guidString, &mapId) + || !ParseComponent(guidString, &serverId) + || !ParseComponent(guidString, &counter) + || !ParseDone(guidString)) return ObjectGuid::FromStringFailed; return ObjectGuidFactory::CreateToolsClient(mapId, serverId, counter); } - std::string FormatWorldLayer(char const* typeName, ObjectGuid guid) + static fmt::appender FormatWorldLayer(fmt::format_context& ctx, std::string const& typeName, ObjectGuid const& guid) { - return Trinity::StringFormat("{}-{:X}-{}-{}-{}", typeName, uint32((guid.GetRawValue(1) >> 10) & 0xFFFFFFFF), uint32(guid.GetRawValue(1) & 0x1FF), - uint32((guid.GetRawValue(0) >> 24) & 0xFF), uint32(guid.GetRawValue(0) & 0x7FFFFF)); + ctx.advance_to(AppendTypeName(ctx, typeName)); + ctx.advance_to(AppendComponent, hex>(ctx, guid.GetRawValue(1) >> 10 & 0xFFFFFFFF)); + ctx.advance_to(AppendComponent(ctx, guid.GetRawValue(1) & 0x1FF)); + ctx.advance_to(AppendComponent(ctx, guid.GetRawValue(0) >> 24 & 0xFF)); + ctx.advance_to(AppendComponent(ctx, guid.GetRawValue(0) & 0x7FFFFF)); + return ctx.out(); } - ObjectGuid ParseWorldLayer(HighGuid /*type*/, char const* guidString) + static ObjectGuid ParseWorldLayer(HighGuid /*type*/, std::string_view guidString) { uint32 arg1 = 0; uint16 arg2 = 0; uint8 arg3 = 0; uint32 arg4 = 0; - if (std::sscanf(guidString, "%x-%hu-%hhu-%u", &arg1, &arg2, &arg3, &arg4) != 4) + + if (!ParseComponent(guidString, &arg1) + || !ParseComponent(guidString, &arg2) + || !ParseComponent(guidString, &arg3) + || !ParseComponent(guidString, &arg4) + || !ParseDone(guidString)) return ObjectGuid::FromStringFailed; return ObjectGuidFactory::CreateWorldLayer(arg1, arg2, arg3, arg4); } - std::string FormatLMMLobby(char const* typeName, ObjectGuid guid) + static fmt::appender FormatLMMLobby(fmt::format_context& ctx, std::string const& typeName, ObjectGuid const& guid) { - return Trinity::StringFormat("{}-{}-{}-{}-{}-{:X}", typeName, guid.GetRealmId(), uint32(guid.GetRawValue(1) >> 26) & 0xFFFFFF, - uint32(guid.GetRawValue(1) >> 18) & 0xFF, uint32(guid.GetRawValue(1) >> 10) & 0xFF, guid.GetRawValue(0)); + ctx.advance_to(AppendTypeName(ctx, typeName)); + ctx.advance_to(AppendComponent(ctx, guid.GetRealmId())); + ctx.advance_to(AppendComponent(ctx, uint32(guid.GetRawValue(1) >> 26) & 0xFFFFFF)); + ctx.advance_to(AppendComponent(ctx, uint32(guid.GetRawValue(1) >> 18) & 0xFF)); + ctx.advance_to(AppendComponent(ctx, uint32(guid.GetRawValue(1) >> 10) & 0xFF)); + ctx.advance_to(AppendComponent, hex>(ctx, guid.GetRawValue(0))); + return ctx.out(); } - ObjectGuid ParseLMMLobby(HighGuid /*type*/, char const* guidString) + static ObjectGuid ParseLMMLobby(HighGuid /*type*/, std::string_view guidString) { uint32 realmId = 0; uint32 arg2 = 0; uint8 arg3 = 0; uint8 arg4 = 0; uint64 arg5 = 0; - if (std::sscanf(guidString, "%u-%u-%hhu-%hhu-%" SCNx64, &realmId, &arg2, &arg3, &arg4, &arg5) != 5) + + if (!ParseComponent(guidString, &realmId) + || !ParseComponent(guidString, &arg2) + || !ParseComponent(guidString, &arg3) + || !ParseComponent(guidString, &arg4) + || !ParseComponent(guidString, &arg5) + || !ParseDone(guidString)) return ObjectGuid::FromStringFailed; return ObjectGuidFactory::CreateLMMLobby(realmId, arg2, arg3, arg4, arg5); @@ -543,17 +748,32 @@ namespace } } -char const* ObjectGuid::GetTypeName(HighGuid high) +template +inline auto fmt::formatter::format(ObjectGuid const& guid, FormatContext& ctx) const -> decltype(ctx.out()) +{ + if (guid.GetHigh() >= HighGuid::Count) + return format(ObjectGuid::ToStringFailed, ctx); + + int32 type = AsUnderlyingType(guid.GetHigh()); + if (!Info.ClientFormatFunction[type]) + return format(ObjectGuid::ToStringFailed, ctx); + + return Info.ClientFormatFunction[type](ctx, Info.Names[type].c_str(), guid); +} + +template TC_GAME_API fmt::appender fmt::formatter::format(ObjectGuid const&, format_context&) const; + +std::string_view ObjectGuid::GetTypeName(HighGuid high) { if (high >= HighGuid::Count) return ""; - return Info.Names[uint32(high)].c_str(); + return Info.Names[uint32(high)]; } std::string ObjectGuid::ToString() const { - return Info.Format(*this); + return ObjectGuidInfo::Format(*this); } std::string ObjectGuid::ToHexString() const @@ -561,7 +781,7 @@ std::string ObjectGuid::ToHexString() const return Trinity::StringFormat("0x{:016X}{:016X}", _data[1], _data[0]); } -ObjectGuid ObjectGuid::FromString(std::string const& guidString) +ObjectGuid ObjectGuid::FromString(std::string_view guidString) { return Info.Parse(guidString); } @@ -752,6 +972,7 @@ ObjectGuid ObjectGuidFactory::CreateLMMLobby(uint32 realmId, uint32 arg2, uint8 } ObjectGuid const ObjectGuid::Empty = ObjectGuid(); +ObjectGuid const ObjectGuid::ToStringFailed = ObjectGuid::Create(UI64LIT(3)); ObjectGuid const ObjectGuid::FromStringFailed = ObjectGuid::Create(UI64LIT(4)); ObjectGuid const ObjectGuid::TradeItem = ObjectGuid::Create(UI64LIT(10)); diff --git a/src/server/game/Entities/Object/ObjectGuid.h b/src/server/game/Entities/Object/ObjectGuid.h index e0d8d0f1c94..5be69654e21 100644 --- a/src/server/game/Entities/Object/ObjectGuid.h +++ b/src/server/game/Entities/Object/ObjectGuid.h @@ -272,6 +272,7 @@ class TC_GAME_API ObjectGuid public: static ObjectGuid const Empty; + static ObjectGuid const ToStringFailed; static ObjectGuid const FromStringFailed; static ObjectGuid const TradeItem; @@ -349,11 +350,11 @@ class TC_GAME_API ObjectGuid return std::strong_ordering::equal; } - static char const* GetTypeName(HighGuid high); - char const* GetTypeName() const { return !IsEmpty() ? GetTypeName(GetHigh()) : "None"; } + static std::string_view GetTypeName(HighGuid high); + std::string_view GetTypeName() const { return !IsEmpty() ? GetTypeName(GetHigh()) : "None"; } std::string ToString() const; std::string ToHexString() const; - static ObjectGuid FromString(std::string const& guidString); + static ObjectGuid FromString(std::string_view guidString); std::size_t GetHash() const; template static std::enable_if_t::Format::value == ObjectGuidFormatType::Null, ObjectGuid> Create() { return ObjectGuidFactory::CreateNull(); } @@ -378,10 +379,8 @@ class TC_GAME_API ObjectGuid template static std::enable_if_t::Format::value == ObjectGuidFormatType::LMMLobby, ObjectGuid> Create(uint32 arg2, uint8 arg3, uint8 arg4, ObjectGuid::LowType counter) { return ObjectGuidFactory::CreateLMMLobby(0, arg2, arg3, arg4, counter); } protected: - ObjectGuid(uint64 high, uint64 low) + ObjectGuid(uint64 high, uint64 low) : _data({{ low, high }}) { - _data[0] = low; - _data[1] = high; } std::array _data = { }; @@ -428,6 +427,35 @@ namespace std }; } +namespace fmt +{ +inline namespace v9 +{ +template +struct formatter; + +template <> +struct formatter +{ + template + constexpr auto parse(ParseContext& ctx) -> decltype(ctx.begin()) + { + auto begin = ctx.begin(), end = ctx.end(); + if (begin == end) + return begin; + + if (*begin != '}') + ctx.on_error("invalid type specifier"); + + return begin; + } + + template + auto format(ObjectGuid const& guid, FormatContext& ctx) const -> decltype(ctx.out()); +}; +} +} + namespace Trinity { namespace Legacy -- cgit v1.2.3