Cuberite
A lightweight, fast and extensible game server for Minecraft
BlockState.cpp
Go to the documentation of this file.
1 #include "Globals.h"
2 #include "BlockState.h"
3 
4 
5 
6 
7 
9  mChecksum(initializeChecksum())
10 {
11  // Nothing needed yet
12 }
13 
14 
15 
16 
17 
18 BlockState::BlockState(const AString & aKey, const AString & aValue):
19  mState({{aKey, aValue}}),
20  mChecksum(initializeChecksum())
21 {
22 }
23 
24 
25 
26 
27 
28 BlockState::BlockState(std::initializer_list<std::pair<const AString, AString>> aKeysAndValues):
29  mState(aKeysAndValues),
30  mChecksum(initializeChecksum())
31 {
32 }
33 
34 
35 
36 
37 
38 BlockState::BlockState(const std::map<AString, AString> & aKeysAndValues):
39  mState(aKeysAndValues),
40  mChecksum(initializeChecksum())
41 {
42 }
43 
44 
45 
46 
47 
48 BlockState::BlockState(std::map<AString, AString> && aKeysAndValues):
49  mState(std::move(aKeysAndValues)),
50  mChecksum(initializeChecksum())
51 {
52 }
53 
54 
55 
56 
57 
58 BlockState::BlockState(const BlockState & aCopyFrom, std::initializer_list<std::pair<const AString, AString>> aAdditionalKeysAndValues):
59  mState(aCopyFrom.mState)
60 {
61  for (const auto & kav: aAdditionalKeysAndValues)
62  {
63  mState[kav.first] = kav.second;
64  }
66 }
67 
68 
69 
70 
71 
72 BlockState::BlockState(const BlockState & aCopyFrom, const std::map<AString, AString> & aAdditionalKeysAndValues):
73  mState(aCopyFrom.mState)
74 {
75  for (const auto & kav: aAdditionalKeysAndValues)
76  {
77  mState[kav.first] = kav.second;
78  }
80 }
81 
82 
83 
84 
85 
86 bool BlockState::operator <(const BlockState & aOther) const
87 {
88  // Fast-return this using checksum
89  if (mChecksum != aOther.mChecksum)
90  {
91  return (mChecksum < aOther.mChecksum);
92  }
93 
94  // Can fast-return this due to how comparison works
95  if (mState.size() != aOther.mState.size())
96  {
97  return (mState.size() < aOther.mState.size());
98  }
99 
100  auto itA = mState.begin();
101  auto itOther = aOther.mState.begin();
102 
103  // don't need to check itOther, size checks above ensure size(A) == size(O)
104  while (itA != mState.end())
105  {
106  {
107  const auto cmp = itA->first.compare(itOther->first);
108  if (cmp != 0)
109  {
110  return (cmp < 0);
111  }
112  }
113  {
114  const auto cmp = itA->second.compare(itOther->second);
115  if (cmp != 0)
116  {
117  return (cmp < 0);
118  }
119  }
120 
121  ++itA;
122  ++itOther;
123  }
124 
125  return false;
126 }
127 
128 
129 
130 
131 
132 bool BlockState::operator ==(const BlockState & aOther) const
133 {
134  // Fast-fail if the checksums differ or differrent counts:
135  if ((mChecksum != aOther.mChecksum) || (mState.size() != aOther.mState.size()))
136  {
137  return false;
138  }
139 
140  // Slow-check everything if the checksums match:
141  return std::equal(mState.begin(), mState.end(), aOther.mState.begin());
142 }
143 
144 
145 
146 
147 
148 const AString & BlockState::value(const AString & aKey) const
149 {
150  auto itr = mState.find(aKey);
151  if (itr == mState.end())
152  {
153  static AString empty;
154  return empty;
155  }
156  return itr->second;
157 }
158 
159 
160 
161 
162 
164 {
165  removeEmptyKeys();
166 
167  // Calculate the checksum as a XOR of all mState keys' and values' checksums
168  // This way we don't depend on the std::map's ordering
169  UInt32 res = 0;
170  for (const auto & kv: mState)
171  {
172  auto partial = partialChecksum(kv.first) ^ partialChecksum(kv.second);
173  res = res ^ partial;
174  }
175  return res;
176 }
177 
178 
179 
180 
181 
183 {
184  for (auto itr = mState.begin(); itr != mState.end();)
185  {
186  if (itr->second.empty())
187  {
188  itr = mState.erase(itr);
189  }
190  else
191  {
192  ++itr;
193  }
194  }
195 }
196 
197 
198 
199 
200 
202 {
203  UInt32 shift = 0;
204  UInt32 res = 0;
205  for (auto ch: aString)
206  {
207  UInt32 v = static_cast<UInt8>(ch);
208  v = v << shift;
209  shift = (shift + 1) % 24;
210  res = res ^ v;
211  }
212  return res;
213 }
unsigned int UInt32
Definition: Globals.h:157
unsigned char UInt8
Definition: Globals.h:159
std::string AString
Definition: StringUtils.h:11
Definition: FastNBT.h:132
Represents the state of a single block (previously known as "block meta").
Definition: BlockState.h:20
UInt32 partialChecksum(const AString &aString)
Calculates the partial checksum of a single string.
Definition: BlockState.cpp:201
BlockState()
Creates a new instance with an empty map.
Definition: BlockState.cpp:8
bool operator<(const BlockState &aOther) const
Less-than comparison.
Definition: BlockState.cpp:86
UInt32 initializeChecksum()
Normalizes mState and calculates the checksum from it.
Definition: BlockState.cpp:163
const AString & value(const AString &aKey) const
Returns the value at the specified key.
Definition: BlockState.cpp:148
UInt32 mChecksum
The checksum used for the fast equality check.
Definition: BlockState.h:79
bool operator==(const BlockState &aOther) const
Fast equality check.
Definition: BlockState.cpp:132
void removeEmptyKeys()
Removes all the keys from mState that have an empty value.
Definition: BlockState.cpp:182
std::map< AString, AString > mState
The state, represented as a string->string map.
Definition: BlockState.h:75