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(rapidjson)
|
||||||
add_subdirectory(efsw)
|
add_subdirectory(efsw)
|
||||||
add_subdirectory(protobuf)
|
add_subdirectory(protobuf)
|
||||||
|
add_subdirectory(short_alloc)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(TOOLS)
|
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/)
|
protobuf (Protocol Buffers - Google's data interchange format https://developers.google.com/protocol-buffers/)
|
||||||
https://github.com/google/protobuf
|
https://github.com/google/protobuf
|
||||||
Version: v2.6.1
|
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
|
||||||
|
|||||||
@@ -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})
|
||||||
@@ -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
|
valgrind
|
||||||
threads
|
threads
|
||||||
jemalloc
|
jemalloc
|
||||||
openssl_ed25519)
|
openssl_ed25519
|
||||||
|
short_alloc)
|
||||||
|
|
||||||
add_dependencies(common revision_data.h)
|
add_dependencies(common revision_data.h)
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,6 @@
|
|||||||
#include "PacketUtilities.h"
|
#include "PacketUtilities.h"
|
||||||
#include "Hyperlinks.h"
|
#include "Hyperlinks.h"
|
||||||
#include <utf8.h>
|
#include <utf8.h>
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
WorldPackets::InvalidStringValueException::InvalidStringValueException(std::string const& value) : ByteBufferInvalidValueException("string", value.c_str())
|
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)
|
WorldPackets::PacketArrayMaxCapacityException::PacketArrayMaxCapacityException(std::size_t requestedSize, std::size_t sizeLimit)
|
||||||
{
|
{
|
||||||
std::ostringstream builder;
|
message().assign("Attempted to read more array elements from packet " + Trinity::ToString(requestedSize) + " than allowed " + Trinity::ToString(sizeLimit));
|
||||||
builder << "Attempted to read more array elements from packet " << requestedSize << " than allowed " << sizeLimit;
|
|
||||||
message().assign(builder.str());
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
#include "ByteBuffer.h"
|
#include "ByteBuffer.h"
|
||||||
#include "Duration.h"
|
#include "Duration.h"
|
||||||
#include "Tuples.h"
|
#include "Tuples.h"
|
||||||
#include <boost/container/static_vector.hpp>
|
#include <short_alloc/short_alloc.h>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
|
||||||
@@ -133,24 +133,49 @@ namespace WorldPackets
|
|||||||
/**
|
/**
|
||||||
* Utility class for automated prevention of loop counter spoofing in client packets
|
* 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
|
class Array
|
||||||
{
|
{
|
||||||
public:
|
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;
|
using max_capacity = std::integral_constant<std::size_t, N>;
|
||||||
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;
|
|
||||||
|
|
||||||
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(); }
|
iterator begin() { return _storage.begin(); }
|
||||||
const_iterator begin() const { return _storage.begin(); }
|
const_iterator begin() const { return _storage.begin(); }
|
||||||
@@ -209,6 +234,7 @@ namespace WorldPackets
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
arena_type _data;
|
||||||
storage_type _storage;
|
storage_type _storage;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -71,7 +71,11 @@ ByteBuffer& operator>>(ByteBuffer& data, TraitConfig& traitConfig)
|
|||||||
{
|
{
|
||||||
data >> traitConfig.ID;
|
data >> traitConfig.ID;
|
||||||
traitConfig.Type = data.read<TraitConfigType, int32>();
|
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)
|
switch (traitConfig.Type)
|
||||||
{
|
{
|
||||||
case TraitConfigType::Combat:
|
case TraitConfigType::Combat:
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ struct TraitConfig
|
|||||||
int32 LocalIdentifier = 0; // Local to specialization
|
int32 LocalIdentifier = 0; // Local to specialization
|
||||||
int32 SkillLineID = 0;
|
int32 SkillLineID = 0;
|
||||||
int32 TraitSystemID = 0;
|
int32 TraitSystemID = 0;
|
||||||
Array<TraitEntry, 100, std::vector<TraitEntry>> Entries;
|
std::vector<TraitEntry> Entries;
|
||||||
String<259> Name;
|
String<259> Name;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user