TrinityCore
ByteBuffer.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "ByteBuffer.h"
19#include "Errors.h"
20#include "MessageBuffer.h"
21#include "Log.h"
22#include "Util.h"
23#include <utf8.h>
24#include <sstream>
25#include <cmath>
26
27ByteBuffer::ByteBuffer(MessageBuffer&& buffer) : _rpos(0), _wpos(0), _bitpos(InitialBitPos), _curbitval(0), _storage(buffer.Move())
28{
29}
30
32{
33 std::ostringstream ss;
34
35 ss << "Attempted to get value with size: "
36 << valueSize << " in ByteBuffer (pos: " << pos << " size: " << size
37 << ")";
38
39 message().assign(ss.str());
40}
41
43{
44 message().assign(Trinity::StringFormat("Invalid {} value ({}) found in ByteBuffer", type, value));
45}
46
48{
49 value = read<float>();
50 if (!std::isfinite(value))
51 throw ByteBufferInvalidValueException("float", "infinity");
52 return *this;
53}
54
56{
57 value = read<double>();
58 if (!std::isfinite(value))
59 throw ByteBufferInvalidValueException("double", "infinity");
60 return *this;
61}
62
63std::string ByteBuffer::ReadCString(bool requireValidUtf8 /*= true*/)
64{
65 std::string value;
66 while (rpos() < size()) // prevent crash at wrong string format in packet
67 {
68 char c = read<char>();
69 if (c == 0)
70 break;
71 value += c;
72 }
73 if (requireValidUtf8 && !utf8::is_valid(value.begin(), value.end()))
74 throw ByteBufferInvalidValueException("string", value.c_str());
75 return value;
76}
77
78std::string ByteBuffer::ReadString(uint32 length, bool requireValidUtf8 /*= true*/)
79{
80 if (_rpos + length > size())
81 throw ByteBufferPositionException(_rpos, length, size());
82
84 if (!length)
85 return std::string();
86
87 std::string value(reinterpret_cast<char const*>(&_storage[_rpos]), length);
88 _rpos += length;
89 if (requireValidUtf8 && !utf8::is_valid(value.begin(), value.end()))
90 throw ByteBufferInvalidValueException("string", value.c_str());
91 return value;
92}
93
94void ByteBuffer::append(uint8 const* src, size_t cnt)
95{
96 ASSERT(src, "Attempted to put a NULL-pointer in ByteBuffer (pos: " SZFMTD " size: " SZFMTD ")", _wpos, size());
97 ASSERT(cnt, "Attempted to put a zero-sized value in ByteBuffer (pos: " SZFMTD " size: " SZFMTD ")", _wpos, size());
98 ASSERT(size() < 10000000);
99
100 FlushBits();
101
102 size_t const newSize = _wpos + cnt;
103 if (_storage.capacity() < newSize) // custom memory allocation rules
104 {
105 if (newSize < 100)
106 _storage.reserve(300);
107 else if (newSize < 750)
108 _storage.reserve(2500);
109 else if (newSize < 6000)
110 _storage.reserve(10000);
111 else
112 _storage.reserve(400000);
113 }
114
115 if (_storage.size() < newSize)
116 _storage.resize(newSize);
117 std::memcpy(&_storage[_wpos], src, cnt);
118 _wpos = newSize;
119}
120
121void ByteBuffer::put(size_t pos, uint8 const* src, size_t cnt)
122{
123 ASSERT(pos + cnt <= size(), "Attempted to put value with size: " SZFMTD " in ByteBuffer (pos: " SZFMTD " size: " SZFMTD ")", cnt, pos, size());
124 ASSERT(src, "Attempted to put a NULL-pointer in ByteBuffer (pos: " SZFMTD " size: " SZFMTD ")", pos, size());
125 ASSERT(cnt, "Attempted to put a zero-sized value in ByteBuffer (pos: " SZFMTD " size: " SZFMTD ")", pos, size());
126
127 std::memcpy(&_storage[pos], src, cnt);
128}
129
130void ByteBuffer::PutBits(std::size_t pos, std::size_t value, uint32 bitCount)
131{
132 ASSERT(pos + bitCount <= size() * 8, "Attempted to put %u bits in ByteBuffer (bitpos: " SZFMTD " size: " SZFMTD ")", bitCount, pos, size());
133 ASSERT(bitCount, "Attempted to put a zero bits in ByteBuffer");
134
135 for (uint32 i = 0; i < bitCount; ++i)
136 {
137 std::size_t wp = (pos + i) / 8;
138 std::size_t bit = (pos + i) % 8;
139 if ((value >> (bitCount - i - 1)) & 1)
140 _storage[wp] |= 1 << (7 - bit);
141 else
142 _storage[wp] &= ~(1 << (7 - bit));
143 }
144}
145
147{
148 if (!sLog->ShouldLog("network", LOG_LEVEL_TRACE)) // optimize disabled trace output
149 return;
150
151 std::ostringstream o;
152 o << "STORAGE_SIZE: " << size();
153 for (uint32 i = 0; i < size(); ++i)
154 o << read<uint8>(i) << " - ";
155 o << " ";
156
157 TC_LOG_TRACE("network", "{}", o.str());
158}
159
161{
162 if (!sLog->ShouldLog("network", LOG_LEVEL_TRACE)) // optimize disabled trace output
163 return;
164
165 std::ostringstream o;
166 o << "STORAGE_SIZE: " << size();
167 for (uint32 i = 0; i < size(); ++i)
168 {
169 char buf[2];
170 snprintf(buf, 2, "%c", read<uint8>(i));
171 o << buf;
172 }
173 o << " ";
174 TC_LOG_TRACE("network", "{}", o.str());
175}
176
178{
179 if (!sLog->ShouldLog("network", LOG_LEVEL_TRACE)) // optimize disabled trace output
180 return;
181
182 uint32 j = 1, k = 1;
183
184 std::ostringstream o;
185 o << "STORAGE_SIZE: " << size();
186
187 for (uint32 i = 0; i < size(); ++i)
188 {
189 char buf[4];
190 snprintf(buf, 4, "%2X", read<uint8>(i));
191 if ((i == (j * 8)) && ((i != (k * 16))))
192 {
193 o << "| ";
194 ++j;
195 }
196 else if (i == (k * 16))
197 {
198 o << "\n";
199 ++k;
200 ++j;
201 }
202
203 o << buf;
204 }
205 o << " ";
206 TC_LOG_TRACE("network", "{}", o.str());
207}
uint8_t uint8
Definition: Define.h:144
uint32_t uint32
Definition: Define.h:142
#define SZFMTD
Definition: Define.h:132
#define ASSERT
Definition: Errors.h:68
@ LOG_LEVEL_TRACE
Definition: LogCommon.h:27
#define TC_LOG_TRACE(filterType__,...)
Definition: Log.h:153
#define sLog
Definition: Log.h:130
std::string & message() noexcept
Definition: ByteBuffer.h:39
ByteBufferInvalidValueException(char const *type, char const *value)
Definition: ByteBuffer.cpp:42
ByteBufferPositionException(size_t pos, size_t size, size_t valueSize)
Definition: ByteBuffer.cpp:31
size_t _wpos
Definition: ByteBuffer.h:634
size_t rpos() const
Definition: ByteBuffer.h:399
std::vector< uint8 > _storage
Definition: ByteBuffer.h:636
void PutBits(std::size_t pos, std::size_t value, uint32 bitCount)
Definition: ByteBuffer.cpp:130
void hexlike() const
Definition: ByteBuffer.cpp:177
void print_storage() const
Definition: ByteBuffer.cpp:146
void append(T value)
Definition: ByteBuffer.h:143
void ResetBitPos()
Definition: ByteBuffer.h:166
std::string ReadCString(bool requireValidUtf8=true)
Definition: ByteBuffer.cpp:63
void textlike() const
Definition: ByteBuffer.cpp:160
void put(std::size_t pos, T value)
Definition: ByteBuffer.h:220
size_t size() const
Definition: ByteBuffer.h:536
void FlushBits()
Definition: ByteBuffer.h:155
size_t _rpos
Definition: ByteBuffer.h:634
ByteBuffer & operator>>(bool &value)
Definition: ByteBuffer.h:321
std::string ReadString(uint32 length, bool requireValidUtf8=true)
Definition: ByteBuffer.cpp:78
std::string StringFormat(FormatString< Args... > fmt, Args &&... args)
Default TC string format function.
Definition: StringFormat.h:38
constexpr std::size_t size()
Definition: UpdateField.h:796