mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-02-06 00:48:39 +01:00
Core/Misc: Replaced boost::container::static_vector in packet classes with plain vector with custom static storage allocatlr
This commit is contained in:
@@ -32,6 +32,7 @@ if(SERVERS)
|
||||
add_subdirectory(rapidjson)
|
||||
add_subdirectory(efsw)
|
||||
add_subdirectory(protobuf)
|
||||
add_subdirectory(short_alloc)
|
||||
endif()
|
||||
|
||||
if(TOOLS)
|
||||
|
||||
@@ -72,3 +72,7 @@ rapidjson (A fast JSON parser/generator for C++ with both SAX/DOM style API http
|
||||
protobuf (Protocol Buffers - Google's data interchange format https://developers.google.com/protocol-buffers/)
|
||||
https://github.com/google/protobuf
|
||||
Version: v2.6.1
|
||||
|
||||
short_alloc (Stack based allocator) https://howardhinnant.github.io/stack_alloc.html
|
||||
https://howardhinnant.github.io/short_alloc.h
|
||||
Version: N/A
|
||||
|
||||
15
dep/short_alloc/CMakeLists.txt
Normal file
15
dep/short_alloc/CMakeLists.txt
Normal file
@@ -0,0 +1,15 @@
|
||||
# This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
#
|
||||
# This file is free software; as a special exception the author gives
|
||||
# unlimited permission to copy and/or distribute it, with or without
|
||||
# modifications, as long as this notice is preserved.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
|
||||
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
add_library(short_alloc INTERFACE)
|
||||
|
||||
target_include_directories(short_alloc
|
||||
INTERFACE
|
||||
${CMAKE_CURRENT_SOURCE_DIR})
|
||||
162
dep/short_alloc/short_alloc/short_alloc.h
Normal file
162
dep/short_alloc/short_alloc/short_alloc.h
Normal file
@@ -0,0 +1,162 @@
|
||||
#ifndef SHORT_ALLOC_H
|
||||
#define SHORT_ALLOC_H
|
||||
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2015 Howard Hinnant
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
namespace short_alloc
|
||||
{
|
||||
template <std::size_t N, std::size_t alignment = alignof(std::max_align_t)>
|
||||
class arena
|
||||
{
|
||||
alignas(alignment) char buf_[N];
|
||||
char* ptr_;
|
||||
|
||||
public:
|
||||
~arena() {ptr_ = nullptr;}
|
||||
arena() noexcept : ptr_(buf_) {}
|
||||
arena(const arena&) = delete;
|
||||
arena& operator=(const arena&) = delete;
|
||||
|
||||
template <std::size_t ReqAlign> char* allocate(std::size_t n);
|
||||
void deallocate(char* p, std::size_t n) noexcept;
|
||||
|
||||
static constexpr std::size_t size() noexcept {return N;}
|
||||
std::size_t used() const noexcept {return static_cast<std::size_t>(ptr_ - buf_);}
|
||||
void reset() noexcept {ptr_ = buf_;}
|
||||
|
||||
private:
|
||||
static
|
||||
std::size_t
|
||||
align_up(std::size_t n) noexcept
|
||||
{return (n + (alignment-1)) & ~(alignment-1);}
|
||||
|
||||
bool
|
||||
pointer_in_buffer(char* p) noexcept
|
||||
{
|
||||
return std::uintptr_t(buf_) <= std::uintptr_t(p) &&
|
||||
std::uintptr_t(p) <= std::uintptr_t(buf_) + N;
|
||||
}
|
||||
};
|
||||
|
||||
template <std::size_t N, std::size_t alignment>
|
||||
template <std::size_t ReqAlign>
|
||||
char*
|
||||
arena<N, alignment>::allocate(std::size_t n)
|
||||
{
|
||||
static_assert(ReqAlign <= alignment, "alignment is too small for this arena");
|
||||
assert(pointer_in_buffer(ptr_) && "short_alloc has outlived arena");
|
||||
auto const aligned_n = align_up(n);
|
||||
if (static_cast<decltype(aligned_n)>(buf_ + N - ptr_) >= aligned_n)
|
||||
{
|
||||
char* r = ptr_;
|
||||
ptr_ += aligned_n;
|
||||
return r;
|
||||
}
|
||||
|
||||
static_assert(alignment <= alignof(std::max_align_t), "you've chosen an "
|
||||
"alignment that is larger than alignof(std::max_align_t), and "
|
||||
"cannot be guaranteed by normal operator new");
|
||||
return static_cast<char*>(::operator new(n));
|
||||
}
|
||||
|
||||
template <std::size_t N, std::size_t alignment>
|
||||
void
|
||||
arena<N, alignment>::deallocate(char* p, std::size_t n) noexcept
|
||||
{
|
||||
assert(pointer_in_buffer(ptr_) && "short_alloc has outlived arena");
|
||||
if (pointer_in_buffer(p))
|
||||
{
|
||||
n = align_up(n);
|
||||
if (p + n == ptr_)
|
||||
ptr_ = p;
|
||||
}
|
||||
else
|
||||
::operator delete(p);
|
||||
}
|
||||
|
||||
template <class T, std::size_t N, std::size_t Align = alignof(std::max_align_t)>
|
||||
class short_alloc
|
||||
{
|
||||
public:
|
||||
using value_type = T;
|
||||
static auto constexpr alignment = Align;
|
||||
static auto constexpr size = N;
|
||||
using arena_type = arena<size, alignment>;
|
||||
|
||||
private:
|
||||
arena_type& a_;
|
||||
|
||||
public:
|
||||
short_alloc(const short_alloc&) = default;
|
||||
short_alloc& operator=(const short_alloc&) = delete;
|
||||
|
||||
short_alloc(arena_type& a) noexcept : a_(a)
|
||||
{
|
||||
static_assert(size % alignment == 0,
|
||||
"size N needs to be a multiple of alignment Align");
|
||||
}
|
||||
template <class U>
|
||||
short_alloc(const short_alloc<U, N, alignment>& a) noexcept
|
||||
: a_(a.a_) {}
|
||||
|
||||
template <class _Up> struct rebind {using other = short_alloc<_Up, N, alignment>;};
|
||||
|
||||
T* allocate(std::size_t n)
|
||||
{
|
||||
return reinterpret_cast<T*>(a_.template allocate<alignof(T)>(n*sizeof(T)));
|
||||
}
|
||||
void deallocate(T* p, std::size_t n) noexcept
|
||||
{
|
||||
a_.deallocate(reinterpret_cast<char*>(p), n*sizeof(T));
|
||||
}
|
||||
|
||||
template <class T1, std::size_t N1, std::size_t A1,
|
||||
class U, std::size_t M, std::size_t A2>
|
||||
friend
|
||||
bool
|
||||
operator==(const short_alloc<T1, N1, A1>& x, const short_alloc<U, M, A2>& y) noexcept;
|
||||
|
||||
template <class U, std::size_t M, std::size_t A> friend class short_alloc;
|
||||
};
|
||||
|
||||
template <class T, std::size_t N, std::size_t A1, class U, std::size_t M, std::size_t A2>
|
||||
inline
|
||||
bool
|
||||
operator==(const short_alloc<T, N, A1>& x, const short_alloc<U, M, A2>& y) noexcept
|
||||
{
|
||||
return N == M && A1 == A2 && &x.a_ == &y.a_;
|
||||
}
|
||||
|
||||
template <class T, std::size_t N, std::size_t A1, class U, std::size_t M, std::size_t A2>
|
||||
inline
|
||||
bool
|
||||
operator!=(const short_alloc<T, N, A1>& x, const short_alloc<U, M, A2>& y) noexcept
|
||||
{
|
||||
return !(x == y);
|
||||
}
|
||||
}
|
||||
#endif // SHORT_ALLOC_H
|
||||
@@ -73,7 +73,8 @@ target_link_libraries(common
|
||||
valgrind
|
||||
threads
|
||||
jemalloc
|
||||
openssl_ed25519)
|
||||
openssl_ed25519
|
||||
short_alloc)
|
||||
|
||||
add_dependencies(common revision_data.h)
|
||||
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
#include "PacketUtilities.h"
|
||||
#include "Hyperlinks.h"
|
||||
#include <utf8.h>
|
||||
#include <sstream>
|
||||
|
||||
WorldPackets::InvalidStringValueException::InvalidStringValueException(std::string const& value) : ByteBufferInvalidValueException("string", value.c_str())
|
||||
{
|
||||
@@ -59,7 +58,5 @@ bool WorldPackets::Strings::NoHyperlinks::Validate(std::string const& value)
|
||||
|
||||
WorldPackets::PacketArrayMaxCapacityException::PacketArrayMaxCapacityException(std::size_t requestedSize, std::size_t sizeLimit)
|
||||
{
|
||||
std::ostringstream builder;
|
||||
builder << "Attempted to read more array elements from packet " << requestedSize << " than allowed " << sizeLimit;
|
||||
message().assign(builder.str());
|
||||
message().assign("Attempted to read more array elements from packet " + Trinity::ToString(requestedSize) + " than allowed " + Trinity::ToString(sizeLimit));
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
#include "ByteBuffer.h"
|
||||
#include "Duration.h"
|
||||
#include "Tuples.h"
|
||||
#include <boost/container/static_vector.hpp>
|
||||
#include <short_alloc/short_alloc.h>
|
||||
#include <string_view>
|
||||
#include <ctime>
|
||||
|
||||
@@ -133,24 +133,49 @@ namespace WorldPackets
|
||||
/**
|
||||
* Utility class for automated prevention of loop counter spoofing in client packets
|
||||
*/
|
||||
template<typename T, std::size_t N, typename Container = boost::container::static_vector<T, N>>
|
||||
template<typename T, std::size_t N>
|
||||
class Array
|
||||
{
|
||||
public:
|
||||
typedef Container storage_type;
|
||||
using allocator_type = short_alloc::short_alloc<T, (N * sizeof(T) + (alignof(std::max_align_t) - 1)) & ~(alignof(std::max_align_t) - 1)>;
|
||||
using arena_type = typename allocator_type::arena_type;
|
||||
|
||||
typedef std::integral_constant<std::size_t, N> max_capacity;
|
||||
using storage_type = std::vector<T, allocator_type>;
|
||||
|
||||
typedef typename storage_type::value_type value_type;
|
||||
typedef typename storage_type::size_type size_type;
|
||||
typedef typename storage_type::pointer pointer;
|
||||
typedef typename storage_type::const_pointer const_pointer;
|
||||
typedef typename storage_type::reference reference;
|
||||
typedef typename storage_type::const_reference const_reference;
|
||||
typedef typename storage_type::iterator iterator;
|
||||
typedef typename storage_type::const_iterator const_iterator;
|
||||
using max_capacity = std::integral_constant<std::size_t, N>;
|
||||
|
||||
Array() { }
|
||||
using value_type = typename storage_type::value_type;
|
||||
using size_type = typename storage_type::size_type;
|
||||
using pointer = typename storage_type::pointer;
|
||||
using const_pointer = typename storage_type::const_pointer;
|
||||
using reference = typename storage_type::reference;
|
||||
using const_reference = typename storage_type::const_reference;
|
||||
using iterator = typename storage_type::iterator;
|
||||
using const_iterator = typename storage_type::const_iterator;
|
||||
|
||||
Array() : _storage(_data) { }
|
||||
|
||||
Array(Array const& other) : Array()
|
||||
{
|
||||
for (T const& element : other)
|
||||
_storage.push_back(element);
|
||||
}
|
||||
|
||||
Array(Array&& other) noexcept = delete;
|
||||
|
||||
Array& operator=(Array const& other)
|
||||
{
|
||||
if (this == &other)
|
||||
return *this;
|
||||
|
||||
_storage.clear();
|
||||
for (T const& element : other)
|
||||
_storage.push_back(element);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
Array& operator=(Array&& other) noexcept = delete;
|
||||
|
||||
iterator begin() { return _storage.begin(); }
|
||||
const_iterator begin() const { return _storage.begin(); }
|
||||
@@ -209,6 +234,7 @@ namespace WorldPackets
|
||||
}
|
||||
|
||||
private:
|
||||
arena_type _data;
|
||||
storage_type _storage;
|
||||
};
|
||||
|
||||
|
||||
@@ -71,7 +71,11 @@ ByteBuffer& operator>>(ByteBuffer& data, TraitConfig& traitConfig)
|
||||
{
|
||||
data >> traitConfig.ID;
|
||||
traitConfig.Type = data.read<TraitConfigType, int32>();
|
||||
traitConfig.Entries.resize(data.read<uint32>());
|
||||
uint32 entriesSize = data.read<uint32>();
|
||||
if (entriesSize > 100)
|
||||
throw PacketArrayMaxCapacityException(entriesSize, 100);
|
||||
|
||||
traitConfig.Entries.resize(entriesSize);
|
||||
switch (traitConfig.Type)
|
||||
{
|
||||
case TraitConfigType::Combat:
|
||||
|
||||
@@ -54,7 +54,7 @@ struct TraitConfig
|
||||
int32 LocalIdentifier = 0; // Local to specialization
|
||||
int32 SkillLineID = 0;
|
||||
int32 TraitSystemID = 0;
|
||||
Array<TraitEntry, 100, std::vector<TraitEntry>> Entries;
|
||||
std::vector<TraitEntry> Entries;
|
||||
String<259> Name;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user