refactor(Core/Misc): add braces and impove codestyle (#6402)

This commit is contained in:
Kargatum
2021-06-25 00:50:18 +07:00
committed by GitHub
parent 33c271cc7c
commit 3c24b511f2
72 changed files with 1486 additions and 401 deletions

View File

@@ -31,11 +31,17 @@ namespace Acore::Net
inline boost::asio::ip::address_v4 GetDefaultNetmaskV4(boost::asio::ip::address_v4 const& networkAddress) inline boost::asio::ip::address_v4 GetDefaultNetmaskV4(boost::asio::ip::address_v4 const& networkAddress)
{ {
if ((address_to_uint(networkAddress) & 0x80000000) == 0) if ((address_to_uint(networkAddress) & 0x80000000) == 0)
{
return boost::asio::ip::address_v4(0xFF000000); return boost::asio::ip::address_v4(0xFF000000);
}
if ((address_to_uint(networkAddress) & 0xC0000000) == 0x80000000) if ((address_to_uint(networkAddress) & 0xC0000000) == 0x80000000)
{
return boost::asio::ip::address_v4(0xFFFF0000); return boost::asio::ip::address_v4(0xFFFF0000);
}
if ((address_to_uint(networkAddress) & 0xE0000000) == 0xC0000000) if ((address_to_uint(networkAddress) & 0xE0000000) == 0xC0000000)
{
return boost::asio::ip::address_v4(0xFFFFFF00); return boost::asio::ip::address_v4(0xFFFFFF00);
}
return boost::asio::ip::address_v4(0xFFFFFFFF); return boost::asio::ip::address_v4(0xFFFFFFFF);
} }

View File

@@ -47,7 +47,9 @@ void BIH::subdivide(int left, int right, std::vector<uint32>& tempTree, buildDat
// perform quick consistency checks // perform quick consistency checks
G3D::Vector3 d( gridBox.hi - gridBox.lo ); G3D::Vector3 d( gridBox.hi - gridBox.lo );
if (d.x < 0 || d.y < 0 || d.z < 0) if (d.x < 0 || d.y < 0 || d.z < 0)
{
throw std::logic_error("negative node extents"); throw std::logic_error("negative node extents");
}
for (int i = 0; i < 3; i++) for (int i = 0; i < 3; i++)
{ {
if (nodeBox.hi[i] < gridBox.lo[i] || nodeBox.lo[i] > gridBox.hi[i]) if (nodeBox.hi[i] < gridBox.lo[i] || nodeBox.lo[i] > gridBox.hi[i])
@@ -76,7 +78,9 @@ void BIH::subdivide(int left, int right, std::vector<uint32>& tempTree, buildDat
// stay left // stay left
i++; i++;
if (clipL < maxb) if (clipL < maxb)
{
clipL = maxb; clipL = maxb;
}
} }
else else
{ {
@@ -86,7 +90,9 @@ void BIH::subdivide(int left, int right, std::vector<uint32>& tempTree, buildDat
dat.indices[right] = t; dat.indices[right] = t;
right--; right--;
if (clipR > minb) if (clipR > minb)
{
clipR = minb; clipR = minb;
}
} }
nodeL = std::min(nodeL, minb); nodeL = std::min(nodeL, minb);
nodeR = std::max(nodeR, maxb); nodeR = std::max(nodeR, maxb);
@@ -212,7 +218,9 @@ void BIH::subdivide(int left, int right, std::vector<uint32>& tempTree, buildDat
tempTree.push_back(0); tempTree.push_back(0);
} }
else else
{
nextIndex -= 3; nextIndex -= 3;
}
// allocate right node // allocate right node
if (nr > 0) if (nr > 0)
{ {
@@ -233,13 +241,21 @@ void BIH::subdivide(int left, int right, std::vector<uint32>& tempTree, buildDat
nodeBoxR.lo[axis] = clipR; nodeBoxR.lo[axis] = clipR;
// recurse // recurse
if (nl > 0) if (nl > 0)
{
subdivide(left, right, tempTree, dat, gridBoxL, nodeBoxL, nextIndex, depth + 1, stats); subdivide(left, right, tempTree, dat, gridBoxL, nodeBoxL, nextIndex, depth + 1, stats);
}
else else
{
stats.updateLeaf(depth + 1, 0); stats.updateLeaf(depth + 1, 0);
}
if (nr > 0) if (nr > 0)
{
subdivide(right + 1, rightOrig, tempTree, dat, gridBoxR, nodeBoxR, nextIndex + 3, depth + 1, stats); subdivide(right + 1, rightOrig, tempTree, dat, gridBoxR, nodeBoxR, nextIndex + 3, depth + 1, stats);
}
else else
{
stats.updateLeaf(depth + 1, 0); stats.updateLeaf(depth + 1, 0);
}
} }
bool BIH::writeToFile(FILE* wf) const bool BIH::writeToFile(FILE* wf) const

View File

@@ -90,11 +90,15 @@ public:
BuildStats stats; BuildStats stats;
buildHierarchy(tempTree, dat, stats); buildHierarchy(tempTree, dat, stats);
if (printStats) if (printStats)
{
stats.printStats(); stats.printStats();
}
objects.resize(dat.numPrims); objects.resize(dat.numPrims);
for (uint32 i = 0; i < dat.numPrims; ++i) for (uint32 i = 0; i < dat.numPrims; ++i)
{
objects[i] = dat.indices[i]; objects[i] = dat.indices[i];
}
//nObjects = dat.numPrims; //nObjects = dat.numPrims;
tree = tempTree; tree = tempTree;
delete[] dat.primBound; delete[] dat.primBound;
@@ -118,20 +122,30 @@ public:
float t1 = (bounds.low()[i] - org[i]) * invDir[i]; float t1 = (bounds.low()[i] - org[i]) * invDir[i];
float t2 = (bounds.high()[i] - org[i]) * invDir[i]; float t2 = (bounds.high()[i] - org[i]) * invDir[i];
if (t1 > t2) if (t1 > t2)
{
std::swap(t1, t2); std::swap(t1, t2);
}
if (t1 > intervalMin) if (t1 > intervalMin)
{
intervalMin = t1; intervalMin = t1;
}
if (t2 < intervalMax || intervalMax < 0.f) if (t2 < intervalMax || intervalMax < 0.f)
{
intervalMax = t2; intervalMax = t2;
}
// intervalMax can only become smaller for other axis, // intervalMax can only become smaller for other axis,
// and intervalMin only larger respectively, so stop early // and intervalMin only larger respectively, so stop early
if (intervalMax <= 0 || intervalMin >= maxDist) if (intervalMax <= 0 || intervalMin >= maxDist)
{
return; return;
}
} }
} }
if (intervalMin > intervalMax) if (intervalMin > intervalMax)
{
return; return;
}
intervalMin = std::max(intervalMin, 0.f); intervalMin = std::max(intervalMin, 0.f);
intervalMax = std::min(intervalMax, maxDist); intervalMax = std::min(intervalMax, maxDist);
@@ -174,7 +188,9 @@ public:
float tb = (intBitsToFloat(tree[node + offsetBack[axis]]) - org[axis]) * invDir[axis]; float tb = (intBitsToFloat(tree[node + offsetBack[axis]]) - org[axis]) * invDir[axis];
// ray passes between clip zones // ray passes between clip zones
if (tf < intervalMin && tb > intervalMax) if (tf < intervalMin && tb > intervalMax)
{
break; break;
}
int back = offset + offsetBack3[axis]; int back = offset + offsetBack3[axis];
node = back; node = back;
// ray passes through far node only // ray passes through far node only
@@ -207,7 +223,7 @@ public:
while (n > 0) while (n > 0)
{ {
bool hit = intersectCallback(r, objects[offset], maxDist, stopAtFirstHit); bool hit = intersectCallback(r, objects[offset], maxDist, stopAtFirstHit);
if (stopAtFirstHit && hit) return; if (stopAtFirstHit && hit) { return; }
--n; --n;
++offset; ++offset;
} }
@@ -217,14 +233,18 @@ public:
else else
{ {
if (axis > 2) if (axis > 2)
return; // should not happen {
return; // should not happen
}
float tf = (intBitsToFloat(tree[node + offsetFront[axis]]) - org[axis]) * invDir[axis]; float tf = (intBitsToFloat(tree[node + offsetFront[axis]]) - org[axis]) * invDir[axis];
float tb = (intBitsToFloat(tree[node + offsetBack[axis]]) - org[axis]) * invDir[axis]; float tb = (intBitsToFloat(tree[node + offsetBack[axis]]) - org[axis]) * invDir[axis];
node = offset; node = offset;
intervalMin = (tf >= intervalMin) ? tf : intervalMin; intervalMin = (tf >= intervalMin) ? tf : intervalMin;
intervalMax = (tb <= intervalMax) ? tb : intervalMax; intervalMax = (tb <= intervalMax) ? tb : intervalMax;
if (intervalMin > intervalMax) if (intervalMin > intervalMax)
{
break; break;
}
continue; continue;
} }
} // traversal loop } // traversal loop
@@ -232,12 +252,16 @@ public:
{ {
// stack is empty? // stack is empty?
if (stackPos == 0) if (stackPos == 0)
{
return; return;
}
// move back up the stack // move back up the stack
stackPos--; stackPos--;
intervalMin = stack[stackPos].tnear; intervalMin = stack[stackPos].tnear;
if (maxDist < intervalMin) if (maxDist < intervalMin)
{
continue; continue;
}
node = stack[stackPos].node; node = stack[stackPos].node;
intervalMax = stack[stackPos].tfar; intervalMax = stack[stackPos].tfar;
break; break;
@@ -249,7 +273,9 @@ public:
void intersectPoint(const G3D::Vector3& p, IsectCallback& intersectCallback) const void intersectPoint(const G3D::Vector3& p, IsectCallback& intersectCallback) const
{ {
if (!bounds.contains(p)) if (!bounds.contains(p))
{
return; return;
}
StackNode stack[MAX_STACK_SIZE]; StackNode stack[MAX_STACK_SIZE];
int stackPos = 0; int stackPos = 0;
@@ -272,7 +298,9 @@ public:
float tr = intBitsToFloat(tree[node + 2]); float tr = intBitsToFloat(tree[node + 2]);
// point is between clip zones // point is between clip zones
if (tl < p[axis] && tr > p[axis]) if (tl < p[axis] && tr > p[axis])
{
break; break;
}
int right = offset + 3; int right = offset + 3;
node = right; node = right;
// point is in right node only // point is in right node only
@@ -308,19 +336,25 @@ public:
else // BVH2 node (empty space cut off left and right) else // BVH2 node (empty space cut off left and right)
{ {
if (axis > 2) if (axis > 2)
return; // should not happen {
return; // should not happen
}
float tl = intBitsToFloat(tree[node + 1]); float tl = intBitsToFloat(tree[node + 1]);
float tr = intBitsToFloat(tree[node + 2]); float tr = intBitsToFloat(tree[node + 2]);
node = offset; node = offset;
if (tl > p[axis] || tr < p[axis]) if (tl > p[axis] || tr < p[axis])
{
break; break;
}
continue; continue;
} }
} // traversal loop } // traversal loop
// stack is empty? // stack is empty?
if (stackPos == 0) if (stackPos == 0)
{
return; return;
}
// move back up the stack // move back up the stack
stackPos--; stackPos--;
node = stack[stackPos].node; node = stack[stackPos].node;
@@ -366,7 +400,7 @@ protected:
public: public:
BuildStats() BuildStats()
{ {
for (int & i : numLeavesN) i = 0; for (int& i : numLeavesN) { i = 0; }
} }
void updateInner() { numNodes++; } void updateInner() { numNodes++; }

View File

@@ -28,9 +28,13 @@ class BIHWrap
bool operator() (const G3D::Ray& ray, uint32 idx, float& maxDist, bool stopAtFirstHit) bool operator() (const G3D::Ray& ray, uint32 idx, float& maxDist, bool stopAtFirstHit)
{ {
if (idx >= objects_size) if (idx >= objects_size)
{
return false; return false;
}
if (const T* obj = objects[idx]) if (const T* obj = objects[idx])
{
return _callback(ray, *obj, maxDist, stopAtFirstHit); return _callback(ray, *obj, maxDist, stopAtFirstHit);
}
return false; return false;
} }
@@ -38,9 +42,13 @@ class BIHWrap
void operator() (const G3D::Vector3& p, uint32 idx) void operator() (const G3D::Vector3& p, uint32 idx)
{ {
if (idx >= objects_size) if (idx >= objects_size)
{
return; return;
}
if (const T* obj = objects[idx]) if (const T* obj = objects[idx])
{
_callback(p, *obj); _callback(p, *obj);
}
} }
}; };
@@ -67,15 +75,21 @@ public:
uint32 Idx = 0; uint32 Idx = 0;
const T* temp; const T* temp;
if (m_obj2Idx.getRemove(&obj, temp, Idx)) if (m_obj2Idx.getRemove(&obj, temp, Idx))
{
m_objects[Idx] = nullptr; m_objects[Idx] = nullptr;
}
else else
{
m_objects_to_push.remove(&obj); m_objects_to_push.remove(&obj);
}
} }
void balance() void balance()
{ {
if (unbalanced_times == 0) if (unbalanced_times == 0)
{
return; return;
}
unbalanced_times = 0; unbalanced_times = 0;
m_objects.fastClear(); m_objects.fastClear();

View File

@@ -72,14 +72,18 @@ struct DynTreeImpl : public ParentTree
void update(uint32 difftime) void update(uint32 difftime)
{ {
if (!size()) if (!size())
{
return; return;
}
rebalance_timer.Update(difftime); rebalance_timer.Update(difftime);
if (rebalance_timer.Passed()) if (rebalance_timer.Passed())
{ {
rebalance_timer.Reset(CHECK_TREE_PERIOD); rebalance_timer.Reset(CHECK_TREE_PERIOD);
if (unbalanced_times > 0) if (unbalanced_times > 0)
{
balance(); balance();
}
} }
} }
@@ -133,7 +137,9 @@ struct DynamicTreeIntersectionCallback
{ {
bool result = obj.intersectRay(r, distance, stopAtFirstHit, phase_mask); bool result = obj.intersectRay(r, distance, stopAtFirstHit, phase_mask);
if (result) if (result)
{
did_hit = result; did_hit = result;
}
return result; return result;
} }
bool didHit() const { return did_hit;} bool didHit() const { return did_hit;}
@@ -146,7 +152,9 @@ bool DynamicMapTree::getIntersectionTime(const uint32 phasemask, const G3D::Ray&
DynamicTreeIntersectionCallback callback(phasemask); DynamicTreeIntersectionCallback callback(phasemask);
impl->intersectRay(ray, callback, distance, endPos, false); impl->intersectRay(ray, callback, distance, endPos, false);
if (callback.didHit()) if (callback.didHit())
{
maxDist = distance; maxDist = distance;
}
return callback.didHit(); return callback.didHit();
} }
@@ -173,12 +181,18 @@ bool DynamicMapTree::getObjectHitPos(const uint32 phasemask, const G3D::Vector3&
if (modifyDist < 0) if (modifyDist < 0)
{ {
if ((resultHit - startPos).magnitude() > -modifyDist) if ((resultHit - startPos).magnitude() > -modifyDist)
{
resultHit = resultHit + dir * modifyDist; resultHit = resultHit + dir * modifyDist;
}
else else
{
resultHit = startPos; resultHit = startPos;
}
} }
else else
{
resultHit = resultHit + dir * modifyDist; resultHit = resultHit + dir * modifyDist;
}
result = true; result = true;
} }
@@ -197,7 +211,9 @@ bool DynamicMapTree::isInLineOfSight(float x1, float y1, float z1, float x2, flo
float maxDist = (v2 - v1).magnitude(); float maxDist = (v2 - v1).magnitude();
if (!G3D::fuzzyGt(maxDist, 0) ) if (!G3D::fuzzyGt(maxDist, 0) )
{
return true; return true;
}
G3D::Ray r(v1, (v2 - v1) / maxDist); G3D::Ray r(v1, (v2 - v1) / maxDist);
DynamicTreeIntersectionCallback callback(phasemask); DynamicTreeIntersectionCallback callback(phasemask);
@@ -214,7 +230,11 @@ float DynamicMapTree::getHeight(float x, float y, float z, float maxSearchDist,
impl->intersectZAllignedRay(r, callback, maxSearchDist); impl->intersectZAllignedRay(r, callback, maxSearchDist);
if (callback.didHit()) if (callback.didHit())
{
return v.z - maxSearchDist; return v.z - maxSearchDist;
}
else else
{
return -G3D::finf(); return -G3D::finf();
}
} }

View File

@@ -27,7 +27,7 @@ public:
~DynamicMapTree(); ~DynamicMapTree();
[[nodiscard]] bool isInLineOfSight(float x1, float y1, float z1, float x2, float y2, [[nodiscard]] bool isInLineOfSight(float x1, float y1, float z1, float x2, float y2,
float z2, uint32 phasemask) const; float z2, uint32 phasemask) const;
bool getIntersectionTime(uint32 phasemask, const G3D::Ray& ray, bool getIntersectionTime(uint32 phasemask, const G3D::Ray& ray,
const G3D::Vector3& endPos, float& maxDist) const; const G3D::Vector3& endPos, float& maxDist) const;

View File

@@ -18,7 +18,9 @@ namespace MMAP
MMapManager* MMapFactory::createOrGetMMapManager() MMapManager* MMapFactory::createOrGetMMapManager()
{ {
if (g_MMapManager == nullptr) if (g_MMapManager == nullptr)
{
g_MMapManager = new MMapManager(); g_MMapManager = new MMapManager();
}
return g_MMapManager; return g_MMapManager;
} }
@@ -29,7 +31,9 @@ namespace MMAP
int32 f[] = {616 /*EoE*/, 649 /*ToC25*/, 650 /*ToC5*/, -1}; int32 f[] = {616 /*EoE*/, 649 /*ToC25*/, 650 /*ToC5*/, -1};
uint32 i = 0; uint32 i = 0;
while (f[i] >= 0) while (f[i] >= 0)
{
forbiddenMaps[f[i++]] = true; forbiddenMaps[f[i++]] = true;
}
} }
void MMapFactory::clear() void MMapFactory::clear()

View File

@@ -20,7 +20,9 @@ namespace MMAP
MMapManager::~MMapManager() MMapManager::~MMapManager()
{ {
for (MMapDataSet::iterator i = loadedMMaps.begin(); i != loadedMMaps.end(); ++i) for (MMapDataSet::iterator i = loadedMMaps.begin(); i != loadedMMaps.end(); ++i)
{
delete i->second; delete i->second;
}
// by now we should not have maps loaded // by now we should not have maps loaded
// if we had, tiles in MMapData->mmapLoadedTiles, their actual data is lost! // if we had, tiles in MMapData->mmapLoadedTiles, their actual data is lost!
@@ -30,7 +32,9 @@ namespace MMAP
{ {
// the caller must pass the list of all mapIds that will be used in the VMapManager2 lifetime // the caller must pass the list of all mapIds that will be used in the VMapManager2 lifetime
for (const uint32& mapId : mapIds) for (const uint32& mapId : mapIds)
{
loadedMMaps.emplace(mapId, nullptr); loadedMMaps.emplace(mapId, nullptr);
}
thread_safe_environment = false; thread_safe_environment = false;
} }
@@ -40,7 +44,9 @@ namespace MMAP
// return the iterator if found or end() if not found/NULL // return the iterator if found or end() if not found/NULL
MMapDataSet::const_iterator itr = loadedMMaps.find(mapId); MMapDataSet::const_iterator itr = loadedMMaps.find(mapId);
if (itr != loadedMMaps.cend() && !itr->second) if (itr != loadedMMaps.cend() && !itr->second)
{
itr = loadedMMaps.cend(); itr = loadedMMaps.cend();
}
return itr; return itr;
} }
@@ -52,14 +58,20 @@ namespace MMAP
if (itr != loadedMMaps.end()) if (itr != loadedMMaps.end())
{ {
if (itr->second) if (itr->second)
{
return true; return true;
}
} }
else else
{ {
if (thread_safe_environment) if (thread_safe_environment)
{
itr = loadedMMaps.insert(MMapDataSet::value_type(mapId, nullptr)).first; itr = loadedMMaps.insert(MMapDataSet::value_type(mapId, nullptr)).first;
}
else else
{
ASSERT(false, "Invalid mapId %u passed to MMapManager after startup in thread unsafe environment", mapId); ASSERT(false, "Invalid mapId %u passed to MMapManager after startup in thread unsafe environment", mapId);
}
} }
// load and init dtNavMesh - read parameters from file // load and init dtNavMesh - read parameters from file
@@ -107,7 +119,9 @@ namespace MMAP
{ {
// make sure the mmap is loaded and ready to load tiles // make sure the mmap is loaded and ready to load tiles
if (!loadMapData(mapId)) if (!loadMapData(mapId))
{
return false; return false;
}
// get this mmap data // get this mmap data
MMapData* mmap = loadedMMaps[mapId]; MMapData* mmap = loadedMMaps[mapId];
@@ -243,7 +257,9 @@ namespace MMAP
uint32 y = (i.first & 0x0000FFFF); uint32 y = (i.first & 0x0000FFFF);
if (dtStatusFailed(mmap->navMesh->removeTile(i.second, nullptr, nullptr))) if (dtStatusFailed(mmap->navMesh->removeTile(i.second, nullptr, nullptr)))
{
LOG_ERROR("maps", "MMAP:unloadMap: Could not unload %03u%02i%02i.mmtile from navmesh", mapId, x, y); LOG_ERROR("maps", "MMAP:unloadMap: Could not unload %03u%02i%02i.mmtile from navmesh", mapId, x, y);
}
else else
{ {
--loadedTiles; --loadedTiles;
@@ -289,7 +305,9 @@ namespace MMAP
{ {
MMapDataSet::const_iterator itr = GetMMapData(mapId); MMapDataSet::const_iterator itr = GetMMapData(mapId);
if (itr == loadedMMaps.end()) if (itr == loadedMMaps.end())
{
return nullptr; return nullptr;
}
return itr->second->navMesh; return itr->second->navMesh;
} }
@@ -298,7 +316,9 @@ namespace MMAP
{ {
MMapDataSet::const_iterator itr = GetMMapData(mapId); MMapDataSet::const_iterator itr = GetMMapData(mapId);
if (itr == loadedMMaps.end()) if (itr == loadedMMaps.end())
{
return nullptr; return nullptr;
}
MMapData* mmap = itr->second; MMapData* mmap = itr->second;
if (mmap->navMeshQueries.find(instanceId) == mmap->navMeshQueries.end()) if (mmap->navMeshQueries.find(instanceId) == mmap->navMeshQueries.end())

View File

@@ -40,10 +40,14 @@ namespace MMAP
~MMapData() ~MMapData()
{ {
for (NavMeshQuerySet::iterator i = navMeshQueries.begin(); i != navMeshQueries.end(); ++i) for (NavMeshQuerySet::iterator i = navMeshQueries.begin(); i != navMeshQueries.end(); ++i)
{
dtFreeNavMeshQuery(i->second); dtFreeNavMeshQuery(i->second);
}
if (navMesh) if (navMesh)
{
dtFreeNavMesh(navMesh); dtFreeNavMesh(navMesh);
}
} }
// we have to use single dtNavMeshQuery for every instance, since those are not thread safe // we have to use single dtNavMeshQuery for every instance, since those are not thread safe

View File

@@ -16,7 +16,9 @@ namespace VMAP
VMapManager2* VMapFactory::createOrGetVMapManager() VMapManager2* VMapFactory::createOrGetVMapManager()
{ {
if (!gVMapManager) if (!gVMapManager)
{
gVMapManager = new VMapManager2(); gVMapManager = new VMapManager2();
}
return gVMapManager; return gVMapManager;
} }

View File

@@ -57,7 +57,9 @@ namespace VMAP
{ {
// the caller must pass the list of all mapIds that will be used in the VMapManager2 lifetime // the caller must pass the list of all mapIds that will be used in the VMapManager2 lifetime
for (const uint32& mapId : mapIds) for (const uint32& mapId : mapIds)
{
iInstanceMapTrees.emplace(mapId, nullptr); iInstanceMapTrees.emplace(mapId, nullptr);
}
thread_safe_environment = false; thread_safe_environment = false;
} }
@@ -78,7 +80,9 @@ namespace VMAP
// return the iterator if found or end() if not found/NULL // return the iterator if found or end() if not found/NULL
InstanceTreeMap::const_iterator itr = iInstanceMapTrees.find(mapId); InstanceTreeMap::const_iterator itr = iInstanceMapTrees.find(mapId);
if (itr != iInstanceMapTrees.cend() && !itr->second) if (itr != iInstanceMapTrees.cend() && !itr->second)
{
itr = iInstanceMapTrees.cend(); itr = iInstanceMapTrees.cend();
}
return itr; return itr;
} }
@@ -99,9 +103,13 @@ namespace VMAP
if (isMapLoadingEnabled()) if (isMapLoadingEnabled())
{ {
if (_loadMap(mapId, basePath, x, y)) if (_loadMap(mapId, basePath, x, y))
{
result = VMAP_LOAD_RESULT_OK; result = VMAP_LOAD_RESULT_OK;
}
else else
{
result = VMAP_LOAD_RESULT_ERROR; result = VMAP_LOAD_RESULT_ERROR;
}
} }
return result; return result;
@@ -114,10 +122,12 @@ namespace VMAP
if (instanceTree == iInstanceMapTrees.end()) if (instanceTree == iInstanceMapTrees.end())
{ {
if (thread_safe_environment) if (thread_safe_environment)
{
instanceTree = iInstanceMapTrees.insert(InstanceTreeMap::value_type(mapId, nullptr)).first; instanceTree = iInstanceMapTrees.insert(InstanceTreeMap::value_type(mapId, nullptr)).first;
}
else else
ASSERT(false, "Invalid mapId %u tile [%u, %u] passed to VMapManager2 after startup in thread unsafe environment", ASSERT(false, "Invalid mapId %u tile [%u, %u] passed to VMapManager2 after startup in thread unsafe environment",
mapId, tileX, tileY); mapId, tileX, tileY);
} }
if (!instanceTree->second) if (!instanceTree->second)
@@ -167,7 +177,9 @@ namespace VMAP
{ {
#if defined(ENABLE_VMAP_CHECKS) #if defined(ENABLE_VMAP_CHECKS)
if (!isLineOfSightCalcEnabled() || IsVMAPDisabledForPtr(mapId, VMAP_DISABLE_LOS)) if (!isLineOfSightCalcEnabled() || IsVMAPDisabledForPtr(mapId, VMAP_DISABLE_LOS))
{
return true; return true;
}
#endif #endif
InstanceTreeMap::const_iterator instanceTree = GetMapTree(mapId); InstanceTreeMap::const_iterator instanceTree = GetMapTree(mapId);
@@ -232,7 +244,9 @@ namespace VMAP
Vector3 pos = convertPositionToInternalRep(x, y, z); Vector3 pos = convertPositionToInternalRep(x, y, z);
float height = instanceTree->second->getHeight(pos, maxSearchDist); float height = instanceTree->second->getHeight(pos, maxSearchDist);
if (!(height < G3D::finf())) if (!(height < G3D::finf()))
return height = VMAP_INVALID_HEIGHT_VALUE; // No height {
return height = VMAP_INVALID_HEIGHT_VALUE; // No height
}
return height; return height;
} }
@@ -278,9 +292,13 @@ namespace VMAP
ASSERT(floor < std::numeric_limits<float>::max()); ASSERT(floor < std::numeric_limits<float>::max());
type = info.hitModel->GetLiquidType(); // entry from LiquidType.dbc type = info.hitModel->GetLiquidType(); // entry from LiquidType.dbc
if (reqLiquidType && !(GetLiquidFlagsPtr(type) & reqLiquidType)) if (reqLiquidType && !(GetLiquidFlagsPtr(type) & reqLiquidType))
{
return false; return false;
}
if (info.hitInstance->GetLiquidLevel(pos, info, level)) if (info.hitInstance->GetLiquidLevel(pos, info, level))
{
return true; return true;
}
} }
} }
} }

View File

@@ -22,7 +22,7 @@ struct MmapTileHeader
uint32 mmapVersion{MMAP_VERSION}; uint32 mmapVersion{MMAP_VERSION};
uint32 size{0}; uint32 size{0};
char usesLiquids{true}; char usesLiquids{true};
char padding[3]{}; char padding[3] {};
MmapTileHeader() : dtVersion(DT_NAVMESH_VERSION) { } MmapTileHeader() : dtVersion(DT_NAVMESH_VERSION) { }
}; };

View File

@@ -27,7 +27,9 @@ namespace VMAP
{ {
bool result = prims[entry].intersectRay(ray, distance, StopAtFirstHit); bool result = prims[entry].intersectRay(ray, distance, StopAtFirstHit);
if (result) if (result)
{
hit = true; hit = true;
}
return result; return result;
} }
bool didHit() { return hit; } bool didHit() { return hit; }
@@ -62,7 +64,9 @@ namespace VMAP
LOG_DEBUG("maps", "LocationInfoCallback: trying to intersect '%s'", prims[entry].name.c_str()); LOG_DEBUG("maps", "LocationInfoCallback: trying to intersect '%s'", prims[entry].name.c_str());
#endif #endif
if (prims[entry].GetLocationInfo(point, locInfo)) if (prims[entry].GetLocationInfo(point, locInfo))
{
result = true; result = true;
}
} }
ModelInstance* prims; ModelInstance* prims;
@@ -133,7 +137,9 @@ namespace VMAP
MapRayCallback intersectionCallBack(iTreeValues); MapRayCallback intersectionCallBack(iTreeValues);
iTree.intersectRay(pRay, intersectionCallBack, distance, StopAtFirstHit); iTree.intersectRay(pRay, intersectionCallBack, distance, StopAtFirstHit);
if (intersectionCallBack.didHit()) if (intersectionCallBack.didHit())
{
pMaxDist = distance; pMaxDist = distance;
}
return intersectionCallBack.didHit(); return intersectionCallBack.didHit();
} }
//========================================================= //=========================================================
@@ -143,17 +149,23 @@ namespace VMAP
float maxDist = (pos2 - pos1).magnitude(); float maxDist = (pos2 - pos1).magnitude();
// return false if distance is over max float, in case of cheater teleporting to the end of the universe // return false if distance is over max float, in case of cheater teleporting to the end of the universe
if (maxDist == std::numeric_limits<float>::max() || !std::isfinite(maxDist)) if (maxDist == std::numeric_limits<float>::max() || !std::isfinite(maxDist))
{
return false; return false;
}
// valid map coords should *never ever* produce float overflow, but this would produce NaNs too // valid map coords should *never ever* produce float overflow, but this would produce NaNs too
ASSERT(maxDist < std::numeric_limits<float>::max()); ASSERT(maxDist < std::numeric_limits<float>::max());
// prevent NaN values which can cause BIH intersection to enter infinite loop // prevent NaN values which can cause BIH intersection to enter infinite loop
if (maxDist < 1e-10f) if (maxDist < 1e-10f)
{
return true; return true;
}
// direction with length of 1 // direction with length of 1
G3D::Ray ray = G3D::Ray::fromOriginAndDirection(pos1, (pos2 - pos1) / maxDist); G3D::Ray ray = G3D::Ray::fromOriginAndDirection(pos1, (pos2 - pos1) / maxDist);
if (getIntersectionTime(ray, maxDist, true)) if (getIntersectionTime(ray, maxDist, true))
{
return false; return false;
}
return true; return true;
} }
@@ -227,12 +239,16 @@ namespace VMAP
{ {
std::string basePath = vmapPath; std::string basePath = vmapPath;
if (basePath.length() > 0 && basePath[basePath.length() - 1] != '/' && basePath[basePath.length() - 1] != '\\') if (basePath.length() > 0 && basePath[basePath.length() - 1] != '/' && basePath[basePath.length() - 1] != '\\')
{
basePath.push_back('/'); basePath.push_back('/');
}
std::string fullname = basePath + VMapManager2::getMapFileName(mapID); std::string fullname = basePath + VMapManager2::getMapFileName(mapID);
bool success = true; bool success = true;
FILE* rf = fopen(fullname.c_str(), "rb"); FILE* rf = fopen(fullname.c_str(), "rb");
if (!rf) if (!rf)
{
return false; return false;
}
// TODO: check magic number when implemented... // TODO: check magic number when implemented...
char tiled; char tiled;
char chunk[8]; char chunk[8];
@@ -246,11 +262,15 @@ namespace VMAP
std::string tilefile = basePath + getTileFileName(mapID, tileX, tileY); std::string tilefile = basePath + getTileFileName(mapID, tileX, tileY);
FILE* tf = fopen(tilefile.c_str(), "rb"); FILE* tf = fopen(tilefile.c_str(), "rb");
if (!tf) if (!tf)
{
success = false; success = false;
}
else else
{ {
if (!readChunk(tf, chunk, VMAP_MAGIC, 8)) if (!readChunk(tf, chunk, VMAP_MAGIC, 8))
{
success = false; success = false;
}
fclose(tf); fclose(tf);
} }
} }
@@ -267,7 +287,9 @@ namespace VMAP
std::string fullname = iBasePath + fname; std::string fullname = iBasePath + fname;
FILE* rf = fopen(fullname.c_str(), "rb"); FILE* rf = fopen(fullname.c_str(), "rb");
if (!rf) if (!rf)
{
return false; return false;
}
char chunk[8]; char chunk[8];
char tiled = '\0'; char tiled = '\0';
@@ -317,7 +339,9 @@ namespace VMAP
{ {
iTreeValues[i->first].setUnloaded(); iTreeValues[i->first].setUnloaded();
for (uint32 refCount = 0; refCount < i->second; ++refCount) for (uint32 refCount = 0; refCount < i->second; ++refCount)
{
vm->releaseModelInstance(iTreeValues[i->first].name); vm->releaseModelInstance(iTreeValues[i->first].name);
}
} }
iLoadedSpawns.clear(); iLoadedSpawns.clear();
iLoadedTiles.clear(); iLoadedTiles.clear();
@@ -348,10 +372,14 @@ namespace VMAP
char chunk[8]; char chunk[8];
if (!readChunk(tf, chunk, VMAP_MAGIC, 8)) if (!readChunk(tf, chunk, VMAP_MAGIC, 8))
{
result = false; result = false;
}
uint32 numSpawns = 0; uint32 numSpawns = 0;
if (result && fread(&numSpawns, sizeof(uint32), 1, tf) != 1) if (result && fread(&numSpawns, sizeof(uint32), 1, tf) != 1)
{
result = false; result = false;
}
for (uint32 i = 0; i < numSpawns && result; ++i) for (uint32 i = 0; i < numSpawns && result; ++i)
{ {
// read model spawns // read model spawns
@@ -362,7 +390,9 @@ namespace VMAP
// acquire model instance // acquire model instance
WorldModel* model = vm->acquireModelInstance(iBasePath, spawn.name); WorldModel* model = vm->acquireModelInstance(iBasePath, spawn.name);
if (!model) if (!model)
{
LOG_ERROR("maps", "StaticMapTree::LoadMapTile() : could not acquire WorldModel pointer [%u, %u]", tileX, tileY); LOG_ERROR("maps", "StaticMapTree::LoadMapTile() : could not acquire WorldModel pointer [%u, %u]", tileX, tileY);
}
// update tree // update tree
uint32 referencedVal; uint32 referencedVal;
@@ -386,21 +416,29 @@ namespace VMAP
++iLoadedSpawns[referencedVal]; ++iLoadedSpawns[referencedVal];
#if defined(VMAP_DEBUG) #if defined(VMAP_DEBUG)
if (iTreeValues[referencedVal].ID != spawn.ID) if (iTreeValues[referencedVal].ID != spawn.ID)
{
LOG_DEBUG("maps", "StaticMapTree::LoadMapTile() : trying to load wrong spawn in node"); LOG_DEBUG("maps", "StaticMapTree::LoadMapTile() : trying to load wrong spawn in node");
}
else if (iTreeValues[referencedVal].name != spawn.name) else if (iTreeValues[referencedVal].name != spawn.name)
{
LOG_DEBUG("maps", "StaticMapTree::LoadMapTile() : name collision on GUID=%u", spawn.ID); LOG_DEBUG("maps", "StaticMapTree::LoadMapTile() : name collision on GUID=%u", spawn.ID);
}
#endif #endif
} }
} }
else else
{
result = false; result = false;
}
} }
} }
iLoadedTiles[packTileID(tileX, tileY)] = true; iLoadedTiles[packTileID(tileX, tileY)] = true;
fclose(tf); fclose(tf);
} }
else else
{
iLoadedTiles[packTileID(tileX, tileY)] = false; iLoadedTiles[packTileID(tileX, tileY)] = false;
}
return result; return result;
} }
@@ -424,10 +462,14 @@ namespace VMAP
bool result = true; bool result = true;
char chunk[8]; char chunk[8];
if (!readChunk(tf, chunk, VMAP_MAGIC, 8)) if (!readChunk(tf, chunk, VMAP_MAGIC, 8))
{
result = false; result = false;
}
uint32 numSpawns; uint32 numSpawns;
if (fread(&numSpawns, sizeof(uint32), 1, tf) != 1) if (fread(&numSpawns, sizeof(uint32), 1, tf) != 1)
{
result = false; result = false;
}
for (uint32 i = 0; i < numSpawns && result; ++i) for (uint32 i = 0; i < numSpawns && result; ++i)
{ {
// read model spawns // read model spawns
@@ -442,11 +484,15 @@ namespace VMAP
uint32 referencedNode; uint32 referencedNode;
if (fread(&referencedNode, sizeof(uint32), 1, tf) != 1) if (fread(&referencedNode, sizeof(uint32), 1, tf) != 1)
{
result = false; result = false;
}
else else
{ {
if (!iLoadedSpawns.count(referencedNode)) if (!iLoadedSpawns.count(referencedNode))
{
LOG_ERROR("maps", "StaticMapTree::UnloadMapTile() : trying to unload non-referenced model '%s' (ID:%u)", spawn.name.c_str(), spawn.ID); LOG_ERROR("maps", "StaticMapTree::UnloadMapTile() : trying to unload non-referenced model '%s' (ID:%u)", spawn.name.c_str(), spawn.ID);
}
else if (--iLoadedSpawns[referencedNode] == 0) else if (--iLoadedSpawns[referencedNode] == 0)
{ {
iTreeValues[referencedNode].setUnloaded(); iTreeValues[referencedNode].setUnloaded();

View File

@@ -27,7 +27,7 @@ namespace VMAP
{ {
bool readChunk(FILE* rf, char* dest, const char* compare, uint32 len) bool readChunk(FILE* rf, char* dest, const char* compare, uint32 len)
{ {
if (fread(dest, sizeof(char), len, rf) != len) return false; if (fread(dest, sizeof(char), len, rf) != len) { return false; }
return memcmp(dest, compare, len) == 0; return memcmp(dest, compare, len) == 0;
} }
@@ -56,7 +56,9 @@ namespace VMAP
{ {
bool success = readMapSpawns(); bool success = readMapSpawns();
if (!success) if (!success)
{
return false; return false;
}
// export Map data // export Map data
for (MapData::iterator map_iter = mapData.begin(); map_iter != mapData.end() && success; ++map_iter) for (MapData::iterator map_iter = mapData.begin(); map_iter != mapData.end() && success; ++map_iter)
@@ -71,7 +73,9 @@ namespace VMAP
if (entry->second.flags & MOD_M2) if (entry->second.flags & MOD_M2)
{ {
if (!calculateTransformedBound(entry->second)) if (!calculateTransformedBound(entry->second))
{
break; break;
}
} }
else if (entry->second.flags & MOD_WORLDSPAWN) // WMO maps and terrain maps use different origin, so we need to adapt :/ else if (entry->second.flags & MOD_WORLDSPAWN) // WMO maps and terrain maps use different origin, so we need to adapt :/
{ {
@@ -99,7 +103,9 @@ namespace VMAP
// ===> possibly move this code to StaticMapTree class // ===> possibly move this code to StaticMapTree class
std::map<uint32, uint32> modelNodeIdx; std::map<uint32, uint32> modelNodeIdx;
for (uint32 i = 0; i < mapSpawns.size(); ++i) for (uint32 i = 0; i < mapSpawns.size(); ++i)
{
modelNodeIdx.insert(pair<uint32, uint32>(mapSpawns[i]->ID, i)); modelNodeIdx.insert(pair<uint32, uint32>(mapSpawns[i]->ID, i));
}
// write map tree file // write map tree file
std::stringstream mapfilename; std::stringstream mapfilename;
@@ -113,16 +119,16 @@ namespace VMAP
} }
//general info //general info
if (success && fwrite(VMAP_MAGIC, 1, 8, mapfile) != 8) success = false; if (success && fwrite(VMAP_MAGIC, 1, 8, mapfile) != 8) { success = false; }
uint32 globalTileID = StaticMapTree::packTileID(65, 65); uint32 globalTileID = StaticMapTree::packTileID(65, 65);
pair<TileMap::iterator, TileMap::iterator> globalRange = map_iter->second->TileEntries.equal_range(globalTileID); pair<TileMap::iterator, TileMap::iterator> globalRange = map_iter->second->TileEntries.equal_range(globalTileID);
char isTiled = globalRange.first == globalRange.second; // only maps without terrain (tiles) have global WMO char isTiled = globalRange.first == globalRange.second; // only maps without terrain (tiles) have global WMO
if (success && fwrite(&isTiled, sizeof(char), 1, mapfile) != 1) success = false; if (success && fwrite(&isTiled, sizeof(char), 1, mapfile) != 1) { success = false; }
// Nodes // Nodes
if (success && fwrite("NODE", 4, 1, mapfile) != 1) success = false; if (success && fwrite("NODE", 4, 1, mapfile) != 1) { success = false; }
if (success) success = pTree.writeToFile(mapfile); if (success) { success = pTree.writeToFile(mapfile); }
// global map spawns (WDT), if any (most instances) // global map spawns (WDT), if any (most instances)
if (success && fwrite("GOBJ", 4, 1, mapfile) != 1) success = false; if (success && fwrite("GOBJ", 4, 1, mapfile) != 1) { success = false; }
for (TileMap::iterator glob = globalRange.first; glob != globalRange.second && success; ++glob) for (TileMap::iterator glob = globalRange.first; glob != globalRange.second && success; ++glob)
{ {
@@ -140,7 +146,9 @@ namespace VMAP
{ {
const ModelSpawn& spawn = map_iter->second->UniqueEntries[tile->second]; const ModelSpawn& spawn = map_iter->second->UniqueEntries[tile->second];
if (spawn.flags & MOD_WORLDSPAWN) // WDT spawn, saved as tile 65/65 currently... if (spawn.flags & MOD_WORLDSPAWN) // WDT spawn, saved as tile 65/65 currently...
{
continue; continue;
}
uint32 nSpawns = tileEntries.count(tile->first); uint32 nSpawns = tileEntries.count(tile->first);
std::stringstream tilefilename; std::stringstream tilefilename;
tilefilename.fill('0'); tilefilename.fill('0');
@@ -151,19 +159,21 @@ namespace VMAP
if (FILE* tilefile = fopen(tilefilename.str().c_str(), "wb")) if (FILE* tilefile = fopen(tilefilename.str().c_str(), "wb"))
{ {
// file header // file header
if (success && fwrite(VMAP_MAGIC, 1, 8, tilefile) != 8) success = false; if (success && fwrite(VMAP_MAGIC, 1, 8, tilefile) != 8) { success = false; }
// write number of tile spawns // write number of tile spawns
if (success && fwrite(&nSpawns, sizeof(uint32), 1, tilefile) != 1) success = false; if (success && fwrite(&nSpawns, sizeof(uint32), 1, tilefile) != 1) { success = false; }
// write tile spawns // write tile spawns
for (uint32 s = 0; s < nSpawns; ++s) for (uint32 s = 0; s < nSpawns; ++s)
{ {
if (s) if (s)
{
++tile; ++tile;
}
const ModelSpawn& spawn2 = map_iter->second->UniqueEntries[tile->second]; const ModelSpawn& spawn2 = map_iter->second->UniqueEntries[tile->second];
success = success && ModelSpawn::writeToFile(tilefile, spawn2); success = success && ModelSpawn::writeToFile(tilefile, spawn2);
// MapTree nodes to update when loading tile: // MapTree nodes to update when loading tile:
std::map<uint32, uint32>::iterator nIdx = modelNodeIdx.find(spawn2.ID); std::map<uint32, uint32>::iterator nIdx = modelNodeIdx.find(spawn2.ID);
if (success && fwrite(&nIdx->second, sizeof(uint32), 1, tilefile) != 1) success = false; if (success && fwrite(&nIdx->second, sizeof(uint32), 1, tilefile) != 1) { success = false; }
} }
fclose(tilefile); fclose(tilefile);
} }
@@ -212,11 +222,15 @@ namespace VMAP
// read mapID, tileX, tileY, Flags, NameSet, UniqueId, Pos, Rot, Scale, Bound_lo, Bound_hi, name // read mapID, tileX, tileY, Flags, NameSet, UniqueId, Pos, Rot, Scale, Bound_lo, Bound_hi, name
check = fread(&mapID, sizeof(uint32), 1, dirf); check = fread(&mapID, sizeof(uint32), 1, dirf);
if (check == 0) // EoF... if (check == 0) // EoF...
{
break; break;
}
check += fread(&tileX, sizeof(uint32), 1, dirf); check += fread(&tileX, sizeof(uint32), 1, dirf);
check += fread(&tileY, sizeof(uint32), 1, dirf); check += fread(&tileY, sizeof(uint32), 1, dirf);
if (!ModelSpawn::readFromFile(dirf, spawn)) if (!ModelSpawn::readFromFile(dirf, spawn))
{
break; break;
}
MapSpawns* current; MapSpawns* current;
MapData::iterator map_iter = mapData.find(mapID); MapData::iterator map_iter = mapData.find(mapID);
@@ -226,7 +240,9 @@ namespace VMAP
mapData[mapID] = current = new MapSpawns(); mapData[mapID] = current = new MapSpawns();
} }
else else
{
current = map_iter->second; current = map_iter->second;
}
current->UniqueEntries.emplace(spawn.ID, spawn); current->UniqueEntries.emplace(spawn.ID, spawn);
current->TileEntries.insert(pair<uint32, uint32>(StaticMapTree::packTileID(tileX, tileY), spawn.ID)); current->TileEntries.insert(pair<uint32, uint32>(StaticMapTree::packTileID(tileX, tileY), spawn.ID));
@@ -249,11 +265,15 @@ namespace VMAP
WorldModel_Raw raw_model; WorldModel_Raw raw_model;
if (!raw_model.Read(modelFilename.c_str())) if (!raw_model.Read(modelFilename.c_str()))
{
return false; return false;
}
uint32 groups = raw_model.groupsArray.size(); uint32 groups = raw_model.groupsArray.size();
if (groups != 1) if (groups != 1)
{
printf("Warning: '%s' does not seem to be a M2 model!\n", modelFilename.c_str()); printf("Warning: '%s' does not seem to be a M2 model!\n", modelFilename.c_str());
}
AABox modelBound; AABox modelBound;
bool boundEmpty = true; bool boundEmpty = true;
@@ -274,9 +294,13 @@ namespace VMAP
Vector3 v = modelPosition.transform(vertices[i]); Vector3 v = modelPosition.transform(vertices[i]);
if (boundEmpty) if (boundEmpty)
{
modelBound = AABox(v, v), boundEmpty = false; modelBound = AABox(v, v), boundEmpty = false;
}
else else
{
modelBound.merge(v); modelBound.merge(v);
}
} }
} }
spawn.iBound = modelBound + spawn.iPos; spawn.iBound = modelBound + spawn.iPos;
@@ -300,12 +324,16 @@ namespace VMAP
bool success = true; bool success = true;
std::string filename = iSrcDir; std::string filename = iSrcDir;
if (filename.length() > 0) if (filename.length() > 0)
{
filename.push_back('/'); filename.push_back('/');
}
filename.append(pModelFilename); filename.append(pModelFilename);
WorldModel_Raw raw_model; WorldModel_Raw raw_model;
if (!raw_model.Read(filename.c_str())) if (!raw_model.Read(filename.c_str()))
{
return false; return false;
}
// write WorldModel // write WorldModel
WorldModel model; WorldModel model;
@@ -335,11 +363,15 @@ namespace VMAP
{ {
FILE* model_list = fopen((iSrcDir + "/" + "temp_gameobject_models").c_str(), "rb"); FILE* model_list = fopen((iSrcDir + "/" + "temp_gameobject_models").c_str(), "rb");
if (!model_list) if (!model_list)
{
return; return;
}
char ident[8]; char ident[8];
if (fread(ident, 1, 8, model_list) != 8 || memcmp(ident, VMAP::RAW_VMAP_MAGIC, 8) != 0) if (fread(ident, 1, 8, model_list) != 8 || memcmp(ident, VMAP::RAW_VMAP_MAGIC, 8) != 0)
{
return; return;
}
FILE* model_list_copy = fopen((iDestDir + "/" + GAMEOBJECT_MODELS).c_str(), "wb"); FILE* model_list_copy = fopen((iDestDir + "/" + GAMEOBJECT_MODELS).c_str(), "wb");
if (!model_list_copy) if (!model_list_copy)
@@ -357,12 +389,14 @@ namespace VMAP
{ {
if (fread(&displayId, sizeof(uint32), 1, model_list) != 1) if (fread(&displayId, sizeof(uint32), 1, model_list) != 1)
if (feof(model_list)) // EOF flag is only set after failed reading attempt if (feof(model_list)) // EOF flag is only set after failed reading attempt
{
break; break;
}
if (fread(&isWmo, sizeof(uint8), 1, model_list) != 1 if (fread(&isWmo, sizeof(uint8), 1, model_list) != 1
|| fread(&name_length, sizeof(uint32), 1, model_list) != 1 || fread(&name_length, sizeof(uint32), 1, model_list) != 1
|| name_length >= sizeof(buff) || name_length >= sizeof(buff)
|| fread(&buff, sizeof(char), name_length, model_list) != name_length) || fread(&buff, sizeof(char), name_length, model_list) != name_length)
{ {
std::cout << "\nFile 'temp_gameobject_models' seems to be corrupted" << std::endl; std::cout << "\nFile 'temp_gameobject_models' seems to be corrupted" << std::endl;
break; break;
@@ -372,7 +406,9 @@ namespace VMAP
WorldModel_Raw raw_model; WorldModel_Raw raw_model;
if ( !raw_model.Read((iSrcDir + "/" + model_name).c_str()) ) if ( !raw_model.Read((iSrcDir + "/" + model_name).c_str()) )
{
continue; continue;
}
spawnedModelFiles.insert(model_name); spawnedModelFiles.insert(model_name);
AABox bounds; AABox bounds;
@@ -386,9 +422,13 @@ namespace VMAP
{ {
Vector3& v = vertices[i]; Vector3& v = vertices[i];
if (boundEmpty) if (boundEmpty)
{
bounds = AABox(v, v), boundEmpty = false; bounds = AABox(v, v), boundEmpty = false;
}
else else
{
bounds.merge(v); bounds.merge(v);
}
} }
} }
@@ -454,7 +494,9 @@ namespace VMAP
READ_OR_RETURN_WITH_DELETE(indexarray, nindexes * sizeof(uint16)); READ_OR_RETURN_WITH_DELETE(indexarray, nindexes * sizeof(uint16));
triangles.reserve(nindexes / 3); triangles.reserve(nindexes / 3);
for (uint32 i = 0; i < nindexes; i += 3) for (uint32 i = 0; i < nindexes; i += 3)
{
triangles.push_back(MeshTriangle(indexarray[i], indexarray[i + 1], indexarray[i + 2])); triangles.push_back(MeshTriangle(indexarray[i], indexarray[i + 1], indexarray[i + 2]));
}
delete[] indexarray; delete[] indexarray;
} }
@@ -471,7 +513,9 @@ namespace VMAP
float* vectorarray = new float[nvectors * 3]; float* vectorarray = new float[nvectors * 3];
READ_OR_RETURN_WITH_DELETE(vectorarray, nvectors * sizeof(float) * 3); READ_OR_RETURN_WITH_DELETE(vectorarray, nvectors * sizeof(float) * 3);
for (uint32 i = 0; i < nvectors; ++i) for (uint32 i = 0; i < nvectors; ++i)
{
vertexArray.push_back( Vector3(vectorarray + 3 * i) ); vertexArray.push_back( Vector3(vectorarray + 3 * i) );
}
delete[] vectorarray; delete[] vectorarray;
} }
@@ -526,10 +570,14 @@ namespace VMAP
groupsArray.resize(groups); groupsArray.resize(groups);
bool succeed = true; bool succeed = true;
for (uint32 g = 0; g < groups && succeed; ++g) for (uint32 g = 0; g < groups && succeed; ++g)
{
succeed = groupsArray[g].Read(rf); succeed = groupsArray[g].Read(rf);
}
if (succeed) /// rf will be freed inside Read if the function had any errors. if (succeed) /// rf will be freed inside Read if the function had any errors.
{
fclose(rf); fclose(rf);
}
return succeed; return succeed;
} }

View File

@@ -80,23 +80,23 @@ namespace VMAP
class TileAssembler class TileAssembler
{ {
private: private:
std::string iDestDir; std::string iDestDir;
std::string iSrcDir; std::string iSrcDir;
G3D::Table<std::string, unsigned int > iUniqueNameIds; G3D::Table<std::string, unsigned int > iUniqueNameIds;
MapData mapData; MapData mapData;
std::set<std::string> spawnedModelFiles; std::set<std::string> spawnedModelFiles;
public: public:
TileAssembler(const std::string& pSrcDirName, const std::string& pDestDirName); TileAssembler(const std::string& pSrcDirName, const std::string& pDestDirName);
virtual ~TileAssembler(); virtual ~TileAssembler();
bool convertWorld2(); bool convertWorld2();
bool readMapSpawns(); bool readMapSpawns();
bool calculateTransformedBound(ModelSpawn &spawn); bool calculateTransformedBound(ModelSpawn& spawn);
void exportGameobjectModels(); void exportGameobjectModels();
bool convertRawFile(const std::string& pModelFilename); bool convertRawFile(const std::string& pModelFilename);
}; };
} // VMAP } // VMAP

View File

@@ -55,14 +55,16 @@ void LoadGameObjectModelList(std::string const& dataPath)
Vector3 v1, v2; Vector3 v1, v2;
if (fread(&displayId, sizeof(uint32), 1, model_list_file) != 1) if (fread(&displayId, sizeof(uint32), 1, model_list_file) != 1)
if (feof(model_list_file)) // EOF flag is only set after failed reading attempt if (feof(model_list_file)) // EOF flag is only set after failed reading attempt
{
break; break;
}
if (fread(&isWmo, sizeof(uint8), 1, model_list_file) != 1 if (fread(&isWmo, sizeof(uint8), 1, model_list_file) != 1
|| fread(&name_length, sizeof(uint32), 1, model_list_file) != 1 || fread(&name_length, sizeof(uint32), 1, model_list_file) != 1
|| name_length >= sizeof(buff) || name_length >= sizeof(buff)
|| fread(&buff, sizeof(char), name_length, model_list_file) != name_length || fread(&buff, sizeof(char), name_length, model_list_file) != name_length
|| fread(&v1, sizeof(Vector3), 1, model_list_file) != 1 || fread(&v1, sizeof(Vector3), 1, model_list_file) != 1
|| fread(&v2, sizeof(Vector3), 1, model_list_file) != 1) || fread(&v2, sizeof(Vector3), 1, model_list_file) != 1)
{ {
LOG_ERROR("maps", "File '%s' seems to be corrupted!", VMAP::GAMEOBJECT_MODELS); LOG_ERROR("maps", "File '%s' seems to be corrupted!", VMAP::GAMEOBJECT_MODELS);
fclose(model_list_file); fclose(model_list_file);
@@ -72,7 +74,7 @@ void LoadGameObjectModelList(std::string const& dataPath)
if (v1.isNaN() || v2.isNaN()) if (v1.isNaN() || v2.isNaN())
{ {
LOG_ERROR("maps", "File '%s' Model '%s' has invalid v1%s v2%s values!", LOG_ERROR("maps", "File '%s' Model '%s' has invalid v1%s v2%s values!",
VMAP::GAMEOBJECT_MODELS, std::string(buff, name_length).c_str(), v1.toString().c_str(), v2.toString().c_str()); VMAP::GAMEOBJECT_MODELS, std::string(buff, name_length).c_str(), v1.toString().c_str(), v2.toString().c_str());
continue; continue;
} }
@@ -88,14 +90,18 @@ void LoadGameObjectModelList(std::string const& dataPath)
GameObjectModel::~GameObjectModel() GameObjectModel::~GameObjectModel()
{ {
if (iModel) if (iModel)
{
VMAP::VMapFactory::createOrGetVMapManager()->releaseModelInstance(name); VMAP::VMapFactory::createOrGetVMapManager()->releaseModelInstance(name);
}
} }
bool GameObjectModel::initialize(std::unique_ptr<GameObjectModelOwnerBase> modelOwner, std::string const& dataPath) bool GameObjectModel::initialize(std::unique_ptr<GameObjectModelOwnerBase> modelOwner, std::string const& dataPath)
{ {
ModelList::const_iterator it = model_list.find(modelOwner->GetDisplayId()); ModelList::const_iterator it = model_list.find(modelOwner->GetDisplayId());
if (it == model_list.end()) if (it == model_list.end())
{
return false; return false;
}
G3D::AABox mdl_box(it->second.bound); G3D::AABox mdl_box(it->second.bound);
// ignore models with no bounds // ignore models with no bounds
@@ -108,7 +114,9 @@ bool GameObjectModel::initialize(std::unique_ptr<GameObjectModelOwnerBase> model
iModel = VMAP::VMapFactory::createOrGetVMapManager()->acquireModelInstance(dataPath + "vmaps/", it->second.name); iModel = VMAP::VMapFactory::createOrGetVMapManager()->acquireModelInstance(dataPath + "vmaps/", it->second.name);
if (!iModel) if (!iModel)
{
return false; return false;
}
name = it->second.name; name = it->second.name;
iPos = modelOwner->GetPosition(); iPos = modelOwner->GetPosition();
@@ -122,7 +130,9 @@ bool GameObjectModel::initialize(std::unique_ptr<GameObjectModelOwnerBase> model
mdl_box = AABox(mdl_box.low() * iScale, mdl_box.high() * iScale); mdl_box = AABox(mdl_box.low() * iScale, mdl_box.high() * iScale);
AABox rotated_bounds; AABox rotated_bounds;
for (int i = 0; i < 8; ++i) for (int i = 0; i < 8; ++i)
{
rotated_bounds.merge(iRotation * mdl_box.corner(i)); rotated_bounds.merge(iRotation * mdl_box.corner(i));
}
iBound = rotated_bounds + iPos; iBound = rotated_bounds + iPos;
@@ -154,11 +164,15 @@ GameObjectModel* GameObjectModel::Create(std::unique_ptr<GameObjectModelOwnerBas
bool GameObjectModel::intersectRay(const G3D::Ray& ray, float& MaxDist, bool StopAtFirstHit, uint32 ph_mask) const bool GameObjectModel::intersectRay(const G3D::Ray& ray, float& MaxDist, bool StopAtFirstHit, uint32 ph_mask) const
{ {
if (!(phasemask & ph_mask) || !owner->IsSpawned()) if (!(phasemask & ph_mask) || !owner->IsSpawned())
{
return false; return false;
}
float time = ray.intersectionTime(iBound); float time = ray.intersectionTime(iBound);
if (time == G3D::inf()) if (time == G3D::inf())
{
return false; return false;
}
// child bounds are defined in object space: // child bounds are defined in object space:
Vector3 p = iInvRot * (ray.origin() - iPos) * iInvScale; Vector3 p = iInvRot * (ray.origin() - iPos) * iInvScale;
@@ -176,11 +190,15 @@ bool GameObjectModel::intersectRay(const G3D::Ray& ray, float& MaxDist, bool Sto
bool GameObjectModel::UpdatePosition() bool GameObjectModel::UpdatePosition()
{ {
if (!iModel) if (!iModel)
{
return false; return false;
}
ModelList::const_iterator it = model_list.find(owner->GetDisplayId()); ModelList::const_iterator it = model_list.find(owner->GetDisplayId());
if (it == model_list.end()) if (it == model_list.end())
{
return false; return false;
}
G3D::AABox mdl_box(it->second.bound); G3D::AABox mdl_box(it->second.bound);
@@ -200,7 +218,9 @@ bool GameObjectModel::UpdatePosition()
AABox rotated_bounds; AABox rotated_bounds;
for (int i = 0; i < 8; ++i) for (int i = 0; i < 8; ++i)
{
rotated_bounds.merge(iRotation * mdl_box.corner(i)); rotated_bounds.merge(iRotation * mdl_box.corner(i));
}
iBound = rotated_bounds + iPos; iBound = rotated_bounds + iPos;
#ifdef SPAWN_CORNERS #ifdef SPAWN_CORNERS

View File

@@ -65,9 +65,13 @@ namespace VMAP
// M2 files don't contain area info, only WMO files // M2 files don't contain area info, only WMO files
if (flags & MOD_M2) if (flags & MOD_M2)
{
return; return;
}
if (!iBound.contains(p)) if (!iBound.contains(p))
{
return; return;
}
// child bounds are defined in object space: // child bounds are defined in object space:
Vector3 pModel = iInvRot * (p - iPos) * iInvScale; Vector3 pModel = iInvRot * (p - iPos) * iInvScale;
Vector3 zDirModel = iInvRot * Vector3(0.f, 0.f, -1.f); Vector3 zDirModel = iInvRot * Vector3(0.f, 0.f, -1.f);
@@ -99,9 +103,13 @@ namespace VMAP
// M2 files don't contain area info, only WMO files // M2 files don't contain area info, only WMO files
if (flags & MOD_M2) if (flags & MOD_M2)
{
return false; return false;
}
if (!iBound.contains(p)) if (!iBound.contains(p))
{
return false; return false;
}
// child bounds are defined in object space: // child bounds are defined in object space:
Vector3 pModel = iInvRot * (p - iPos) * iInvScale; Vector3 pModel = iInvRot * (p - iPos) * iInvScale;
Vector3 zDirModel = iInvRot * Vector3(0.f, 0.f, -1.f); Vector3 zDirModel = iInvRot * Vector3(0.f, 0.f, -1.f);
@@ -147,7 +155,9 @@ namespace VMAP
if (!check) if (!check)
{ {
if (ferror(rf)) if (ferror(rf))
{
std::cout << "Error reading ModelSpawn!\n"; std::cout << "Error reading ModelSpawn!\n";
}
return false; return false;
} }
check += fread(&spawn.adtId, sizeof(uint16), 1, rf); check += fread(&spawn.adtId, sizeof(uint16), 1, rf);
@@ -202,9 +212,9 @@ namespace VMAP
} }
uint32 nameLen = spawn.name.length(); uint32 nameLen = spawn.name.length();
check += fwrite(&nameLen, sizeof(uint32), 1, wf); check += fwrite(&nameLen, sizeof(uint32), 1, wf);
if (check != uint32(has_bound ? 17 : 11)) return false; if (check != uint32(has_bound ? 17 : 11)) { return false; }
check = fwrite(spawn.name.c_str(), sizeof(char), nameLen, wf); check = fwrite(spawn.name.c_str(), sizeof(char), nameLen, wf);
if (check != nameLen) return false; if (check != nameLen) { return false; }
return true; return true;
} }

View File

@@ -113,7 +113,9 @@ namespace VMAP
WmoLiquid& WmoLiquid::operator=(const WmoLiquid& other) WmoLiquid& WmoLiquid::operator=(const WmoLiquid& other)
{ {
if (this == &other) if (this == &other)
{
return *this; return *this;
}
iTilesX = other.iTilesX; iTilesX = other.iTilesX;
iTilesY = other.iTilesY; iTilesY = other.iTilesY;
iCorner = other.iCorner; iCorner = other.iCorner;
@@ -126,14 +128,18 @@ namespace VMAP
memcpy(iHeight, other.iHeight, (iTilesX + 1) * (iTilesY + 1)*sizeof(float)); memcpy(iHeight, other.iHeight, (iTilesX + 1) * (iTilesY + 1)*sizeof(float));
} }
else else
{
iHeight = 0; iHeight = 0;
}
if (other.iFlags) if (other.iFlags)
{ {
iFlags = new uint8[iTilesX * iTilesY]; iFlags = new uint8[iTilesX * iTilesY];
memcpy(iFlags, other.iFlags, iTilesX * iTilesY); memcpy(iFlags, other.iFlags, iTilesX * iTilesY);
} }
else else
{
iFlags = 0; iFlags = 0;
}
return *this; return *this;
} }
@@ -142,16 +148,22 @@ namespace VMAP
float tx_f = (pos.x - iCorner.x) / LIQUID_TILE_SIZE; float tx_f = (pos.x - iCorner.x) / LIQUID_TILE_SIZE;
uint32 tx = uint32(tx_f); uint32 tx = uint32(tx_f);
if (tx_f < 0.0f || tx >= iTilesX) if (tx_f < 0.0f || tx >= iTilesX)
{
return false; return false;
}
float ty_f = (pos.y - iCorner.y) / LIQUID_TILE_SIZE; float ty_f = (pos.y - iCorner.y) / LIQUID_TILE_SIZE;
uint32 ty = uint32(ty_f); uint32 ty = uint32(ty_f);
if (ty_f < 0.0f || ty >= iTilesY) if (ty_f < 0.0f || ty >= iTilesY)
{
return false; return false;
}
// check if tile shall be used for liquid level // check if tile shall be used for liquid level
// checking for 0x08 *might* be enough, but disabled tiles always are 0x?F: // checking for 0x08 *might* be enough, but disabled tiles always are 0x?F:
if ((iFlags[tx + ty * iTilesX] & 0x0F) == 0x0F) if ((iFlags[tx + ty * iTilesX] & 0x0F) == 0x0F)
{
return false; return false;
}
// (dx, dy) coordinates inside tile, in [0, 1]^2 // (dx, dy) coordinates inside tile, in [0, 1]^2
float dx = tx_f - (float)tx; float dx = tx_f - (float)tx;
@@ -234,9 +246,13 @@ namespace VMAP
} }
if (!result) if (!result)
{
delete liquid; delete liquid;
}
else else
{
out = liquid; out = liquid;
}
return result; return result;
} }
@@ -255,7 +271,9 @@ namespace VMAP
vertices(other.vertices), triangles(other.triangles), meshTree(other.meshTree), iLiquid(0) vertices(other.vertices), triangles(other.triangles), meshTree(other.meshTree), iLiquid(0)
{ {
if (other.iLiquid) if (other.iLiquid)
{
iLiquid = new WmoLiquid(*other.iLiquid); iLiquid = new WmoLiquid(*other.iLiquid);
}
} }
void GroupModel::setMeshData(std::vector<Vector3>& vert, std::vector<MeshTriangle>& tri) void GroupModel::setMeshData(std::vector<Vector3>& vert, std::vector<MeshTriangle>& tri)
@@ -271,43 +289,45 @@ namespace VMAP
bool result = true; bool result = true;
uint32 chunkSize, count; uint32 chunkSize, count;
if (result && fwrite(&iBound, sizeof(G3D::AABox), 1, wf) != 1) result = false; if (result && fwrite(&iBound, sizeof(G3D::AABox), 1, wf) != 1) { result = false; }
if (result && fwrite(&iMogpFlags, sizeof(uint32), 1, wf) != 1) result = false; if (result && fwrite(&iMogpFlags, sizeof(uint32), 1, wf) != 1) { result = false; }
if (result && fwrite(&iGroupWMOID, sizeof(uint32), 1, wf) != 1) result = false; if (result && fwrite(&iGroupWMOID, sizeof(uint32), 1, wf) != 1) { result = false; }
// write vertices // write vertices
if (result && fwrite("VERT", 1, 4, wf) != 4) result = false; if (result && fwrite("VERT", 1, 4, wf) != 4) { result = false; }
count = vertices.size(); count = vertices.size();
chunkSize = sizeof(uint32) + sizeof(Vector3) * count; chunkSize = sizeof(uint32) + sizeof(Vector3) * count;
if (result && fwrite(&chunkSize, sizeof(uint32), 1, wf) != 1) result = false; if (result && fwrite(&chunkSize, sizeof(uint32), 1, wf) != 1) { result = false; }
if (result && fwrite(&count, sizeof(uint32), 1, wf) != 1) result = false; if (result && fwrite(&count, sizeof(uint32), 1, wf) != 1) { result = false; }
if (!count) // models without (collision) geometry end here, unsure if they are useful if (!count) // models without (collision) geometry end here, unsure if they are useful
{
return result; return result;
if (result && fwrite(&vertices[0], sizeof(Vector3), count, wf) != count) result = false; }
if (result && fwrite(&vertices[0], sizeof(Vector3), count, wf) != count) { result = false; }
// write triangle mesh // write triangle mesh
if (result && fwrite("TRIM", 1, 4, wf) != 4) result = false; if (result && fwrite("TRIM", 1, 4, wf) != 4) { result = false; }
count = triangles.size(); count = triangles.size();
chunkSize = sizeof(uint32) + sizeof(MeshTriangle) * count; chunkSize = sizeof(uint32) + sizeof(MeshTriangle) * count;
if (result && fwrite(&chunkSize, sizeof(uint32), 1, wf) != 1) result = false; if (result && fwrite(&chunkSize, sizeof(uint32), 1, wf) != 1) { result = false; }
if (result && fwrite(&count, sizeof(uint32), 1, wf) != 1) result = false; if (result && fwrite(&count, sizeof(uint32), 1, wf) != 1) { result = false; }
if (result && fwrite(&triangles[0], sizeof(MeshTriangle), count, wf) != count) result = false; if (result && fwrite(&triangles[0], sizeof(MeshTriangle), count, wf) != count) { result = false; }
// write mesh BIH // write mesh BIH
if (result && fwrite("MBIH", 1, 4, wf) != 4) result = false; if (result && fwrite("MBIH", 1, 4, wf) != 4) { result = false; }
if (result) result = meshTree.writeToFile(wf); if (result) { result = meshTree.writeToFile(wf); }
// write liquid data // write liquid data
if (result && fwrite("LIQU", 1, 4, wf) != 4) result = false; if (result && fwrite("LIQU", 1, 4, wf) != 4) { result = false; }
if (!iLiquid) if (!iLiquid)
{ {
chunkSize = 0; chunkSize = 0;
if (result && fwrite(&chunkSize, sizeof(uint32), 1, wf) != 1) result = false; if (result && fwrite(&chunkSize, sizeof(uint32), 1, wf) != 1) { result = false; }
return result; return result;
} }
chunkSize = iLiquid->GetFileSize(); chunkSize = iLiquid->GetFileSize();
if (result && fwrite(&chunkSize, sizeof(uint32), 1, wf) != 1) result = false; if (result && fwrite(&chunkSize, sizeof(uint32), 1, wf) != 1) { result = false; }
if (result) result = iLiquid->writeToFile(wf); if (result) { result = iLiquid->writeToFile(wf); }
return result; return result;
} }
@@ -323,35 +343,39 @@ namespace VMAP
delete iLiquid; delete iLiquid;
iLiquid = nullptr; iLiquid = nullptr;
if (result && fread(&iBound, sizeof(G3D::AABox), 1, rf) != 1) result = false; if (result && fread(&iBound, sizeof(G3D::AABox), 1, rf) != 1) { result = false; }
if (result && fread(&iMogpFlags, sizeof(uint32), 1, rf) != 1) result = false; if (result && fread(&iMogpFlags, sizeof(uint32), 1, rf) != 1) { result = false; }
if (result && fread(&iGroupWMOID, sizeof(uint32), 1, rf) != 1) result = false; if (result && fread(&iGroupWMOID, sizeof(uint32), 1, rf) != 1) { result = false; }
// read vertices // read vertices
if (result && !readChunk(rf, chunk, "VERT", 4)) result = false; if (result && !readChunk(rf, chunk, "VERT", 4)) { result = false; }
if (result && fread(&chunkSize, sizeof(uint32), 1, rf) != 1) result = false; if (result && fread(&chunkSize, sizeof(uint32), 1, rf) != 1) { result = false; }
if (result && fread(&count, sizeof(uint32), 1, rf) != 1) result = false; if (result && fread(&count, sizeof(uint32), 1, rf) != 1) { result = false; }
if (!count) // models without (collision) geometry end here, unsure if they are useful if (!count) // models without (collision) geometry end here, unsure if they are useful
{
return result; return result;
if (result) vertices.resize(count); }
if (result && fread(&vertices[0], sizeof(Vector3), count, rf) != count) result = false; if (result) { vertices.resize(count); }
if (result && fread(&vertices[0], sizeof(Vector3), count, rf) != count) { result = false; }
// read triangle mesh // read triangle mesh
if (result && !readChunk(rf, chunk, "TRIM", 4)) result = false; if (result && !readChunk(rf, chunk, "TRIM", 4)) { result = false; }
if (result && fread(&chunkSize, sizeof(uint32), 1, rf) != 1) result = false; if (result && fread(&chunkSize, sizeof(uint32), 1, rf) != 1) { result = false; }
if (result && fread(&count, sizeof(uint32), 1, rf) != 1) result = false; if (result && fread(&count, sizeof(uint32), 1, rf) != 1) { result = false; }
if (result) triangles.resize(count); if (result) { triangles.resize(count); }
if (result && fread(&triangles[0], sizeof(MeshTriangle), count, rf) != count) result = false; if (result && fread(&triangles[0], sizeof(MeshTriangle), count, rf) != count) { result = false; }
// read mesh BIH // read mesh BIH
if (result && !readChunk(rf, chunk, "MBIH", 4)) result = false; if (result && !readChunk(rf, chunk, "MBIH", 4)) { result = false; }
if (result) result = meshTree.readFromFile(rf); if (result) { result = meshTree.readFromFile(rf); }
// write liquid data // write liquid data
if (result && !readChunk(rf, chunk, "LIQU", 4)) result = false; if (result && !readChunk(rf, chunk, "LIQU", 4)) { result = false; }
if (result && fread(&chunkSize, sizeof(uint32), 1, rf) != 1) result = false; if (result && fread(&chunkSize, sizeof(uint32), 1, rf) != 1) { result = false; }
if (result && chunkSize > 0) if (result && chunkSize > 0)
{
result = WmoLiquid::readFromFile(rf, iLiquid); result = WmoLiquid::readFromFile(rf, iLiquid);
}
return result; return result;
} }
@@ -362,7 +386,7 @@ namespace VMAP
bool operator()(const G3D::Ray& ray, uint32 entry, float& distance, bool /*StopAtFirstHit*/) bool operator()(const G3D::Ray& ray, uint32 entry, float& distance, bool /*StopAtFirstHit*/)
{ {
bool result = IntersectTriangle(triangles[entry], vertices, ray, distance); bool result = IntersectTriangle(triangles[entry], vertices, ray, distance);
if (result) hit = true; if (result) { hit = true; }
return hit; return hit;
} }
std::vector<Vector3>::const_iterator vertices; std::vector<Vector3>::const_iterator vertices;
@@ -373,7 +397,9 @@ namespace VMAP
bool GroupModel::IntersectRay(const G3D::Ray& ray, float& distance, bool stopAtFirstHit) const bool GroupModel::IntersectRay(const G3D::Ray& ray, float& distance, bool stopAtFirstHit) const
{ {
if (triangles.empty()) if (triangles.empty())
{
return false; return false;
}
GModelRayCallback callback(triangles, vertices); GModelRayCallback callback(triangles, vertices);
meshTree.intersectRay(ray, callback, distance, stopAtFirstHit); meshTree.intersectRay(ray, callback, distance, stopAtFirstHit);
@@ -383,28 +409,36 @@ namespace VMAP
bool GroupModel::IsInsideObject(const Vector3& pos, const Vector3& down, float& z_dist) const bool GroupModel::IsInsideObject(const Vector3& pos, const Vector3& down, float& z_dist) const
{ {
if (triangles.empty() || !iBound.contains(pos)) if (triangles.empty() || !iBound.contains(pos))
{
return false; return false;
}
GModelRayCallback callback(triangles, vertices); GModelRayCallback callback(triangles, vertices);
Vector3 rPos = pos - 0.1f * down; Vector3 rPos = pos - 0.1f * down;
float dist = G3D::inf(); float dist = G3D::inf();
G3D::Ray ray(rPos, down); G3D::Ray ray(rPos, down);
bool hit = IntersectRay(ray, dist, false); bool hit = IntersectRay(ray, dist, false);
if (hit) if (hit)
{
z_dist = dist - 0.1f; z_dist = dist - 0.1f;
}
return hit; return hit;
} }
bool GroupModel::GetLiquidLevel(const Vector3& pos, float& liqHeight) const bool GroupModel::GetLiquidLevel(const Vector3& pos, float& liqHeight) const
{ {
if (iLiquid) if (iLiquid)
{
return iLiquid->GetLiquidHeight(pos, liqHeight); return iLiquid->GetLiquidHeight(pos, liqHeight);
}
return false; return false;
} }
uint32 GroupModel::GetLiquidType() const uint32 GroupModel::GetLiquidType() const
{ {
if (iLiquid) if (iLiquid)
{
return iLiquid->GetType(); return iLiquid->GetType();
}
return 0; return 0;
} }
@@ -429,7 +463,7 @@ namespace VMAP
bool operator()(const G3D::Ray& ray, uint32 entry, float& distance, bool StopAtFirstHit) bool operator()(const G3D::Ray& ray, uint32 entry, float& distance, bool StopAtFirstHit)
{ {
bool result = models[entry].IntersectRay(ray, distance, StopAtFirstHit); bool result = models[entry].IntersectRay(ray, distance, StopAtFirstHit);
if (result) hit = true; if (result) { hit = true; }
return hit; return hit;
} }
std::vector<GroupModel>::const_iterator models; std::vector<GroupModel>::const_iterator models;
@@ -441,7 +475,9 @@ namespace VMAP
// small M2 workaround, maybe better make separate class with virtual intersection funcs // small M2 workaround, maybe better make separate class with virtual intersection funcs
// in any case, there's no need to use a bound tree if we only have one submodel // in any case, there's no need to use a bound tree if we only have one submodel
if (groupModels.size() == 1) if (groupModels.size() == 1)
{
return groupModels[0].IntersectRay(ray, distance, stopAtFirstHit); return groupModels[0].IntersectRay(ray, distance, stopAtFirstHit);
}
WModelRayCallBack isc(groupModels); WModelRayCallBack isc(groupModels);
groupTree.intersectRay(ray, isc, distance, stopAtFirstHit); groupTree.intersectRay(ray, isc, distance, stopAtFirstHit);
@@ -489,7 +525,9 @@ namespace VMAP
bool WorldModel::IntersectPoint(const G3D::Vector3& p, const G3D::Vector3& down, float& dist, AreaInfo& info) const bool WorldModel::IntersectPoint(const G3D::Vector3& p, const G3D::Vector3& down, float& dist, AreaInfo& info) const
{ {
if (groupModels.empty()) if (groupModels.empty())
{
return false; return false;
}
WModelAreaCallback callback(groupModels, down); WModelAreaCallback callback(groupModels, down);
groupTree.intersectPoint(p, callback); groupTree.intersectPoint(p, callback);
@@ -508,7 +546,9 @@ namespace VMAP
bool WorldModel::GetLocationInfo(const G3D::Vector3& p, const G3D::Vector3& down, float& dist, LocationInfo& info) const bool WorldModel::GetLocationInfo(const G3D::Vector3& p, const G3D::Vector3& down, float& dist, LocationInfo& info) const
{ {
if (groupModels.empty()) if (groupModels.empty())
{
return false; return false;
}
WModelAreaCallback callback(groupModels, down); WModelAreaCallback callback(groupModels, down);
groupTree.intersectPoint(p, callback); groupTree.intersectPoint(p, callback);
@@ -525,29 +565,33 @@ namespace VMAP
{ {
FILE* wf = fopen(filename.c_str(), "wb"); FILE* wf = fopen(filename.c_str(), "wb");
if (!wf) if (!wf)
{
return false; return false;
}
uint32 chunkSize, count; uint32 chunkSize, count;
bool result = fwrite(VMAP_MAGIC, 1, 8, wf) == 8; bool result = fwrite(VMAP_MAGIC, 1, 8, wf) == 8;
if (result && fwrite("WMOD", 1, 4, wf) != 4) result = false; if (result && fwrite("WMOD", 1, 4, wf) != 4) { result = false; }
chunkSize = sizeof(uint32) + sizeof(uint32); chunkSize = sizeof(uint32) + sizeof(uint32);
if (result && fwrite(&chunkSize, sizeof(uint32), 1, wf) != 1) result = false; if (result && fwrite(&chunkSize, sizeof(uint32), 1, wf) != 1) { result = false; }
if (result && fwrite(&RootWMOID, sizeof(uint32), 1, wf) != 1) result = false; if (result && fwrite(&RootWMOID, sizeof(uint32), 1, wf) != 1) { result = false; }
// write group models // write group models
count = groupModels.size(); count = groupModels.size();
if (count) if (count)
{ {
if (result && fwrite("GMOD", 1, 4, wf) != 4) result = false; if (result && fwrite("GMOD", 1, 4, wf) != 4) { result = false; }
//chunkSize = sizeof(uint32)+ sizeof(GroupModel)*count; //chunkSize = sizeof(uint32)+ sizeof(GroupModel)*count;
//if (result && fwrite(&chunkSize, sizeof(uint32), 1, wf) != 1) result = false; //if (result && fwrite(&chunkSize, sizeof(uint32), 1, wf) != 1) result = false;
if (result && fwrite(&count, sizeof(uint32), 1, wf) != 1) result = false; if (result && fwrite(&count, sizeof(uint32), 1, wf) != 1) { result = false; }
for (uint32 i = 0; i < groupModels.size() && result; ++i) for (uint32 i = 0; i < groupModels.size() && result; ++i)
{
result = groupModels[i].writeToFile(wf); result = groupModels[i].writeToFile(wf);
}
// write group BIH // write group BIH
if (result && fwrite("GBIH", 1, 4, wf) != 4) result = false; if (result && fwrite("GBIH", 1, 4, wf) != 4) { result = false; }
if (result) result = groupTree.writeToFile(wf); if (result) { result = groupTree.writeToFile(wf); }
} }
fclose(wf); fclose(wf);
@@ -558,32 +602,36 @@ namespace VMAP
{ {
FILE* rf = fopen(filename.c_str(), "rb"); FILE* rf = fopen(filename.c_str(), "rb");
if (!rf) if (!rf)
{
return false; return false;
}
bool result = true; bool result = true;
uint32 chunkSize = 0; uint32 chunkSize = 0;
uint32 count = 0; uint32 count = 0;
char chunk[8]; // Ignore the added magic header char chunk[8]; // Ignore the added magic header
if (!readChunk(rf, chunk, VMAP_MAGIC, 8)) result = false; if (!readChunk(rf, chunk, VMAP_MAGIC, 8)) { result = false; }
if (result && !readChunk(rf, chunk, "WMOD", 4)) result = false; if (result && !readChunk(rf, chunk, "WMOD", 4)) { result = false; }
if (result && fread(&chunkSize, sizeof(uint32), 1, rf) != 1) result = false; if (result && fread(&chunkSize, sizeof(uint32), 1, rf) != 1) { result = false; }
if (result && fread(&RootWMOID, sizeof(uint32), 1, rf) != 1) result = false; if (result && fread(&RootWMOID, sizeof(uint32), 1, rf) != 1) { result = false; }
// read group models // read group models
if (result && readChunk(rf, chunk, "GMOD", 4)) if (result && readChunk(rf, chunk, "GMOD", 4))
{ {
//if (fread(&chunkSize, sizeof(uint32), 1, rf) != 1) result = false; //if (fread(&chunkSize, sizeof(uint32), 1, rf) != 1) result = false;
if (result && fread(&count, sizeof(uint32), 1, rf) != 1) result = false; if (result && fread(&count, sizeof(uint32), 1, rf) != 1) { result = false; }
if (result) groupModels.resize(count); if (result) { groupModels.resize(count); }
//if (result && fread(&groupModels[0], sizeof(GroupModel), count, rf) != count) result = false; //if (result && fread(&groupModels[0], sizeof(GroupModel), count, rf) != count) result = false;
for (uint32 i = 0; i < count && result; ++i) for (uint32 i = 0; i < count && result; ++i)
{
result = groupModels[i].readFromFile(rf); result = groupModels[i].readFromFile(rf);
}
// read group BIH // read group BIH
if (result && !readChunk(rf, chunk, "GBIH", 4)) result = false; if (result && !readChunk(rf, chunk, "GBIH", 4)) { result = false; }
if (result) result = groupTree.readFromFile(rf); if (result) { result = groupTree.readFromFile(rf); }
} }
fclose(rf); fclose(rf);

View File

@@ -22,7 +22,9 @@ public:
return; return;
} }
else if (_nodes[i] == n) else if (_nodes[i] == n)
{
return; return;
}
} }
Node* _nodes[9]; Node* _nodes[9];
}; };
@@ -64,7 +66,9 @@ public:
{ {
for (int x = 0; x < CELL_NUMBER; ++x) for (int x = 0; x < CELL_NUMBER; ++x)
for (int y = 0; y < CELL_NUMBER; ++y) for (int y = 0; y < CELL_NUMBER; ++y)
{
delete nodes[x][y]; delete nodes[x][y];
}
} }
void insert(const T& value) void insert(const T& value)
@@ -85,7 +89,9 @@ public:
{ {
Cell c = Cell::ComputeCell(pos[i].x, pos[i].y); Cell c = Cell::ComputeCell(pos[i].x, pos[i].y);
if (!c.isValid()) if (!c.isValid())
{
continue; continue;
}
Node& node = getGridFor(pos[i].x, pos[i].y); Node& node = getGridFor(pos[i].x, pos[i].y);
na.AddNode(&node); na.AddNode(&node);
} }
@@ -93,9 +99,13 @@ public:
for (uint8 i = 0; i < 9; ++i) for (uint8 i = 0; i < 9; ++i)
{ {
if (na._nodes[i]) if (na._nodes[i])
{
na._nodes[i]->insert(value); na._nodes[i]->insert(value);
}
else else
{
break; break;
}
} }
memberTable.set(&value, na); memberTable.set(&value, na);
@@ -107,9 +117,13 @@ public:
for (uint8 i = 0; i < 9; ++i) for (uint8 i = 0; i < 9; ++i)
{ {
if (na._nodes[i]) if (na._nodes[i])
{
na._nodes[i]->remove(value); na._nodes[i]->remove(value);
}
else else
{
break; break;
}
} }
// Remove the member // Remove the member
@@ -121,7 +135,9 @@ public:
for (int x = 0; x < CELL_NUMBER; ++x) for (int x = 0; x < CELL_NUMBER; ++x)
for (int y = 0; y < CELL_NUMBER; ++y) for (int y = 0; y < CELL_NUMBER; ++y)
if (Node* n = nodes[x][y]) if (Node* n = nodes[x][y])
{
n->balance(); n->balance();
}
} }
bool contains(const T& value) const { return memberTable.containsKey(&value); } bool contains(const T& value) const { return memberTable.containsKey(&value); }
@@ -151,7 +167,9 @@ public:
{ {
ASSERT(x < CELL_NUMBER && y < CELL_NUMBER); ASSERT(x < CELL_NUMBER && y < CELL_NUMBER);
if (!nodes[x][y]) if (!nodes[x][y])
{
nodes[x][y] = NodeCreatorFunc::makeNode(x, y); nodes[x][y] = NodeCreatorFunc::makeNode(x, y);
}
return *nodes[x][y]; return *nodes[x][y];
} }
@@ -166,14 +184,18 @@ public:
{ {
Cell cell = Cell::ComputeCell(ray.origin().x, ray.origin().y); Cell cell = Cell::ComputeCell(ray.origin().x, ray.origin().y);
if (!cell.isValid()) if (!cell.isValid())
{
return; return;
}
Cell last_cell = Cell::ComputeCell(end.x, end.y); Cell last_cell = Cell::ComputeCell(end.x, end.y);
if (cell == last_cell) if (cell == last_cell)
{ {
if (Node* node = nodes[cell.x][cell.y]) if (Node* node = nodes[cell.x][cell.y])
{
node->intersectRay(ray, intersectCallback, max_dist, stopAtFirstHit); node->intersectRay(ray, intersectCallback, max_dist, stopAtFirstHit);
}
return; return;
} }
@@ -222,7 +244,9 @@ public:
node->intersectRay(ray, intersectCallback, max_dist, stopAtFirstHit); node->intersectRay(ray, intersectCallback, max_dist, stopAtFirstHit);
} }
if (cell == last_cell) if (cell == last_cell)
{
break; break;
}
if (tMaxX < tMaxY) if (tMaxX < tMaxY)
{ {
tMaxX += tDeltaX; tMaxX += tDeltaX;
@@ -242,9 +266,13 @@ public:
{ {
Cell cell = Cell::ComputeCell(point.x, point.y); Cell cell = Cell::ComputeCell(point.x, point.y);
if (!cell.isValid()) if (!cell.isValid())
{
return; return;
}
if (Node* node = nodes[cell.x][cell.y]) if (Node* node = nodes[cell.x][cell.y])
{
node->intersectPoint(point, intersectCallback); node->intersectPoint(point, intersectCallback);
}
} }
// Optimized verson of intersectRay function for rays with vertical directions // Optimized verson of intersectRay function for rays with vertical directions
@@ -253,9 +281,13 @@ public:
{ {
Cell cell = Cell::ComputeCell(ray.origin().x, ray.origin().y); Cell cell = Cell::ComputeCell(ray.origin().x, ray.origin().y);
if (!cell.isValid()) if (!cell.isValid())
{
return; return;
}
if (Node* node = nodes[cell.x][cell.y]) if (Node* node = nodes[cell.x][cell.y])
{
node->intersectRay(ray, intersectCallback, max_dist, false); node->intersectRay(ray, intersectCallback, max_dist, false);
}
} }
}; };

View File

@@ -23,7 +23,9 @@ LocaleConstant GetLocaleByName(const std::string& name)
{ {
for (uint32 i = 0; i < TOTAL_LOCALES; ++i) for (uint32 i = 0; i < TOTAL_LOCALES; ++i)
if (name == localeNames[i]) if (name == localeNames[i])
{
return LocaleConstant(i); return LocaleConstant(i);
}
return LOCALE_enUS; // including enGB case return LOCALE_enUS; // including enGB case
} }
@@ -31,7 +33,7 @@ LocaleConstant GetLocaleByName(const std::string& name)
void CleanStringForMysqlQuery(std::string& str) void CleanStringForMysqlQuery(std::string& str)
{ {
std::string::size_type n = 0; std::string::size_type n = 0;
while ((n = str.find('\\')) != str.npos) str.erase(n, 1); while ((n = str.find('\\')) != str.npos) { str.erase(n, 1); }
while ((n = str.find('"')) != str.npos) str.erase(n, 1); while ((n = str.find('"')) != str.npos) { str.erase(n, 1); }
while ((n = str.find('\'')) != str.npos) str.erase(n, 1); while ((n = str.find('\'')) != str.npos) { str.erase(n, 1); }
} }

View File

@@ -153,7 +153,9 @@ namespace
// No lines read // No lines read
if (!count) if (!count)
{
throw ConfigException(Acore::StringFormat("Config::LoadFile: Empty file '%s'", file.c_str())); throw ConfigException(Acore::StringFormat("Config::LoadFile: Empty file '%s'", file.c_str()));
}
// Add correct keys if file load without errors // Add correct keys if file load without errors
for (auto const& [entry, key] : fileConfigs) for (auto const& [entry, key] : fileConfigs)
@@ -200,7 +202,9 @@ ConfigMgr* ConfigMgr::instance()
bool ConfigMgr::Reload() bool ConfigMgr::Reload()
{ {
if (!LoadAppConfigs()) if (!LoadAppConfigs())
{
return false; return false;
}
return LoadModulesConfigs(); return LoadModulesConfigs();
} }
@@ -287,7 +291,9 @@ std::vector<std::string> ConfigMgr::GetKeysByString(std::string const& name)
for (auto const& [optionName, key] : _configOptions) for (auto const& [optionName, key] : _configOptions)
if (!optionName.compare(0, name.length(), name)) if (!optionName.compare(0, name.length(), name))
{
keys.emplace_back(optionName); keys.emplace_back(optionName);
}
return keys; return keys;
} }
@@ -324,7 +330,9 @@ void ConfigMgr::Configure(std::string const& initFileName, std::vector<std::stri
{ {
Tokenizer configFileList(modulesConfigList, ','); Tokenizer configFileList(modulesConfigList, ',');
for (auto const& itr : configFileList) for (auto const& itr : configFileList)
{
_additonalFiles.emplace_back(std::string(itr)); _additonalFiles.emplace_back(std::string(itr));
}
} }
} }
@@ -332,11 +340,15 @@ bool ConfigMgr::LoadAppConfigs()
{ {
// #1 - Load init config file .conf.dist // #1 - Load init config file .conf.dist
if (!LoadInitial(_filename + ".dist")) if (!LoadInitial(_filename + ".dist"))
{
return false; return false;
}
// #2 - Load .conf file // #2 - Load .conf file
if (!LoadAdditionalFile(_filename)) if (!LoadAdditionalFile(_filename))
{
return false; return false;
}
return true; return true;
} }
@@ -344,7 +356,9 @@ bool ConfigMgr::LoadAppConfigs()
bool ConfigMgr::LoadModulesConfigs() bool ConfigMgr::LoadModulesConfigs()
{ {
if (_additonalFiles.empty()) if (_additonalFiles.empty())
{
return true; return true;
}
// Start loading module configs // Start loading module configs
std::string const& moduleConfigPath = GetConfigPath() + "modules/"; std::string const& moduleConfigPath = GetConfigPath() + "modules/";
@@ -356,20 +370,30 @@ bool ConfigMgr::LoadModulesConfigs()
std::string defaultFileName = distFileName; std::string defaultFileName = distFileName;
if (!defaultFileName.empty()) if (!defaultFileName.empty())
{
defaultFileName.erase(defaultFileName.end() - 5, defaultFileName.end()); defaultFileName.erase(defaultFileName.end() - 5, defaultFileName.end());
}
// Load .conf.dist config // Load .conf.dist config
if (!LoadAdditionalFile(moduleConfigPath + distFileName)) if (!LoadAdditionalFile(moduleConfigPath + distFileName))
{
isExistDistConfig = false; isExistDistConfig = false;
}
// Load .conf config // Load .conf config
if (!LoadAdditionalFile(moduleConfigPath + defaultFileName)) if (!LoadAdditionalFile(moduleConfigPath + defaultFileName))
{
isExistDefaultConfig = false; isExistDefaultConfig = false;
}
if (isExistDefaultConfig && isExistDistConfig) if (isExistDefaultConfig && isExistDistConfig)
{
_moduleConfigFiles.emplace_back(defaultFileName); _moduleConfigFiles.emplace_back(defaultFileName);
}
else if (!isExistDefaultConfig && isExistDistConfig) else if (!isExistDefaultConfig && isExistDistConfig)
{
_moduleConfigFiles.emplace_back(distFileName); _moduleConfigFiles.emplace_back(distFileName);
}
} }
// If module configs not exist - no load // If module configs not exist - no load
@@ -383,7 +407,9 @@ void ConfigMgr::PrintLoadedModulesConfigs()
LOG_INFO("server.loading", "Using modules configuration:"); LOG_INFO("server.loading", "Using modules configuration:");
for (auto const& itr : _moduleConfigFiles) for (auto const& itr : _moduleConfigFiles)
{
LOG_INFO("server.loading", "> %s", itr.c_str()); LOG_INFO("server.loading", "> %s", itr.c_str());
}
LOG_INFO("server.loading", " "); LOG_INFO("server.loading", " ");
} }

View File

@@ -30,24 +30,34 @@ bool Acore::Crypto::AES::Process(IV const& iv, uint8* data, size_t length, Tag&
ASSERT(length <= static_cast<size_t>(std::numeric_limits<int>::max())); ASSERT(length <= static_cast<size_t>(std::numeric_limits<int>::max()));
int len = static_cast<int>(length); int len = static_cast<int>(length);
if (!EVP_CipherInit_ex(_ctx, nullptr, nullptr, nullptr, iv.data(), -1)) if (!EVP_CipherInit_ex(_ctx, nullptr, nullptr, nullptr, iv.data(), -1))
{
return false; return false;
}
int outLen; int outLen;
if (!EVP_CipherUpdate(_ctx, data, &outLen, data, len)) if (!EVP_CipherUpdate(_ctx, data, &outLen, data, len))
{
return false; return false;
}
len -= outLen; len -= outLen;
if (!_encrypting && !EVP_CIPHER_CTX_ctrl(_ctx, EVP_CTRL_GCM_SET_TAG, sizeof(tag), tag)) if (!_encrypting && !EVP_CIPHER_CTX_ctrl(_ctx, EVP_CTRL_GCM_SET_TAG, sizeof(tag), tag))
{
return false; return false;
}
if (!EVP_CipherFinal_ex(_ctx, data + outLen, &outLen)) if (!EVP_CipherFinal_ex(_ctx, data + outLen, &outLen))
{
return false; return false;
}
ASSERT(len == outLen); ASSERT(len == outLen);
if (_encrypting && !EVP_CIPHER_CTX_ctrl(_ctx, EVP_CTRL_GCM_GET_TAG, sizeof(tag), tag)) if (_encrypting && !EVP_CIPHER_CTX_ctrl(_ctx, EVP_CTRL_GCM_GET_TAG, sizeof(tag), tag))
{
return false; return false;
}
return true; return true;
} }

View File

@@ -20,7 +20,9 @@
); );
if (status == ARGON2_OK) if (status == ARGON2_OK)
{
return std::string(buf); return std::string(buf);
}
return {}; return {};
} }

View File

@@ -30,7 +30,7 @@ void AuthCrypt::Init(SessionKey const& K)
void AuthCrypt::DecryptRecv(uint8* data, size_t len) void AuthCrypt::DecryptRecv(uint8* data, size_t len)
{ {
ASSERT(_initialized); ASSERT(_initialized);
_clientDecrypt.UpdateData(data, len); _clientDecrypt.UpdateData(data, len);
} }

View File

@@ -48,13 +48,13 @@ using SRP6 = Acore::Crypto::SRP6;
// find position of first nonzero byte // find position of first nonzero byte
size_t p = 0; size_t p = 0;
while (p < EPHEMERAL_KEY_LENGTH && !S[p]) ++p; while (p < EPHEMERAL_KEY_LENGTH && !S[p]) { ++p; }
if (p & 1) ++p; // skip one extra byte if p is odd if (p & 1) { ++p; } // skip one extra byte if p is odd
p /= 2; // offset into buffers p /= 2; // offset into buffers
// hash each of the halves, starting at the first nonzero byte // hash each of the halves, starting at the first nonzero byte
SHA1::Digest const hash0 = SHA1::GetDigestOf(buf0.data() + p, EPHEMERAL_KEY_LENGTH/2 - p); SHA1::Digest const hash0 = SHA1::GetDigestOf(buf0.data() + p, EPHEMERAL_KEY_LENGTH / 2 - p);
SHA1::Digest const hash1 = SHA1::GetDigestOf(buf1.data() + p, EPHEMERAL_KEY_LENGTH/2 - p); SHA1::Digest const hash1 = SHA1::GetDigestOf(buf1.data() + p, EPHEMERAL_KEY_LENGTH / 2 - p);
// stick the two hashes back together // stick the two hashes back together
SessionKey K; SessionKey K;
@@ -76,7 +76,9 @@ std::optional<SessionKey> SRP6::VerifyChallengeResponse(EphemeralKey const& A, S
BigNumber const _A(A); BigNumber const _A(A);
if ((_A % _N).IsZero()) if ((_A % _N).IsZero())
{
return std::nullopt; return std::nullopt;
}
BigNumber const u(SHA1::GetDigestOf(A, B)); BigNumber const u(SHA1::GetDigestOf(A, B));
EphemeralKey const S = (_A * (_v.ModExp(u, _N))).ModExp(_b, N).ToByteArray<32>(); EphemeralKey const S = (_A * (_v.ModExp(u, _N))).ModExp(_b, N).ToByteArray<32>();
@@ -91,7 +93,11 @@ std::optional<SessionKey> SRP6::VerifyChallengeResponse(EphemeralKey const& A, S
SHA1::Digest const ourM = SHA1::GetDigestOf(NgHash, _I, s, A, B, K); SHA1::Digest const ourM = SHA1::GetDigestOf(NgHash, _I, s, A, B, K);
if (ourM == clientM) if (ourM == clientM)
{
return K; return K;
}
else else
{
return std::nullopt; return std::nullopt;
}
} }

View File

@@ -18,53 +18,53 @@ namespace Acore::Crypto
{ {
class SRP6 class SRP6
{ {
public: public:
static constexpr size_t SALT_LENGTH = 32; static constexpr size_t SALT_LENGTH = 32;
using Salt = std::array<uint8, SALT_LENGTH>; using Salt = std::array<uint8, SALT_LENGTH>;
static constexpr size_t VERIFIER_LENGTH = 32; static constexpr size_t VERIFIER_LENGTH = 32;
using Verifier = std::array<uint8, VERIFIER_LENGTH>; using Verifier = std::array<uint8, VERIFIER_LENGTH>;
static constexpr size_t EPHEMERAL_KEY_LENGTH = 32; static constexpr size_t EPHEMERAL_KEY_LENGTH = 32;
using EphemeralKey = std::array<uint8, EPHEMERAL_KEY_LENGTH>; using EphemeralKey = std::array<uint8, EPHEMERAL_KEY_LENGTH>;
static std::array<uint8, 1> const g; static std::array<uint8, 1> const g;
static std::array<uint8, 32> const N; static std::array<uint8, 32> const N;
// username + password must be passed through Utf8ToUpperOnlyLatin FIRST! // username + password must be passed through Utf8ToUpperOnlyLatin FIRST!
static std::pair<Salt, Verifier> MakeRegistrationData(std::string const& username, std::string const& password); static std::pair<Salt, Verifier> MakeRegistrationData(std::string const& username, std::string const& password);
// username + password must be passed through Utf8ToUpperOnlyLatin FIRST! // username + password must be passed through Utf8ToUpperOnlyLatin FIRST!
static bool CheckLogin(std::string const& username, std::string const& password, Salt const& salt, Verifier const& verifier) static bool CheckLogin(std::string const& username, std::string const& password, Salt const& salt, Verifier const& verifier)
{ {
return (verifier == CalculateVerifier(username, password, salt)); return (verifier == CalculateVerifier(username, password, salt));
} }
static SHA1::Digest GetSessionVerifier(EphemeralKey const& A, SHA1::Digest const& clientM, SessionKey const& K) static SHA1::Digest GetSessionVerifier(EphemeralKey const& A, SHA1::Digest const& clientM, SessionKey const& K)
{ {
return SHA1::GetDigestOf(A, clientM, K); return SHA1::GetDigestOf(A, clientM, K);
} }
SRP6(std::string const& username, Salt const& salt, Verifier const& verifier); SRP6(std::string const& username, Salt const& salt, Verifier const& verifier);
std::optional<SessionKey> VerifyChallengeResponse(EphemeralKey const& A, SHA1::Digest const& clientM); std::optional<SessionKey> VerifyChallengeResponse(EphemeralKey const& A, SHA1::Digest const& clientM);
private: private:
bool _used = false; // a single instance can only be used to verify once bool _used = false; // a single instance can only be used to verify once
static Verifier CalculateVerifier(std::string const& username, std::string const& password, Salt const& salt); static Verifier CalculateVerifier(std::string const& username, std::string const& password, Salt const& salt);
static SessionKey SHA1Interleave(EphemeralKey const& S); static SessionKey SHA1Interleave(EphemeralKey const& S);
/* global algorithm parameters */ /* global algorithm parameters */
static BigNumber const _g; // a [g]enerator for the ring of integers mod N, algorithm parameter static BigNumber const _g; // a [g]enerator for the ring of integers mod N, algorithm parameter
static BigNumber const _N; // the modulus, an algorithm parameter; all operations are mod this static BigNumber const _N; // the modulus, an algorithm parameter; all operations are mod this
static EphemeralKey _B(BigNumber const& b, BigNumber const& v) { return ((_g.ModExp(b,_N) + (v * 3)) % N).ToByteArray<EPHEMERAL_KEY_LENGTH>(); } static EphemeralKey _B(BigNumber const& b, BigNumber const& v) { return ((_g.ModExp(b, _N) + (v * 3)) % N).ToByteArray<EPHEMERAL_KEY_LENGTH>(); }
/* per-instantiation parameters, set on construction */ /* per-instantiation parameters, set on construction */
SHA1::Digest const _I; // H(I) - the username, all uppercase SHA1::Digest const _I; // H(I) - the username, all uppercase
BigNumber const _b; // b - randomly chosen by the server, 19 bytes, never given out BigNumber const _b; // b - randomly chosen by the server, 19 bytes, never given out
BigNumber const _v; // v - the user's password verifier, derived from s + H(USERNAME || ":" || PASSWORD) BigNumber const _v; // v - the user's password verifier, derived from s + H(USERNAME || ":" || PASSWORD)
public: public:
Salt const s; // s - the user's password salt, random, used to calculate v on registration Salt const s; // s - the user's password salt, random, used to calculate v on registration
EphemeralKey const B; // B = 3v + g^b EphemeralKey const B; // B = 3v + g^b
}; };
} }

View File

@@ -27,7 +27,9 @@ void BigNumber::SetDword(int32 val)
{ {
SetDword(uint32(abs(val))); SetDword(uint32(abs(val)));
if (val < 0) if (val < 0)
{
BN_set_negative(_bn, 1); BN_set_negative(_bn, 1);
}
} }
void BigNumber::SetDword(uint32 val) void BigNumber::SetDword(uint32 val)
@@ -50,7 +52,9 @@ void BigNumber::SetBinary(uint8 const* bytes, int32 len, bool littleEndian)
uint8* array = new uint8[len]; uint8* array = new uint8[len];
for (int i = 0; i < len; i++) for (int i = 0; i < len; i++)
{
array[i] = bytes[len - 1 - i]; array[i] = bytes[len - 1 - i];
}
BN_bin2bn(array, len, _bn); BN_bin2bn(array, len, _bn);
@@ -60,7 +64,9 @@ void BigNumber::SetBinary(uint8 const* bytes, int32 len, bool littleEndian)
#endif #endif
} }
else else
{
BN_bin2bn(bytes, len, _bn); BN_bin2bn(bytes, len, _bn);
}
} }
bool BigNumber::SetHexStr(char const* str) bool BigNumber::SetHexStr(char const* str)
@@ -77,7 +83,9 @@ void BigNumber::SetRand(int32 numbits)
BigNumber& BigNumber::operator=(BigNumber const& bn) BigNumber& BigNumber::operator=(BigNumber const& bn)
{ {
if (this == &bn) if (this == &bn)
{
return *this; return *this;
}
BN_copy(_bn, bn._bn); BN_copy(_bn, bn._bn);
return *this; return *this;
@@ -195,13 +203,17 @@ void BigNumber::GetBytes(uint8* buf, size_t bufsize, bool littleEndian) const
// If we need more bytes than length of BigNumber set the rest to 0 // If we need more bytes than length of BigNumber set the rest to 0
if (numBytes < bufsize) if (numBytes < bufsize)
{
memset((void*)buf, 0, bufsize); memset((void*)buf, 0, bufsize);
}
BN_bn2bin(_bn, buf + (bufsize - numBytes)); BN_bn2bin(_bn, buf + (bufsize - numBytes));
// openssl's BN stores data internally in big endian format, reverse if little endian desired // openssl's BN stores data internally in big endian format, reverse if little endian desired
if (littleEndian) if (littleEndian)
{
std::reverse(buf, buf + bufsize); std::reverse(buf, buf + bufsize);
}
#else #else
int res = littleEndian ? BN_bn2lebinpad(_bn, buf, bufsize) : BN_bn2binpad(_bn, buf, bufsize); int res = littleEndian ? BN_bn2lebinpad(_bn, buf, bufsize) : BN_bn2binpad(_bn, buf, bufsize);
ASSERT(res > 0, "Buffer of size %zu is too small to hold bignum with %d bytes.\n", bufsize, BN_num_bytes(_bn)); ASSERT(res > 0, "Buffer of size %zu is too small to hold bignum with %d bytes.\n", bufsize, BN_num_bytes(_bn));

View File

@@ -34,67 +34,69 @@ namespace Acore::Impl
template <GenericHashImpl::HashCreator HashCreator, size_t DigestLength> template <GenericHashImpl::HashCreator HashCreator, size_t DigestLength>
class GenericHash class GenericHash
{ {
public: public:
static constexpr size_t DIGEST_LENGTH = DigestLength; static constexpr size_t DIGEST_LENGTH = DigestLength;
using Digest = std::array<uint8, DIGEST_LENGTH>; using Digest = std::array<uint8, DIGEST_LENGTH>;
static Digest GetDigestOf(uint8 const* data, size_t len) static Digest GetDigestOf(uint8 const* data, size_t len)
{
GenericHash hash;
hash.UpdateData(data, len);
hash.Finalize();
return hash.GetDigest();
}
template <typename... Ts>
static auto GetDigestOf(Ts&& ... pack) -> std::enable_if_t < !(std::is_integral_v<std::decay_t<Ts>> || ...), Digest >
{
GenericHash hash;
(hash.UpdateData(std::forward<Ts>(pack)), ...);
hash.Finalize();
return hash.GetDigest();
}
GenericHash() : _ctx(GenericHashImpl::MakeCTX())
{
int result = EVP_DigestInit_ex(_ctx, HashCreator(), nullptr);
ASSERT(result == 1);
}
~GenericHash()
{
if (!_ctx)
{ {
GenericHash hash; return;
hash.UpdateData(data, len);
hash.Finalize();
return hash.GetDigest();
} }
GenericHashImpl::DestroyCTX(_ctx);
_ctx = nullptr;
}
template <typename... Ts> void UpdateData(uint8 const* data, size_t len)
static auto GetDigestOf(Ts&&... pack) -> std::enable_if_t<!(std::is_integral_v<std::decay_t<Ts>> || ...), Digest> {
{ int result = EVP_DigestUpdate(_ctx, data, len);
GenericHash hash; ASSERT(result == 1);
(hash.UpdateData(std::forward<Ts>(pack)), ...); }
hash.Finalize(); void UpdateData(std::string_view str) { UpdateData(reinterpret_cast<uint8 const*>(str.data()), str.size()); }
return hash.GetDigest(); void UpdateData(std::string const& str) { UpdateData(std::string_view(str)); } /* explicit overload to avoid using the container template */
} void UpdateData(char const* str) { UpdateData(std::string_view(str)); } /* explicit overload to avoid using the container template */
template <typename Container>
void UpdateData(Container const& c) { UpdateData(std::data(c), std::size(c)); }
GenericHash() : _ctx(GenericHashImpl::MakeCTX()) void Finalize()
{ {
int result = EVP_DigestInit_ex(_ctx, HashCreator(), nullptr); uint32 length;
ASSERT(result == 1); int result = EVP_DigestFinal_ex(_ctx, _digest.data(), &length);
} ASSERT(result == 1);
ASSERT(length == DIGEST_LENGTH);
GenericHashImpl::DestroyCTX(_ctx);
_ctx = nullptr;
}
~GenericHash() Digest const& GetDigest() const { return _digest; }
{
if (!_ctx)
return;
GenericHashImpl::DestroyCTX(_ctx);
_ctx = nullptr;
}
void UpdateData(uint8 const* data, size_t len) private:
{ EVP_MD_CTX* _ctx;
int result = EVP_DigestUpdate(_ctx, data, len); Digest _digest = { };
ASSERT(result == 1);
}
void UpdateData(std::string_view str) { UpdateData(reinterpret_cast<uint8 const*>(str.data()), str.size()); }
void UpdateData(std::string const& str) { UpdateData(std::string_view(str)); } /* explicit overload to avoid using the container template */
void UpdateData(char const* str) { UpdateData(std::string_view(str)); } /* explicit overload to avoid using the container template */
template <typename Container>
void UpdateData(Container const& c) { UpdateData(std::data(c), std::size(c)); }
void Finalize()
{
uint32 length;
int result = EVP_DigestFinal_ex(_ctx, _digest.data(), &length);
ASSERT(result == 1);
ASSERT(length == DIGEST_LENGTH);
GenericHashImpl::DestroyCTX(_ctx);
_ctx = nullptr;
}
Digest const& GetDigest() const { return _digest; }
private:
EVP_MD_CTX* _ctx;
Digest _digest = { };
}; };
} }

View File

@@ -44,69 +44,70 @@ namespace Acore::Impl
template <HMACImpl::HashCreator HashCreator, size_t DigestLength> template <HMACImpl::HashCreator HashCreator, size_t DigestLength>
class GenericHMAC class GenericHMAC
{ {
public: public:
static constexpr size_t DIGEST_LENGTH = DigestLength; static constexpr size_t DIGEST_LENGTH = DigestLength;
using Digest = std::array<uint8, DIGEST_LENGTH>; using Digest = std::array<uint8, DIGEST_LENGTH>;
template <typename Container> template <typename Container>
static Digest GetDigestOf(Container const& seed, uint8 const* data, size_t len) static Digest GetDigestOf(Container const& seed, uint8 const* data, size_t len)
{
GenericHMAC hash(seed);
hash.UpdateData(data, len);
hash.Finalize();
return hash.GetDigest();
}
template <typename Container, typename... Ts>
static auto GetDigestOf(Container const& seed, Ts&& ... pack) -> std::enable_if_t < !(std::is_integral_v<std::decay_t<Ts>> || ...), Digest >
{
GenericHMAC hash(seed);
(hash.UpdateData(std::forward<Ts>(pack)), ...);
hash.Finalize();
return hash.GetDigest();
}
GenericHMAC(uint8 const* seed, size_t len) : _ctx(HMACImpl::MakeCTX())
{
int result = HMAC_Init_ex(_ctx, seed, len, HashCreator(), nullptr);
ASSERT(result == 1);
}
template <typename Container> GenericHMAC(Container const& container) : GenericHMAC(std::data(container), std::size(container)) {}
~GenericHMAC()
{
if (!_ctx)
{ {
GenericHMAC hash(seed); return;
hash.UpdateData(data, len);
hash.Finalize();
return hash.GetDigest();
} }
HMACImpl::DestroyCTX(_ctx);
_ctx = nullptr;
}
template <typename Container, typename... Ts> void UpdateData(uint8 const* data, size_t len)
static auto GetDigestOf(Container const& seed, Ts&&... pack) -> std::enable_if_t<!(std::is_integral_v<std::decay_t<Ts>> || ...), Digest> {
{ int result = HMAC_Update(_ctx, data, len);
GenericHMAC hash(seed); ASSERT(result == 1);
(hash.UpdateData(std::forward<Ts>(pack)), ...); }
hash.Finalize(); void UpdateData(std::string_view str) { UpdateData(reinterpret_cast<uint8 const*>(str.data()), str.size()); }
return hash.GetDigest(); void UpdateData(std::string const& str) { UpdateData(std::string_view(str)); } /* explicit overload to avoid using the container template */
} void UpdateData(char const* str) { UpdateData(std::string_view(str)); } /* explicit overload to avoid using the container template */
template <typename Container>
void UpdateData(Container const& c) { UpdateData(std::data(c), std::size(c)); }
GenericHMAC(uint8 const* seed, size_t len) : _ctx(HMACImpl::MakeCTX()) void Finalize()
{ {
int result = HMAC_Init_ex(_ctx, seed, len, HashCreator(), nullptr); uint32 length = 0;
ASSERT(result == 1); int result = HMAC_Final(_ctx, _digest.data(), &length);
} ASSERT(result == 1);
template <typename Container> ASSERT(length == DIGEST_LENGTH);
GenericHMAC(Container const& container) : GenericHMAC(std::data(container), std::size(container)) {} HMACImpl::DestroyCTX(_ctx);
_ctx = nullptr;
}
~GenericHMAC() Digest const& GetDigest() const { return _digest; }
{ private:
if (!_ctx) HMAC_CTX* _ctx;
return; Digest _digest = { };
HMACImpl::DestroyCTX(_ctx);
_ctx = nullptr;
}
void UpdateData(uint8 const* data, size_t len)
{
int result = HMAC_Update(_ctx, data, len);
ASSERT(result == 1);
}
void UpdateData(std::string_view str) { UpdateData(reinterpret_cast<uint8 const*>(str.data()), str.size()); }
void UpdateData(std::string const& str) { UpdateData(std::string_view(str)); } /* explicit overload to avoid using the container template */
void UpdateData(char const* str) { UpdateData(std::string_view(str)); } /* explicit overload to avoid using the container template */
template <typename Container>
void UpdateData(Container const& c) { UpdateData(std::data(c), std::size(c)); }
void Finalize()
{
uint32 length = 0;
int result = HMAC_Final(_ctx, _digest.data(), &length);
ASSERT(result == 1);
ASSERT(length == DIGEST_LENGTH);
HMACImpl::DestroyCTX(_ctx);
_ctx = nullptr;
}
Digest const& GetDigest() const { return _digest; }
private:
HMAC_CTX* _ctx;
Digest _digest = { };
}; };
} }

View File

@@ -15,9 +15,13 @@ std::vector<std::mutex*> cryptoLocks;
static void lockingCallback(int mode, int type, char const* /*file*/, int /*line*/) static void lockingCallback(int mode, int type, char const* /*file*/, int /*line*/)
{ {
if (mode & CRYPTO_LOCK) if (mode & CRYPTO_LOCK)
{
cryptoLocks[type]->lock(); cryptoLocks[type]->lock();
}
else else
{
cryptoLocks[type]->unlock(); cryptoLocks[type]->unlock();
}
} }
static void threadIdCallback(CRYPTO_THREADID* id) static void threadIdCallback(CRYPTO_THREADID* id)
{ {

View File

@@ -12,39 +12,38 @@
template <typename Hash> template <typename Hash>
class SessionKeyGenerator class SessionKeyGenerator
{ {
public: public:
template <typename C> template <typename C> SessionKeyGenerator(C const& buf) :
SessionKeyGenerator(C const& buf) : o0it(o0.begin())
o0it(o0.begin()) {
{ uint8 const* data = std::data(buf);
uint8 const* data = std::data(buf); size_t const len = std::size(buf);
size_t const len = std::size(buf); size_t const halflen = (len / 2);
size_t const halflen = (len / 2);
o1 = Hash::GetDigestOf(data, halflen); o1 = Hash::GetDigestOf(data, halflen);
o2 = Hash::GetDigestOf(data + halflen, len - halflen); o2 = Hash::GetDigestOf(data + halflen, len - halflen);
o0 = Hash::GetDigestOf(o1, o0, o2); o0 = Hash::GetDigestOf(o1, o0, o2);
} }
void Generate(uint8* buf, uint32 sz) void Generate(uint8* buf, uint32 sz)
{
for (uint32 i = 0; i < sz; ++i)
{ {
for (uint32 i = 0; i < sz; ++i) if (o0it == o0.end())
{ {
if (o0it == o0.end()) o0 = Hash::GetDigestOf(o1, o0, o2);
{ o0it = o0.begin();
o0 = Hash::GetDigestOf(o1, o0, o2);
o0it = o0.begin();
}
buf[i] = *(o0it++);
} }
}
private: buf[i] = *(o0it++);
typename Hash::Digest o0 = { }; }
typename Hash::Digest o1 = { }; }
typename Hash::Digest o2 = { };
typename Hash::Digest::const_iterator o0it; private:
}; typename Hash::Digest o0 = { };
typename Hash::Digest o1 = { };
typename Hash::Digest o2 = { };
typename Hash::Digest::const_iterator o0it;
};
#endif #endif

View File

@@ -18,7 +18,9 @@ static constexpr uint32 HMAC_RESULT_SIZE = 20;
unsigned char challenge[8]; unsigned char challenge[8];
for (int i = 8; i--; timestamp >>= 8) for (int i = 8; i--; timestamp >>= 8)
{
challenge[i] = timestamp; challenge[i] = timestamp;
}
unsigned char digest[HMAC_RESULT_SIZE]; unsigned char digest[HMAC_RESULT_SIZE];
uint32 digestSize = HMAC_RESULT_SIZE; uint32 digestSize = HMAC_RESULT_SIZE;

View File

@@ -23,7 +23,9 @@ bool DBCFileLoader::Load(char const* filename, char const* fmt)
FILE* f = fopen(filename, "rb"); FILE* f = fopen(filename, "rb");
if (!f) if (!f)
{
return false; return false;
}
if (fread(&header, 4, 1, f) != 1) // Number of records if (fread(&header, 4, 1, f) != 1) // Number of records
{ {
@@ -78,9 +80,13 @@ bool DBCFileLoader::Load(char const* filename, char const* fmt)
{ {
fieldsOffset[i] = fieldsOffset[i - 1]; fieldsOffset[i] = fieldsOffset[i - 1];
if (fmt[i - 1] == 'b' || fmt[i - 1] == 'X') // byte fields if (fmt[i - 1] == 'b' || fmt[i - 1] == 'X') // byte fields
{
fieldsOffset[i] += sizeof(uint8); fieldsOffset[i] += sizeof(uint8);
}
else // 4 byte fields (int32/float/strings) else // 4 byte fields (int32/float/strings)
{
fieldsOffset[i] += sizeof(uint32); fieldsOffset[i] += sizeof(uint32);
}
} }
data = new unsigned char[recordSize * recordCount + stringSize]; data = new unsigned char[recordSize * recordCount + stringSize];
@@ -151,7 +157,9 @@ uint32 DBCFileLoader::GetFormatRecordSize(char const* format, int32* index_pos)
} }
if (index_pos) if (index_pos)
{
*index_pos = i; *index_pos = i;
}
return recordsize; return recordsize;
} }
@@ -171,7 +179,9 @@ char* DBCFileLoader::AutoProduceData(char const* format, uint32& records, char**
typedef char* ptr; typedef char* ptr;
if (strlen(format) != fieldCount) if (strlen(format) != fieldCount)
{
return nullptr; return nullptr;
}
//get struct size and index pos //get struct size and index pos
int32 i; int32 i;
@@ -185,7 +195,9 @@ char* DBCFileLoader::AutoProduceData(char const* format, uint32& records, char**
{ {
uint32 ind = getRecord(y).getUInt(i); uint32 ind = getRecord(y).getUInt(i);
if (ind > maxi) if (ind > maxi)
{
maxi = ind; maxi = ind;
}
} }
++maxi; ++maxi;
@@ -206,9 +218,13 @@ char* DBCFileLoader::AutoProduceData(char const* format, uint32& records, char**
for (uint32 y = 0; y < recordCount; ++y) for (uint32 y = 0; y < recordCount; ++y)
{ {
if (i >= 0) if (i >= 0)
{
indexTable[getRecord(y).getUInt(i)] = &dataTable[offset]; indexTable[getRecord(y).getUInt(i)] = &dataTable[offset];
}
else else
{
indexTable[y] = &dataTable[offset]; indexTable[y] = &dataTable[offset];
}
for (uint32 x = 0; x < fieldCount; ++x) for (uint32 x = 0; x < fieldCount; ++x)
{ {
@@ -251,7 +267,9 @@ char* DBCFileLoader::AutoProduceData(char const* format, uint32& records, char**
char* DBCFileLoader::AutoProduceStrings(char const* format, char* dataTable) char* DBCFileLoader::AutoProduceStrings(char const* format, char* dataTable)
{ {
if (strlen(format) != fieldCount) if (strlen(format) != fieldCount)
{
return nullptr; return nullptr;
}
char* stringPool = new char[stringSize]; char* stringPool = new char[stringSize];
memcpy(stringPool, stringTable, stringSize); memcpy(stringPool, stringTable, stringSize);

View File

@@ -41,7 +41,9 @@ inline LPTSTR ErrorMessage(DWORD dw)
(LPTSTR) &lpMsgBuf, (LPTSTR) &lpMsgBuf,
0, nullptr); 0, nullptr);
if (formatResult != 0) if (formatResult != 0)
{
return (LPTSTR)lpMsgBuf; return (LPTSTR)lpMsgBuf;
}
else else
{ {
LPTSTR msgBuf = (LPTSTR)LocalAlloc(LPTR, 30); LPTSTR msgBuf = (LPTSTR)LocalAlloc(LPTR, 30);
@@ -98,9 +100,13 @@ WheatyExceptionReport::WheatyExceptionReport() // Constructor
WheatyExceptionReport::~WheatyExceptionReport() WheatyExceptionReport::~WheatyExceptionReport()
{ {
if (m_previousFilter) if (m_previousFilter)
{
SetUnhandledExceptionFilter(m_previousFilter); SetUnhandledExceptionFilter(m_previousFilter);
}
if (m_previousCrtHandler) if (m_previousCrtHandler)
{
_set_invalid_parameter_handler(m_previousCrtHandler); _set_invalid_parameter_handler(m_previousCrtHandler);
}
ClearSymbols(); ClearSymbols();
} }
@@ -113,18 +119,24 @@ LONG WINAPI WheatyExceptionReport::WheatyUnhandledExceptionFilter(
std::unique_lock<std::mutex> guard(alreadyCrashedLock); std::unique_lock<std::mutex> guard(alreadyCrashedLock);
// Handle only 1 exception in the whole process lifetime // Handle only 1 exception in the whole process lifetime
if (alreadyCrashed) if (alreadyCrashed)
{
return EXCEPTION_EXECUTE_HANDLER; return EXCEPTION_EXECUTE_HANDLER;
}
alreadyCrashed = true; alreadyCrashed = true;
if (pExceptionInfo->ExceptionRecord->ExceptionCode == STATUS_STACK_OVERFLOW) if (pExceptionInfo->ExceptionRecord->ExceptionCode == STATUS_STACK_OVERFLOW)
{
stackOverflowException = true; stackOverflowException = true;
}
TCHAR module_folder_name[MAX_PATH]; TCHAR module_folder_name[MAX_PATH];
GetModuleFileName(0, module_folder_name, MAX_PATH); GetModuleFileName(0, module_folder_name, MAX_PATH);
TCHAR* pos = _tcsrchr(module_folder_name, '\\'); TCHAR* pos = _tcsrchr(module_folder_name, '\\');
if (!pos) if (!pos)
{
return 0; return 0;
}
pos[0] = '\0'; pos[0] = '\0';
++pos; ++pos;
@@ -133,7 +145,9 @@ LONG WINAPI WheatyExceptionReport::WheatyUnhandledExceptionFilter(
if (!CreateDirectory(crash_folder_path, nullptr)) if (!CreateDirectory(crash_folder_path, nullptr))
{ {
if (GetLastError() != ERROR_ALREADY_EXISTS) if (GetLastError() != ERROR_ALREADY_EXISTS)
{
return 0; return 0;
}
} }
SYSTEMTIME systime; SYSTEMTIME systime;
@@ -197,9 +211,13 @@ LONG WINAPI WheatyExceptionReport::WheatyUnhandledExceptionFilter(
} }
if (m_previousFilter) if (m_previousFilter)
{
return m_previousFilter(pExceptionInfo); return m_previousFilter(pExceptionInfo);
}
else else
{
return EXCEPTION_EXECUTE_HANDLER/*EXCEPTION_CONTINUE_SEARCH*/; return EXCEPTION_EXECUTE_HANDLER/*EXCEPTION_CONTINUE_SEARCH*/;
}
} }
void __cdecl WheatyExceptionReport::WheatyCrtHandler(wchar_t const* /*expression*/, wchar_t const* /*function*/, wchar_t const* /*file*/, unsigned int /*line*/, uintptr_t /*pReserved*/) void __cdecl WheatyExceptionReport::WheatyCrtHandler(wchar_t const* /*expression*/, wchar_t const* /*function*/, wchar_t const* /*file*/, unsigned int /*line*/, uintptr_t /*pReserved*/)
@@ -210,26 +228,34 @@ void __cdecl WheatyExceptionReport::WheatyCrtHandler(wchar_t const* /*expression
BOOL WheatyExceptionReport::_GetProcessorName(TCHAR* sProcessorName, DWORD maxcount) BOOL WheatyExceptionReport::_GetProcessorName(TCHAR* sProcessorName, DWORD maxcount)
{ {
if (!sProcessorName) if (!sProcessorName)
{
return FALSE; return FALSE;
}
HKEY hKey; HKEY hKey;
LONG lRet; LONG lRet;
lRet = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0"), lRet = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0"),
0, KEY_QUERY_VALUE, &hKey); 0, KEY_QUERY_VALUE, &hKey);
if (lRet != ERROR_SUCCESS) if (lRet != ERROR_SUCCESS)
{
return FALSE; return FALSE;
}
TCHAR szTmp[2048]; TCHAR szTmp[2048];
DWORD cntBytes = sizeof(szTmp); DWORD cntBytes = sizeof(szTmp);
lRet = ::RegQueryValueEx(hKey, _T("ProcessorNameString"), nullptr, nullptr, lRet = ::RegQueryValueEx(hKey, _T("ProcessorNameString"), nullptr, nullptr,
(LPBYTE)szTmp, &cntBytes); (LPBYTE)szTmp, &cntBytes);
if (lRet != ERROR_SUCCESS) if (lRet != ERROR_SUCCESS)
{
return FALSE; return FALSE;
}
::RegCloseKey(hKey); ::RegCloseKey(hKey);
sProcessorName[0] = '\0'; sProcessorName[0] = '\0';
// Skip spaces // Skip spaces
TCHAR* psz = szTmp; TCHAR* psz = szTmp;
while (iswspace(*psz)) while (iswspace(*psz))
{
++psz; ++psz;
}
_tcsncpy(sProcessorName, psz, maxcount); _tcsncpy(sProcessorName, psz, maxcount);
return TRUE; return TRUE;
} }
@@ -257,7 +283,9 @@ BOOL WheatyExceptionReport::_GetWindowsVersion(TCHAR* szVersion, DWORD cntMax)
{ {
osvi.dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOW); osvi.dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOW);
if (!RtlGetVersion((PRTL_OSVERSIONINFOW)&osvi)) if (!RtlGetVersion((PRTL_OSVERSIONINFOW)&osvi))
{
return FALSE; return FALSE;
}
} }
*szVersion = _T('\0'); *szVersion = _T('\0');
@@ -282,40 +310,68 @@ BOOL WheatyExceptionReport::_GetWindowsVersion(TCHAR* szVersion, DWORD cntMax)
if (osvi.dwMajorVersion == 10) if (osvi.dwMajorVersion == 10)
{ {
if (productType == VER_NT_WORKSTATION) if (productType == VER_NT_WORKSTATION)
{
_tcsncat(szVersion, _T("Windows 10 "), cntMax); _tcsncat(szVersion, _T("Windows 10 "), cntMax);
}
else else
{
_tcsncat(szVersion, _T("Windows Server 2016 "), cntMax); _tcsncat(szVersion, _T("Windows Server 2016 "), cntMax);
}
} }
else if (osvi.dwMajorVersion == 6) else if (osvi.dwMajorVersion == 6)
{ {
if (productType == VER_NT_WORKSTATION) if (productType == VER_NT_WORKSTATION)
{ {
if (osvi.dwMinorVersion == 3) if (osvi.dwMinorVersion == 3)
{
_tcsncat(szVersion, _T("Windows 8.1 "), cntMax); _tcsncat(szVersion, _T("Windows 8.1 "), cntMax);
}
else if (osvi.dwMinorVersion == 2) else if (osvi.dwMinorVersion == 2)
{
_tcsncat(szVersion, _T("Windows 8 "), cntMax); _tcsncat(szVersion, _T("Windows 8 "), cntMax);
}
else if (osvi.dwMinorVersion == 1) else if (osvi.dwMinorVersion == 1)
{
_tcsncat(szVersion, _T("Windows 7 "), cntMax); _tcsncat(szVersion, _T("Windows 7 "), cntMax);
}
else else
{
_tcsncat(szVersion, _T("Windows Vista "), cntMax); _tcsncat(szVersion, _T("Windows Vista "), cntMax);
}
} }
else if (osvi.dwMinorVersion == 3) else if (osvi.dwMinorVersion == 3)
{
_tcsncat(szVersion, _T("Windows Server 2012 R2 "), cntMax); _tcsncat(szVersion, _T("Windows Server 2012 R2 "), cntMax);
}
else if (osvi.dwMinorVersion == 2) else if (osvi.dwMinorVersion == 2)
{
_tcsncat(szVersion, _T("Windows Server 2012 "), cntMax); _tcsncat(szVersion, _T("Windows Server 2012 "), cntMax);
}
else if (osvi.dwMinorVersion == 1) else if (osvi.dwMinorVersion == 1)
{
_tcsncat(szVersion, _T("Windows Server 2008 R2 "), cntMax); _tcsncat(szVersion, _T("Windows Server 2008 R2 "), cntMax);
}
else else
{
_tcsncat(szVersion, _T("Windows Server 2008 "), cntMax); _tcsncat(szVersion, _T("Windows Server 2008 "), cntMax);
}
} }
else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2) else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2)
{
_tcsncat(szVersion, _T("Microsoft Windows Server 2003 "), cntMax); _tcsncat(szVersion, _T("Microsoft Windows Server 2003 "), cntMax);
}
else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1) else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1)
{
_tcsncat(szVersion, _T("Microsoft Windows XP "), cntMax); _tcsncat(szVersion, _T("Microsoft Windows XP "), cntMax);
}
else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0) else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0)
{
_tcsncat(szVersion, _T("Microsoft Windows 2000 "), cntMax); _tcsncat(szVersion, _T("Microsoft Windows 2000 "), cntMax);
}
else if (osvi.dwMajorVersion <= 4) else if (osvi.dwMajorVersion <= 4)
{
_tcsncat(szVersion, _T("Microsoft Windows NT "), cntMax); _tcsncat(szVersion, _T("Microsoft Windows NT "), cntMax);
}
// Test for specific product on Windows NT 4.0 SP6 and later. // Test for specific product on Windows NT 4.0 SP6 and later.
if (bVersionEx >= 0) if (bVersionEx >= 0)
@@ -324,13 +380,21 @@ BOOL WheatyExceptionReport::_GetWindowsVersion(TCHAR* szVersion, DWORD cntMax)
if (productType == VER_NT_WORKSTATION) if (productType == VER_NT_WORKSTATION)
{ {
if (osvi.dwMajorVersion == 4) if (osvi.dwMajorVersion == 4)
{
_tcsncat(szVersion, _T("Workstation 4.0 "), cntMax); _tcsncat(szVersion, _T("Workstation 4.0 "), cntMax);
}
else if (suiteMask & VER_SUITE_PERSONAL) else if (suiteMask & VER_SUITE_PERSONAL)
{
_tcsncat(szVersion, _T("Home Edition "), cntMax); _tcsncat(szVersion, _T("Home Edition "), cntMax);
}
else if (suiteMask & VER_SUITE_EMBEDDEDNT) else if (suiteMask & VER_SUITE_EMBEDDEDNT)
{
_tcsncat(szVersion, _T("Embedded "), cntMax); _tcsncat(szVersion, _T("Embedded "), cntMax);
}
else else
{
_tcsncat(szVersion, _T("Professional "), cntMax); _tcsncat(szVersion, _T("Professional "), cntMax);
}
} }
// Test for the server type. // Test for the server type.
else if (productType == VER_NT_SERVER) else if (productType == VER_NT_SERVER)
@@ -338,40 +402,66 @@ BOOL WheatyExceptionReport::_GetWindowsVersion(TCHAR* szVersion, DWORD cntMax)
if (osvi.dwMajorVersion == 6 || osvi.dwMajorVersion == 10) if (osvi.dwMajorVersion == 6 || osvi.dwMajorVersion == 10)
{ {
if (suiteMask & VER_SUITE_SMALLBUSINESS_RESTRICTED) if (suiteMask & VER_SUITE_SMALLBUSINESS_RESTRICTED)
{
_tcsncat(szVersion, _T("Essentials "), cntMax); _tcsncat(szVersion, _T("Essentials "), cntMax);
}
else if (suiteMask & VER_SUITE_DATACENTER) else if (suiteMask & VER_SUITE_DATACENTER)
{
_tcsncat(szVersion, _T("Datacenter "), cntMax); _tcsncat(szVersion, _T("Datacenter "), cntMax);
}
else if (suiteMask & VER_SUITE_ENTERPRISE) else if (suiteMask & VER_SUITE_ENTERPRISE)
{
_tcsncat(szVersion, _T("Enterprise "), cntMax); _tcsncat(szVersion, _T("Enterprise "), cntMax);
}
else else
{
_tcsncat(szVersion, _T("Standard "), cntMax); _tcsncat(szVersion, _T("Standard "), cntMax);
}
} }
else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2) else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2)
{ {
if (suiteMask & VER_SUITE_DATACENTER) if (suiteMask & VER_SUITE_DATACENTER)
{
_tcsncat(szVersion, _T("Datacenter Edition "), cntMax); _tcsncat(szVersion, _T("Datacenter Edition "), cntMax);
}
else if (suiteMask & VER_SUITE_ENTERPRISE) else if (suiteMask & VER_SUITE_ENTERPRISE)
{
_tcsncat(szVersion, _T("Enterprise Edition "), cntMax); _tcsncat(szVersion, _T("Enterprise Edition "), cntMax);
}
else if (suiteMask == VER_SUITE_BLADE) else if (suiteMask == VER_SUITE_BLADE)
{
_tcsncat(szVersion, _T("Web Edition "), cntMax); _tcsncat(szVersion, _T("Web Edition "), cntMax);
}
else else
{
_tcsncat(szVersion, _T("Standard Edition "), cntMax); _tcsncat(szVersion, _T("Standard Edition "), cntMax);
}
} }
else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0) else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0)
{ {
if (suiteMask & VER_SUITE_DATACENTER) if (suiteMask & VER_SUITE_DATACENTER)
{
_tcsncat(szVersion, _T("Datacenter Server "), cntMax); _tcsncat(szVersion, _T("Datacenter Server "), cntMax);
}
else if (suiteMask & VER_SUITE_ENTERPRISE) else if (suiteMask & VER_SUITE_ENTERPRISE)
{
_tcsncat(szVersion, _T("Advanced Server "), cntMax); _tcsncat(szVersion, _T("Advanced Server "), cntMax);
}
else else
{
_tcsncat(szVersion, _T("Server "), cntMax); _tcsncat(szVersion, _T("Server "), cntMax);
}
} }
else // Windows NT 4.0 else // Windows NT 4.0
{ {
if (suiteMask & VER_SUITE_ENTERPRISE) if (suiteMask & VER_SUITE_ENTERPRISE)
{
_tcsncat(szVersion, _T("Server 4.0, Enterprise Edition "), cntMax); _tcsncat(szVersion, _T("Server 4.0, Enterprise Edition "), cntMax);
}
else else
{
_tcsncat(szVersion, _T("Server 4.0 "), cntMax); _tcsncat(szVersion, _T("Server 4.0 "), cntMax);
}
} }
} }
} }
@@ -438,9 +528,13 @@ void WheatyExceptionReport::PrintSystemInfo()
SystemInfo.dwNumberOfProcessors, MemoryStatus.dwTotalPhys / 0x400, MemoryStatus.dwAvailPhys / 0x400, MemoryStatus.dwTotalPageFile / 0x400); SystemInfo.dwNumberOfProcessors, MemoryStatus.dwTotalPhys / 0x400, MemoryStatus.dwAvailPhys / 0x400, MemoryStatus.dwTotalPageFile / 0x400);
if (_GetWindowsVersion(sString, countof(sString))) if (_GetWindowsVersion(sString, countof(sString)))
{
Log(_T("\r\n*** Operation System ***\r\n%s\r\n"), sString); Log(_T("\r\n*** Operation System ***\r\n%s\r\n"), sString);
}
else else
{
Log(_T("\r\n*** Operation System:\r\n<unknown>\r\n")); Log(_T("\r\n*** Operation System:\r\n<unknown>\r\n"));
}
} }
//=========================================================================== //===========================================================================
@@ -453,7 +547,9 @@ void WheatyExceptionReport::printTracesForAllThreads(bool bWriteVariables)
// Take a snapshot of all running threads // Take a snapshot of all running threads
HANDLE hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); HANDLE hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
if (hThreadSnap == INVALID_HANDLE_VALUE) if (hThreadSnap == INVALID_HANDLE_VALUE)
{
return; return;
}
// Fill in the size of the structure before using it. // Fill in the size of the structure before using it.
te32.dwSize = sizeof(THREADENTRY32); te32.dwSize = sizeof(THREADENTRY32);
@@ -480,7 +576,9 @@ void WheatyExceptionReport::printTracesForAllThreads(bool bWriteVariables)
if (threadHandle) if (threadHandle)
{ {
if (GetThreadContext(threadHandle, &context)) if (GetThreadContext(threadHandle, &context))
{
WriteStackDetails(&context, bWriteVariables, threadHandle); WriteStackDetails(&context, bWriteVariables, threadHandle);
}
CloseHandle(threadHandle); CloseHandle(threadHandle);
} }
} }
@@ -663,15 +761,21 @@ BOOL WheatyExceptionReport::GetLogicalAddress(
MEMORY_BASIC_INFORMATION mbi; MEMORY_BASIC_INFORMATION mbi;
if (!VirtualQuery(addr, &mbi, sizeof(mbi))) if (!VirtualQuery(addr, &mbi, sizeof(mbi)))
{
return FALSE; return FALSE;
}
DWORD_PTR hMod = (DWORD_PTR)mbi.AllocationBase; DWORD_PTR hMod = (DWORD_PTR)mbi.AllocationBase;
if (!hMod) if (!hMod)
{
return FALSE; return FALSE;
}
if (!GetModuleFileName((HMODULE)hMod, szModule, len)) if (!GetModuleFileName((HMODULE)hMod, szModule, len))
{
return FALSE; return FALSE;
}
// Point to the DOS header in memory // Point to the DOS header in memory
PIMAGE_DOS_HEADER pDosHdr = (PIMAGE_DOS_HEADER)hMod; PIMAGE_DOS_HEADER pDosHdr = (PIMAGE_DOS_HEADER)hMod;
@@ -771,9 +875,13 @@ void WheatyExceptionReport::WriteStackDetails(
SymFunctionTableAccess64, SymFunctionTableAccess64,
SymGetModuleBase64, SymGetModuleBase64,
0)) 0))
{
break; break;
}
if (0 == sf.AddrFrame.Offset) // Basic sanity check to make sure if (0 == sf.AddrFrame.Offset) // Basic sanity check to make sure
break; // the frame is OK. Bail if not. {
break; // the frame is OK. Bail if not.
}
#ifdef _M_IX86 #ifdef _M_IX86
Log(_T("%08X %08X "), sf.AddrPC.Offset, sf.AddrFrame.Offset); Log(_T("%08X %08X "), sf.AddrPC.Offset, sf.AddrFrame.Offset);
#endif #endif
@@ -870,7 +978,9 @@ bool WheatyExceptionReport::FormatSymbolValue(
{ {
// If it's a function, don't do anything. // If it's a function, don't do anything.
if (pSym->Tag == SymTagFunction) // SymTagFunction from CVCONST.H from the DIA SDK if (pSym->Tag == SymTagFunction) // SymTagFunction from CVCONST.H from the DIA SDK
{
return false; return false;
}
DWORD_PTR pVariable = 0; // Will point to the variable's data in memory DWORD_PTR pVariable = 0; // Will point to the variable's data in memory
@@ -890,7 +1000,9 @@ bool WheatyExceptionReport::FormatSymbolValue(
// return false; // return false;
} }
else if (pSym->Flags & IMAGEHLP_SYMBOL_INFO_REGISTER) else if (pSym->Flags & IMAGEHLP_SYMBOL_INFO_REGISTER)
return false; // Don't try to report register variable {
return false; // Don't try to report register variable
}
else else
{ {
pVariable = (DWORD_PTR)pSym->Address; // It must be a global variable pVariable = (DWORD_PTR)pSym->Address; // It must be a global variable
@@ -900,9 +1012,13 @@ bool WheatyExceptionReport::FormatSymbolValue(
// Indicate if the variable is a local or parameter // Indicate if the variable is a local or parameter
if (pSym->Flags & IMAGEHLP_SYMBOL_INFO_PARAMETER) if (pSym->Flags & IMAGEHLP_SYMBOL_INFO_PARAMETER)
{
symbolDetails.top().Prefix = "Parameter "; symbolDetails.top().Prefix = "Parameter ";
}
else if (pSym->Flags & IMAGEHLP_SYMBOL_INFO_LOCAL) else if (pSym->Flags & IMAGEHLP_SYMBOL_INFO_LOCAL)
{
symbolDetails.top().Prefix = "Local "; symbolDetails.top().Prefix = "Local ";
}
// Determine if the variable is a user defined type (UDT). IF so, bHandled // Determine if the variable is a user defined type (UDT). IF so, bHandled
// will return true. // will return true.
@@ -916,11 +1032,15 @@ bool WheatyExceptionReport::FormatSymbolValue(
// DWORD. // DWORD.
BasicType basicType = GetBasicType(pSym->TypeIndex, pSym->ModBase); BasicType basicType = GetBasicType(pSym->TypeIndex, pSym->ModBase);
if (symbolDetails.top().Type.empty()) if (symbolDetails.top().Type.empty())
{
symbolDetails.top().Type = rgBaseType[basicType]; symbolDetails.top().Type = rgBaseType[basicType];
}
// Emit the variable name // Emit the variable name
if (pSym->Name[0] != '\0') if (pSym->Name[0] != '\0')
{
symbolDetails.top().Name = pSym->Name; symbolDetails.top().Name = pSym->Name;
}
char buffer[50]; char buffer[50];
FormatOutputValue(buffer, basicType, pSym->Size, (PVOID)pVariable, sizeof(buffer)); FormatOutputValue(buffer, basicType, pSym->Size, (PVOID)pVariable, sizeof(buffer));
@@ -949,11 +1069,15 @@ void WheatyExceptionReport::DumpTypeIndex(
bHandled = false; bHandled = false;
if (newSymbol) if (newSymbol)
{
PushSymbolDetail(); PushSymbolDetail();
}
DWORD typeTag; DWORD typeTag;
if (!SymGetTypeInfo(m_hProcess, modBase, dwTypeIndex, TI_GET_SYMTAG, &typeTag)) if (!SymGetTypeInfo(m_hProcess, modBase, dwTypeIndex, TI_GET_SYMTAG, &typeTag))
{
return; return;
}
// Get the name of the symbol. This will either be a Type name (if a UDT), // Get the name of the symbol. This will either be a Type name (if a UDT),
// or the structure member name. // or the structure member name.
@@ -970,7 +1094,9 @@ void WheatyExceptionReport::DumpTypeIndex(
FormatOutputValue(buffer, btStdString, 0, (PVOID)offset, sizeof(buffer)); FormatOutputValue(buffer, btStdString, 0, (PVOID)offset, sizeof(buffer));
symbolDetails.top().Value = buffer; symbolDetails.top().Value = buffer;
if (Name != nullptr && Name[0] != '\0') if (Name != nullptr && Name[0] != '\0')
{
symbolDetails.top().Name = Name; symbolDetails.top().Name = Name;
}
bHandled = true; bHandled = true;
return; return;
} }
@@ -984,18 +1110,24 @@ void WheatyExceptionReport::DumpTypeIndex(
symbolDetails.top().Name = Name; symbolDetails.top().Name = Name;
} }
else if (buffer[0] != '\0') else if (buffer[0] != '\0')
{
symbolDetails.top().Name = buffer; symbolDetails.top().Name = buffer;
}
LocalFree(pwszTypeName); LocalFree(pwszTypeName);
} }
else if (Name != nullptr && Name[0] != '\0') else if (Name != nullptr && Name[0] != '\0')
{
symbolDetails.top().Name = Name; symbolDetails.top().Name = Name;
}
if (!StoreSymbol(dwTypeIndex, offset)) if (!StoreSymbol(dwTypeIndex, offset))
{ {
// Skip printing address and base class if it has been printed already // Skip printing address and base class if it has been printed already
if (typeTag == SymTagBaseClass) if (typeTag == SymTagBaseClass)
{
bHandled = true; bHandled = true;
}
return; return;
} }
@@ -1006,7 +1138,9 @@ void WheatyExceptionReport::DumpTypeIndex(
if (SymGetTypeInfo(m_hProcess, modBase, dwTypeIndex, TI_GET_TYPEID, &innerTypeID)) if (SymGetTypeInfo(m_hProcess, modBase, dwTypeIndex, TI_GET_TYPEID, &innerTypeID))
{ {
if (Name != nullptr && Name[0] != '\0') if (Name != nullptr && Name[0] != '\0')
{
symbolDetails.top().Name = Name; symbolDetails.top().Name = Name;
}
BOOL isReference; BOOL isReference;
SymGetTypeInfo(m_hProcess, modBase, dwTypeIndex, TI_GET_IS_REFERENCE, &isReference); SymGetTypeInfo(m_hProcess, modBase, dwTypeIndex, TI_GET_IS_REFERENCE, &isReference);
@@ -1015,9 +1149,13 @@ void WheatyExceptionReport::DumpTypeIndex(
memset(addressStr, 0, sizeof(addressStr)); memset(addressStr, 0, sizeof(addressStr));
if (isReference) if (isReference)
{
symbolDetails.top().Suffix += "&"; symbolDetails.top().Suffix += "&";
}
else else
{
symbolDetails.top().Suffix += "*"; symbolDetails.top().Suffix += "*";
}
// Try to dereference the pointer in a try/except block since it might be invalid // Try to dereference the pointer in a try/except block since it might be invalid
DWORD_PTR address = DereferenceUnsafePointer(offset); DWORD_PTR address = DereferenceUnsafePointer(offset);
@@ -1027,11 +1165,15 @@ void WheatyExceptionReport::DumpTypeIndex(
symbolDetails.top().Value = buffer; symbolDetails.top().Value = buffer;
if (symbolDetails.size() >= WER_MAX_NESTING_LEVEL) if (symbolDetails.size() >= WER_MAX_NESTING_LEVEL)
{
logChildren = false; logChildren = false;
}
// no need to log any children since the address is invalid anyway // no need to log any children since the address is invalid anyway
if (address == NULL || address == DWORD_PTR(-1)) if (address == NULL || address == DWORD_PTR(-1))
{
logChildren = false; logChildren = false;
}
DumpTypeIndex(modBase, innerTypeID, address, bHandled, Name, addressStr, false, logChildren); DumpTypeIndex(modBase, innerTypeID, address, bHandled, Name, addressStr, false, logChildren);
@@ -1039,12 +1181,18 @@ void WheatyExceptionReport::DumpTypeIndex(
{ {
BasicType basicType = GetBasicType(dwTypeIndex, modBase); BasicType basicType = GetBasicType(dwTypeIndex, modBase);
if (symbolDetails.top().Type.empty()) if (symbolDetails.top().Type.empty())
{
symbolDetails.top().Type = rgBaseType[basicType]; symbolDetails.top().Type = rgBaseType[basicType];
}
if (address == NULL) if (address == NULL)
{
symbolDetails.top().Value = "NULL"; symbolDetails.top().Value = "NULL";
}
else if (address == DWORD_PTR(-1)) else if (address == DWORD_PTR(-1))
{
symbolDetails.top().Value = "<Unable to read memory>"; symbolDetails.top().Value = "<Unable to read memory>";
}
else else
{ {
// Get the size of the child member // Get the size of the child member
@@ -1058,7 +1206,9 @@ void WheatyExceptionReport::DumpTypeIndex(
return; return;
} }
else if (address == NULL) else if (address == NULL)
{
symbolDetails.top().Value = "NULL"; symbolDetails.top().Value = "NULL";
}
else if (address == DWORD_PTR(-1)) else if (address == DWORD_PTR(-1))
{ {
symbolDetails.top().Value = "<Unable to read memory>"; symbolDetails.top().Value = "<Unable to read memory>";
@@ -1072,19 +1222,25 @@ void WheatyExceptionReport::DumpTypeIndex(
{ {
DWORD innerTypeTag; DWORD innerTypeTag;
if (!SymGetTypeInfo(m_hProcess, modBase, innerTypeID, TI_GET_SYMTAG, &innerTypeTag)) if (!SymGetTypeInfo(m_hProcess, modBase, innerTypeID, TI_GET_SYMTAG, &innerTypeTag))
{
break; break;
}
switch (innerTypeTag) switch (innerTypeTag)
{ {
case SymTagUDT: case SymTagUDT:
if (symbolDetails.size() >= WER_MAX_NESTING_LEVEL) if (symbolDetails.size() >= WER_MAX_NESTING_LEVEL)
{
logChildren = false; logChildren = false;
}
DumpTypeIndex(modBase, innerTypeID, DumpTypeIndex(modBase, innerTypeID,
offset, bHandled, symbolDetails.top().Name.c_str(), "", false, logChildren); offset, bHandled, symbolDetails.top().Name.c_str(), "", false, logChildren);
break; break;
case SymTagPointerType: case SymTagPointerType:
if (Name != nullptr && Name[0] != '\0') if (Name != nullptr && Name[0] != '\0')
{
symbolDetails.top().Name = Name; symbolDetails.top().Name = Name;
}
DumpTypeIndex(modBase, innerTypeID, DumpTypeIndex(modBase, innerTypeID,
offset, bHandled, symbolDetails.top().Name.c_str(), "", false, logChildren); offset, bHandled, symbolDetails.top().Name.c_str(), "", false, logChildren);
break; break;
@@ -1112,15 +1268,21 @@ void WheatyExceptionReport::DumpTypeIndex(
DWORD elementsCount; DWORD elementsCount;
if (SymGetTypeInfo(m_hProcess, modBase, dwTypeIndex, TI_GET_COUNT, &elementsCount)) if (SymGetTypeInfo(m_hProcess, modBase, dwTypeIndex, TI_GET_COUNT, &elementsCount))
{
symbolDetails.top().Suffix += "[" + std::to_string(elementsCount) + "]"; symbolDetails.top().Suffix += "[" + std::to_string(elementsCount) + "]";
}
else else
{
symbolDetails.top().Suffix += "[<unknown count>]"; symbolDetails.top().Suffix += "[<unknown count>]";
}
if (!bHandled) if (!bHandled)
{ {
basicType = GetBasicType(dwTypeIndex, modBase); basicType = GetBasicType(dwTypeIndex, modBase);
if (symbolDetails.top().Type.empty()) if (symbolDetails.top().Type.empty())
{
symbolDetails.top().Type = rgBaseType[basicType]; symbolDetails.top().Type = rgBaseType[basicType];
}
bHandled = true; bHandled = true;
} }
@@ -1184,7 +1346,9 @@ void WheatyExceptionReport::DumpTypeIndex(
SymGetTypeInfo(m_hProcess, modBase, dwTypeIndex, TI_GET_CHILDRENCOUNT, &dwChildrenCount); SymGetTypeInfo(m_hProcess, modBase, dwTypeIndex, TI_GET_CHILDRENCOUNT, &dwChildrenCount);
if (!dwChildrenCount) // If no children, we're done if (!dwChildrenCount) // If no children, we're done
{
return; return;
}
// Prepare to get an array of "TypeIds", representing each of the children. // Prepare to get an array of "TypeIds", representing each of the children.
// SymGetTypeInfo(TI_FINDCHILDREN) expects more memory than just a // SymGetTypeInfo(TI_FINDCHILDREN) expects more memory than just a
@@ -1215,7 +1379,9 @@ void WheatyExceptionReport::DumpTypeIndex(
symTag == SymTagEnum || symTag == SymTagEnum ||
symTag == SymTagTypedef || symTag == SymTagTypedef ||
symTag == SymTagVTable) symTag == SymTagVTable)
{
continue; continue;
}
// Ignore static fields // Ignore static fields
DWORD dataKind; DWORD dataKind;
@@ -1223,7 +1389,9 @@ void WheatyExceptionReport::DumpTypeIndex(
if (dataKind == DataIsStaticLocal || if (dataKind == DataIsStaticLocal ||
dataKind == DataIsGlobal || dataKind == DataIsGlobal ||
dataKind == DataIsStaticMember) dataKind == DataIsStaticMember)
{
continue; continue;
}
symbolDetails.top().HasChildren = true; symbolDetails.top().HasChildren = true;
if (!logChildren) if (!logChildren)
@@ -1252,7 +1420,9 @@ void WheatyExceptionReport::DumpTypeIndex(
if (!bHandled2) if (!bHandled2)
{ {
if (symbolDetails.top().Type.empty()) if (symbolDetails.top().Type.empty())
{
symbolDetails.top().Type = rgBaseType[basicType]; symbolDetails.top().Type = rgBaseType[basicType];
}
// Get the real "TypeId" of the child. We need this for the // Get the real "TypeId" of the child. We need this for the
// SymGetTypeInfo(TI_GET_TYPEID) call below. // SymGetTypeInfo(TI_GET_TYPEID) call below.
@@ -1291,36 +1461,56 @@ void WheatyExceptionReport::FormatOutputValue(char* pszCurrBuffer,
{ {
// Special case handling for char[] type // Special case handling for char[] type
if (countOverride != 0) if (countOverride != 0)
{
length = countOverride; length = countOverride;
}
else else
{
length = strlen((char*)pAddress); length = strlen((char*)pAddress);
}
if (length > bufferSize - 6) if (length > bufferSize - 6)
{
pszCurrBuffer += sprintf(pszCurrBuffer, "\"%.*s...\"", (DWORD)(bufferSize - 6), (char*)pAddress); pszCurrBuffer += sprintf(pszCurrBuffer, "\"%.*s...\"", (DWORD)(bufferSize - 6), (char*)pAddress);
}
else else
{
pszCurrBuffer += sprintf(pszCurrBuffer, "\"%.*s\"", (DWORD)length, (char*)pAddress); pszCurrBuffer += sprintf(pszCurrBuffer, "\"%.*s\"", (DWORD)length, (char*)pAddress);
}
break; break;
} }
case btStdString: case btStdString:
{ {
std::string* value = static_cast<std::string*>(pAddress); std::string* value = static_cast<std::string*>(pAddress);
if (value->length() > bufferSize - 6) if (value->length() > bufferSize - 6)
{
pszCurrBuffer += sprintf(pszCurrBuffer, "\"%.*s...\"", (DWORD)(bufferSize - 6), value->c_str()); pszCurrBuffer += sprintf(pszCurrBuffer, "\"%.*s...\"", (DWORD)(bufferSize - 6), value->c_str());
}
else else
{
pszCurrBuffer += sprintf(pszCurrBuffer, "\"%s\"", value->c_str()); pszCurrBuffer += sprintf(pszCurrBuffer, "\"%s\"", value->c_str());
}
break; break;
} }
default: default:
// Format appropriately (assuming it's a 1, 2, or 4 bytes (!!!) // Format appropriately (assuming it's a 1, 2, or 4 bytes (!!!)
if (length == 1) if (length == 1)
{
pszCurrBuffer += sprintf(pszCurrBuffer, "0x%X", *(PBYTE)pAddress); pszCurrBuffer += sprintf(pszCurrBuffer, "0x%X", *(PBYTE)pAddress);
}
else if (length == 2) else if (length == 2)
{
pszCurrBuffer += sprintf(pszCurrBuffer, "0x%X", *(PWORD)pAddress); pszCurrBuffer += sprintf(pszCurrBuffer, "0x%X", *(PWORD)pAddress);
}
else if (length == 4) else if (length == 4)
{ {
if (basicType == btFloat) if (basicType == btFloat)
{
pszCurrBuffer += sprintf(pszCurrBuffer, "%f", *(PFLOAT)pAddress); pszCurrBuffer += sprintf(pszCurrBuffer, "%f", *(PFLOAT)pAddress);
}
else else
{
pszCurrBuffer += sprintf(pszCurrBuffer, "0x%X", *(PDWORD)pAddress); pszCurrBuffer += sprintf(pszCurrBuffer, "0x%X", *(PDWORD)pAddress);
}
} }
else if (length == 8) else if (length == 8)
{ {
@@ -1401,9 +1591,13 @@ int __cdecl WheatyExceptionReport::Log(const TCHAR* format, ...)
va_start(argptr, format); va_start(argptr, format);
if (stackOverflowException) if (stackOverflowException)
{
retValue = HeapLog(format, argptr); retValue = HeapLog(format, argptr);
}
else else
{
retValue = StackLog(format, argptr); retValue = StackLog(format, argptr);
}
va_end(argptr); va_end(argptr);
@@ -1446,7 +1640,9 @@ void WheatyExceptionReport::ClearSymbols()
{ {
symbols.clear(); symbols.clear();
while (!symbolDetails.empty()) while (!symbolDetails.empty())
{
symbolDetails.pop(); symbolDetails.pop();
}
} }
void WheatyExceptionReport::PushSymbolDetail() void WheatyExceptionReport::PushSymbolDetail()
@@ -1465,15 +1661,21 @@ void WheatyExceptionReport::PopSymbolDetail()
void WheatyExceptionReport::PrintSymbolDetail() void WheatyExceptionReport::PrintSymbolDetail()
{ {
if (symbolDetails.empty()) if (symbolDetails.empty())
{
return; return;
}
// Don't log anything if has been logged already or if it's empty // Don't log anything if has been logged already or if it's empty
if (symbolDetails.top().Logged || symbolDetails.top().empty()) if (symbolDetails.top().Logged || symbolDetails.top().empty())
{
return; return;
}
// Add appropriate indentation level (since this routine is recursive) // Add appropriate indentation level (since this routine is recursive)
for (size_t i = 0; i < symbolDetails.size(); i++) for (size_t i = 0; i < symbolDetails.size(); i++)
{
Log(_T("\t")); Log(_T("\t"));
}
Log(_T("%s\r\n"), symbolDetails.top().ToString().c_str()); Log(_T("%s\r\n"), symbolDetails.top().ToString().c_str());
@@ -1487,13 +1689,17 @@ std::string SymbolDetail::ToString()
if (!Name.empty()) if (!Name.empty())
{ {
if (!formatted.empty()) if (!formatted.empty())
{
formatted += " "; formatted += " ";
}
formatted += Name; formatted += Name;
} }
if (!Value.empty()) if (!Value.empty())
{ {
if (Name == "passwd" || Name == "password") if (Name == "passwd" || Name == "password")
{
Value = "<sensitive data>"; Value = "<sensitive data>";
}
formatted += " = " + Value; formatted += " = " + Value;
} }
return formatted; return formatted;

View File

@@ -115,7 +115,9 @@ public:
return result; return result;
} }
else else
{
return iSize; return iSize;
}
} }
void incSize() { ++iSize; } void incSize() { ++iSize; }

View File

@@ -35,7 +35,9 @@ public:
{ {
ASSERT(fromObj); // fromObj MUST not be nullptr ASSERT(fromObj); // fromObj MUST not be nullptr
if (isValid()) if (isValid())
{
unlink(); unlink();
}
if (toObj != nullptr) if (toObj != nullptr)
{ {
iRefTo = toObj; iRefTo = toObj;

View File

@@ -41,7 +41,9 @@ public:
if ( iter != i_registeredObjects.end() ) if ( iter != i_registeredObjects.end() )
{ {
if ( !override ) if ( !override )
{
return false; return false;
}
delete iter->second; delete iter->second;
i_registeredObjects.erase(iter); i_registeredObjects.erase(iter);
} }
@@ -57,7 +59,9 @@ public:
if ( iter != i_registeredObjects.end() ) if ( iter != i_registeredObjects.end() )
{ {
if ( delete_object ) if ( delete_object )
{
delete iter->second; delete iter->second;
}
i_registeredObjects.erase(iter); i_registeredObjects.erase(iter);
} }
} }
@@ -74,7 +78,9 @@ public:
unsigned int sz = l.size(); unsigned int sz = l.size();
l.resize(sz + i_registeredObjects.size()); l.resize(sz + i_registeredObjects.size());
for (typename RegistryMapType::const_iterator iter = i_registeredObjects.begin(); iter != i_registeredObjects.end(); ++iter) for (typename RegistryMapType::const_iterator iter = i_registeredObjects.begin(); iter != i_registeredObjects.end(); ++iter)
{
l[sz++] = iter->first; l[sz++] = iter->first;
}
return i_registeredObjects.size(); return i_registeredObjects.size();
} }
@@ -88,7 +94,9 @@ public:
~ObjectRegistry() ~ObjectRegistry()
{ {
for (typename RegistryMapType::iterator iter = i_registeredObjects.begin(); iter != i_registeredObjects.end(); ++iter) for (typename RegistryMapType::iterator iter = i_registeredObjects.begin(); iter != i_registeredObjects.end(); ++iter)
{
delete iter->second; delete iter->second;
}
i_registeredObjects.clear(); i_registeredObjects.clear();
} }
private: private:

View File

@@ -63,9 +63,13 @@ namespace Acore
{ {
auto i = elements._element.find(handle); auto i = elements._element.find(handle);
if (i == elements._element.end()) if (i == elements._element.end())
{
return nullptr; return nullptr;
}
else else
{
return i->second; return i->second;
}
} }
template<class SPECIFIC_TYPE, class KEY_TYPE> template<class SPECIFIC_TYPE, class KEY_TYPE>

View File

@@ -90,7 +90,9 @@ namespace Acore
{ {
CountedPtr<SPECIFIC_TYPE>& t = Find(elements._elements, hdl, fake); CountedPtr<SPECIFIC_TYPE>& t = Find(elements._elements, hdl, fake);
if (!t) if (!t)
{
t = Find(elements._TailElement, hdl, fake); t = Find(elements._TailElement, hdl, fake);
}
return t; return t;
} }

View File

@@ -15,19 +15,19 @@ struct B32Impl
static constexpr char Encode(uint8 v) static constexpr char Encode(uint8 v)
{ {
ASSERT(v < 0x20); ASSERT(v < 0x20);
if (v < 26) return 'A'+v; if (v < 26) { return 'A' + v; }
else return '2' + (v-26); else { return '2' + (v - 26); }
} }
static constexpr uint8 DECODE_ERROR = 0xff; static constexpr uint8 DECODE_ERROR = 0xff;
static constexpr uint8 Decode(uint8 v) static constexpr uint8 Decode(uint8 v)
{ {
if (v == '0') return Decode('O'); if (v == '0') { return Decode('O'); }
if (v == '1') return Decode('l'); if (v == '1') { return Decode('l'); }
if (v == '8') return Decode('B'); if (v == '8') { return Decode('B'); }
if (('A' <= v) && (v <= 'Z')) return (v-'A'); if (('A' <= v) && (v <= 'Z')) { return (v - 'A'); }
if (('a' <= v) && (v <= 'z')) return (v-'a'); if (('a' <= v) && (v <= 'z')) { return (v - 'a'); }
if (('2' <= v) && (v <= '7')) return (v-'2')+26; if (('2' <= v) && (v <= '7')) { return (v - '2') + 26; }
return DECODE_ERROR; return DECODE_ERROR;
} }
}; };

View File

@@ -15,21 +15,21 @@ struct B64Impl
static constexpr char Encode(uint8 v) static constexpr char Encode(uint8 v)
{ {
ASSERT(v < 0x40); ASSERT(v < 0x40);
if (v < 26) return 'A' + v; if (v < 26) { return 'A' + v; }
if (v < 52) return 'a' + (v - 26); if (v < 52) { return 'a' + (v - 26); }
if (v < 62) return '0' + (v - 52); if (v < 62) { return '0' + (v - 52); }
if (v == 62) return '+'; if (v == 62) { return '+'; }
else return '/'; else { return '/'; }
} }
static constexpr uint8 DECODE_ERROR = 0xff; static constexpr uint8 DECODE_ERROR = 0xff;
static constexpr uint8 Decode(uint8 v) static constexpr uint8 Decode(uint8 v)
{ {
if (('A' <= v) && (v <= 'Z')) return (v - 'A'); if (('A' <= v) && (v <= 'Z')) { return (v - 'A'); }
if (('a' <= v) && (v <= 'z')) return (v - 'a') + 26; if (('a' <= v) && (v <= 'z')) { return (v - 'a') + 26; }
if (('0' <= v) && (v <= '9')) return (v - '0') + 52; if (('0' <= v) && (v <= '9')) { return (v - '0') + 52; }
if (v == '+') return 62; if (v == '+') { return 62; }
if (v == '/') return 63; if (v == '/') { return 63; }
return DECODE_ERROR; return DECODE_ERROR;
} }
}; };

View File

@@ -29,7 +29,9 @@ namespace Acore::Impl
{ {
size *= 8; // bits in input size *= 8; // bits in input
if (size % PAD_TO) // pad to boundary if (size % PAD_TO) // pad to boundary
{
size += (PAD_TO - (size % PAD_TO)); size += (PAD_TO - (size % PAD_TO));
}
return (size / BITS_PER_CHAR); return (size / BITS_PER_CHAR);
} }
@@ -37,7 +39,9 @@ namespace Acore::Impl
{ {
size *= BITS_PER_CHAR; // bits in input size *= BITS_PER_CHAR; // bits in input
if (size % PAD_TO) // pad to boundary if (size % PAD_TO) // pad to boundary
{
size += (PAD_TO - (size % PAD_TO)); size += (PAD_TO - (size % PAD_TO));
}
return (size / 8); return (size / 8);
} }
@@ -45,7 +49,9 @@ namespace Acore::Impl
{ {
auto it = data.begin(), end = data.end(); auto it = data.begin(), end = data.end();
if (it == end) if (it == end)
{
return ""; return "";
}
std::string s; std::string s;
s.reserve(EncodedSize(data.size())); s.reserve(EncodedSize(data.size()));
@@ -57,7 +63,7 @@ namespace Acore::Impl
if (bitsLeft >= BITS_PER_CHAR) if (bitsLeft >= BITS_PER_CHAR)
{ {
bitsLeft -= BITS_PER_CHAR; bitsLeft -= BITS_PER_CHAR;
thisC = ((*it >> bitsLeft) & ((1 << BITS_PER_CHAR)-1)); thisC = ((*it >> bitsLeft) & ((1 << BITS_PER_CHAR) - 1));
if (!bitsLeft) if (!bitsLeft)
{ {
++it; ++it;
@@ -69,7 +75,9 @@ namespace Acore::Impl
thisC = (*it & ((1 << bitsLeft) - 1)) << (BITS_PER_CHAR - bitsLeft); thisC = (*it & ((1 << bitsLeft) - 1)) << (BITS_PER_CHAR - bitsLeft);
bitsLeft += (8 - BITS_PER_CHAR); bitsLeft += (8 - BITS_PER_CHAR);
if ((++it) != end) if ((++it) != end)
{
thisC |= (*it >> bitsLeft); thisC |= (*it >> bitsLeft);
}
} }
s.append(1, Encoding::Encode(thisC)); s.append(1, Encoding::Encode(thisC));
} while (it != end); } while (it != end);
@@ -77,9 +85,13 @@ namespace Acore::Impl
while (bitsLeft != 8) while (bitsLeft != 8)
{ {
if (bitsLeft > BITS_PER_CHAR) if (bitsLeft > BITS_PER_CHAR)
{
bitsLeft -= BITS_PER_CHAR; bitsLeft -= BITS_PER_CHAR;
}
else else
{
bitsLeft += (8 - BITS_PER_CHAR); bitsLeft += (8 - BITS_PER_CHAR);
}
s.append(1, PADDING); s.append(1, PADDING);
} }
@@ -90,7 +102,9 @@ namespace Acore::Impl
{ {
auto it = data.begin(), end = data.end(); auto it = data.begin(), end = data.end();
if (it == end) if (it == end)
{
return std::vector<uint8>(); return std::vector<uint8>();
}
std::vector<uint8> v; std::vector<uint8> v;
v.reserve(DecodedSize(data.size())); v.reserve(DecodedSize(data.size()));
@@ -126,15 +140,21 @@ namespace Acore::Impl
while ((it != end) && (*it == PADDING) && (bitsLeft != 8)) while ((it != end) && (*it == PADDING) && (bitsLeft != 8))
{ {
if (bitsLeft > BITS_PER_CHAR) if (bitsLeft > BITS_PER_CHAR)
{
bitsLeft -= BITS_PER_CHAR; bitsLeft -= BITS_PER_CHAR;
}
else else
{
bitsLeft += (8 - BITS_PER_CHAR); bitsLeft += (8 - BITS_PER_CHAR);
}
++it; ++it;
} }
// ok, all padding should be consumed, and we should be at end of string // ok, all padding should be consumed, and we should be at end of string
if (it == end) if (it == end)
{
return v; return v;
}
// anything else is an error // anything else is an error
return {}; return {};

View File

@@ -9,7 +9,7 @@
#include <sstream> #include <sstream>
Appender::Appender(uint8 _id, std::string const& _name, LogLevel _level /* = LOG_LEVEL_DISABLED */, AppenderFlags _flags /* = APPENDER_FLAGS_NONE */): Appender::Appender(uint8 _id, std::string const& _name, LogLevel _level /* = LOG_LEVEL_DISABLED */, AppenderFlags _flags /* = APPENDER_FLAGS_NONE */):
id(_id), name(_name), level(_level), flags(_flags) { } id(_id), name(_name), level(_level), flags(_flags) { }
Appender::~Appender() { } Appender::~Appender() { }
@@ -41,18 +41,26 @@ void Appender::setLogLevel(LogLevel _level)
void Appender::write(LogMessage* message) void Appender::write(LogMessage* message)
{ {
if (!level || level < message->level) if (!level || level < message->level)
{
return; return;
}
std::ostringstream ss; std::ostringstream ss;
if (flags & APPENDER_FLAGS_PREFIX_TIMESTAMP) if (flags & APPENDER_FLAGS_PREFIX_TIMESTAMP)
{
ss << message->getTimeStr() << ' '; ss << message->getTimeStr() << ' ';
}
if (flags & APPENDER_FLAGS_PREFIX_LOGLEVEL) if (flags & APPENDER_FLAGS_PREFIX_LOGLEVEL)
{
ss << Acore::StringFormat("%-5s ", Appender::getLogLevelString(message->level)); ss << Acore::StringFormat("%-5s ", Appender::getLogLevelString(message->level));
}
if (flags & APPENDER_FLAGS_PREFIX_LOGFILTERTYPE) if (flags & APPENDER_FLAGS_PREFIX_LOGFILTERTYPE)
{
ss << '[' << message->type << "] "; ss << '[' << message->type << "] ";
}
message->prefix = ss.str(); message->prefix = ss.str();
_write(message); _write(message);

View File

@@ -20,10 +20,14 @@ AppenderConsole::AppenderConsole(uint8 id, std::string const& name, LogLevel lev
: Appender(id, name, level, flags), _colored(false) : Appender(id, name, level, flags), _colored(false)
{ {
for (uint8 i = 0; i < NUM_ENABLED_LOG_LEVELS; ++i) for (uint8 i = 0; i < NUM_ENABLED_LOG_LEVELS; ++i)
{
_colors[i] = ColorTypes(NUM_COLOR_TYPES); _colors[i] = ColorTypes(NUM_COLOR_TYPES);
}
if (3 < args.size()) if (3 < args.size())
{
InitColors(name, args[3]); InitColors(name, args[3]);
}
} }
void AppenderConsole::InitColors(std::string const& name, std::string_view str) void AppenderConsole::InitColors(std::string const& name, std::string_view str)
@@ -44,7 +48,9 @@ void AppenderConsole::InitColors(std::string const& name, std::string_view str)
for (uint8 i = 0; i < NUM_ENABLED_LOG_LEVELS; ++i) for (uint8 i = 0; i < NUM_ENABLED_LOG_LEVELS; ++i)
{ {
if (Optional<uint8> color = Acore::StringTo<uint8>(colorStrs[i]); color && EnumUtils::IsValid<ColorTypes>(*color)) if (Optional<uint8> color = Acore::StringTo<uint8>(colorStrs[i]); color && EnumUtils::IsValid<ColorTypes>(*color))
{
_colors[i] = static_cast<ColorTypes>(*color); _colors[i] = static_cast<ColorTypes>(*color);
}
else else
{ {
throw InvalidAppenderArgsException(Acore::StringFormat("Log::CreateAppenderFromConfig: Invalid color '%s' for log level %s on console appender %s", throw InvalidAppenderArgsException(Acore::StringFormat("Log::CreateAppenderFromConfig: Invalid color '%s' for log level %s on console appender %s",
@@ -138,8 +144,8 @@ void AppenderConsole::SetColor(bool stdout_stream, ColorTypes color)
FG_WHITE // LWHITE FG_WHITE // LWHITE
}; };
fprintf((stdout_stream? stdout : stderr), "\x1b[%d%sm", UnixColorFG[color], (color >= YELLOW && color < NUM_COLOR_TYPES ? ";1" : "")); fprintf((stdout_stream ? stdout : stderr), "\x1b[%d%sm", UnixColorFG[color], (color >= YELLOW && color < NUM_COLOR_TYPES ? ";1" : ""));
#endif #endif
} }
void AppenderConsole::ResetColor(bool stdout_stream) void AppenderConsole::ResetColor(bool stdout_stream)
@@ -163,23 +169,23 @@ void AppenderConsole::_write(LogMessage const* message)
switch (message->level) switch (message->level)
{ {
case LOG_LEVEL_TRACE: case LOG_LEVEL_TRACE:
index = 5; index = 5;
break; break;
case LOG_LEVEL_DEBUG: case LOG_LEVEL_DEBUG:
index = 4; index = 4;
break; break;
case LOG_LEVEL_INFO: case LOG_LEVEL_INFO:
index = 3; index = 3;
break; break;
case LOG_LEVEL_WARN: case LOG_LEVEL_WARN:
index = 2; index = 2;
break; break;
case LOG_LEVEL_FATAL: case LOG_LEVEL_FATAL:
index = 0; index = 0;
break; break;
default: default:
index = 1; index = 1;
break; break;
} }
SetColor(stdout_stream, _colors[index]); SetColor(stdout_stream, _colors[index]);
@@ -187,5 +193,7 @@ void AppenderConsole::_write(LogMessage const* message)
ResetColor(stdout_stream); ResetColor(stdout_stream);
} }
else else
{
utf8printf(stdout_stream ? stdout : stderr, "%s%s\n", message->prefix.c_str(), message->text.c_str()); utf8printf(stdout_stream ? stdout : stderr, "%s%s\n", message->prefix.c_str(), message->text.c_str());
}
} }

View File

@@ -18,36 +18,50 @@ AppenderFile::AppenderFile(uint8 id, std::string const& name, LogLevel level, Ap
_fileSize(0) _fileSize(0)
{ {
if (args.size() < 4) if (args.size() < 4)
{
throw InvalidAppenderArgsException(Acore::StringFormat("Log::CreateAppenderFromConfig: Missing file name for appender %s", name.c_str())); throw InvalidAppenderArgsException(Acore::StringFormat("Log::CreateAppenderFromConfig: Missing file name for appender %s", name.c_str()));
}
_fileName.assign(args[3]); _fileName.assign(args[3]);
std::string mode = "a"; std::string mode = "a";
if (4 < args.size()) if (4 < args.size())
{
mode.assign(args[4]); mode.assign(args[4]);
}
if (flags & APPENDER_FLAGS_USE_TIMESTAMP) if (flags & APPENDER_FLAGS_USE_TIMESTAMP)
{ {
size_t dot_pos = _fileName.find_last_of('.'); size_t dot_pos = _fileName.find_last_of('.');
if (dot_pos != std::string::npos) if (dot_pos != std::string::npos)
{
_fileName.insert(dot_pos, sLog->GetLogsTimestamp()); _fileName.insert(dot_pos, sLog->GetLogsTimestamp());
}
else else
{
_fileName += sLog->GetLogsTimestamp(); _fileName += sLog->GetLogsTimestamp();
}
} }
if (5 < args.size()) if (5 < args.size())
{ {
if (Optional<uint32> size = Acore::StringTo<uint32>(args[5])) if (Optional<uint32> size = Acore::StringTo<uint32>(args[5]))
{
_maxFileSize = *size; _maxFileSize = *size;
}
else else
{
throw InvalidAppenderArgsException(Acore::StringFormat("Log::CreateAppenderFromConfig: Invalid size '%s' for appender %s", std::string(args[5]).c_str(), name.c_str())); throw InvalidAppenderArgsException(Acore::StringFormat("Log::CreateAppenderFromConfig: Invalid size '%s' for appender %s", std::string(args[5]).c_str(), name.c_str()));
}
} }
_dynamicName = std::string::npos != _fileName.find("%s"); _dynamicName = std::string::npos != _fileName.find("%s");
_backup = (flags & APPENDER_FLAGS_MAKE_FILE_BACKUP) != 0; _backup = (flags & APPENDER_FLAGS_MAKE_FILE_BACKUP) != 0;
if (!_dynamicName) if (!_dynamicName)
{
logfile = OpenFile(_fileName, mode, (mode == "w") && _backup); logfile = OpenFile(_fileName, mode, (mode == "w") && _backup);
}
} }
AppenderFile::~AppenderFile() AppenderFile::~AppenderFile()
@@ -67,7 +81,9 @@ void AppenderFile::_write(LogMessage const* message)
// always use "a" with dynamic name otherwise it could delete the log we wrote in last _write() call // always use "a" with dynamic name otherwise it could delete the log we wrote in last _write() call
FILE* file = OpenFile(namebuf, "a", _backup || exceedMaxSize); FILE* file = OpenFile(namebuf, "a", _backup || exceedMaxSize);
if (!file) if (!file)
{
return; return;
}
fprintf(file, "%s%s\n", message->prefix.c_str(), message->text.c_str()); fprintf(file, "%s%s\n", message->prefix.c_str(), message->text.c_str());
fflush(file); fflush(file);
@@ -77,10 +93,14 @@ void AppenderFile::_write(LogMessage const* message)
return; return;
} }
else if (exceedMaxSize) else if (exceedMaxSize)
{
logfile = OpenFile(_fileName, "w", true); logfile = OpenFile(_fileName, "w", true);
}
if (!logfile) if (!logfile)
{
return; return;
}
fprintf(logfile, "%s%s\n", message->prefix.c_str(), message->text.c_str()); fprintf(logfile, "%s%s\n", message->prefix.c_str(), message->text.c_str());
fflush(logfile); fflush(logfile);

View File

@@ -39,7 +39,9 @@ Appender* Log::GetAppenderByName(std::string_view name)
{ {
auto it = appenders.begin(); auto it = appenders.begin();
while (it != appenders.end() && it->second && it->second->getName() != name) while (it != appenders.end() && it->second && it->second->getName() != name)
{
++it; ++it;
}
return it == appenders.end() ? nullptr : it->second.get(); return it == appenders.end() ? nullptr : it->second.get();
} }
@@ -47,7 +49,9 @@ Appender* Log::GetAppenderByName(std::string_view name)
void Log::CreateAppenderFromConfig(std::string const& appenderName) void Log::CreateAppenderFromConfig(std::string const& appenderName)
{ {
if (appenderName.empty()) if (appenderName.empty())
{
return; return;
}
// Format = type, level, flags, optional1, optional2 // Format = type, level, flags, optional1, optional2
// if type = File. optional1 = file and option2 = mode // if type = File. optional1 = file and option2 = mode
@@ -85,7 +89,9 @@ void Log::CreateAppenderFromConfig(std::string const& appenderName)
if (size > 2) if (size > 2)
{ {
if (Optional<uint8> flagsVal = Acore::StringTo<uint8>(tokens[2])) if (Optional<uint8> flagsVal = Acore::StringTo<uint8>(tokens[2]))
{
flags = AppenderFlags(*flagsVal); flags = AppenderFlags(*flagsVal);
}
else else
{ {
fprintf(stderr, "Log::CreateAppenderFromConfig: Unknown flags '%s' for appender %s\n", std::string(tokens[2]).c_str(), name.c_str()); fprintf(stderr, "Log::CreateAppenderFromConfig: Unknown flags '%s' for appender %s\n", std::string(tokens[2]).c_str(), name.c_str());
@@ -107,7 +113,9 @@ void Log::CreateAppenderFromConfig(std::string const& appenderName)
void Log::CreateLoggerFromConfig(std::string const& appenderName) void Log::CreateLoggerFromConfig(std::string const& appenderName)
{ {
if (appenderName.empty()) if (appenderName.empty())
{
return; return;
}
LogLevel level = LOG_LEVEL_DISABLED; LogLevel level = LOG_LEVEL_DISABLED;
@@ -143,7 +151,9 @@ void Log::CreateLoggerFromConfig(std::string const& appenderName)
} }
if (level > highestLogLevel) if (level > highestLogLevel)
{
highestLogLevel = level; highestLogLevel = level;
}
logger = std::make_unique<Logger>(name, level); logger = std::make_unique<Logger>(name, level);
//fprintf(stdout, "Log::CreateLoggerFromConfig: Created Logger %s, Level %u\n", name.c_str(), level); //fprintf(stdout, "Log::CreateLoggerFromConfig: Created Logger %s, Level %u\n", name.c_str(), level);
@@ -156,7 +166,9 @@ void Log::CreateLoggerFromConfig(std::string const& appenderName)
//fprintf(stdout, "Log::CreateLoggerFromConfig: Added Appender %s to Logger %s\n", appender->getName().c_str(), name.c_str()); //fprintf(stdout, "Log::CreateLoggerFromConfig: Added Appender %s to Logger %s\n", appender->getName().c_str(), name.c_str());
} }
else else
{
fprintf(stderr, "Error while configuring Appender %s in Logger %s. Appender does not exist\n", std::string(appenderName).c_str(), name.c_str()); fprintf(stderr, "Error while configuring Appender %s in Logger %s. Appender does not exist\n", std::string(appenderName).c_str(), name.c_str());
}
} }
} }
@@ -164,14 +176,18 @@ void Log::ReadAppendersFromConfig()
{ {
std::vector<std::string> keys = sConfigMgr->GetKeysByString("Appender."); std::vector<std::string> keys = sConfigMgr->GetKeysByString("Appender.");
for (std::string const& appenderName : keys) for (std::string const& appenderName : keys)
{
CreateAppenderFromConfig(appenderName); CreateAppenderFromConfig(appenderName);
}
} }
void Log::ReadLoggersFromConfig() void Log::ReadLoggersFromConfig()
{ {
std::vector<std::string> keys = sConfigMgr->GetKeysByString("Logger."); std::vector<std::string> keys = sConfigMgr->GetKeysByString("Logger.");
for (std::string const& loggerName : keys) for (std::string const& loggerName : keys)
{
CreateLoggerFromConfig(loggerName); CreateLoggerFromConfig(loggerName);
}
// Bad config configuration, creating default config // Bad config configuration, creating default config
if (loggers.find(LOGGER_ROOT) == loggers.end()) if (loggers.find(LOGGER_ROOT) == loggers.end())
@@ -222,15 +238,21 @@ Logger const* Log::GetLoggerByType(std::string const& type) const
{ {
auto it = loggers.find(type); auto it = loggers.find(type);
if (it != loggers.end()) if (it != loggers.end())
{
return it->second.get(); return it->second.get();
}
if (type == LOGGER_ROOT) if (type == LOGGER_ROOT)
{
return nullptr; return nullptr;
}
std::string parentLogger = LOGGER_ROOT; std::string parentLogger = LOGGER_ROOT;
size_t found = type.find_last_of('.'); size_t found = type.find_last_of('.');
if (found != std::string::npos) if (found != std::string::npos)
{
parentLogger = type.substr(0, found); parentLogger = type.substr(0, found);
}
return GetLoggerByType(parentLogger); return GetLoggerByType(parentLogger);
} }
@@ -255,7 +277,9 @@ std::string Log::GetTimestampStr()
bool Log::SetLogLevel(std::string const& name, int32 newLeveli, bool isLogger /* = true */) bool Log::SetLogLevel(std::string const& name, int32 newLeveli, bool isLogger /* = true */)
{ {
if (newLeveli < 0) if (newLeveli < 0)
{
return false; return false;
}
LogLevel newLevel = LogLevel(newLeveli); LogLevel newLevel = LogLevel(newLeveli);
@@ -263,21 +287,29 @@ bool Log::SetLogLevel(std::string const& name, int32 newLeveli, bool isLogger /*
{ {
auto it = loggers.begin(); auto it = loggers.begin();
while (it != loggers.end() && it->second->getName() != name) while (it != loggers.end() && it->second->getName() != name)
{
++it; ++it;
}
if (it == loggers.end()) if (it == loggers.end())
{
return false; return false;
}
it->second->setLogLevel(newLevel); it->second->setLogLevel(newLevel);
if (newLevel != LOG_LEVEL_DISABLED && newLevel > highestLogLevel) if (newLevel != LOG_LEVEL_DISABLED && newLevel > highestLogLevel)
{
highestLogLevel = newLevel; highestLogLevel = newLevel;
}
} }
else else
{ {
Appender* appender = GetAppenderByName(name); Appender* appender = GetAppenderByName(name);
if (!appender) if (!appender)
{
return false; return false;
}
appender->setLogLevel(newLevel); appender->setLogLevel(newLevel);
} }
@@ -288,7 +320,9 @@ bool Log::SetLogLevel(std::string const& name, int32 newLeveli, bool isLogger /*
void Log::outCharDump(char const* str, uint32 accountId, uint64 guid, char const* name) void Log::outCharDump(char const* str, uint32 accountId, uint64 guid, char const* name)
{ {
if (!str || !ShouldLog("entities.player.dump", LOG_LEVEL_INFO)) if (!str || !ShouldLog("entities.player.dump", LOG_LEVEL_INFO))
{
return; return;
}
std::ostringstream ss; std::ostringstream ss;
ss << "== START DUMP == (account: " << accountId << " guid: " << guid << " name: " << name ss << "== START DUMP == (account: " << accountId << " guid: " << guid << " name: " << name
@@ -306,7 +340,9 @@ void Log::outCharDump(char const* str, uint32 accountId, uint64 guid, char const
void Log::SetRealmId(uint32 id) void Log::SetRealmId(uint32 id)
{ {
for (std::pair<uint8 const, std::unique_ptr<Appender>>& appender : appenders) for (std::pair<uint8 const, std::unique_ptr<Appender>>& appender : appenders)
{
appender.second->setRealmId(id); appender.second->setRealmId(id);
}
} }
void Log::Close() void Log::Close()
@@ -323,11 +359,15 @@ bool Log::ShouldLog(std::string const& type, LogLevel level) const
// Don't even look for a logger if the LogLevel is higher than the highest log levels across all loggers // Don't even look for a logger if the LogLevel is higher than the highest log levels across all loggers
if (level > highestLogLevel) if (level > highestLogLevel)
{
return false; return false;
}
Logger const* logger = GetLoggerByType(type); Logger const* logger = GetLoggerByType(type);
if (!logger) if (!logger)
{
return false; return false;
}
LogLevel logLevel = logger->getLogLevel(); LogLevel logLevel = logger->getLogLevel();
return logLevel != LOG_LEVEL_DISABLED && logLevel >= level; return logLevel != LOG_LEVEL_DISABLED && logLevel >= level;
@@ -354,7 +394,9 @@ void Log::LoadFromConfig()
if (!m_logsDir.empty()) if (!m_logsDir.empty())
if ((m_logsDir.at(m_logsDir.length() - 1) != '/') && (m_logsDir.at(m_logsDir.length() - 1) != '\\')) if ((m_logsDir.at(m_logsDir.length() - 1) != '/') && (m_logsDir.at(m_logsDir.length() - 1) != '\\'))
{
m_logsDir.push_back('/'); m_logsDir.push_back('/');
}
ReadAppendersFromConfig(); ReadAppendersFromConfig();
ReadLoggersFromConfig(); ReadLoggersFromConfig();

View File

@@ -59,7 +59,9 @@ public:
void outCommand(uint32 account, Format&& fmt, Args&&... args) void outCommand(uint32 account, Format&& fmt, Args&&... args)
{ {
if (!ShouldLog("commands.gm", LOG_LEVEL_INFO)) if (!ShouldLog("commands.gm", LOG_LEVEL_INFO))
{
return; return;
}
outCommand(Acore::StringFormat(std::forward<Format>(fmt), std::forward<Args>(args)...), std::to_string(account)); outCommand(Acore::StringFormat(std::forward<Format>(fmt), std::forward<Args>(args)...), std::to_string(account));
} }
@@ -99,7 +101,9 @@ public:
void outErrorDb(Format&& fmt, Args&& ... args) void outErrorDb(Format&& fmt, Args&& ... args)
{ {
if (!ShouldLog("sql.sql", LOG_LEVEL_ERROR)) if (!ShouldLog("sql.sql", LOG_LEVEL_ERROR))
{
return; return;
}
outMessage("sql.sql", LOG_LEVEL_ERROR, Acore::StringFormat(std::forward<Format>(fmt), std::forward<Args>(args)...)); outMessage("sql.sql", LOG_LEVEL_ERROR, Acore::StringFormat(std::forward<Format>(fmt), std::forward<Args>(args)...));
} }
@@ -120,7 +124,9 @@ public:
void outSQLDev(Format&& fmt, Args&& ... args) void outSQLDev(Format&& fmt, Args&& ... args)
{ {
if (!ShouldLog("sql.dev", LOG_LEVEL_INFO)) if (!ShouldLog("sql.dev", LOG_LEVEL_INFO))
{
return; return;
}
outMessage("sql.dev", LOG_LEVEL_INFO, Acore::StringFormat(std::forward<Format>(fmt), std::forward<Args>(args)...)); outMessage("sql.dev", LOG_LEVEL_INFO, Acore::StringFormat(std::forward<Format>(fmt), std::forward<Args>(args)...));
} }
@@ -129,7 +135,9 @@ public:
void outSQLDriver(Format&& fmt, Args&& ... args) void outSQLDriver(Format&& fmt, Args&& ... args)
{ {
if (!ShouldLog("sql.driver", LOG_LEVEL_INFO)) if (!ShouldLog("sql.driver", LOG_LEVEL_INFO))
{
return; return;
}
outMessage("sql.driver", LOG_LEVEL_INFO, Acore::StringFormat(std::forward<Format>(fmt), std::forward<Args>(args)...)); outMessage("sql.driver", LOG_LEVEL_INFO, Acore::StringFormat(std::forward<Format>(fmt), std::forward<Args>(args)...));
} }
@@ -144,10 +152,14 @@ public:
void outDebug(DebugLogFilters filter, Format&& fmt, Args&& ... args) void outDebug(DebugLogFilters filter, Format&& fmt, Args&& ... args)
{ {
if (!(_debugLogMask & filter)) if (!(_debugLogMask & filter))
{
return; return;
}
if (!ShouldLog("server", LOG_LEVEL_DEBUG)) if (!ShouldLog("server", LOG_LEVEL_DEBUG))
{
return; return;
}
outMessage("server", LOG_LEVEL_DEBUG, Acore::StringFormat(std::forward<Format>(fmt), std::forward<Args>(args)...)); outMessage("server", LOG_LEVEL_DEBUG, Acore::StringFormat(std::forward<Format>(fmt), std::forward<Args>(args)...));
} }

View File

@@ -44,5 +44,7 @@ void Logger::write(LogMessage* message) const
for (std::pair<uint8 const, Appender*> const& appender : appenders) for (std::pair<uint8 const, Appender*> const& appender : appenders)
if (appender.second) if (appender.second)
{
appender.second->write(message); appender.second->write(message);
}
} }

View File

@@ -11,12 +11,12 @@ float dtQueryFilterExt::getCost(const float* pa, const float* pb,
const dtPolyRef /*curRef*/, const dtMeshTile* /*curTile*/, const dtPoly* curPoly, const dtPolyRef /*curRef*/, const dtMeshTile* /*curTile*/, const dtPoly* curPoly,
const dtPolyRef /*nextRef*/, const dtMeshTile* /*nextTile*/, const dtPoly* /*nextPoly*/) const const dtPolyRef /*nextRef*/, const dtMeshTile* /*nextTile*/, const dtPoly* /*nextPoly*/) const
{ {
float startX=pa[2], startY=pa[0], startZ=pa[1]; float startX = pa[2], startY = pa[0], startZ = pa[1];
float destX=pb[2], destY=pb[0], destZ=pb[1]; float destX = pb[2], destY = pb[0], destZ = pb[1];
float slopeAngle = getSlopeAngle(startX, startY, startZ, destX, destY, destZ); float slopeAngle = getSlopeAngle(startX, startY, startZ, destX, destY, destZ);
float slopeAngleDegree = (slopeAngle * 180.0f / M_PI); float slopeAngleDegree = (slopeAngle * 180.0f / M_PI);
float cost = slopeAngleDegree > 0 ? 1.0f + (1.0f * (slopeAngleDegree/100)) : 1.0f; float cost = slopeAngleDegree > 0 ? 1.0f + (1.0f * (slopeAngleDegree / 100)) : 1.0f;
float dist = dtVdist(pa, pb); float dist = dtVdist(pa, pb);
auto totalCost = dist * cost * getAreaCost(curPoly->getArea()); auto totalCost = dist * cost * getAreaCost(curPoly->getArea());
return totalCost; return totalCost;
} }

View File

@@ -123,7 +123,9 @@ bool WinServiceUninstall()
if (QueryServiceStatus(service, &serviceStatus2)) if (QueryServiceStatus(service, &serviceStatus2))
{ {
if (serviceStatus2.dwCurrentState == SERVICE_STOPPED) if (serviceStatus2.dwCurrentState == SERVICE_STOPPED)
{
DeleteService(service); DeleteService(service);
}
} }
CloseServiceHandle(service); CloseServiceHandle(service);
} }
@@ -163,10 +165,14 @@ void WINAPI ServiceControlHandler(DWORD controlCode)
default: default:
if ( controlCode >= 128 && controlCode <= 255 ) if ( controlCode >= 128 && controlCode <= 255 )
// user defined control code // user defined control code
{
break; break;
}
else else
// unrecognized control code // unrecognized control code
{
break; break;
}
} }
SetServiceStatus(serviceStatusHandle, &serviceStatus); SetServiceStatus(serviceStatusHandle, &serviceStatus);
@@ -194,7 +200,7 @@ void WINAPI ServiceMain(DWORD argc, char* argv[])
for (i = 0; i < std::strlen(path); i++) for (i = 0; i < std::strlen(path); i++)
{ {
if (path[i] == '\\') last_slash = i; if (path[i] == '\\') { last_slash = i; }
} }
path[last_slash] = 0; path[last_slash] = 0;

View File

@@ -10,7 +10,7 @@
#include <deque> #include <deque>
#include <mutex> #include <mutex>
template <class T, typename StorageType = std::deque<T> > template <class T, typename StorageType = std::deque<T>>
class LockedQueue class LockedQueue
{ {
//! Lock access to the queue. //! Lock access to the queue.
@@ -59,7 +59,9 @@ public:
std::lock_guard<std::mutex> lock(_lock); std::lock_guard<std::mutex> lock(_lock);
if (_queue.empty()) if (_queue.empty())
{
return false; return false;
}
result = _queue.front(); result = _queue.front();
_queue.pop_front(); _queue.pop_front();
@@ -73,11 +75,15 @@ public:
std::lock_guard<std::mutex> lock(_lock); std::lock_guard<std::mutex> lock(_lock);
if (_queue.empty()) if (_queue.empty())
{
return false; return false;
}
result = _queue.front(); result = _queue.front();
if (!check.Process(result)) if (!check.Process(result))
{
return false; return false;
}
_queue.pop_front(); _queue.pop_front();
return true; return true;
@@ -91,7 +97,9 @@ public:
T& result = _queue.front(); T& result = _queue.front();
if (autoUnlock) if (autoUnlock)
{
unlock(); unlock();
}
return result; return result;
} }

View File

@@ -45,7 +45,9 @@ public:
std::lock_guard<std::mutex> lock(_queueLock); std::lock_guard<std::mutex> lock(_queueLock);
if (_queue.empty() || _shutdown) if (_queue.empty() || _shutdown)
{
return false; return false;
}
value = _queue.front(); value = _queue.front();
@@ -61,10 +63,14 @@ public:
// we could be using .wait(lock, predicate) overload here but it is broken // we could be using .wait(lock, predicate) overload here but it is broken
// https://connect.microsoft.com/VisualStudio/feedback/details/1098841 // https://connect.microsoft.com/VisualStudio/feedback/details/1098841
while (_queue.empty() && !_shutdown) while (_queue.empty() && !_shutdown)
{
_condition.wait(lock); _condition.wait(lock);
}
if (_queue.empty() || _shutdown) if (_queue.empty() || _shutdown)
{
return; return;
}
value = _queue.front(); value = _queue.front();

View File

@@ -31,20 +31,30 @@ void SetProcessPriority(std::string const& logChannel, uint32 affinity, bool hig
ULONG_PTR currentAffinity = affinity & appAff; ULONG_PTR currentAffinity = affinity & appAff;
if (!currentAffinity) if (!currentAffinity)
{
LOG_ERROR(logChannel, "Processors marked in UseProcessors bitmask (hex) %x are not accessible. Accessible processors bitmask (hex): %x", affinity, appAff); LOG_ERROR(logChannel, "Processors marked in UseProcessors bitmask (hex) %x are not accessible. Accessible processors bitmask (hex): %x", affinity, appAff);
}
else if (SetProcessAffinityMask(hProcess, currentAffinity)) else if (SetProcessAffinityMask(hProcess, currentAffinity))
{
LOG_INFO(logChannel, "Using processors (bitmask, hex): %x", currentAffinity); LOG_INFO(logChannel, "Using processors (bitmask, hex): %x", currentAffinity);
}
else else
{
LOG_ERROR(logChannel, "Can't set used processors (hex): %x", currentAffinity); LOG_ERROR(logChannel, "Can't set used processors (hex): %x", currentAffinity);
}
} }
} }
if (highPriority) if (highPriority)
{ {
if (SetPriorityClass(hProcess, HIGH_PRIORITY_CLASS)) if (SetPriorityClass(hProcess, HIGH_PRIORITY_CLASS))
{
LOG_INFO(logChannel, "Process priority class set to HIGH"); LOG_INFO(logChannel, "Process priority class set to HIGH");
}
else else
{
LOG_ERROR(logChannel, "Can't set process priority class."); LOG_ERROR(logChannel, "Can't set process priority class.");
}
} }
#elif defined(__linux__) // Linux #elif defined(__linux__) // Linux
@@ -56,10 +66,14 @@ void SetProcessPriority(std::string const& logChannel, uint32 affinity, bool hig
for (unsigned int i = 0; i < sizeof(affinity) * 8; ++i) for (unsigned int i = 0; i < sizeof(affinity) * 8; ++i)
if (affinity & (1 << i)) if (affinity & (1 << i))
{
CPU_SET(i, &mask); CPU_SET(i, &mask);
}
if (sched_setaffinity(0, sizeof(mask), &mask)) if (sched_setaffinity(0, sizeof(mask), &mask))
{
LOG_ERROR(logChannel, "Can't set used processors (hex): %x, error: %s", affinity, strerror(errno)); LOG_ERROR(logChannel, "Can't set used processors (hex): %x, error: %s", affinity, strerror(errno));
}
else else
{ {
CPU_ZERO(&mask); CPU_ZERO(&mask);
@@ -71,9 +85,13 @@ void SetProcessPriority(std::string const& logChannel, uint32 affinity, bool hig
if (highPriority) if (highPriority)
{ {
if (setpriority(PRIO_PROCESS, 0, PROCESS_HIGH_PRIORITY)) if (setpriority(PRIO_PROCESS, 0, PROCESS_HIGH_PRIORITY))
{
LOG_ERROR(logChannel, "Can't set process priority class, error: %s", strerror(errno)); LOG_ERROR(logChannel, "Can't set process priority class, error: %s", strerror(errno));
}
else else
{
LOG_INFO(logChannel, "Process priority class set to %i", getpriority(PRIO_PROCESS, 0)); LOG_INFO(logChannel, "Process priority class set to %i", getpriority(PRIO_PROCESS, 0));
}
} }
#else #else

View File

@@ -25,7 +25,9 @@ Thread::Thread(Runnable* instance) : m_task(instance), m_ThreadImp(&Thread::Thre
// register reference to m_task to prevent it deeltion until destructor // register reference to m_task to prevent it deeltion until destructor
if (m_task) if (m_task)
{
m_task->incReference(); m_task->incReference();
}
} }
Thread::~Thread() Thread::~Thread()
@@ -34,13 +36,17 @@ Thread::~Thread()
// deleted runnable object (if no other references) // deleted runnable object (if no other references)
if (m_task) if (m_task)
{
m_task->decReference(); m_task->decReference();
}
} }
bool Thread::wait() bool Thread::wait()
{ {
if (m_iThreadId == std::thread::id() || !m_task) if (m_iThreadId == std::thread::id() || !m_task)
{
return false; return false;
}
bool res = true; bool res = true;
@@ -61,7 +67,9 @@ bool Thread::wait()
void Thread::destroy() void Thread::destroy()
{ {
if (m_iThreadId == std::thread::id() || !m_task) if (m_iThreadId == std::thread::id() || !m_task)
{
return; return;
}
// FIXME: We need to make sure that all threads can be trusted to // FIXME: We need to make sure that all threads can be trusted to
// halt execution on their own as this is not an interrupt // halt execution on their own as this is not an interrupt

View File

@@ -22,7 +22,9 @@ namespace Acore
void decReference() void decReference()
{ {
if (!--m_refs) if (!--m_refs)
{
delete this; delete this;
}
} }
private: private:
std::atomic_long m_refs; std::atomic_long m_refs;

View File

@@ -14,7 +14,8 @@
#include <vector> #include <vector>
template <typename T> template <typename T>
class CircularBuffer { class CircularBuffer
{
public: public:
explicit CircularBuffer(size_t size) : explicit CircularBuffer(size_t size) :
buf_(std::unique_ptr<T[]>(new T[size])), buf_(std::unique_ptr<T[]>(new T[size])),
@@ -77,13 +78,15 @@ public:
// the implementation of this function is simplified by the fact that head_ will never be lower than tail_ // the implementation of this function is simplified by the fact that head_ will never be lower than tail_
// when compared to the original implementation of this class // when compared to the original implementation of this class
std::vector<T> content() { std::vector<T> content()
{
std::lock_guard<std::mutex> lock(mutex_); std::lock_guard<std::mutex> lock(mutex_);
return std::vector<T>(buf_.get(), buf_.get() + size()); return std::vector<T>(buf_.get(), buf_.get() + size());
} }
T peak_back() { T peak_back()
{
std::lock_guard<std::mutex> lock(mutex_); std::lock_guard<std::mutex> lock(mutex_);
return empty() ? T() : buf_[tail_]; return empty() ? T() : buf_[tail_];

View File

@@ -55,7 +55,9 @@ namespace Acore
void check() const void check() const
{ {
if (!(_buf < _end)) if (!(_buf < _end))
{
throw std::out_of_range("index"); throw std::out_of_range("index");
}
} }
}; };
} }
@@ -70,7 +72,9 @@ namespace Acore::Containers
static_assert(std::is_base_of<std::forward_iterator_tag, typename std::iterator_traits<typename C::iterator>::iterator_category>::value, "Invalid container passed to Acore::Containers::RandomResize"); static_assert(std::is_base_of<std::forward_iterator_tag, typename std::iterator_traits<typename C::iterator>::iterator_category>::value, "Invalid container passed to Acore::Containers::RandomResize");
if (std::size(container) <= requestedSize) if (std::size(container) <= requestedSize)
{
return; return;
}
auto keepIt = std::begin(container), curIt = std::begin(container); auto keepIt = std::begin(container), curIt = std::begin(container);
uint32 elementsToKeep = requestedSize, elementsToProcess = std::size(container); uint32 elementsToKeep = requestedSize, elementsToProcess = std::size(container);
@@ -81,7 +85,9 @@ namespace Acore::Containers
if (urand(1, elementsToProcess) <= elementsToKeep) if (urand(1, elementsToProcess) <= elementsToKeep)
{ {
if (keepIt != curIt) if (keepIt != curIt)
{
*keepIt = std::move(*curIt); *keepIt = std::move(*curIt);
}
++keepIt; ++keepIt;
--elementsToKeep; --elementsToKeep;
@@ -102,7 +108,9 @@ namespace Acore::Containers
std::copy_if(std::begin(container), std::end(container), std::inserter(containerCopy, std::end(containerCopy)), predicate); std::copy_if(std::begin(container), std::end(container), std::inserter(containerCopy, std::end(containerCopy)), predicate);
if (requestedSize) if (requestedSize)
{
RandomResize(containerCopy, requestedSize); RandomResize(containerCopy, requestedSize);
}
container = std::move(containerCopy); container = std::move(containerCopy);
} }
@@ -160,7 +168,9 @@ namespace Acore::Containers
} }
if (weightSum <= 0.0) if (weightSum <= 0.0)
{
weights.assign(std::size(container), 1.0); weights.assign(std::size(container), 1.0);
}
return SelectRandomWeightedContainerElement(container, weights); return SelectRandomWeightedContainerElement(container, weights);
} }
@@ -195,9 +205,13 @@ namespace Acore::Containers
for (auto itr = range.first; itr != range.second;) for (auto itr = range.first; itr != range.second;)
{ {
if (itr->second == value) if (itr->second == value)
{
itr = multimap.erase(itr); itr = multimap.erase(itr);
}
else else
{
++itr; ++itr;
}
} }
} }

View File

@@ -30,11 +30,15 @@ public:
{ {
static_assert(std::is_base_of<Base, T>::value, "T must derive from Base"); static_assert(std::is_base_of<Base, T>::value, "T must derive from Base");
if (Container.empty()) if (Container.empty())
{
return nullptr; return nullptr;
}
auto it = Container.find(k); auto it = Container.find(k);
if (it != Container.end()) if (it != Container.end())
{
return dynamic_cast<T*>(it->second.get()); return dynamic_cast<T*>(it->second.get());
}
return nullptr; return nullptr;
} }
@@ -47,7 +51,9 @@ public:
{ {
static_assert(std::is_base_of<Base, T>::value, "T must derive from Base"); static_assert(std::is_base_of<Base, T>::value, "T must derive from Base");
if (T* v = Get<T>(k)) if (T* v = Get<T>(k))
{
return v; return v;
}
T* v = new T(); T* v = new T();
Container.emplace(k, std::unique_ptr<T>(v)); Container.emplace(k, std::unique_ptr<T>(v));
return v; return v;

View File

@@ -64,18 +64,22 @@ void EventProcessor::KillAllEvents(bool force)
delete i_old->second; delete i_old->second;
if (!force) // need per-element cleanup if (!force) // need per-element cleanup
{
m_events.erase (i_old); m_events.erase (i_old);
}
} }
} }
// fast clear event list (in force case) // fast clear event list (in force case)
if (force) if (force)
{
m_events.clear(); m_events.clear();
}
} }
void EventProcessor::AddEvent(BasicEvent* Event, uint64 e_time, bool set_addtime) void EventProcessor::AddEvent(BasicEvent* Event, uint64 e_time, bool set_addtime)
{ {
if (set_addtime) Event->m_addTime = m_time; if (set_addtime) { Event->m_addTime = m_time; }
Event->m_execTime = e_time; Event->m_execTime = e_time;
m_events.insert(std::pair<uint64, BasicEvent*>(e_time, Event)); m_events.insert(std::pair<uint64, BasicEvent*>(e_time, Event));
} }

View File

@@ -28,7 +28,7 @@
[[nodiscard]] inline float getSlopeAngle(float startX, float startY, float startZ, float destX, float destY, float destZ) [[nodiscard]] inline float getSlopeAngle(float startX, float startY, float startZ, float destX, float destY, float destZ)
{ {
float floorDist = sqrt(pow(startY - destY, 2.0f) + pow(startX - destX,2.0f)); float floorDist = sqrt(pow(startY - destY, 2.0f) + pow(startX - destX, 2.0f));
return atan(abs(destZ - startZ) / abs(floorDist)); return atan(abs(destZ - startZ) / abs(floorDist));
} }

View File

@@ -20,11 +20,15 @@ inline T standard_deviation(Container&& c)
auto mean = sum / size; auto mean = sum / size;
if (size == 1) if (size == 1)
{
return (T) 0; return (T) 0;
}
T accum = T(); T accum = T();
for (const auto d : c) for (const auto d : c)
{
accum += (d - mean) * (d - mean); accum += (d - mean) * (d - mean);
}
return std::sqrt(accum / (size - 1)); return std::sqrt(accum / (size - 1));
} }
@@ -43,7 +47,8 @@ inline T median(std::vector<T> a)
{ {
size_t n = a.size(); size_t n = a.size();
// If size of the arr[] is even // If size of the arr[] is even
if (n % 2 == 0) { if (n % 2 == 0)
{
// Applying nth_element // Applying nth_element
// on n/2th index // on n/2th index
@@ -65,7 +70,8 @@ inline T median(std::vector<T> a)
} }
// If size of the arr[] is odd // If size of the arr[] is odd
else { else
{
// Applying nth_element // Applying nth_element
// on n/2 // on n/2

View File

@@ -15,7 +15,9 @@ static RandomEngine engine;
static SFMTRand* GetRng() static SFMTRand* GetRng()
{ {
if (!sfmtRand) if (!sfmtRand)
{
sfmtRand = std::make_unique<SFMTRand>(); sfmtRand = std::make_unique<SFMTRand>();
}
return sfmtRand.get(); return sfmtRand.get();
} }
@@ -51,7 +53,7 @@ Milliseconds randtime(Milliseconds min, Milliseconds max)
{ {
long long diff = max.count() - min.count(); long long diff = max.count() - min.count();
ASSERT(diff >= 0); ASSERT(diff >= 0);
ASSERT(diff <= (uint32)-1); ASSERT(diff <= (uint32) - 1);
return min + Milliseconds(urand(0, diff)); return min + Milliseconds(urand(0, diff));
} }

View File

@@ -26,7 +26,9 @@ namespace Acore
std::lock_guard lock(_mutex); std::lock_guard lock(_mutex);
if (_handled.find(sig) != _handled.end()) if (_handled.find(sig) != _handled.end())
{
return false; return false;
}
_handled.insert(sig); _handled.insert(sig);
signal(sig, func); signal(sig, func);
@@ -36,7 +38,9 @@ namespace Acore
~SignalHandler() ~SignalHandler()
{ {
for (auto const& sig : _handled) for (auto const& sig : _handled)
{
signal(sig, nullptr); signal(sig, nullptr);
}
} }
}; };
} }

View File

@@ -34,87 +34,88 @@ namespace Acore::Impl::EnumUtilsImpl
class EnumUtils class EnumUtils
{ {
public: public:
template <typename Enum> template <typename Enum>
static size_t Count() { return Acore::Impl::EnumUtilsImpl::EnumUtils<Enum>::Count(); } static size_t Count() { return Acore::Impl::EnumUtilsImpl::EnumUtils<Enum>::Count(); }
template <typename Enum> template <typename Enum>
static EnumText ToString(Enum value) { return Acore::Impl::EnumUtilsImpl::EnumUtils<Enum>::ToString(value); } static EnumText ToString(Enum value) { return Acore::Impl::EnumUtilsImpl::EnumUtils<Enum>::ToString(value); }
template <typename Enum> template <typename Enum>
static Enum FromIndex(size_t index) { return Acore::Impl::EnumUtilsImpl::EnumUtils<Enum>::FromIndex(index); } static Enum FromIndex(size_t index) { return Acore::Impl::EnumUtilsImpl::EnumUtils<Enum>::FromIndex(index); }
template <typename Enum> template <typename Enum>
static uint32 ToIndex(Enum value) { return Acore::Impl::EnumUtilsImpl::EnumUtils<Enum>::ToIndex(value);} static uint32 ToIndex(Enum value) { return Acore::Impl::EnumUtilsImpl::EnumUtils<Enum>::ToIndex(value);}
template<typename Enum> template<typename Enum>
static bool IsValid(Enum value) static bool IsValid(Enum value)
{
try
{ {
try Acore::Impl::EnumUtilsImpl::EnumUtils<Enum>::ToIndex(value);
{ return true;
Acore::Impl::EnumUtilsImpl::EnumUtils<Enum>::ToIndex(value);
return true;
} catch (...)
{
return false;
}
} }
catch (...)
template<typename Enum>
static bool IsValid(std::underlying_type_t<Enum> value) { return IsValid(static_cast<Enum>(value)); }
template <typename Enum>
class Iterator
{ {
public: return false;
using iterator_category = std::random_access_iterator_tag; }
using value_type = Enum; }
using pointer = Enum*;
using reference = Enum&;
using difference_type = std::ptrdiff_t;
Iterator() : _index(EnumUtils::Count<Enum>()) {} template<typename Enum>
explicit Iterator(size_t index) : _index(index) { } static bool IsValid(std::underlying_type_t<Enum> value) { return IsValid(static_cast<Enum>(value)); }
bool operator==(const Iterator& other) const { return other._index == _index; } template <typename Enum>
bool operator!=(const Iterator& other) const { return !operator==(other); } class Iterator
difference_type operator-(Iterator const& other) const { return _index - other._index; } {
bool operator<(const Iterator& other) const { return _index < other._index; } public:
bool operator<=(const Iterator& other) const { return _index <= other._index; } using iterator_category = std::random_access_iterator_tag;
bool operator>(const Iterator& other) const { return _index > other._index; } using value_type = Enum;
bool operator>=(const Iterator& other) const { return _index >= other._index; } using pointer = Enum*;
using reference = Enum&;
using difference_type = std::ptrdiff_t;
value_type operator[](difference_type d) const { return FromIndex<Enum>(_index + d); } Iterator() : _index(EnumUtils::Count<Enum>()) {}
value_type operator*() const { return operator[](0); } explicit Iterator(size_t index) : _index(index) { }
Iterator& operator+=(difference_type d) { _index += d; return *this; } bool operator==(const Iterator& other) const { return other._index == _index; }
Iterator& operator++() { return operator+=(1); } bool operator!=(const Iterator& other) const { return !operator==(other); }
Iterator operator++(int) { Iterator i = *this; operator++(); return i; } difference_type operator-(Iterator const& other) const { return _index - other._index; }
Iterator operator+(difference_type d) const { Iterator i = *this; i += d; return i; } bool operator<(const Iterator& other) const { return _index < other._index; }
bool operator<=(const Iterator& other) const { return _index <= other._index; }
bool operator>(const Iterator& other) const { return _index > other._index; }
bool operator>=(const Iterator& other) const { return _index >= other._index; }
Iterator& operator-=(difference_type d) { _index -= d; return *this; } value_type operator[](difference_type d) const { return FromIndex<Enum>(_index + d); }
Iterator& operator--() { return operator-=(1); } value_type operator*() const { return operator[](0); }
Iterator operator--(int) { Iterator i = *this; operator--(); return i; }
Iterator operator-(difference_type d) const { Iterator i = *this; i -= d; return i; }
private: Iterator& operator+=(difference_type d) { _index += d; return *this; }
difference_type _index; Iterator& operator++() { return operator+=(1); }
}; Iterator operator++(int) { Iterator i = *this; operator++(); return i; }
Iterator operator+(difference_type d) const { Iterator i = *this; i += d; return i; }
template <typename Enum> Iterator& operator-=(difference_type d) { _index -= d; return *this; }
static Iterator<Enum> Begin() { return Iterator<Enum>(0); } Iterator& operator--() { return operator-=(1); }
Iterator operator--(int) { Iterator i = *this; operator--(); return i; }
Iterator operator-(difference_type d) const { Iterator i = *this; i -= d; return i; }
template <typename Enum> private:
static Iterator<Enum> End() { return Iterator<Enum>(); } difference_type _index;
};
template <typename Enum> template <typename Enum>
static Acore::IteratorPair<Iterator<Enum>> Iterate() { return { Begin<Enum>(), End<Enum>() }; } static Iterator<Enum> Begin() { return Iterator<Enum>(0); }
template <typename Enum> template <typename Enum>
static char const* ToConstant(Enum value) { return ToString(value).Constant; } static Iterator<Enum> End() { return Iterator<Enum>(); }
template <typename Enum> template <typename Enum>
static char const* ToTitle(Enum value) { return ToString(value).Title; } static Acore::IteratorPair<Iterator<Enum>> Iterate() { return { Begin<Enum>(), End<Enum>() }; }
template <typename Enum> template <typename Enum>
static char const* ToDescription(Enum value) { return ToString(value).Description; } static char const* ToConstant(Enum value) { return ToString(value).Constant; }
template <typename Enum>
static char const* ToTitle(Enum value) { return ToString(value).Title; }
template <typename Enum>
static char const* ToDescription(Enum value) { return ToString(value).Description; }
}; };
#endif #endif

View File

@@ -41,10 +41,14 @@ namespace Acore::Impl::StringConvertImpl
str.remove_prefix(2); str.remove_prefix(2);
} }
else else
{
base = 10; base = 10;
}
if (str.empty()) if (str.empty())
{
return std::nullopt; return std::nullopt;
}
} }
char const* const start = str.data(); char const* const start = str.data();
@@ -53,14 +57,18 @@ namespace Acore::Impl::StringConvertImpl
T val; T val;
std::from_chars_result const res = std::from_chars(start, end, val, base); std::from_chars_result const res = std::from_chars(start, end, val, base);
if ((res.ptr == end) && (res.ec == std::errc())) if ((res.ptr == end) && (res.ec == std::errc()))
{
return val; return val;
}
else else
{
return std::nullopt; return std::nullopt;
}
} }
static std::string ToString(T val) static std::string ToString(T val)
{ {
std::string buf(20,'\0'); /* 2^64 is 20 decimal characters, -(2^63) is 20 including the sign */ std::string buf(20, '\0'); /* 2^64 is 20 decimal characters, -(2^63) is 20 including the sign */
char* const start = buf.data(); char* const start = buf.data();
char* const end = (start + buf.length()); char* const end = (start + buf.length());
std::to_chars_result const res = std::to_chars(start, end, val); std::to_chars_result const res = std::to_chars(start, end, val);
@@ -84,13 +92,17 @@ namespace Acore::Impl::StringConvertImpl
static Optional<uint64> FromString(std::string_view str, int base = 10) static Optional<uint64> FromString(std::string_view str, int base = 10)
{ {
if (str.empty()) if (str.empty())
{
return std::nullopt; return std::nullopt;
}
try try
{ {
size_t n; size_t n;
uint64 val = std::stoull(std::string(str), &n, base); uint64 val = std::stoull(std::string(str), &n, base);
if (n != str.length()) if (n != str.length())
{
return std::nullopt; return std::nullopt;
}
return val; return val;
} }
catch (...) { return std::nullopt; } catch (...) { return std::nullopt; }
@@ -107,13 +119,18 @@ namespace Acore::Impl::StringConvertImpl
{ {
static Optional<int64> FromString(std::string_view str, int base = 10) static Optional<int64> FromString(std::string_view str, int base = 10)
{ {
try { try
{
if (str.empty()) if (str.empty())
{
return std::nullopt; return std::nullopt;
}
size_t n; size_t n;
int64 val = std::stoll(std::string(str), &n, base); int64 val = std::stoll(std::string(str), &n, base);
if (n != str.length()) if (n != str.length())
{
return std::nullopt; return std::nullopt;
}
return val; return val;
} }
catch (...) { return std::nullopt; } catch (...) { return std::nullopt; }
@@ -134,17 +151,25 @@ namespace Acore::Impl::StringConvertImpl
if (strict) if (strict)
{ {
if (str == "1") if (str == "1")
{
return true; return true;
}
if (str == "0") if (str == "0")
{
return false; return false;
}
return std::nullopt; return std::nullopt;
} }
else else
{ {
if ((str == "1") || StringEqualI(str, "y") || StringEqualI(str, "on") || StringEqualI(str, "yes") || StringEqualI(str, "true")) if ((str == "1") || StringEqualI(str, "y") || StringEqualI(str, "on") || StringEqualI(str, "yes") || StringEqualI(str, "true"))
{
return true; return true;
}
if ((str == "0") || StringEqualI(str, "n") || StringEqualI(str, "off") || StringEqualI(str, "no") || StringEqualI(str, "false")) if ((str == "0") || StringEqualI(str, "n") || StringEqualI(str, "off") || StringEqualI(str, "no") || StringEqualI(str, "false"))
{
return false; return false;
}
return std::nullopt; return std::nullopt;
} }
} }
@@ -162,7 +187,9 @@ namespace Acore::Impl::StringConvertImpl
static Optional<T> FromString(std::string_view str, std::chars_format fmt = std::chars_format()) static Optional<T> FromString(std::string_view str, std::chars_format fmt = std::chars_format())
{ {
if (str.empty()) if (str.empty())
{
return std::nullopt; return std::nullopt;
}
if (fmt == std::chars_format()) if (fmt == std::chars_format())
{ {
@@ -172,10 +199,14 @@ namespace Acore::Impl::StringConvertImpl
str.remove_prefix(2); str.remove_prefix(2);
} }
else else
{
fmt = std::chars_format::general; fmt = std::chars_format::general;
}
if (str.empty()) if (str.empty())
{
return std::nullopt; return std::nullopt;
}
} }
char const* const start = str.data(); char const* const start = str.data();
@@ -184,20 +215,30 @@ namespace Acore::Impl::StringConvertImpl
T val; T val;
std::from_chars_result const res = std::from_chars(start, end, val, fmt); std::from_chars_result const res = std::from_chars(start, end, val, fmt);
if ((res.ptr == end) && (res.ec == std::errc())) if ((res.ptr == end) && (res.ec == std::errc()))
{
return val; return val;
}
else else
{
return std::nullopt; return std::nullopt;
}
} }
// this allows generic converters for all numeric types (easier templating!) // this allows generic converters for all numeric types (easier templating!)
static Optional<T> FromString(std::string_view str, int base) static Optional<T> FromString(std::string_view str, int base)
{ {
if (base == 16) if (base == 16)
{
return FromString(str, std::chars_format::hex); return FromString(str, std::chars_format::hex);
}
else if (base == 10) else if (base == 10)
{
return FromString(str, std::chars_format::general); return FromString(str, std::chars_format::general);
}
else else
{
return FromString(str, std::chars_format()); return FromString(str, std::chars_format());
}
} }
static std::string ToString(T val) static std::string ToString(T val)
@@ -212,22 +253,31 @@ namespace Acore::Impl::StringConvertImpl
{ {
static Optional<T> FromString(std::string_view str, int base = 0) static Optional<T> FromString(std::string_view str, int base = 0)
{ {
try { try
{
if (str.empty()) if (str.empty())
{
return std::nullopt; return std::nullopt;
}
if ((base == 10) && StringEqualI(str.substr(0, 2), "0x")) if ((base == 10) && StringEqualI(str.substr(0, 2), "0x"))
{
return std::nullopt; return std::nullopt;
}
std::string tmp; std::string tmp;
if (base == 16) if (base == 16)
{
tmp.append("0x"); tmp.append("0x");
}
tmp.append(str); tmp.append(str);
size_t n; size_t n;
T val = static_cast<T>(std::stold(tmp, &n)); T val = static_cast<T>(std::stold(tmp, &n));
if (n != tmp.length()) if (n != tmp.length())
{
return std::nullopt; return std::nullopt;
}
return val; return val;
} }
catch (...) { return std::nullopt; } catch (...) { return std::nullopt; }

View File

@@ -13,19 +13,26 @@ Str Acore::String::Trim(const Str& s, const std::locale& loc /*= std::locale()*/
typename Str::const_iterator end = s.end(); typename Str::const_iterator end = s.end();
while (first != end && std::isspace(*first, loc)) while (first != end && std::isspace(*first, loc))
{
++first; ++first;
}
if (first == end) if (first == end)
{
return Str(); return Str();
}
typename Str::const_iterator last = end; typename Str::const_iterator last = end;
do do
{
--last; --last;
while (std::isspace(*last, loc)); } while (std::isspace(*last, loc));
if (first != s.begin() || last + 1 != end) if (first != s.begin() || last + 1 != end)
{
return Str(first, last + 1); return Str(first, last + 1);
}
return s; return s;
} }

View File

@@ -65,7 +65,9 @@ void TaskScheduler::Dispatch(success_t const& callback)
{ {
// If the validation failed abort the dispatching here. // If the validation failed abort the dispatching here.
if (!_predicate()) if (!_predicate())
{
return; return;
}
// Process all asyncs // Process all asyncs
while (!_asyncHolder.empty()) while (!_asyncHolder.empty())
@@ -75,13 +77,17 @@ void TaskScheduler::Dispatch(success_t const& callback)
// If the validation failed abort the dispatching here. // If the validation failed abort the dispatching here.
if (!_predicate()) if (!_predicate())
{
return; return;
}
} }
while (!_task_holder.IsEmpty()) while (!_task_holder.IsEmpty())
{ {
if (_task_holder.First()->_end > _now) if (_task_holder.First()->_end > _now)
{
break; break;
}
// Perfect forward the context to the handler // Perfect forward the context to the handler
// Use weak references to catch destruction before callbacks. // Use weak references to catch destruction before callbacks.
@@ -92,7 +98,9 @@ void TaskScheduler::Dispatch(success_t const& callback)
// If the validation failed abort the dispatching here. // If the validation failed abort the dispatching here.
if (!_predicate()) if (!_predicate())
{
return; return;
}
} }
// On finish call the final callback // On finish call the final callback
@@ -125,9 +133,13 @@ void TaskScheduler::TaskQueue::RemoveIf(std::function<bool(TaskContainer const&)
{ {
for (auto itr = container.begin(); itr != container.end();) for (auto itr = container.begin(); itr != container.end();)
if (filter(*itr)) if (filter(*itr))
{
itr = container.erase(itr); itr = container.erase(itr);
}
else else
{
++itr; ++itr;
}
} }
void TaskScheduler::TaskQueue::ModifyIf(std::function<bool(TaskContainer const&)> const& filter) void TaskScheduler::TaskQueue::ModifyIf(std::function<bool(TaskContainer const&)> const& filter)
@@ -140,7 +152,9 @@ void TaskScheduler::TaskQueue::ModifyIf(std::function<bool(TaskContainer const&)
itr = container.erase(itr); itr = container.erase(itr);
} }
else else
{
++itr; ++itr;
}
container.insert(cache.begin(), cache.end()); container.insert(cache.begin(), cache.end());
} }
@@ -153,7 +167,9 @@ bool TaskScheduler::TaskQueue::IsEmpty() const
TaskContext& TaskContext::Dispatch(std::function<TaskScheduler&(TaskScheduler&)> const& apply) TaskContext& TaskContext::Dispatch(std::function<TaskScheduler&(TaskScheduler&)> const& apply)
{ {
if (auto const owner = _owner.lock()) if (auto const owner = _owner.lock())
{
apply(*owner); apply(*owner);
}
return *this; return *this;
} }

View File

@@ -292,7 +292,9 @@ public:
return true; return true;
} }
else else
{
return false; return false;
}
}); });
return *this; return *this;
} }
@@ -340,7 +342,9 @@ public:
return true; return true;
} }
else else
{
return false; return false;
}
}); });
return *this; return *this;
} }

View File

@@ -30,9 +30,13 @@ inline uint32 getMSTimeDiff(uint32 oldMSTime, uint32 newMSTime)
{ {
// getMSTime() have limited data range and this is case when it overflow in this tick // getMSTime() have limited data range and this is case when it overflow in this tick
if (oldMSTime > newMSTime) if (oldMSTime > newMSTime)
{
return (0xFFFFFFFF - oldMSTime) + newMSTime; return (0xFFFFFFFF - oldMSTime) + newMSTime;
}
else else
{
return newMSTime - oldMSTime; return newMSTime - oldMSTime;
}
} }
inline uint32 getMSTimeDiff(uint32 oldMSTime, TimePoint newTime) inline uint32 getMSTimeDiff(uint32 oldMSTime, TimePoint newTime)
@@ -60,7 +64,9 @@ public:
{ {
_current += diff; _current += diff;
if (_current < 0) if (_current < 0)
{
_current = 0; _current = 0;
}
} }
bool Passed() bool Passed()
@@ -71,7 +77,9 @@ public:
void Reset() void Reset()
{ {
if (_current >= _interval) if (_current >= _interval)
{
_current %= _interval; _current %= _interval;
}
} }
void SetCurrent(time_t current) void SetCurrent(time_t current)
@@ -174,7 +182,9 @@ public:
bool Update(const uint32 diff) bool Update(const uint32 diff)
{ {
if ((i_expireTime -= diff) > 0) if ((i_expireTime -= diff) > 0)
{
return false; return false;
}
i_expireTime += i_period > int32(diff) ? i_period : diff; i_expireTime += i_period > int32(diff) ? i_period : diff;
return true; return true;

View File

@@ -13,13 +13,17 @@ std::vector<std::string_view> Acore::Tokenize(std::string_view str, char sep, bo
for (size_t end = str.find(sep); end != std::string_view::npos; end = str.find(sep, start)) for (size_t end = str.find(sep); end != std::string_view::npos; end = str.find(sep, start))
{ {
if (keepEmpty || (start < end)) if (keepEmpty || (start < end))
{
tokens.push_back(str.substr(start, end - start)); tokens.push_back(str.substr(start, end - start));
}
start = end + 1; start = end + 1;
} }
if (keepEmpty || (start < str.length())) if (keepEmpty || (start < str.length()))
{
tokens.push_back(str.substr(start)); tokens.push_back(str.substr(start));
}
return tokens; return tokens;
} }

View File

@@ -26,7 +26,9 @@ Tokenizer::Tokenizer(const std::string& src, const char sep, uint32 vectorReserv
memcpy(m_str, src.c_str(), src.length() + 1); memcpy(m_str, src.c_str(), src.length() + 1);
if (vectorReserve) if (vectorReserve)
{
m_storage.reserve(vectorReserve); m_storage.reserve(vectorReserve);
}
char* posold = m_str; char* posold = m_str;
char* posnew = m_str; char* posnew = m_str;
@@ -45,7 +47,9 @@ Tokenizer::Tokenizer(const std::string& src, const char sep, uint32 vectorReserv
// Hack like, but the old code accepted these kind of broken strings, // Hack like, but the old code accepted these kind of broken strings,
// so changing it would break other things // so changing it would break other things
if (posold != posnew) if (posold != posnew)
{
m_storage.push_back(posold); m_storage.push_back(posold);
}
break; break;
} }
@@ -88,7 +92,9 @@ time_t GetLocalHourTimestamp(time_t time, uint8 hour, bool onlyAfterTime)
time_t hourLocal = midnightLocal + hour * HOUR; time_t hourLocal = midnightLocal + hour * HOUR;
if (onlyAfterTime && hourLocal <= time) if (onlyAfterTime && hourLocal <= time)
{
hourLocal += DAY; hourLocal += DAY;
}
return hourLocal; return hourLocal;
} }
@@ -113,17 +119,25 @@ void stripLineInvisibleChars(std::string& str)
else else
{ {
if (wpos != pos) if (wpos != pos)
{
str[wpos++] = str[pos]; str[wpos++] = str[pos];
}
else else
{
++wpos; ++wpos;
}
space = false; space = false;
} }
} }
if (wpos < str.size()) if (wpos < str.size())
{
str.erase(wpos, str.size()); str.erase(wpos, str.size());
}
if (str.find("|TInterface") != std::string::npos) if (str.find("|TInterface") != std::string::npos)
{
str.clear(); str.clear();
}
} }
std::string secsToTimeString(uint64 timeInSecs, bool shortText) std::string secsToTimeString(uint64 timeInSecs, bool shortText)
@@ -135,18 +149,28 @@ std::string secsToTimeString(uint64 timeInSecs, bool shortText)
std::ostringstream ss; std::ostringstream ss;
if (days) if (days)
{
ss << days << (shortText ? "d" : " day(s) "); ss << days << (shortText ? "d" : " day(s) ");
}
if (hours) if (hours)
{
ss << hours << (shortText ? "h" : " hour(s) "); ss << hours << (shortText ? "h" : " hour(s) ");
}
if (minutes) if (minutes)
{
ss << minutes << (shortText ? "m" : " minute(s) "); ss << minutes << (shortText ? "m" : " minute(s) ");
}
if (secs || (!days && !hours && !minutes) ) if (secs || (!days && !hours && !minutes) )
{
ss << secs << (shortText ? "s" : " second(s) "); ss << secs << (shortText ? "s" : " second(s) ");
}
std::string str = ss.str(); std::string str = ss.str();
if (!shortText && !str.empty() && str[str.size() - 1] == ' ') if (!shortText && !str.empty() && str[str.size() - 1] == ' ')
{
str.resize(str.size() - 1); str.resize(str.size() - 1);
}
return str; return str;
} }
@@ -158,7 +182,9 @@ int32 MoneyStringToMoney(const std::string& moneyString)
if (!(std::count(moneyString.begin(), moneyString.end(), 'g') == 1 || if (!(std::count(moneyString.begin(), moneyString.end(), 'g') == 1 ||
std::count(moneyString.begin(), moneyString.end(), 's') == 1 || std::count(moneyString.begin(), moneyString.end(), 's') == 1 ||
std::count(moneyString.begin(), moneyString.end(), 'c') == 1)) std::count(moneyString.begin(), moneyString.end(), 'c') == 1))
return 0; // Bad format {
return 0; // Bad format
}
Tokenizer tokens(moneyString, ' '); Tokenizer tokens(moneyString, ' ');
for (Tokenizer::const_iterator itr = tokens.begin(); itr != tokens.end(); ++itr) for (Tokenizer::const_iterator itr = tokens.begin(); itr != tokens.end(); ++itr)
@@ -168,15 +194,23 @@ int32 MoneyStringToMoney(const std::string& moneyString)
size_t sCount = std::count(tokenString.begin(), tokenString.end(), 's'); size_t sCount = std::count(tokenString.begin(), tokenString.end(), 's');
size_t cCount = std::count(tokenString.begin(), tokenString.end(), 'c'); size_t cCount = std::count(tokenString.begin(), tokenString.end(), 'c');
if (gCount + sCount + cCount != 1) if (gCount + sCount + cCount != 1)
{
return 0; return 0;
}
uint32 amount = atoi(*itr); uint32 amount = atoi(*itr);
if (gCount == 1) if (gCount == 1)
{
money += amount * 100 * 100; money += amount * 100 * 100;
}
else if (sCount == 1) else if (sCount == 1)
{
money += amount * 100; money += amount * 100;
}
else if (cCount == 1) else if (cCount == 1)
{
money += amount; money += amount;
}
} }
return money; return money;
@@ -257,7 +291,9 @@ std::string TimeToHumanReadable(time_t t)
bool IsIPAddress(char const* ipaddress) bool IsIPAddress(char const* ipaddress)
{ {
if (!ipaddress) if (!ipaddress)
{
return false; return false;
}
// Let the big boys do it. // Let the big boys do it.
// Drawback: all valid ip address formats are recognized e.g.: 12.23, 121234, 0xABCD) // Drawback: all valid ip address formats are recognized e.g.: 12.23, 121234, 0xABCD)
@@ -275,7 +311,9 @@ bool IsIPAddrInNetwork(ACE_INET_Addr const& net, ACE_INET_Addr const& addr, ACE_
{ {
uint32 mask = subnetMask.get_ip_address(); uint32 mask = subnetMask.get_ip_address();
if ((net.get_ip_address() & mask) == (addr.get_ip_address() & mask)) if ((net.get_ip_address() & mask) == (addr.get_ip_address() & mask))
{
return true; return true;
}
return false; return false;
} }
@@ -284,7 +322,9 @@ uint32 CreatePIDFile(std::string const& filename)
{ {
FILE* pid_file = fopen(filename.c_str(), "w"); FILE* pid_file = fopen(filename.c_str(), "w");
if (pid_file == nullptr) if (pid_file == nullptr)
{
return 0; return 0;
}
uint32 pid = GetPID(); uint32 pid = GetPID();
@@ -324,7 +364,9 @@ void utf8truncate(std::string& utf8str, size_t len)
{ {
size_t wlen = utf8::distance(utf8str.c_str(), utf8str.c_str() + utf8str.size()); size_t wlen = utf8::distance(utf8str.c_str(), utf8str.c_str() + utf8str.size());
if (wlen <= len) if (wlen <= len)
{
return; return;
}
std::wstring wstr; std::wstring wstr;
wstr.resize(wlen); wstr.resize(wlen);
@@ -365,7 +407,9 @@ bool Utf8toWStr(char const* utf8str, size_t csize, wchar_t* wstr, size_t& wsize)
wsize = 0; wsize = 0;
} }
else else
{
wsize = 0; wsize = 0;
}
return false; return false;
} }
@@ -451,7 +495,9 @@ std::wstring GetMainPartOfName(std::wstring const& wname, uint32 declension)
{ {
// supported only Cyrillic cases // supported only Cyrillic cases
if (wname.empty() || !isCyrillicCharacter(wname[0]) || declension > 5) if (wname.empty() || !isCyrillicCharacter(wname[0]) || declension > 5)
{
return wname; return wname;
}
// Important: end length must be <= MAX_INTERNAL_PLAYER_NAME-MAX_PLAYER_NAME (3 currently) // Important: end length must be <= MAX_INTERNAL_PLAYER_NAME-MAX_PLAYER_NAME (3 currently)
static std::wstring const a_End = { wchar_t(0x0430), wchar_t(0x0000) }; static std::wstring const a_End = { wchar_t(0x0430), wchar_t(0x0000) };
@@ -488,10 +534,14 @@ std::wstring GetMainPartOfName(std::wstring const& wname, uint32 declension)
std::wstring const& ending = **itr; std::wstring const& ending = **itr;
std::size_t const endLen = ending.length(); std::size_t const endLen = ending.length();
if (!(endLen <= thisLen)) if (!(endLen <= thisLen))
{
continue; continue;
}
if (wname.substr(thisLen - endLen, thisLen) == ending) if (wname.substr(thisLen - endLen, thisLen) == ending)
{
return wname.substr(0, thisLen - endLen); return wname.substr(0, thisLen - endLen);
}
} }
return wname; return wname;
@@ -502,7 +552,9 @@ bool utf8ToConsole(const std::string& utf8str, std::string& conStr)
#if AC_PLATFORM == AC_PLATFORM_WINDOWS #if AC_PLATFORM == AC_PLATFORM_WINDOWS
std::wstring wstr; std::wstring wstr;
if (!Utf8toWStr(utf8str, wstr)) if (!Utf8toWStr(utf8str, wstr))
{
return false; return false;
}
conStr.resize(wstr.size()); conStr.resize(wstr.size());
CharToOemBuffW(&wstr[0], &conStr[0], wstr.size()); CharToOemBuffW(&wstr[0], &conStr[0], wstr.size());
@@ -534,13 +586,17 @@ bool Utf8FitTo(const std::string& str, std::wstring const& search)
std::wstring temp; std::wstring temp;
if (!Utf8toWStr(str, temp)) if (!Utf8toWStr(str, temp))
{
return false; return false;
}
// converting to lower case // converting to lower case
wstrToLower(temp); wstrToLower(temp);
if (temp.find(search) == std::wstring::npos) if (temp.find(search) == std::wstring::npos)
{
return false; return false;
}
return true; return true;
} }
@@ -562,7 +618,9 @@ void vutf8printf(FILE* out, const char* str, va_list* ap)
size_t temp_len = vsnprintf(temp_buf, 32 * 1024, str, *ap); size_t temp_len = vsnprintf(temp_buf, 32 * 1024, str, *ap);
//vsnprintf returns -1 if the buffer is too small //vsnprintf returns -1 if the buffer is too small
if (temp_len == size_t(-1)) if (temp_len == size_t(-1))
{
temp_len = 32 * 1024 - 1; temp_len = 32 * 1024 - 1;
}
size_t wtemp_len = 32 * 1024 - 1; size_t wtemp_len = 32 * 1024 - 1;
Utf8toWStr(temp_buf, temp_len, wtemp_buf, wtemp_len); Utf8toWStr(temp_buf, temp_len, wtemp_buf, wtemp_len);
@@ -578,7 +636,9 @@ bool Utf8ToUpperOnlyLatin(std::string& utf8String)
{ {
std::wstring wstr; std::wstring wstr;
if (!Utf8toWStr(utf8String, wstr)) if (!Utf8toWStr(utf8String, wstr))
{
return false; return false;
}
std::transform(wstr.begin(), wstr.end(), wstr.begin(), wcharToUpperOnlyLatin); std::transform(wstr.begin(), wstr.end(), wstr.begin(), wcharToUpperOnlyLatin);

View File

@@ -74,7 +74,9 @@ std::string TimeToHumanReadable(time_t t);
inline void ApplyPercentModFloatVar(float& var, float val, bool apply) inline void ApplyPercentModFloatVar(float& var, float val, bool apply)
{ {
if (val == -100.0f) // prevent set var to zero if (val == -100.0f) // prevent set var to zero
{
val = -99.99f; val = -99.99f;
}
var *= (apply ? (100.0f + val) / 100.0f : 100.0f / (100.0f + val)); var *= (apply ? (100.0f + val) / 100.0f : 100.0f / (100.0f + val));
} }
@@ -125,60 +127,100 @@ void utf8truncate(std::string& utf8str, size_t len);
inline bool isBasicLatinCharacter(wchar_t wchar) inline bool isBasicLatinCharacter(wchar_t wchar)
{ {
if (wchar >= L'a' && wchar <= L'z') // LATIN SMALL LETTER A - LATIN SMALL LETTER Z if (wchar >= L'a' && wchar <= L'z') // LATIN SMALL LETTER A - LATIN SMALL LETTER Z
{
return true; return true;
}
if (wchar >= L'A' && wchar <= L'Z') // LATIN CAPITAL LETTER A - LATIN CAPITAL LETTER Z if (wchar >= L'A' && wchar <= L'Z') // LATIN CAPITAL LETTER A - LATIN CAPITAL LETTER Z
{
return true; return true;
}
return false; return false;
} }
inline bool isExtendedLatinCharacter(wchar_t wchar) inline bool isExtendedLatinCharacter(wchar_t wchar)
{ {
if (isBasicLatinCharacter(wchar)) if (isBasicLatinCharacter(wchar))
{
return true; return true;
}
if (wchar >= 0x00C0 && wchar <= 0x00D6) // LATIN CAPITAL LETTER A WITH GRAVE - LATIN CAPITAL LETTER O WITH DIAERESIS if (wchar >= 0x00C0 && wchar <= 0x00D6) // LATIN CAPITAL LETTER A WITH GRAVE - LATIN CAPITAL LETTER O WITH DIAERESIS
{
return true; return true;
}
if (wchar >= 0x00D8 && wchar <= 0x00DE) // LATIN CAPITAL LETTER O WITH STROKE - LATIN CAPITAL LETTER THORN if (wchar >= 0x00D8 && wchar <= 0x00DE) // LATIN CAPITAL LETTER O WITH STROKE - LATIN CAPITAL LETTER THORN
{
return true; return true;
}
if (wchar == 0x00DF) // LATIN SMALL LETTER SHARP S if (wchar == 0x00DF) // LATIN SMALL LETTER SHARP S
{
return true; return true;
}
if (wchar >= 0x00E0 && wchar <= 0x00F6) // LATIN SMALL LETTER A WITH GRAVE - LATIN SMALL LETTER O WITH DIAERESIS if (wchar >= 0x00E0 && wchar <= 0x00F6) // LATIN SMALL LETTER A WITH GRAVE - LATIN SMALL LETTER O WITH DIAERESIS
{
return true; return true;
}
if (wchar >= 0x00F8 && wchar <= 0x00FE) // LATIN SMALL LETTER O WITH STROKE - LATIN SMALL LETTER THORN if (wchar >= 0x00F8 && wchar <= 0x00FE) // LATIN SMALL LETTER O WITH STROKE - LATIN SMALL LETTER THORN
{
return true; return true;
}
if (wchar >= 0x0100 && wchar <= 0x012F) // LATIN CAPITAL LETTER A WITH MACRON - LATIN SMALL LETTER I WITH OGONEK if (wchar >= 0x0100 && wchar <= 0x012F) // LATIN CAPITAL LETTER A WITH MACRON - LATIN SMALL LETTER I WITH OGONEK
{
return true; return true;
}
if (wchar == 0x1E9E) // LATIN CAPITAL LETTER SHARP S if (wchar == 0x1E9E) // LATIN CAPITAL LETTER SHARP S
{
return true; return true;
}
return false; return false;
} }
inline bool isCyrillicCharacter(wchar_t wchar) inline bool isCyrillicCharacter(wchar_t wchar)
{ {
if (wchar >= 0x0410 && wchar <= 0x044F) // CYRILLIC CAPITAL LETTER A - CYRILLIC SMALL LETTER YA if (wchar >= 0x0410 && wchar <= 0x044F) // CYRILLIC CAPITAL LETTER A - CYRILLIC SMALL LETTER YA
{
return true; return true;
}
if (wchar == 0x0401 || wchar == 0x0451) // CYRILLIC CAPITAL LETTER IO, CYRILLIC SMALL LETTER IO if (wchar == 0x0401 || wchar == 0x0451) // CYRILLIC CAPITAL LETTER IO, CYRILLIC SMALL LETTER IO
{
return true; return true;
}
return false; return false;
} }
inline bool isEastAsianCharacter(wchar_t wchar) inline bool isEastAsianCharacter(wchar_t wchar)
{ {
if (wchar >= 0x1100 && wchar <= 0x11F9) // Hangul Jamo if (wchar >= 0x1100 && wchar <= 0x11F9) // Hangul Jamo
{
return true; return true;
}
if (wchar >= 0x3041 && wchar <= 0x30FF) // Hiragana + Katakana if (wchar >= 0x3041 && wchar <= 0x30FF) // Hiragana + Katakana
{
return true; return true;
}
if (wchar >= 0x3131 && wchar <= 0x318E) // Hangul Compatibility Jamo if (wchar >= 0x3131 && wchar <= 0x318E) // Hangul Compatibility Jamo
{
return true; return true;
}
if (wchar >= 0x31F0 && wchar <= 0x31FF) // Katakana Phonetic Ext. if (wchar >= 0x31F0 && wchar <= 0x31FF) // Katakana Phonetic Ext.
{
return true; return true;
}
if (wchar >= 0x3400 && wchar <= 0x4DB5) // CJK Ideographs Ext. A if (wchar >= 0x3400 && wchar <= 0x4DB5) // CJK Ideographs Ext. A
{
return true; return true;
}
if (wchar >= 0x4E00 && wchar <= 0x9FC3) // Unified CJK Ideographs if (wchar >= 0x4E00 && wchar <= 0x9FC3) // Unified CJK Ideographs
{
return true; return true;
}
if (wchar >= 0xAC00 && wchar <= 0xD7A3) // Hangul Syllables if (wchar >= 0xAC00 && wchar <= 0xD7A3) // Hangul Syllables
{
return true; return true;
}
if (wchar >= 0xFF01 && wchar <= 0xFFEE) // Halfwidth forms if (wchar >= 0xFF01 && wchar <= 0xFFEE) // Halfwidth forms
{
return true; return true;
}
return false; return false;
} }
@@ -196,7 +238,9 @@ inline bool isNumeric(char const* str)
{ {
for (char const* c = str; *c; ++c) for (char const* c = str; *c; ++c)
if (!isNumeric(*c)) if (!isNumeric(*c))
{
return false; return false;
}
return true; return true;
} }
@@ -210,7 +254,9 @@ inline bool isBasicLatinString(const std::wstring& wstr, bool numericOrSpace)
{ {
for (wchar_t i : wstr) for (wchar_t i : wstr)
if (!isBasicLatinCharacter(i) && (!numericOrSpace || !isNumericOrSpace(i))) if (!isBasicLatinCharacter(i) && (!numericOrSpace || !isNumericOrSpace(i)))
{
return false; return false;
}
return true; return true;
} }
@@ -218,7 +264,9 @@ inline bool isExtendedLatinString(const std::wstring& wstr, bool numericOrSpace)
{ {
for (wchar_t i : wstr) for (wchar_t i : wstr)
if (!isExtendedLatinCharacter(i) && (!numericOrSpace || !isNumericOrSpace(i))) if (!isExtendedLatinCharacter(i) && (!numericOrSpace || !isNumericOrSpace(i)))
{
return false; return false;
}
return true; return true;
} }
@@ -226,7 +274,9 @@ inline bool isCyrillicString(const std::wstring& wstr, bool numericOrSpace)
{ {
for (wchar_t i : wstr) for (wchar_t i : wstr)
if (!isCyrillicCharacter(i) && (!numericOrSpace || !isNumericOrSpace(i))) if (!isCyrillicCharacter(i) && (!numericOrSpace || !isNumericOrSpace(i)))
{
return false; return false;
}
return true; return true;
} }
@@ -234,29 +284,45 @@ inline bool isEastAsianString(const std::wstring& wstr, bool numericOrSpace)
{ {
for (wchar_t i : wstr) for (wchar_t i : wstr)
if (!isEastAsianCharacter(i) && (!numericOrSpace || !isNumericOrSpace(i))) if (!isEastAsianCharacter(i) && (!numericOrSpace || !isNumericOrSpace(i)))
{
return false; return false;
}
return true; return true;
} }
inline wchar_t wcharToUpper(wchar_t wchar) inline wchar_t wcharToUpper(wchar_t wchar)
{ {
if (wchar >= L'a' && wchar <= L'z') // LATIN SMALL LETTER A - LATIN SMALL LETTER Z if (wchar >= L'a' && wchar <= L'z') // LATIN SMALL LETTER A - LATIN SMALL LETTER Z
{
return wchar_t(uint16(wchar) - 0x0020); return wchar_t(uint16(wchar) - 0x0020);
}
if (wchar == 0x00DF) // LATIN SMALL LETTER SHARP S if (wchar == 0x00DF) // LATIN SMALL LETTER SHARP S
{
return wchar_t(0x1E9E); return wchar_t(0x1E9E);
}
if (wchar >= 0x00E0 && wchar <= 0x00F6) // LATIN SMALL LETTER A WITH GRAVE - LATIN SMALL LETTER O WITH DIAERESIS if (wchar >= 0x00E0 && wchar <= 0x00F6) // LATIN SMALL LETTER A WITH GRAVE - LATIN SMALL LETTER O WITH DIAERESIS
{
return wchar_t(uint16(wchar) - 0x0020); return wchar_t(uint16(wchar) - 0x0020);
}
if (wchar >= 0x00F8 && wchar <= 0x00FE) // LATIN SMALL LETTER O WITH STROKE - LATIN SMALL LETTER THORN if (wchar >= 0x00F8 && wchar <= 0x00FE) // LATIN SMALL LETTER O WITH STROKE - LATIN SMALL LETTER THORN
{
return wchar_t(uint16(wchar) - 0x0020); return wchar_t(uint16(wchar) - 0x0020);
}
if (wchar >= 0x0101 && wchar <= 0x012F) // LATIN SMALL LETTER A WITH MACRON - LATIN SMALL LETTER I WITH OGONEK (only %2=1) if (wchar >= 0x0101 && wchar <= 0x012F) // LATIN SMALL LETTER A WITH MACRON - LATIN SMALL LETTER I WITH OGONEK (only %2=1)
{ {
if (wchar % 2 == 1) if (wchar % 2 == 1)
{
return wchar_t(uint16(wchar) - 0x0001); return wchar_t(uint16(wchar) - 0x0001);
}
} }
if (wchar >= 0x0430 && wchar <= 0x044F) // CYRILLIC SMALL LETTER A - CYRILLIC SMALL LETTER YA if (wchar >= 0x0430 && wchar <= 0x044F) // CYRILLIC SMALL LETTER A - CYRILLIC SMALL LETTER YA
{
return wchar_t(uint16(wchar) - 0x0020); return wchar_t(uint16(wchar) - 0x0020);
}
if (wchar == 0x0451) // CYRILLIC SMALL LETTER IO if (wchar == 0x0451) // CYRILLIC SMALL LETTER IO
{
return wchar_t(0x0401); return wchar_t(0x0401);
}
return wchar; return wchar;
} }
@@ -269,22 +335,36 @@ inline wchar_t wcharToUpperOnlyLatin(wchar_t wchar)
inline wchar_t wcharToLower(wchar_t wchar) inline wchar_t wcharToLower(wchar_t wchar)
{ {
if (wchar >= L'A' && wchar <= L'Z') // LATIN CAPITAL LETTER A - LATIN CAPITAL LETTER Z if (wchar >= L'A' && wchar <= L'Z') // LATIN CAPITAL LETTER A - LATIN CAPITAL LETTER Z
{
return wchar_t(uint16(wchar) + 0x0020); return wchar_t(uint16(wchar) + 0x0020);
}
if (wchar >= 0x00C0 && wchar <= 0x00D6) // LATIN CAPITAL LETTER A WITH GRAVE - LATIN CAPITAL LETTER O WITH DIAERESIS if (wchar >= 0x00C0 && wchar <= 0x00D6) // LATIN CAPITAL LETTER A WITH GRAVE - LATIN CAPITAL LETTER O WITH DIAERESIS
{
return wchar_t(uint16(wchar) + 0x0020); return wchar_t(uint16(wchar) + 0x0020);
}
if (wchar >= 0x00D8 && wchar <= 0x00DE) // LATIN CAPITAL LETTER O WITH STROKE - LATIN CAPITAL LETTER THORN if (wchar >= 0x00D8 && wchar <= 0x00DE) // LATIN CAPITAL LETTER O WITH STROKE - LATIN CAPITAL LETTER THORN
{
return wchar_t(uint16(wchar) + 0x0020); return wchar_t(uint16(wchar) + 0x0020);
}
if (wchar >= 0x0100 && wchar <= 0x012E) // LATIN CAPITAL LETTER A WITH MACRON - LATIN CAPITAL LETTER I WITH OGONEK (only %2=0) if (wchar >= 0x0100 && wchar <= 0x012E) // LATIN CAPITAL LETTER A WITH MACRON - LATIN CAPITAL LETTER I WITH OGONEK (only %2=0)
{ {
if (wchar % 2 == 0) if (wchar % 2 == 0)
{
return wchar_t(uint16(wchar) + 0x0001); return wchar_t(uint16(wchar) + 0x0001);
}
} }
if (wchar == 0x1E9E) // LATIN CAPITAL LETTER SHARP S if (wchar == 0x1E9E) // LATIN CAPITAL LETTER SHARP S
{
return wchar_t(0x00DF); return wchar_t(0x00DF);
}
if (wchar == 0x0401) // CYRILLIC CAPITAL LETTER IO if (wchar == 0x0401) // CYRILLIC CAPITAL LETTER IO
{
return wchar_t(0x0451); return wchar_t(0x0451);
}
if (wchar >= 0x0410 && wchar <= 0x042F) // CYRILLIC CAPITAL LETTER A - CYRILLIC CAPITAL LETTER YA if (wchar >= 0x0410 && wchar <= 0x042F) // CYRILLIC CAPITAL LETTER A - CYRILLIC CAPITAL LETTER YA
{
return wchar_t(uint16(wchar) + 0x0020); return wchar_t(uint16(wchar) + 0x0020);
}
return wchar; return wchar;
} }
@@ -418,9 +498,13 @@ public:
for (uint8 i = 3; i > 0; --i) for (uint8 i = 3; i > 0; --i)
{ {
if (part[i - 1] < right.part[i - 1]) if (part[i - 1] < right.part[i - 1])
{
return true; return true;
}
else if (part[i - 1] > right.part[i - 1]) else if (part[i - 1] > right.part[i - 1])
{
return false; return false;
}
} }
return false; return false;
} }