refactor(Core/Common): restyle common lib with astyle (#3461)

This commit is contained in:
Kargatum
2020-09-12 03:50:48 +07:00
committed by GitHub
parent e15a493927
commit 3a0b0356ac
101 changed files with 4524 additions and 4418 deletions

View File

@@ -12,30 +12,30 @@
namespace acore namespace acore
{ {
template <class Pointer, class Lock> template <class Pointer, class Lock>
class AutoPtr : public ACE_Strong_Bound_Ptr<Pointer, Lock> class AutoPtr : public ACE_Strong_Bound_Ptr<Pointer, Lock>
{
typedef ACE_Strong_Bound_Ptr<Pointer, Lock> Base;
public:
AutoPtr()
: Base()
{ }
AutoPtr(Pointer* x)
: Base(x)
{ }
operator bool() const
{ {
return !Base::null(); typedef ACE_Strong_Bound_Ptr<Pointer, Lock> Base;
}
bool operator !() const public:
{ AutoPtr()
return Base::null(); : Base()
} { }
};
AutoPtr(Pointer* x)
: Base(x)
{ }
operator bool() const
{
return !Base::null();
}
bool operator !() const
{
return Base::null();
}
};
} // namespace acore } // namespace acore

View File

@@ -7,12 +7,12 @@
#include "BoundingIntervalHierarchy.h" #include "BoundingIntervalHierarchy.h"
#ifdef _MSC_VER #ifdef _MSC_VER
#define isnan _isnan #define isnan _isnan
#else #else
#define isnan std::isnan #define isnan std::isnan
#endif #endif
void BIH::buildHierarchy(std::vector<uint32> &tempTree, buildData &dat, BuildStats &stats) void BIH::buildHierarchy(std::vector<uint32>& tempTree, buildData& dat, BuildStats& stats)
{ {
// create space for the first node // create space for the first node
tempTree.push_back(uint32(3 << 30)); // dummy leaf tempTree.push_back(uint32(3 << 30)); // dummy leaf
@@ -26,7 +26,7 @@ void BIH::buildHierarchy(std::vector<uint32> &tempTree, buildData &dat, BuildSta
subdivide(0, dat.numPrims - 1, tempTree, dat, gridBox, nodeBox, 0, 1, stats); subdivide(0, dat.numPrims - 1, tempTree, dat, gridBox, nodeBox, 0, 1, stats);
} }
void BIH::subdivide(int left, int right, std::vector<uint32> &tempTree, buildData &dat, AABound &gridBox, AABound &nodeBox, int nodeIndex, int depth, BuildStats &stats) void BIH::subdivide(int left, int right, std::vector<uint32>& tempTree, buildData& dat, AABound& gridBox, AABound& nodeBox, int nodeIndex, int depth, BuildStats& stats)
{ {
if ((right - left + 1) <= dat.maxPrims || depth >= MAX_STACK_SIZE) if ((right - left + 1) <= dat.maxPrims || depth >= MAX_STACK_SIZE)
{ {
@@ -121,13 +121,15 @@ void BIH::subdivide(int left, int right, std::vector<uint32> &tempTree, buildDat
if (right == rightOrig) if (right == rightOrig)
{ {
// all left // all left
if (prevAxis == axis && G3D::fuzzyEq(prevSplit, split)) { if (prevAxis == axis && G3D::fuzzyEq(prevSplit, split))
{
// we are stuck here - create a leaf // we are stuck here - create a leaf
stats.updateLeaf(depth, right - left + 1); stats.updateLeaf(depth, right - left + 1);
createNode(tempTree, nodeIndex, left, right); createNode(tempTree, nodeIndex, left, right);
return; return;
} }
if (clipL <= split) { if (clipL <= split)
{
// keep looping on left half // keep looping on left half
gridBox.hi[axis] = split; gridBox.hi[axis] = split;
prevClip = clipL; prevClip = clipL;
@@ -140,14 +142,16 @@ void BIH::subdivide(int left, int right, std::vector<uint32> &tempTree, buildDat
else if (left > right) else if (left > right)
{ {
// all right // all right
if (prevAxis == axis && G3D::fuzzyEq(prevSplit, split)) { if (prevAxis == axis && G3D::fuzzyEq(prevSplit, split))
{
// we are stuck here - create a leaf // we are stuck here - create a leaf
stats.updateLeaf(depth, right - left + 1); stats.updateLeaf(depth, right - left + 1);
createNode(tempTree, nodeIndex, left, right); createNode(tempTree, nodeIndex, left, right);
return; return;
} }
right = rightOrig; right = rightOrig;
if (clipR >= split) { if (clipR >= split)
{
// keep looping on right half // keep looping on right half
gridBox.lo[axis] = split; gridBox.lo[axis] = split;
prevClip = clipR; prevClip = clipR;
@@ -169,14 +173,17 @@ void BIH::subdivide(int left, int right, std::vector<uint32> &tempTree, buildDat
tempTree.push_back(0); tempTree.push_back(0);
tempTree.push_back(0); tempTree.push_back(0);
tempTree.push_back(0); tempTree.push_back(0);
if (wasLeft) { if (wasLeft)
{
// create a node with a left child // create a node with a left child
// write leaf node // write leaf node
stats.updateInner(); stats.updateInner();
tempTree[nodeIndex + 0] = (prevAxis << 30) | nextIndex; tempTree[nodeIndex + 0] = (prevAxis << 30) | nextIndex;
tempTree[nodeIndex + 1] = floatToRawIntBits(prevClip); tempTree[nodeIndex + 1] = floatToRawIntBits(prevClip);
tempTree[nodeIndex + 2] = floatToRawIntBits(G3D::inf()); tempTree[nodeIndex + 2] = floatToRawIntBits(G3D::inf());
} else { }
else
{
// create a node with a right child // create a node with a right child
// write leaf node // write leaf node
stats.updateInner(); stats.updateInner();
@@ -198,14 +205,17 @@ void BIH::subdivide(int left, int right, std::vector<uint32> &tempTree, buildDat
// allocate left node // allocate left node
int nl = right - left + 1; int nl = right - left + 1;
int nr = rightOrig - (right + 1) + 1; int nr = rightOrig - (right + 1) + 1;
if (nl > 0) { if (nl > 0)
{
tempTree.push_back(0); tempTree.push_back(0);
tempTree.push_back(0); tempTree.push_back(0);
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)
{
tempTree.push_back(0); tempTree.push_back(0);
tempTree.push_back(0); tempTree.push_back(0);
tempTree.push_back(0); tempTree.push_back(0);
@@ -235,7 +245,7 @@ void BIH::subdivide(int left, int right, std::vector<uint32> &tempTree, buildDat
bool BIH::writeToFile(FILE* wf) const bool BIH::writeToFile(FILE* wf) const
{ {
uint32 treeSize = tree.size(); uint32 treeSize = tree.size();
uint32 check=0, count; uint32 check = 0, count;
check += fwrite(&bounds.low(), sizeof(float), 3, wf); check += fwrite(&bounds.low(), sizeof(float), 3, wf);
check += fwrite(&bounds.high(), sizeof(float), 3, wf); check += fwrite(&bounds.high(), sizeof(float), 3, wf);
check += fwrite(&treeSize, sizeof(uint32), 1, wf); check += fwrite(&treeSize, sizeof(uint32), 1, wf);
@@ -250,7 +260,7 @@ bool BIH::readFromFile(FILE* rf)
{ {
uint32 treeSize; uint32 treeSize;
G3D::Vector3 lo, hi; G3D::Vector3 lo, hi;
uint32 check=0, count=0; uint32 check = 0, count = 0;
check += fread(&lo, sizeof(float), 3, rf); check += fread(&lo, sizeof(float), 3, rf);
check += fread(&hi, sizeof(float), 3, rf); check += fread(&hi, sizeof(float), 3, rf);
bounds = G3D::AABox(lo, hi); bounds = G3D::AABox(lo, hi);

View File

@@ -54,332 +54,340 @@ struct AABound
class BIH class BIH
{ {
private: private:
void init_empty() void init_empty()
{
tree.clear();
objects.clear();
// create space for the first node
tree.push_back(3u << 30u); // dummy leaf
tree.insert(tree.end(), 2, 0);
}
public:
BIH() { init_empty(); }
template< class BoundsFunc, class PrimArray >
void build(const PrimArray& primitives, BoundsFunc& getBounds, uint32 leafSize = 3, bool printStats = false)
{
if (primitives.size() == 0)
{ {
tree.clear(); init_empty();
objects.clear(); return;
// create space for the first node
tree.push_back(3u << 30u); // dummy leaf
tree.insert(tree.end(), 2, 0);
} }
public:
BIH() { init_empty(); } buildData dat;
template< class BoundsFunc, class PrimArray > dat.maxPrims = leafSize;
void build(const PrimArray &primitives, BoundsFunc &getBounds, uint32 leafSize = 3, bool printStats=false) dat.numPrims = primitives.size();
dat.indices = new uint32[dat.numPrims];
dat.primBound = new G3D::AABox[dat.numPrims];
getBounds(primitives[0], bounds);
for (uint32 i = 0; i < dat.numPrims; ++i)
{ {
if (primitives.size() == 0) dat.indices[i] = i;
{ getBounds(primitives[i], dat.primBound[i]);
init_empty(); bounds.merge(dat.primBound[i]);
return;
}
buildData dat;
dat.maxPrims = leafSize;
dat.numPrims = primitives.size();
dat.indices = new uint32[dat.numPrims];
dat.primBound = new G3D::AABox[dat.numPrims];
getBounds(primitives[0], bounds);
for (uint32 i=0; i<dat.numPrims; ++i)
{
dat.indices[i] = i;
getBounds(primitives[i], dat.primBound[i]);
bounds.merge(dat.primBound[i]);
}
std::vector<uint32> tempTree;
BuildStats stats;
buildHierarchy(tempTree, dat, stats);
if (printStats)
stats.printStats();
objects.resize(dat.numPrims);
for (uint32 i=0; i<dat.numPrims; ++i)
objects[i] = dat.indices[i];
//nObjects = dat.numPrims;
tree = tempTree;
delete[] dat.primBound;
delete[] dat.indices;
} }
uint32 primCount() const { return objects.size(); } std::vector<uint32> tempTree;
BuildStats stats;
buildHierarchy(tempTree, dat, stats);
if (printStats)
stats.printStats();
template<typename RayCallback> objects.resize(dat.numPrims);
void intersectRay(const G3D::Ray &r, RayCallback& intersectCallback, float &maxDist, bool stopAtFirstHit) const for (uint32 i = 0; i < dat.numPrims; ++i)
objects[i] = dat.indices[i];
//nObjects = dat.numPrims;
tree = tempTree;
delete[] dat.primBound;
delete[] dat.indices;
}
uint32 primCount() const { return objects.size(); }
template<typename RayCallback>
void intersectRay(const G3D::Ray& r, RayCallback& intersectCallback, float& maxDist, bool stopAtFirstHit) const
{
float intervalMin = -1.f;
float intervalMax = -1.f;
G3D::Vector3 org = r.origin();
G3D::Vector3 dir = r.direction();
G3D::Vector3 invDir;
for (int i = 0; i < 3; ++i)
{ {
float intervalMin = -1.f; invDir[i] = 1.f / dir[i];
float intervalMax = -1.f; if (G3D::fuzzyNe(dir[i], 0.0f))
G3D::Vector3 org = r.origin();
G3D::Vector3 dir = r.direction();
G3D::Vector3 invDir;
for (int i=0; i<3; ++i)
{ {
invDir[i] = 1.f / dir[i]; float t1 = (bounds.low()[i] - org[i]) * invDir[i];
if (G3D::fuzzyNe(dir[i], 0.0f)) float t2 = (bounds.high()[i] - org[i]) * invDir[i];
{ if (t1 > t2)
float t1 = (bounds.low()[i] - org[i]) * invDir[i]; std::swap(t1, t2);
float t2 = (bounds.high()[i] - org[i]) * invDir[i]; if (t1 > intervalMin)
if (t1 > t2) intervalMin = t1;
std::swap(t1, t2); if (t2 < intervalMax || intervalMax < 0.f)
if (t1 > intervalMin) intervalMax = t2;
intervalMin = t1; // intervalMax can only become smaller for other axis,
if (t2 < intervalMax || intervalMax < 0.f) // and intervalMin only larger respectively, so stop early
intervalMax = t2; if (intervalMax <= 0 || intervalMin >= maxDist)
// intervalMax can only become smaller for other axis, return;
// and intervalMin only larger respectively, so stop early
if (intervalMax <= 0 || intervalMin >= maxDist)
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);
uint32 offsetFront[3]; uint32 offsetFront[3];
uint32 offsetBack[3]; uint32 offsetBack[3];
uint32 offsetFront3[3]; uint32 offsetFront3[3];
uint32 offsetBack3[3]; uint32 offsetBack3[3];
// compute custom offsets from direction sign bit // compute custom offsets from direction sign bit
for (int i=0; i<3; ++i) for (int i = 0; i < 3; ++i)
{
offsetFront[i] = floatToRawIntBits(dir[i]) >> 31;
offsetBack[i] = offsetFront[i] ^ 1;
offsetFront3[i] = offsetFront[i] * 3;
offsetBack3[i] = offsetBack[i] * 3;
// avoid always adding 1 during the inner loop
++offsetFront[i];
++offsetBack[i];
}
StackNode stack[MAX_STACK_SIZE];
int stackPos = 0;
int node = 0;
while (true)
{
while (true)
{ {
offsetFront[i] = floatToRawIntBits(dir[i]) >> 31; uint32 tn = tree[node];
offsetBack[i] = offsetFront[i] ^ 1; uint32 axis = (tn & (3 << 30)) >> 30;
offsetFront3[i] = offsetFront[i] * 3; bool BVH2 = tn & (1 << 29);
offsetBack3[i] = offsetBack[i] * 3; int offset = tn & ~(7 << 29);
if (!BVH2)
// avoid always adding 1 during the inner loop
++offsetFront[i];
++offsetBack[i];
}
StackNode stack[MAX_STACK_SIZE];
int stackPos = 0;
int node = 0;
while (true) {
while (true)
{ {
uint32 tn = tree[node]; if (axis < 3)
uint32 axis = (tn & (3 << 30)) >> 30;
bool BVH2 = tn & (1 << 29);
int offset = tn & ~(7 << 29);
if (!BVH2)
{ {
if (axis < 3) // "normal" interior node
float tf = (intBitsToFloat(tree[node + offsetFront[axis]]) - org[axis]) * invDir[axis];
float tb = (intBitsToFloat(tree[node + offsetBack[axis]]) - org[axis]) * invDir[axis];
// ray passes between clip zones
if (tf < intervalMin && tb > intervalMax)
break;
int back = offset + offsetBack3[axis];
node = back;
// ray passes through far node only
if (tf < intervalMin)
{
intervalMin = (tb >= intervalMin) ? tb : intervalMin;
continue;
}
node = offset + offsetFront3[axis]; // front
// ray passes through near node only
if (tb > intervalMax)
{ {
// "normal" interior node
float tf = (intBitsToFloat(tree[node + offsetFront[axis]]) - org[axis]) * invDir[axis];
float tb = (intBitsToFloat(tree[node + offsetBack[axis]]) - org[axis]) * invDir[axis];
// ray passes between clip zones
if (tf < intervalMin && tb > intervalMax)
break;
int back = offset + offsetBack3[axis];
node = back;
// ray passes through far node only
if (tf < intervalMin) {
intervalMin = (tb >= intervalMin) ? tb : intervalMin;
continue;
}
node = offset + offsetFront3[axis]; // front
// ray passes through near node only
if (tb > intervalMax) {
intervalMax = (tf <= intervalMax) ? tf : intervalMax;
continue;
}
// ray passes through both nodes
// push back node
stack[stackPos].node = back;
stack[stackPos].tnear = (tb >= intervalMin) ? tb : intervalMin;
stack[stackPos].tfar = intervalMax;
stackPos++;
// update ray interval for front node
intervalMax = (tf <= intervalMax) ? tf : intervalMax; intervalMax = (tf <= intervalMax) ? tf : intervalMax;
continue; continue;
} }
else // ray passes through both nodes
{ // push back node
// leaf - test some objects stack[stackPos].node = back;
int n = tree[node + 1]; stack[stackPos].tnear = (tb >= intervalMin) ? tb : intervalMin;
while (n > 0) { stack[stackPos].tfar = intervalMax;
bool hit = intersectCallback(r, objects[offset], maxDist, stopAtFirstHit); stackPos++;
if (stopAtFirstHit && hit) return; // update ray interval for front node
--n; intervalMax = (tf <= intervalMax) ? tf : intervalMax;
++offset; continue;
}
break;
}
} }
else else
{ {
if (axis>2) // leaf - test some objects
return; // should not happen int n = tree[node + 1];
float tf = (intBitsToFloat(tree[node + offsetFront[axis]]) - org[axis]) * invDir[axis]; while (n > 0)
float tb = (intBitsToFloat(tree[node + offsetBack[axis]]) - org[axis]) * invDir[axis];
node = offset;
intervalMin = (tf >= intervalMin) ? tf : intervalMin;
intervalMax = (tb <= intervalMax) ? tb : intervalMax;
if (intervalMin > intervalMax)
break;
continue;
}
} // traversal loop
do
{
// stack is empty?
if (stackPos == 0)
return;
// move back up the stack
stackPos--;
intervalMin = stack[stackPos].tnear;
if (maxDist < intervalMin)
continue;
node = stack[stackPos].node;
intervalMax = stack[stackPos].tfar;
break;
} while (true);
}
}
template<typename IsectCallback>
void intersectPoint(const G3D::Vector3 &p, IsectCallback& intersectCallback) const
{
if (!bounds.contains(p))
return;
StackNode stack[MAX_STACK_SIZE];
int stackPos = 0;
int node = 0;
while (true) {
while (true)
{
uint32 tn = tree[node];
uint32 axis = (tn & (3 << 30)) >> 30;
bool BVH2 = tn & (1 << 29);
int offset = tn & ~(7 << 29);
if (!BVH2)
{
if (axis < 3)
{ {
// "normal" interior node bool hit = intersectCallback(r, objects[offset], maxDist, stopAtFirstHit);
float tl = intBitsToFloat(tree[node + 1]); if (stopAtFirstHit && hit) return;
float tr = intBitsToFloat(tree[node + 2]); --n;
// point is between clip zones ++offset;
if (tl < p[axis] && tr > p[axis])
break;
int right = offset + 3;
node = right;
// point is in right node only
if (tl < p[axis]) {
continue;
}
node = offset; // left
// point is in left node only
if (tr > p[axis]) {
continue;
}
// point is in both nodes
// push back right node
stack[stackPos].node = right;
stackPos++;
continue;
}
else
{
// leaf - test some objects
int n = tree[node + 1];
while (n > 0) {
intersectCallback(p, objects[offset]); // !!!
--n;
++offset;
}
break;
} }
break;
} }
else // BVH2 node (empty space cut off left and right) }
{ else
if (axis>2) {
return; // should not happen if (axis > 2)
float tl = intBitsToFloat(tree[node + 1]); return; // should not happen
float tr = intBitsToFloat(tree[node + 2]); float tf = (intBitsToFloat(tree[node + offsetFront[axis]]) - org[axis]) * invDir[axis];
node = offset; float tb = (intBitsToFloat(tree[node + offsetBack[axis]]) - org[axis]) * invDir[axis];
if (tl > p[axis] || tr < p[axis]) node = offset;
break; intervalMin = (tf >= intervalMin) ? tf : intervalMin;
continue; intervalMax = (tb <= intervalMax) ? tb : intervalMax;
} if (intervalMin > intervalMax)
} // traversal loop break;
continue;
}
} // traversal loop
do
{
// 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;
if (maxDist < intervalMin)
continue;
node = stack[stackPos].node; node = stack[stackPos].node;
} intervalMax = stack[stackPos].tfar;
break;
} while (true);
} }
}
bool writeToFile(FILE* wf) const; template<typename IsectCallback>
bool readFromFile(FILE* rf); void intersectPoint(const G3D::Vector3& p, IsectCallback& intersectCallback) const
{
if (!bounds.contains(p))
return;
protected: StackNode stack[MAX_STACK_SIZE];
std::vector<uint32> tree; int stackPos = 0;
std::vector<uint32> objects; int node = 0;
G3D::AABox bounds;
struct buildData while (true)
{ {
uint32 *indices; while (true)
G3D::AABox *primBound;
uint32 numPrims;
int maxPrims;
};
struct StackNode
{
uint32 node;
float tnear;
float tfar;
};
class BuildStats
{
private:
int numNodes;
int numLeaves;
int sumObjects;
int minObjects;
int maxObjects;
int sumDepth;
int minDepth;
int maxDepth;
int numLeavesN[6];
int numBVH2;
public:
BuildStats():
numNodes(0), numLeaves(0), sumObjects(0), minObjects(0x0FFFFFFF),
maxObjects(0xFFFFFFFF), sumDepth(0), minDepth(0x0FFFFFFF),
maxDepth(0xFFFFFFFF), numBVH2(0)
{ {
for (int i=0; i<6; ++i) numLeavesN[i] = 0; uint32 tn = tree[node];
} uint32 axis = (tn & (3 << 30)) >> 30;
bool BVH2 = tn & (1 << 29);
int offset = tn & ~(7 << 29);
if (!BVH2)
{
if (axis < 3)
{
// "normal" interior node
float tl = intBitsToFloat(tree[node + 1]);
float tr = intBitsToFloat(tree[node + 2]);
// point is between clip zones
if (tl < p[axis] && tr > p[axis])
break;
int right = offset + 3;
node = right;
// point is in right node only
if (tl < p[axis])
{
continue;
}
node = offset; // left
// point is in left node only
if (tr > p[axis])
{
continue;
}
// point is in both nodes
// push back right node
stack[stackPos].node = right;
stackPos++;
continue;
}
else
{
// leaf - test some objects
int n = tree[node + 1];
while (n > 0)
{
intersectCallback(p, objects[offset]); // !!!
--n;
++offset;
}
break;
}
}
else // BVH2 node (empty space cut off left and right)
{
if (axis > 2)
return; // should not happen
float tl = intBitsToFloat(tree[node + 1]);
float tr = intBitsToFloat(tree[node + 2]);
node = offset;
if (tl > p[axis] || tr < p[axis])
break;
continue;
}
} // traversal loop
void updateInner() { numNodes++; } // stack is empty?
void updateBVH2() { numBVH2++; } if (stackPos == 0)
void updateLeaf(int depth, int n); return;
void printStats(); // move back up the stack
}; stackPos--;
node = stack[stackPos].node;
}
}
void buildHierarchy(std::vector<uint32> &tempTree, buildData &dat, BuildStats &stats); bool writeToFile(FILE* wf) const;
bool readFromFile(FILE* rf);
void createNode(std::vector<uint32> &tempTree, int nodeIndex, uint32 left, uint32 right) const protected:
std::vector<uint32> tree;
std::vector<uint32> objects;
G3D::AABox bounds;
struct buildData
{
uint32* indices;
G3D::AABox* primBound;
uint32 numPrims;
int maxPrims;
};
struct StackNode
{
uint32 node;
float tnear;
float tfar;
};
class BuildStats
{
private:
int numNodes;
int numLeaves;
int sumObjects;
int minObjects;
int maxObjects;
int sumDepth;
int minDepth;
int maxDepth;
int numLeavesN[6];
int numBVH2;
public:
BuildStats():
numNodes(0), numLeaves(0), sumObjects(0), minObjects(0x0FFFFFFF),
maxObjects(0xFFFFFFFF), sumDepth(0), minDepth(0x0FFFFFFF),
maxDepth(0xFFFFFFFF), numBVH2(0)
{ {
// write leaf node for (int i = 0; i < 6; ++i) numLeavesN[i] = 0;
tempTree[nodeIndex + 0] = (3 << 30) | left;
tempTree[nodeIndex + 1] = right - left + 1;
} }
void subdivide(int left, int right, std::vector<uint32> &tempTree, buildData &dat, AABound &gridBox, AABound &nodeBox, int nodeIndex, int depth, BuildStats &stats); void updateInner() { numNodes++; }
void updateBVH2() { numBVH2++; }
void updateLeaf(int depth, int n);
void printStats();
};
void buildHierarchy(std::vector<uint32>& tempTree, buildData& dat, BuildStats& stats);
void createNode(std::vector<uint32>& tempTree, int nodeIndex, uint32 left, uint32 right) const
{
// write leaf node
tempTree[nodeIndex + 0] = (3 << 30) | left;
tempTree[nodeIndex + 1] = right - left + 1;
}
void subdivide(int left, int right, std::vector<uint32>& tempTree, buildData& dat, AABound& gridBox, AABound& nodeBox, int nodeIndex, int depth, BuildStats& stats);
}; };
#endif // _BIH_H #endif // _BIH_H

View File

@@ -66,7 +66,7 @@ public:
{ {
++unbalanced_times; ++unbalanced_times;
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] = NULL; m_objects[Idx] = NULL;
else else

View File

@@ -21,21 +21,25 @@
using VMAP::ModelInstance; using VMAP::ModelInstance;
namespace { namespace
{
int CHECK_TREE_PERIOD = 200; int CHECK_TREE_PERIOD = 200;
} // namespace } // namespace
template<> struct HashTrait< GameObjectModel>{ template<> struct HashTrait< GameObjectModel>
{
static size_t hashCode(const GameObjectModel& g) { return (size_t)(void*)&g; } static size_t hashCode(const GameObjectModel& g) { return (size_t)(void*)&g; }
}; };
template<> struct PositionTrait< GameObjectModel> { template<> struct PositionTrait< GameObjectModel>
{
static void getPosition(const GameObjectModel& g, G3D::Vector3& p) { p = g.getPosition(); } static void getPosition(const GameObjectModel& g, G3D::Vector3& p) { p = g.getPosition(); }
}; };
template<> struct BoundsTrait< GameObjectModel> { template<> struct BoundsTrait< GameObjectModel>
{
static void getBounds(const GameObjectModel& g, G3D::AABox& out) { out = g.getBounds();} static void getBounds(const GameObjectModel& g, G3D::AABox& out) { out = g.getBounds();}
static void getBounds2(const GameObjectModel* g, G3D::AABox& out) { out = g->getBounds();} static void getBounds2(const GameObjectModel* g, G3D::AABox& out) { out = g->getBounds();}
}; };
@@ -148,7 +152,7 @@ struct DynamicTreeIntersectionCallback
}; };
bool DynamicMapTree::getIntersectionTime(const uint32 phasemask, const G3D::Ray& ray, bool DynamicMapTree::getIntersectionTime(const uint32 phasemask, const G3D::Ray& ray,
const G3D::Vector3& endPos, float& maxDist) const const G3D::Vector3& endPos, float& maxDist) const
{ {
float distance = maxDist; float distance = maxDist;
DynamicTreeIntersectionCallback callback(phasemask); DynamicTreeIntersectionCallback callback(phasemask);
@@ -172,7 +176,7 @@ bool DynamicMapTree::getObjectHitPos(const uint32 phasemask, const G3D::Vector3&
resultHit = endPos; resultHit = endPos;
return false; return false;
} }
G3D::Vector3 dir = (endPos - startPos)/maxDist; // direction with length of 1 G3D::Vector3 dir = (endPos - startPos) / maxDist; // direction with length of 1
G3D::Ray ray(startPos, dir); G3D::Ray ray(startPos, dir);
float dist = maxDist; float dist = maxDist;
if (getIntersectionTime(phasemask, ray, endPos, dist)) if (getIntersectionTime(phasemask, ray, endPos, dist))
@@ -181,12 +185,12 @@ 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;
} }
@@ -207,7 +211,7 @@ bool DynamicMapTree::isInLineOfSight(float x1, float y1, float z1, float x2, flo
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);
impl->intersectRay(r, callback, maxDist, v2, true); impl->intersectRay(r, callback, maxDist, v2, true);

View File

@@ -20,7 +20,7 @@ struct DynTreeImpl;
class DynamicMapTree class DynamicMapTree
{ {
DynTreeImpl *impl; DynTreeImpl* impl;
public: public:

View File

@@ -22,16 +22,16 @@ namespace MMAP
class IMMapManager class IMMapManager
{ {
private: private:
bool iEnablePathFinding; bool iEnablePathFinding;
public: public:
IMMapManager() : iEnablePathFinding(true) {} IMMapManager() : iEnablePathFinding(true) {}
virtual ~IMMapManager(void) {} virtual ~IMMapManager(void) {}
//Enabled/Disabled Pathfinding //Enabled/Disabled Pathfinding
void setEnablePathFinding(bool value) { iEnablePathFinding = value; } void setEnablePathFinding(bool value) { iEnablePathFinding = value; }
bool isEnablePathFinding() const { return (iEnablePathFinding); } bool isEnablePathFinding() const { return (iEnablePathFinding); }
}; };
} }

View File

@@ -26,62 +26,62 @@ namespace VMAP
VMAP_LOAD_RESULT_IGNORED VMAP_LOAD_RESULT_IGNORED
}; };
#define VMAP_INVALID_HEIGHT -100000.0f // for check #define VMAP_INVALID_HEIGHT -100000.0f // for check
#define VMAP_INVALID_HEIGHT_VALUE -200000.0f // real assigned value in unknown height case #define VMAP_INVALID_HEIGHT_VALUE -200000.0f // real assigned value in unknown height case
//=========================================================== //===========================================================
class IVMapManager class IVMapManager
{ {
private: private:
bool iEnableLineOfSightCalc; bool iEnableLineOfSightCalc;
bool iEnableHeightCalc; bool iEnableHeightCalc;
public: public:
IVMapManager() : iEnableLineOfSightCalc(true), iEnableHeightCalc(true) { } IVMapManager() : iEnableLineOfSightCalc(true), iEnableHeightCalc(true) { }
virtual ~IVMapManager(void) { } virtual ~IVMapManager(void) { }
virtual int loadMap(const char* pBasePath, unsigned int pMapId, int x, int y) = 0; virtual int loadMap(const char* pBasePath, unsigned int pMapId, int x, int y) = 0;
virtual bool existsMap(const char* pBasePath, unsigned int pMapId, int x, int y) = 0; virtual bool existsMap(const char* pBasePath, unsigned int pMapId, int x, int y) = 0;
virtual void unloadMap(unsigned int pMapId, int x, int y) = 0; virtual void unloadMap(unsigned int pMapId, int x, int y) = 0;
virtual void unloadMap(unsigned int pMapId) = 0; virtual void unloadMap(unsigned int pMapId) = 0;
virtual bool isInLineOfSight(unsigned int pMapId, float x1, float y1, float z1, float x2, float y2, float z2) = 0; virtual bool isInLineOfSight(unsigned int pMapId, float x1, float y1, float z1, float x2, float y2, float z2) = 0;
virtual float getHeight(unsigned int pMapId, float x, float y, float z, float maxSearchDist) = 0; virtual float getHeight(unsigned int pMapId, float x, float y, float z, float maxSearchDist) = 0;
/** /**
test if we hit an object. return true if we hit one. rx, ry, rz will hold the hit position or the dest position, if no intersection was found test if we hit an object. return true if we hit one. rx, ry, rz will hold the hit position or the dest position, if no intersection was found
return a position, that is pReduceDist closer to the origin return a position, that is pReduceDist closer to the origin
*/ */
virtual bool getObjectHitPos(unsigned int pMapId, float x1, float y1, float z1, float x2, float y2, float z2, float& rx, float &ry, float& rz, float pModifyDist) = 0; virtual bool getObjectHitPos(unsigned int pMapId, float x1, float y1, float z1, float x2, float y2, float z2, float& rx, float& ry, float& rz, float pModifyDist) = 0;
/** /**
send debug commands send debug commands
*/ */
virtual bool processCommand(char *pCommand)= 0; virtual bool processCommand(char* pCommand) = 0;
/** /**
Enable/disable LOS calculation Enable/disable LOS calculation
It is enabled by default. If it is enabled in mid game the maps have to loaded manualy It is enabled by default. If it is enabled in mid game the maps have to loaded manualy
*/ */
void setEnableLineOfSightCalc(bool pVal) { iEnableLineOfSightCalc = pVal; } void setEnableLineOfSightCalc(bool pVal) { iEnableLineOfSightCalc = pVal; }
/** /**
Enable/disable model height calculation Enable/disable model height calculation
It is enabled by default. If it is enabled in mid game the maps have to loaded manualy It is enabled by default. If it is enabled in mid game the maps have to loaded manualy
*/ */
void setEnableHeightCalc(bool pVal) { iEnableHeightCalc = pVal; } void setEnableHeightCalc(bool pVal) { iEnableHeightCalc = pVal; }
bool isLineOfSightCalcEnabled() const { return(iEnableLineOfSightCalc); } bool isLineOfSightCalcEnabled() const { return(iEnableLineOfSightCalc); }
bool isHeightCalcEnabled() const { return(iEnableHeightCalc); } bool isHeightCalcEnabled() const { return(iEnableHeightCalc); }
bool isMapLoadingEnabled() const { return(iEnableLineOfSightCalc || iEnableHeightCalc ); } bool isMapLoadingEnabled() const { return(iEnableLineOfSightCalc || iEnableHeightCalc ); }
virtual std::string getDirFileName(unsigned int pMapId, int x, int y) const =0; virtual std::string getDirFileName(unsigned int pMapId, int x, int y) const = 0;
/** /**
Query world model area info. Query world model area info.
\param z gets adjusted to the ground height for which this are info is valid \param z gets adjusted to the ground height for which this are info is valid
*/ */
virtual bool getAreaInfo(unsigned int pMapId, float x, float y, float &z, uint32 &flags, int32 &adtId, int32 &rootId, int32 &groupId) const=0; virtual bool getAreaInfo(unsigned int pMapId, float x, float y, float& z, uint32& flags, int32& adtId, int32& rootId, int32& groupId) const = 0;
virtual bool GetLiquidLevel(uint32 pMapId, float x, float y, float z, uint8 ReqLiquidType, float &level, float &floor, uint32 &type) const=0; virtual bool GetLiquidLevel(uint32 pMapId, float x, float y, float z, uint8 ReqLiquidType, float& level, float& floor, uint32& type) const = 0;
}; };
} }

View File

@@ -12,7 +12,7 @@ namespace MMAP
{ {
// ######################## MMapFactory ######################## // ######################## MMapFactory ########################
// our global singleton copy // our global singleton copy
MMapManager *g_MMapManager = NULL; MMapManager* g_MMapManager = NULL;
bool MMapFactory::forbiddenMaps[1000] = {0}; bool MMapFactory::forbiddenMaps[1000] = {0};
MMapManager* MMapFactory::createOrGetMMapManager() MMapManager* MMapFactory::createOrGetMMapManager()

View File

@@ -28,12 +28,12 @@ namespace MMAP
// access point to MMapManager singleton // access point to MMapManager singleton
class MMapFactory class MMapFactory
{ {
public: public:
static MMapManager* createOrGetMMapManager(); static MMapManager* createOrGetMMapManager();
static void clear(); static void clear();
static bool IsPathfindingEnabled(const Map* map); static bool IsPathfindingEnabled(const Map* map);
static void InitializeDisabledMaps(); static void InitializeDisabledMaps();
static bool forbiddenMaps[1000]; static bool forbiddenMaps[1000];
}; };
} }

View File

@@ -27,9 +27,9 @@ namespace MMAP
return true; return true;
// load and init dtNavMesh - read parameters from file // load and init dtNavMesh - read parameters from file
uint32 pathLen = sWorld->GetDataPath().length() + strlen("mmaps/%03i.mmap")+1; uint32 pathLen = sWorld->GetDataPath().length() + strlen("mmaps/%03i.mmap") + 1;
char *fileName = new char[pathLen]; char* fileName = new char[pathLen];
snprintf(fileName, pathLen, (sWorld->GetDataPath()+"mmaps/%03i.mmap").c_str(), mapId); snprintf(fileName, pathLen, (sWorld->GetDataPath() + "mmaps/%03i.mmap").c_str(), mapId);
FILE* file = fopen(fileName, "rb"); FILE* file = fopen(fileName, "rb");
if (!file) if (!file)
@@ -112,11 +112,11 @@ namespace MMAP
} }
// load this tile :: mmaps/MMMXXYY.mmtile // load this tile :: mmaps/MMMXXYY.mmtile
uint32 pathLen = sWorld->GetDataPath().length() + strlen("mmaps/%03i%02i%02i.mmtile")+1; uint32 pathLen = sWorld->GetDataPath().length() + strlen("mmaps/%03i%02i%02i.mmtile") + 1;
char *fileName = new char[pathLen]; char* fileName = new char[pathLen];
snprintf(fileName, pathLen, (sWorld->GetDataPath()+"mmaps/%03i%02i%02i.mmtile").c_str(), mapId, x, y); snprintf(fileName, pathLen, (sWorld->GetDataPath() + "mmaps/%03i%02i%02i.mmtile").c_str(), mapId, x, y);
FILE *file = fopen(fileName, "rb"); FILE* file = fopen(fileName, "rb");
if (!file) if (!file)
{ {
#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS) #if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS)
@@ -139,7 +139,7 @@ namespace MMAP
if (fileHeader.mmapVersion != MMAP_VERSION) if (fileHeader.mmapVersion != MMAP_VERSION)
{ {
sLog->outError("MMAP:loadMap: %03u%02i%02i.mmtile was built with generator v%i, expected v%i", sLog->outError("MMAP:loadMap: %03u%02i%02i.mmtile was built with generator v%i, expected v%i",
mapId, x, y, fileHeader.mmapVersion, MMAP_VERSION); mapId, x, y, fileHeader.mmapVersion, MMAP_VERSION);
fclose(file); fclose(file);
return false; return false;
} }
@@ -345,26 +345,26 @@ namespace MMAP
MMapData* mmap = loadedMMaps[mapId]; MMapData* mmap = loadedMMaps[mapId];
if (mmap->navMeshQueries.find(instanceId) == mmap->navMeshQueries.end()) if (mmap->navMeshQueries.find(instanceId) == mmap->navMeshQueries.end())
{ {
// pussywizard: different instances of the same map shouldn't access this simultaneously // pussywizard: different instances of the same map shouldn't access this simultaneously
ACORE_WRITE_GUARD(ACE_RW_Thread_Mutex, GetMMapLock(mapId)); ACORE_WRITE_GUARD(ACE_RW_Thread_Mutex, GetMMapLock(mapId));
// check again after acquiring mutex // check again after acquiring mutex
if (mmap->navMeshQueries.find(instanceId) == mmap->navMeshQueries.end()) if (mmap->navMeshQueries.find(instanceId) == mmap->navMeshQueries.end())
{
// allocate mesh query
dtNavMeshQuery* query = dtAllocNavMeshQuery();
ASSERT(query);
if (DT_SUCCESS != query->init(mmap->navMesh, 1024))
{ {
dtFreeNavMeshQuery(query); // allocate mesh query
sLog->outError("MMAP:GetNavMeshQuery: Failed to initialize dtNavMeshQuery for mapId %03u instanceId %u", mapId, instanceId); dtNavMeshQuery* query = dtAllocNavMeshQuery();
return NULL; ASSERT(query);
} if (DT_SUCCESS != query->init(mmap->navMesh, 1024))
{
dtFreeNavMeshQuery(query);
sLog->outError("MMAP:GetNavMeshQuery: Failed to initialize dtNavMeshQuery for mapId %03u instanceId %u", mapId, instanceId);
return NULL;
}
#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS) #if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS)
sLog->outDetail("MMAP:GetNavMeshQuery: created dtNavMeshQuery for mapId %03u instanceId %u", mapId, instanceId); sLog->outDetail("MMAP:GetNavMeshQuery: created dtNavMeshQuery for mapId %03u instanceId %u", mapId, instanceId);
#endif #endif
mmap->navMeshQueries.insert(std::pair<uint32, dtNavMeshQuery*>(instanceId, query)); mmap->navMeshQueries.insert(std::pair<uint32, dtNavMeshQuery*>(instanceId, query));
} }
} }
return mmap->navMeshQueries[instanceId]; return mmap->navMeshQueries[instanceId];

View File

@@ -57,34 +57,34 @@ namespace MMAP
// holds all all access to mmap loading unloading and meshes // holds all all access to mmap loading unloading and meshes
class MMapManager class MMapManager
{ {
public: public:
MMapManager() : loadedTiles(0) {} MMapManager() : loadedTiles(0) {}
~MMapManager(); ~MMapManager();
bool loadMap(uint32 mapId, int32 x, int32 y); bool loadMap(uint32 mapId, int32 x, int32 y);
bool unloadMap(uint32 mapId, int32 x, int32 y); bool unloadMap(uint32 mapId, int32 x, int32 y);
bool unloadMap(uint32 mapId); bool unloadMap(uint32 mapId);
bool unloadMapInstance(uint32 mapId, uint32 instanceId); bool unloadMapInstance(uint32 mapId, uint32 instanceId);
// the returned [dtNavMeshQuery const*] is NOT threadsafe // the returned [dtNavMeshQuery const*] is NOT threadsafe
dtNavMeshQuery const* GetNavMeshQuery(uint32 mapId, uint32 instanceId); dtNavMeshQuery const* GetNavMeshQuery(uint32 mapId, uint32 instanceId);
dtNavMesh const* GetNavMesh(uint32 mapId); dtNavMesh const* GetNavMesh(uint32 mapId);
uint32 getLoadedTilesCount() const { return loadedTiles; } uint32 getLoadedTilesCount() const { return loadedTiles; }
uint32 getLoadedMapsCount() const { return loadedMMaps.size(); } uint32 getLoadedMapsCount() const { return loadedMMaps.size(); }
ACE_RW_Thread_Mutex& GetMMapLock(uint32 mapId); ACE_RW_Thread_Mutex& GetMMapLock(uint32 mapId);
ACE_RW_Thread_Mutex& GetMMapGeneralLock() { return MMapLock; } // pussywizard: in case a per-map mutex can't be found, should never happen ACE_RW_Thread_Mutex& GetMMapGeneralLock() { return MMapLock; } // pussywizard: in case a per-map mutex can't be found, should never happen
ACE_RW_Thread_Mutex& GetManagerLock() { return MMapManagerLock; } ACE_RW_Thread_Mutex& GetManagerLock() { return MMapManagerLock; }
private: private:
bool loadMapData(uint32 mapId); bool loadMapData(uint32 mapId);
uint32 packTileID(int32 x, int32 y); uint32 packTileID(int32 x, int32 y);
MMapDataSet loadedMMaps; MMapDataSet loadedMMaps;
uint32 loadedTiles; uint32 loadedTiles;
ACE_RW_Thread_Mutex MMapManagerLock; ACE_RW_Thread_Mutex MMapManagerLock;
ACE_RW_Thread_Mutex MMapLock; // pussywizard: in case a per-map mutex can't be found, should never happen ACE_RW_Thread_Mutex MMapLock; // pussywizard: in case a per-map mutex can't be found, should never happen
}; };
} }

View File

@@ -16,7 +16,7 @@ namespace VMAP
IVMapManager* VMapFactory::createOrGetVMapManager() IVMapManager* VMapFactory::createOrGetVMapManager()
{ {
if (gVMapManager == 0) if (gVMapManager == 0)
gVMapManager= new VMapManager2(); // should be taken from config ... Please change if you like :-) gVMapManager = new VMapManager2(); // should be taken from config ... Please change if you like :-)
return gVMapManager; return gVMapManager;
} }

View File

@@ -19,9 +19,9 @@ namespace VMAP
class VMapFactory class VMapFactory
{ {
public: public:
static IVMapManager* createOrGetVMapManager(); static IVMapManager* createOrGetVMapManager();
static void clear(); static void clear();
}; };
} }

View File

@@ -95,10 +95,10 @@ namespace VMAP
std::string mapFileName = getMapFileName(mapId); std::string mapFileName = getMapFileName(mapId);
StaticMapTree* newTree = new StaticMapTree(mapId, basePath); StaticMapTree* newTree = new StaticMapTree(mapId, basePath);
if (!newTree->InitMap(mapFileName, this)) if (!newTree->InitMap(mapFileName, this))
{ {
delete newTree; delete newTree;
return false; return false;
} }
instanceTree = iInstanceMapTrees.insert(InstanceTreeMap::value_type(mapId, newTree)).first; instanceTree = iInstanceMapTrees.insert(InstanceTreeMap::value_type(mapId, newTree)).first;
} }
@@ -158,7 +158,7 @@ namespace VMAP
get the hit position and return true if we hit something get the hit position and return true if we hit something
otherwise the result pos will be the dest pos otherwise the result pos will be the dest pos
*/ */
bool VMapManager2::getObjectHitPos(unsigned int mapId, float x1, float y1, float z1, float x2, float y2, float z2, float& rx, float &ry, float& rz, float modifyDist) bool VMapManager2::getObjectHitPos(unsigned int mapId, float x1, float y1, float z1, float x2, float y2, float z2, float& rx, float& ry, float& rz, float modifyDist)
{ {
#if defined(ENABLE_EXTRAS) && defined(ENABLE_VMAP_CHECKS) #if defined(ENABLE_EXTRAS) && defined(ENABLE_VMAP_CHECKS)
if (isLineOfSightCalcEnabled() && !DisableMgr::IsDisabledFor(DISABLE_TYPE_VMAP, mapId, NULL, VMAP_DISABLE_LOS)) if (isLineOfSightCalcEnabled() && !DisableMgr::IsDisabledFor(DISABLE_TYPE_VMAP, mapId, NULL, VMAP_DISABLE_LOS))
@@ -283,7 +283,7 @@ namespace VMAP
return model->second.getModel(); return model->second.getModel();
} }
void VMapManager2::releaseModelInstance(const std::string &filename) void VMapManager2::releaseModelInstance(const std::string& filename)
{ {
//! Critical section, thread safe access to iLoadedModelFiles //! Critical section, thread safe access to iLoadedModelFiles
ACORE_GUARD(ACE_Thread_Mutex, LoadedModelFilesLock); ACORE_GUARD(ACE_Thread_Mutex, LoadedModelFilesLock);

View File

@@ -51,15 +51,15 @@ namespace VMAP
class ManagedModel class ManagedModel
{ {
public: public:
ManagedModel() : iModel(0), iRefCount(0) { } ManagedModel() : iModel(0), iRefCount(0) { }
void setModel(WorldModel* model) { iModel = model; } void setModel(WorldModel* model) { iModel = model; }
WorldModel* getModel() { return iModel; } WorldModel* getModel() { return iModel; }
void incRefCount() { ++iRefCount; } void incRefCount() { ++iRefCount; }
int decRefCount() { return --iRefCount; } int decRefCount() { return --iRefCount; }
protected: protected:
WorldModel* iModel; WorldModel* iModel;
int iRefCount; int iRefCount;
}; };
typedef std::unordered_map<uint32, StaticMapTree*> InstanceTreeMap; typedef std::unordered_map<uint32, StaticMapTree*> InstanceTreeMap;
@@ -67,57 +67,57 @@ namespace VMAP
class VMapManager2 : public IVMapManager class VMapManager2 : public IVMapManager
{ {
protected: protected:
// Tree to check collision // Tree to check collision
ModelFileMap iLoadedModelFiles; ModelFileMap iLoadedModelFiles;
InstanceTreeMap iInstanceMapTrees; InstanceTreeMap iInstanceMapTrees;
// Mutex for iLoadedModelFiles // Mutex for iLoadedModelFiles
ACE_Thread_Mutex LoadedModelFilesLock; ACE_Thread_Mutex LoadedModelFilesLock;
bool _loadMap(uint32 mapId, const std::string& basePath, uint32 tileX, uint32 tileY); bool _loadMap(uint32 mapId, const std::string& basePath, uint32 tileX, uint32 tileY);
/* void _unloadMap(uint32 pMapId, uint32 x, uint32 y); */ /* void _unloadMap(uint32 pMapId, uint32 x, uint32 y); */
static uint32 GetLiquidFlagsDummy(uint32) { return 0; } static uint32 GetLiquidFlagsDummy(uint32) { return 0; }
public: public:
// public for debug // public for debug
G3D::Vector3 convertPositionToInternalRep(float x, float y, float z) const; G3D::Vector3 convertPositionToInternalRep(float x, float y, float z) const;
static std::string getMapFileName(unsigned int mapId); static std::string getMapFileName(unsigned int mapId);
VMapManager2(); VMapManager2();
~VMapManager2(void); ~VMapManager2(void);
int loadMap(const char* pBasePath, unsigned int mapId, int x, int y); int loadMap(const char* pBasePath, unsigned int mapId, int x, int y);
void unloadMap(unsigned int mapId, int x, int y); void unloadMap(unsigned int mapId, int x, int y);
void unloadMap(unsigned int mapId); void unloadMap(unsigned int mapId);
bool isInLineOfSight(unsigned int mapId, float x1, float y1, float z1, float x2, float y2, float z2) ; bool isInLineOfSight(unsigned int mapId, float x1, float y1, float z1, float x2, float y2, float z2) ;
/** /**
fill the hit pos and return true, if an object was hit fill the hit pos and return true, if an object was hit
*/ */
bool getObjectHitPos(unsigned int mapId, float x1, float y1, float z1, float x2, float y2, float z2, float& rx, float& ry, float& rz, float modifyDist); bool getObjectHitPos(unsigned int mapId, float x1, float y1, float z1, float x2, float y2, float z2, float& rx, float& ry, float& rz, float modifyDist);
float getHeight(unsigned int mapId, float x, float y, float z, float maxSearchDist); float getHeight(unsigned int mapId, float x, float y, float z, float maxSearchDist);
bool processCommand(char* /*command*/) { return false; } // for debug and extensions bool processCommand(char* /*command*/) { return false; } // for debug and extensions
bool getAreaInfo(unsigned int pMapId, float x, float y, float& z, uint32& flags, int32& adtId, int32& rootId, int32& groupId) const; bool getAreaInfo(unsigned int pMapId, float x, float y, float& z, uint32& flags, int32& adtId, int32& rootId, int32& groupId) const;
bool GetLiquidLevel(uint32 pMapId, float x, float y, float z, uint8 reqLiquidType, float& level, float& floor, uint32& type) const; bool GetLiquidLevel(uint32 pMapId, float x, float y, float z, uint8 reqLiquidType, float& level, float& floor, uint32& type) const;
WorldModel* acquireModelInstance(const std::string& basepath, const std::string& filename); WorldModel* acquireModelInstance(const std::string& basepath, const std::string& filename);
void releaseModelInstance(const std::string& filename); void releaseModelInstance(const std::string& filename);
// what's the use of this? o.O // what's the use of this? o.O
virtual std::string getDirFileName(unsigned int mapId, int /*x*/, int /*y*/) const virtual std::string getDirFileName(unsigned int mapId, int /*x*/, int /*y*/) const
{ {
return getMapFileName(mapId); return getMapFileName(mapId);
} }
virtual bool existsMap(const char* basePath, unsigned int mapId, int x, int y); virtual bool existsMap(const char* basePath, unsigned int mapId, int x, int y);
public: public:
void getInstanceMapTree(InstanceTreeMap &instanceMapTree); void getInstanceMapTree(InstanceTreeMap& instanceMapTree);
typedef uint32(*GetLiquidFlagsFn)(uint32 liquidType); typedef uint32(*GetLiquidFlagsFn)(uint32 liquidType);
GetLiquidFlagsFn GetLiquidFlagsPtr; GetLiquidFlagsFn GetLiquidFlagsPtr;
}; };
} }

View File

@@ -23,15 +23,15 @@ namespace VMAP
class MapRayCallback class MapRayCallback
{ {
public: public:
MapRayCallback(ModelInstance* val): prims(val), hit(false) {} MapRayCallback(ModelInstance* val): prims(val), hit(false) {}
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 = 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; }
protected: protected:
ModelInstance* prims; ModelInstance* prims;
@@ -40,36 +40,36 @@ namespace VMAP
class AreaInfoCallback class AreaInfoCallback
{ {
public: public:
AreaInfoCallback(ModelInstance* val): prims(val) {} AreaInfoCallback(ModelInstance* val): prims(val) {}
void operator()(const Vector3& point, uint32 entry) void operator()(const Vector3& point, uint32 entry)
{ {
#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS) && defined(VMAP_DEBUG) #if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS) && defined(VMAP_DEBUG)
sLog->outDebug(LOG_FILTER_MAPS, "AreaInfoCallback: trying to intersect '%s'", prims[entry].name.c_str()); sLog->outDebug(LOG_FILTER_MAPS, "AreaInfoCallback: trying to intersect '%s'", prims[entry].name.c_str());
#endif #endif
prims[entry].intersectPoint(point, aInfo); prims[entry].intersectPoint(point, aInfo);
} }
ModelInstance* prims; ModelInstance* prims;
AreaInfo aInfo; AreaInfo aInfo;
}; };
class LocationInfoCallback class LocationInfoCallback
{ {
public: public:
LocationInfoCallback(ModelInstance* val, LocationInfo &info): prims(val), locInfo(info), result(false) {} LocationInfoCallback(ModelInstance* val, LocationInfo& info): prims(val), locInfo(info), result(false) {}
void operator()(const Vector3& point, uint32 entry) void operator()(const Vector3& point, uint32 entry)
{ {
#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS) && defined(VMAP_DEBUG) #if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS) && defined(VMAP_DEBUG)
sLog->outDebug(LOG_FILTER_MAPS, "LocationInfoCallback: trying to intersect '%s'", prims[entry].name.c_str()); sLog->outDebug(LOG_FILTER_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;
LocationInfo &locInfo; LocationInfo& locInfo;
bool result; bool result;
}; };
//========================================================= //=========================================================
@@ -84,7 +84,7 @@ namespace VMAP
return tilefilename.str(); return tilefilename.str();
} }
bool StaticMapTree::getAreaInfo(Vector3 &pos, uint32 &flags, int32 &adtId, int32 &rootId, int32 &groupId) const bool StaticMapTree::getAreaInfo(Vector3& pos, uint32& flags, int32& adtId, int32& rootId, int32& groupId) const
{ {
AreaInfoCallback intersectionCallBack(iTreeValues); AreaInfoCallback intersectionCallBack(iTreeValues);
iTree.intersectPoint(pos, intersectionCallBack); iTree.intersectPoint(pos, intersectionCallBack);
@@ -100,17 +100,17 @@ namespace VMAP
return false; return false;
} }
bool StaticMapTree::GetLocationInfo(const Vector3 &pos, LocationInfo &info) const bool StaticMapTree::GetLocationInfo(const Vector3& pos, LocationInfo& info) const
{ {
LocationInfoCallback intersectionCallBack(iTreeValues, info); LocationInfoCallback intersectionCallBack(iTreeValues, info);
iTree.intersectPoint(pos, intersectionCallBack); iTree.intersectPoint(pos, intersectionCallBack);
return intersectionCallBack.result; return intersectionCallBack.result;
} }
StaticMapTree::StaticMapTree(uint32 mapID, const std::string &basePath) StaticMapTree::StaticMapTree(uint32 mapID, const std::string& basePath)
: iMapID(mapID), iIsTiled(false), iTreeValues(0), iBasePath(basePath) : iMapID(mapID), iIsTiled(false), iTreeValues(0), iBasePath(basePath)
{ {
if (iBasePath.length() > 0 && iBasePath[iBasePath.length()-1] != '/' && iBasePath[iBasePath.length()-1] != '\\') if (iBasePath.length() > 0 && iBasePath[iBasePath.length() - 1] != '/' && iBasePath[iBasePath.length() - 1] != '\\')
{ {
iBasePath.push_back('/'); iBasePath.push_back('/');
} }
@@ -129,7 +129,7 @@ namespace VMAP
Else, pMaxDist is not modified and returns false; Else, pMaxDist is not modified and returns false;
*/ */
bool StaticMapTree::getIntersectionTime(const G3D::Ray& pRay, float &pMaxDist, bool StopAtFirstHit) const bool StaticMapTree::getIntersectionTime(const G3D::Ray& pRay, float& pMaxDist, bool StopAtFirstHit) const
{ {
float distance = pMaxDist; float distance = pMaxDist;
MapRayCallback intersectionCallBack(iTreeValues); MapRayCallback intersectionCallBack(iTreeValues);
@@ -153,7 +153,7 @@ namespace VMAP
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;
@@ -167,7 +167,7 @@ namespace VMAP
bool StaticMapTree::getObjectHitPos(const Vector3& pPos1, const Vector3& pPos2, Vector3& pResultHitPos, float pModifyDist) const bool StaticMapTree::getObjectHitPos(const Vector3& pPos1, const Vector3& pPos2, Vector3& pResultHitPos, float pModifyDist) const
{ {
bool result=false; bool result = false;
float maxDist = (pPos2 - pPos1).magnitude(); float maxDist = (pPos2 - pPos1).magnitude();
// 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());
@@ -177,7 +177,7 @@ namespace VMAP
pResultHitPos = pPos2; pResultHitPos = pPos2;
return false; return false;
} }
Vector3 dir = (pPos2 - pPos1)/maxDist; // direction with length of 1 Vector3 dir = (pPos2 - pPos1) / maxDist; // direction with length of 1
G3D::Ray ray(pPos1, dir); G3D::Ray ray(pPos1, dir);
float dist = maxDist; float dist = maxDist;
if (getIntersectionTime(ray, dist, false)) if (getIntersectionTime(ray, dist, false))
@@ -187,7 +187,7 @@ namespace VMAP
{ {
if ((pResultHitPos - pPos1).magnitude() > -pModifyDist) if ((pResultHitPos - pPos1).magnitude() > -pModifyDist)
{ {
pResultHitPos = pResultHitPos + dir*pModifyDist; pResultHitPos = pResultHitPos + dir * pModifyDist;
} }
else else
{ {
@@ -196,7 +196,7 @@ namespace VMAP
} }
else else
{ {
pResultHitPos = pResultHitPos + dir*pModifyDist; pResultHitPos = pResultHitPos + dir * pModifyDist;
} }
result = true; result = true;
} }
@@ -225,10 +225,10 @@ namespace VMAP
//========================================================= //=========================================================
bool StaticMapTree::CanLoadMap(const std::string &vmapPath, uint32 mapID, uint32 tileX, uint32 tileY) bool StaticMapTree::CanLoadMap(const std::string& vmapPath, uint32 mapID, uint32 tileX, uint32 tileY)
{ {
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;
@@ -262,7 +262,7 @@ namespace VMAP
//========================================================= //=========================================================
bool StaticMapTree::InitMap(const std::string &fname, VMapManager2* vm) bool StaticMapTree::InitMap(const std::string& fname, VMapManager2* vm)
{ {
//VMAP_DEBUG_LOG(LOG_FILTER_MAPS, "StaticMapTree::InitMap() : initializing StaticMapTree '%s'", fname.c_str()); //VMAP_DEBUG_LOG(LOG_FILTER_MAPS, "StaticMapTree::InitMap() : initializing StaticMapTree '%s'", fname.c_str());
bool success = false; bool success = false;
@@ -275,7 +275,7 @@ namespace VMAP
char tiled = '\0'; char tiled = '\0';
if (readChunk(rf, chunk, VMAP_MAGIC, 8) && fread(&tiled, sizeof(char), 1, rf) == 1 && if (readChunk(rf, chunk, VMAP_MAGIC, 8) && fread(&tiled, sizeof(char), 1, rf) == 1 &&
readChunk(rf, chunk, "NODE", 4) && iTree.readFromFile(rf)) readChunk(rf, chunk, "NODE", 4) && iTree.readFromFile(rf))
{ {
iNTreeValues = iTree.primCount(); iNTreeValues = iTree.primCount();
iTreeValues = new ModelInstance[iNTreeValues]; iTreeValues = new ModelInstance[iNTreeValues];
@@ -354,7 +354,7 @@ namespace VMAP
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
ModelSpawn spawn; ModelSpawn spawn;
@@ -423,14 +423,14 @@ namespace VMAP
FILE* tf = fopen(tilefile.c_str(), "rb"); FILE* tf = fopen(tilefile.c_str(), "rb");
if (tf) if (tf)
{ {
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
ModelSpawn spawn; ModelSpawn spawn;
@@ -448,7 +448,7 @@ namespace VMAP
else else
{ {
if (!iLoadedSpawns.count(referencedNode)) if (!iLoadedSpawns.count(referencedNode))
sLog->outError("StaticMapTree::UnloadMapTile() : trying to unload non-referenced model '%s' (ID:%u)", spawn.name.c_str(), spawn.ID); sLog->outError("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

@@ -29,46 +29,46 @@ namespace VMAP
{ {
typedef std::unordered_map<uint32, bool> loadedTileMap; typedef std::unordered_map<uint32, bool> loadedTileMap;
typedef std::unordered_map<uint32, uint32> loadedSpawnMap; typedef std::unordered_map<uint32, uint32> loadedSpawnMap;
private: private:
uint32 iMapID; uint32 iMapID;
bool iIsTiled; bool iIsTiled;
BIH iTree; BIH iTree;
ModelInstance* iTreeValues; // the tree entries ModelInstance* iTreeValues; // the tree entries
uint32 iNTreeValues; uint32 iNTreeValues;
// Store all the map tile idents that are loaded for that map // Store all the map tile idents that are loaded for that map
// some maps are not splitted into tiles and we have to make sure, not removing the map before all tiles are removed // some maps are not splitted into tiles and we have to make sure, not removing the map before all tiles are removed
// empty tiles have no tile file, hence map with bool instead of just a set (consistency check) // empty tiles have no tile file, hence map with bool instead of just a set (consistency check)
loadedTileMap iLoadedTiles; loadedTileMap iLoadedTiles;
// stores <tree_index, reference_count> to invalidate tree values, unload map, and to be able to report errors // stores <tree_index, reference_count> to invalidate tree values, unload map, and to be able to report errors
loadedSpawnMap iLoadedSpawns; loadedSpawnMap iLoadedSpawns;
std::string iBasePath; std::string iBasePath;
private: private:
bool getIntersectionTime(const G3D::Ray& pRay, float &pMaxDist, bool StopAtFirstHit) const; bool getIntersectionTime(const G3D::Ray& pRay, float& pMaxDist, bool StopAtFirstHit) const;
//bool containsLoadedMapTile(unsigned int pTileIdent) const { return(iLoadedMapTiles.containsKey(pTileIdent)); } //bool containsLoadedMapTile(unsigned int pTileIdent) const { return(iLoadedMapTiles.containsKey(pTileIdent)); }
public: public:
static std::string getTileFileName(uint32 mapID, uint32 tileX, uint32 tileY); static std::string getTileFileName(uint32 mapID, uint32 tileX, uint32 tileY);
static uint32 packTileID(uint32 tileX, uint32 tileY) { return tileX<<16 | tileY; } static uint32 packTileID(uint32 tileX, uint32 tileY) { return tileX << 16 | tileY; }
static void unpackTileID(uint32 ID, uint32 &tileX, uint32 &tileY) { tileX = ID>>16; tileY = ID&0xFF; } static void unpackTileID(uint32 ID, uint32& tileX, uint32& tileY) { tileX = ID >> 16; tileY = ID & 0xFF; }
static bool CanLoadMap(const std::string &basePath, uint32 mapID, uint32 tileX, uint32 tileY); static bool CanLoadMap(const std::string& basePath, uint32 mapID, uint32 tileX, uint32 tileY);
StaticMapTree(uint32 mapID, const std::string &basePath); StaticMapTree(uint32 mapID, const std::string& basePath);
~StaticMapTree(); ~StaticMapTree();
bool isInLineOfSight(const G3D::Vector3& pos1, const G3D::Vector3& pos2) const; bool isInLineOfSight(const G3D::Vector3& pos1, const G3D::Vector3& pos2) const;
bool getObjectHitPos(const G3D::Vector3& pos1, const G3D::Vector3& pos2, G3D::Vector3& pResultHitPos, float pModifyDist) const; bool getObjectHitPos(const G3D::Vector3& pos1, const G3D::Vector3& pos2, G3D::Vector3& pResultHitPos, float pModifyDist) const;
float getHeight(const G3D::Vector3& pPos, float maxSearchDist) const; float getHeight(const G3D::Vector3& pPos, float maxSearchDist) const;
bool getAreaInfo(G3D::Vector3 &pos, uint32 &flags, int32 &adtId, int32 &rootId, int32 &groupId) const; bool getAreaInfo(G3D::Vector3& pos, uint32& flags, int32& adtId, int32& rootId, int32& groupId) const;
bool GetLocationInfo(const G3D::Vector3 &pos, LocationInfo &info) const; bool GetLocationInfo(const G3D::Vector3& pos, LocationInfo& info) const;
bool InitMap(const std::string &fname, VMapManager2* vm); bool InitMap(const std::string& fname, VMapManager2* vm);
void UnloadMap(VMapManager2* vm); void UnloadMap(VMapManager2* vm);
bool LoadMapTile(uint32 tileX, uint32 tileY, VMapManager2* vm); bool LoadMapTile(uint32 tileX, uint32 tileY, VMapManager2* vm);
void UnloadMapTile(uint32 tileX, uint32 tileY, VMapManager2* vm); void UnloadMapTile(uint32 tileX, uint32 tileY, VMapManager2* vm);
bool isTiled() const { return iIsTiled; } bool isTiled() const { return iIsTiled; }
uint32 numLoadedTiles() const { return iLoadedTiles.size(); } uint32 numLoadedTiles() const { return iLoadedTiles.size(); }
void getModelInstances(ModelInstance* &models, uint32 &count); void getModelInstances(ModelInstance*& models, uint32& count);
}; };
struct AreaInfo struct AreaInfo

View File

@@ -22,12 +22,12 @@ using std::pair;
template<> struct BoundsTrait<VMAP::ModelSpawn*> template<> struct BoundsTrait<VMAP::ModelSpawn*>
{ {
static void getBounds(const VMAP::ModelSpawn* const &obj, G3D::AABox& out) { out = obj->getBounds(); } static void getBounds(const VMAP::ModelSpawn* const& obj, G3D::AABox& out) { out = obj->getBounds(); }
}; };
namespace VMAP 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;
@@ -79,7 +79,7 @@ namespace VMAP
{ {
/// @todo remove extractor hack and uncomment below line: /// @todo remove extractor hack and uncomment below line:
//entry->second.iPos += Vector3(533.33333f*32, 533.33333f*32, 0.f); //entry->second.iPos += Vector3(533.33333f*32, 533.33333f*32, 0.f);
entry->second.iBound = entry->second.iBound + Vector3(533.33333f*32, 533.33333f*32, 0.f); entry->second.iBound = entry->second.iBound + Vector3(533.33333f * 32, 533.33333f * 32, 0.f);
} }
mapSpawns.push_back(&(entry->second)); mapSpawns.push_back(&(entry->second));
spawnedModelFiles.insert(entry->second.name); spawnedModelFiles.insert(entry->second.name);
@@ -100,7 +100,7 @@ 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
@@ -126,7 +126,7 @@ namespace VMAP
// 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)
{ {
success = ModelSpawn::writeToFile(mapfile, map_iter->second->UniqueEntries[glob->second]); success = ModelSpawn::writeToFile(mapfile, map_iter->second->UniqueEntries[glob->second]);
} }
@@ -136,11 +136,11 @@ namespace VMAP
// <==== // <====
// write map tile files, similar to ADT files, only with extra BSP tree node info // write map tile files, similar to ADT files, only with extra BSP tree node info
TileMap &tileEntries = map_iter->second->TileEntries; TileMap& tileEntries = map_iter->second->TileEntries;
TileMap::iterator tile; TileMap::iterator tile;
for (tile = tileEntries.begin(); tile != tileEntries.end(); ++tile) for (tile = tileEntries.begin(); tile != tileEntries.end(); ++tile)
{ {
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);
@@ -157,11 +157,11 @@ namespace VMAP
// 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);
@@ -206,7 +206,7 @@ namespace VMAP
return false; return false;
} }
printf("Read coordinate mapping...\n"); printf("Read coordinate mapping...\n");
uint32 mapID, tileX, tileY, check=0; uint32 mapID, tileX, tileY, check = 0;
G3D::Vector3 v1, v2; G3D::Vector3 v1, v2;
ModelSpawn spawn; ModelSpawn spawn;
while (!feof(dirf)) while (!feof(dirf))
@@ -221,7 +221,7 @@ namespace VMAP
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);
if (map_iter == mapData.end()) if (map_iter == mapData.end())
{ {
@@ -237,7 +237,7 @@ namespace VMAP
return success; return success;
} }
bool TileAssembler::calculateTransformedBound(ModelSpawn &spawn) bool TileAssembler::calculateTransformedBound(ModelSpawn& spawn)
{ {
std::string modelFilename(iSrcDir); std::string modelFilename(iSrcDir);
modelFilename.push_back('/'); modelFilename.push_back('/');
@@ -257,9 +257,9 @@ namespace VMAP
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;
for (uint32 g=0; g<groups; ++g) // should be only one for M2 files... for (uint32 g = 0; g < groups; ++g) // should be only one for M2 files...
{ {
std::vector<Vector3>& vertices = raw_model.groupsArray[g].vertexArray; std::vector<Vector3>& vertices = raw_model.groupsArray[g].vertexArray;
@@ -275,7 +275,7 @@ 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);
} }
@@ -298,7 +298,7 @@ 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);
@@ -348,9 +348,9 @@ namespace VMAP
while (!feof(model_list)) while (!feof(model_list))
{ {
if (fread(&displayId, sizeof(uint32), 1, model_list) != 1 if (fread(&displayId, sizeof(uint32), 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;
@@ -390,12 +390,12 @@ namespace VMAP
fclose(model_list); fclose(model_list);
fclose(model_list_copy); fclose(model_list_copy);
} }
// temporary use defines to simplify read/check code (close file and return at fail) // temporary use defines to simplify read/check code (close file and return at fail)
#define READ_OR_RETURN(V, S) if (fread((V), (S), 1, rf) != 1) { \ #define READ_OR_RETURN(V, S) if (fread((V), (S), 1, rf) != 1) { \
fclose(rf); printf("readfail, op = %i\n", readOperation); return(false); } fclose(rf); printf("readfail, op = %i\n", readOperation); return(false); }
#define READ_OR_RETURN_WITH_DELETE(V, S) if (fread((V), (S), 1, rf) != 1) { \ #define READ_OR_RETURN_WITH_DELETE(V, S) if (fread((V), (S), 1, rf) != 1) { \
fclose(rf); printf("readfail, op = %i\n", readOperation); delete[] V; return(false); }; fclose(rf); printf("readfail, op = %i\n", readOperation); delete[] V; return(false); };
#define CMP_OR_RETURN(V, S) if (strcmp((V), (S)) != 0) { \ #define CMP_OR_RETURN(V, S) if (strcmp((V), (S)) != 0) { \
fclose(rf); printf("cmpfail, %s!=%s\n", V, S);return(false); } fclose(rf); printf("cmpfail, %s!=%s\n", V, S);return(false); }
bool GroupModel_Raw::Read(FILE* rf) bool GroupModel_Raw::Read(FILE* rf)
@@ -423,7 +423,7 @@ namespace VMAP
CMP_OR_RETURN(blockId, "GRP "); CMP_OR_RETURN(blockId, "GRP ");
READ_OR_RETURN(&blocksize, sizeof(int)); READ_OR_RETURN(&blocksize, sizeof(int));
READ_OR_RETURN(&branches, sizeof(uint32)); READ_OR_RETURN(&branches, sizeof(uint32));
for (uint32 b=0; b<branches; ++b) for (uint32 b = 0; b < branches; ++b)
{ {
uint32 indexes; uint32 indexes;
// indexes for each branch (not used jet) // indexes for each branch (not used jet)
@@ -436,13 +436,13 @@ namespace VMAP
READ_OR_RETURN(&blocksize, sizeof(int)); READ_OR_RETURN(&blocksize, sizeof(int));
uint32 nindexes; uint32 nindexes;
READ_OR_RETURN(&nindexes, sizeof(uint32)); READ_OR_RETURN(&nindexes, sizeof(uint32));
if (nindexes >0) if (nindexes > 0)
{ {
uint16 *indexarray = new uint16[nindexes]; uint16* indexarray = new uint16[nindexes];
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;
} }
@@ -454,18 +454,18 @@ namespace VMAP
uint32 nvectors; uint32 nvectors;
READ_OR_RETURN(&nvectors, sizeof(uint32)); READ_OR_RETURN(&nvectors, sizeof(uint32));
if (nvectors >0) if (nvectors > 0)
{ {
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;
} }
// ----- liquid // ----- liquid
liquid = 0; liquid = 0;
if (liquidflags& 1) if (liquidflags & 1)
{ {
WMOLiquidHeader hlq; WMOLiquidHeader hlq;
READ_OR_RETURN(&blockId, 4); READ_OR_RETURN(&blockId, 4);
@@ -473,9 +473,9 @@ namespace VMAP
READ_OR_RETURN(&blocksize, sizeof(int)); READ_OR_RETURN(&blocksize, sizeof(int));
READ_OR_RETURN(&hlq, sizeof(WMOLiquidHeader)); READ_OR_RETURN(&hlq, sizeof(WMOLiquidHeader));
liquid = new WmoLiquid(hlq.xtiles, hlq.ytiles, Vector3(hlq.pos_x, hlq.pos_y, hlq.pos_z), hlq.type); liquid = new WmoLiquid(hlq.xtiles, hlq.ytiles, Vector3(hlq.pos_x, hlq.pos_y, hlq.pos_z), hlq.type);
uint32 size = hlq.xverts*hlq.yverts; uint32 size = hlq.xverts * hlq.yverts;
READ_OR_RETURN(liquid->GetHeightStorage(), size*sizeof(float)); READ_OR_RETURN(liquid->GetHeightStorage(), size * sizeof(float));
size = hlq.xtiles*hlq.ytiles; size = hlq.xtiles * hlq.ytiles;
READ_OR_RETURN(liquid->GetFlagsStorage(), size); READ_OR_RETURN(liquid->GetFlagsStorage(), size);
} }
@@ -488,7 +488,7 @@ namespace VMAP
delete liquid; delete liquid;
} }
bool WorldModel_Raw::Read(const char * path) bool WorldModel_Raw::Read(const char* path)
{ {
FILE* rf = fopen(path, "rb"); FILE* rf = fopen(path, "rb");
if (!rf) if (!rf)
@@ -523,6 +523,6 @@ namespace VMAP
} }
// drop of temporary use defines // drop of temporary use defines
#undef READ_OR_RETURN #undef READ_OR_RETURN
#undef CMP_OR_RETURN #undef CMP_OR_RETURN
} }

View File

@@ -25,19 +25,19 @@ namespace VMAP
class ModelPosition class ModelPosition
{ {
private: private:
G3D::Matrix3 iRotation; G3D::Matrix3 iRotation;
public: public:
ModelPosition(): iScale(0.0f) { } ModelPosition(): iScale(0.0f) { }
G3D::Vector3 iPos; G3D::Vector3 iPos;
G3D::Vector3 iDir; G3D::Vector3 iDir;
float iScale; float iScale;
void init() void init()
{ {
iRotation = G3D::Matrix3::fromEulerAnglesZYX(G3D::pif()*iDir.y/180.f, G3D::pif()*iDir.x/180.f, G3D::pif()*iDir.z/180.f); iRotation = G3D::Matrix3::fromEulerAnglesZYX(G3D::pif() * iDir.y / 180.f, G3D::pif() * iDir.x / 180.f, G3D::pif() * iDir.z / 180.f);
} }
G3D::Vector3 transform(const G3D::Vector3& pIn) const; G3D::Vector3 transform(const G3D::Vector3& pIn) const;
void moveToBasePos(const G3D::Vector3& pBasePos) { iPos -= pBasePos; } void moveToBasePos(const G3D::Vector3& pBasePos) { iPos -= pBasePos; }
}; };
typedef std::map<uint32, ModelSpawn> UniqueEntryMap; typedef std::map<uint32, ModelSpawn> UniqueEntryMap;
@@ -75,32 +75,32 @@ namespace VMAP
uint32 RootWMOID; uint32 RootWMOID;
std::vector<GroupModel_Raw> groupsArray; std::vector<GroupModel_Raw> groupsArray;
bool Read(const char * path); bool Read(const char* path);
}; };
class TileAssembler class TileAssembler
{ {
private: private:
std::string iDestDir; std::string iDestDir;
std::string iSrcDir; std::string iSrcDir;
bool (*iFilterMethod)(char *pName); bool (*iFilterMethod)(char* pName);
G3D::Table<std::string, unsigned int > iUniqueNameIds; G3D::Table<std::string, unsigned int > iUniqueNameIds;
unsigned int iCurrentUniqueNameId; unsigned int iCurrentUniqueNameId;
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);
void setModelNameFilterMethod(bool (*pFilterMethod)(char *pName)) { iFilterMethod = pFilterMethod; } void setModelNameFilterMethod(bool (*pFilterMethod)(char* pName)) { iFilterMethod = pFilterMethod; }
std::string getDirEntryNameFromModName(unsigned int pMapId, const std::string& pModPosName); std::string getDirEntryNameFromModName(unsigned int pMapId, const std::string& pModPosName);
}; };
} // VMAP } // VMAP

View File

@@ -36,9 +36,9 @@ ModelList model_list;
void LoadGameObjectModelList() void LoadGameObjectModelList()
{ {
//#ifndef NO_CORE_FUNCS //#ifndef NO_CORE_FUNCS
uint32 oldMSTime = getMSTime(); uint32 oldMSTime = getMSTime();
//#endif //#endif
FILE* model_list_file = fopen((sWorld->GetDataPath() + "vmaps/" + VMAP::GAMEOBJECT_MODELS).c_str(), "rb"); FILE* model_list_file = fopen((sWorld->GetDataPath() + "vmaps/" + VMAP::GAMEOBJECT_MODELS).c_str(), "rb");
if (!model_list_file) if (!model_list_file)
@@ -57,10 +57,10 @@ void LoadGameObjectModelList()
break; break;
if (fread(&name_length, sizeof(uint32), 1, model_list_file) != 1 if (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)
{ {
sLog->outError("File '%s' seems to be corrupted!", VMAP::GAMEOBJECT_MODELS); sLog->outError("File '%s' seems to be corrupted!", VMAP::GAMEOBJECT_MODELS);
break; break;
@@ -108,7 +108,7 @@ bool GameObjectModel::initialize(const GameObject& go, const GameObjectDisplayIn
//ID = 0; //ID = 0;
iPos = Vector3(go.GetPositionX(), go.GetPositionY(), go.GetPositionZ()); iPos = Vector3(go.GetPositionX(), go.GetPositionY(), go.GetPositionZ());
// pussywizard: // pussywizard:
phasemask = (go.GetGoState() == GO_STATE_READY || go.IsTransport()) ? go.GetPhaseMask() : 0; phasemask = (go.GetGoState() == GO_STATE_READY || go.IsTransport()) ? go.GetPhaseMask() : 0;
iScale = go.GetFloatValue(OBJECT_FIELD_SCALE_X); iScale = go.GetFloatValue(OBJECT_FIELD_SCALE_X);

View File

@@ -14,10 +14,10 @@ using G3D::Ray;
namespace VMAP namespace VMAP
{ {
ModelInstance::ModelInstance(const ModelSpawn &spawn, WorldModel* model): ModelSpawn(spawn), iModel(model) ModelInstance::ModelInstance(const ModelSpawn& spawn, WorldModel* model): ModelSpawn(spawn), iModel(model)
{ {
iInvRot = G3D::Matrix3::fromEulerAnglesZYX(G3D::pi()*iRot.y/180.f, G3D::pi()*iRot.x/180.f, G3D::pi()*iRot.z/180.f).inverse(); iInvRot = G3D::Matrix3::fromEulerAnglesZYX(G3D::pi() * iRot.y / 180.f, G3D::pi() * iRot.x / 180.f, G3D::pi() * iRot.z / 180.f).inverse();
iInvScale = 1.f/iScale; iInvScale = 1.f / iScale;
} }
bool ModelInstance::intersectRay(const G3D::Ray& pRay, float& pMaxDist, bool StopAtFirstHit) const bool ModelInstance::intersectRay(const G3D::Ray& pRay, float& pMaxDist, bool StopAtFirstHit) const
@@ -30,16 +30,16 @@ namespace VMAP
float time = pRay.intersectionTime(iBound); float time = pRay.intersectionTime(iBound);
if (time == G3D::inf()) if (time == G3D::inf())
{ {
// std::cout << "Ray does not hit '" << name << "'\n"; // std::cout << "Ray does not hit '" << name << "'\n";
return false; return false;
} }
// std::cout << "Ray crosses bound of '" << name << "'\n"; // std::cout << "Ray crosses bound of '" << name << "'\n";
/* std::cout << "ray from:" << pRay.origin().x << ", " << pRay.origin().y << ", " << pRay.origin().z /* std::cout << "ray from:" << pRay.origin().x << ", " << pRay.origin().y << ", " << pRay.origin().z
<< " dir:" << pRay.direction().x << ", " << pRay.direction().y << ", " << pRay.direction().z << " dir:" << pRay.direction().x << ", " << pRay.direction().y << ", " << pRay.direction().z
<< " t/tmax:" << time << '/' << pMaxDist; << " t/tmax:" << time << '/' << pMaxDist;
std::cout << "\nBound lo:" << iBound.low().x << ", " << iBound.low().y << ", " << iBound.low().z << " hi: " std::cout << "\nBound lo:" << iBound.low().x << ", " << iBound.low().y << ", " << iBound.low().z << " hi: "
<< iBound.high().x << ", " << iBound.high().y << ", " << iBound.high().z << std::endl; */ << iBound.high().x << ", " << iBound.high().y << ", " << iBound.high().z << std::endl; */
// child bounds are defined in object space: // child bounds are defined in object space:
Vector3 p = iInvRot * (pRay.origin() - iPos) * iInvScale; Vector3 p = iInvRot * (pRay.origin() - iPos) * iInvScale;
Ray modRay(p, iInvRot * pRay.direction()); Ray modRay(p, iInvRot * pRay.direction());
@@ -53,7 +53,7 @@ namespace VMAP
return hit; return hit;
} }
void ModelInstance::intersectPoint(const G3D::Vector3& p, AreaInfo &info) const void ModelInstance::intersectPoint(const G3D::Vector3& p, AreaInfo& info) const
{ {
if (!iModel) if (!iModel)
{ {
@@ -87,7 +87,7 @@ namespace VMAP
} }
} }
bool ModelInstance::GetLocationInfo(const G3D::Vector3& p, LocationInfo &info) const bool ModelInstance::GetLocationInfo(const G3D::Vector3& p, LocationInfo& info) const
{ {
if (!iModel) if (!iModel)
{ {
@@ -123,7 +123,7 @@ namespace VMAP
return false; return false;
} }
bool ModelInstance::GetLiquidLevel(const G3D::Vector3& p, LocationInfo &info, float &liqHeight) const bool ModelInstance::GetLiquidLevel(const G3D::Vector3& p, LocationInfo& info, float& liqHeight) const
{ {
// 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;
@@ -139,7 +139,7 @@ namespace VMAP
return false; return false;
} }
bool ModelSpawn::readFromFile(FILE* rf, ModelSpawn &spawn) bool ModelSpawn::readFromFile(FILE* rf, ModelSpawn& spawn)
{ {
uint32 check = 0, nameLen; uint32 check = 0, nameLen;
check += fread(&spawn.flags, sizeof(uint32), 1, rf); check += fread(&spawn.flags, sizeof(uint32), 1, rf);
@@ -185,9 +185,9 @@ namespace VMAP
return true; return true;
} }
bool ModelSpawn::writeToFile(FILE* wf, const ModelSpawn &spawn) bool ModelSpawn::writeToFile(FILE* wf, const ModelSpawn& spawn)
{ {
uint32 check=0; uint32 check = 0;
check += fwrite(&spawn.flags, sizeof(uint32), 1, wf); check += fwrite(&spawn.flags, sizeof(uint32), 1, wf);
check += fwrite(&spawn.adtId, sizeof(uint16), 1, wf); check += fwrite(&spawn.adtId, sizeof(uint16), 1, wf);
check += fwrite(&spawn.ID, sizeof(uint32), 1, wf); check += fwrite(&spawn.ID, sizeof(uint32), 1, wf);

View File

@@ -23,47 +23,47 @@ namespace VMAP
enum ModelFlags enum ModelFlags
{ {
MOD_M2 = 1, MOD_M2 = 1,
MOD_WORLDSPAWN = 1<<1, MOD_WORLDSPAWN = 1 << 1,
MOD_HAS_BOUND = 1<<2 MOD_HAS_BOUND = 1 << 2
}; };
class ModelSpawn class ModelSpawn
{ {
public: public:
//mapID, tileX, tileY, Flags, ID, Pos, Rot, Scale, Bound_lo, Bound_hi, name //mapID, tileX, tileY, Flags, ID, Pos, Rot, Scale, Bound_lo, Bound_hi, name
uint32 flags; uint32 flags;
uint16 adtId; uint16 adtId;
uint32 ID; uint32 ID;
G3D::Vector3 iPos; G3D::Vector3 iPos;
G3D::Vector3 iRot; G3D::Vector3 iRot;
float iScale; float iScale;
G3D::AABox iBound; G3D::AABox iBound;
std::string name; std::string name;
bool operator==(const ModelSpawn &other) const { return ID == other.ID; } bool operator==(const ModelSpawn& other) const { return ID == other.ID; }
//uint32 hashCode() const { return ID; } //uint32 hashCode() const { return ID; }
// temp? // temp?
const G3D::AABox& getBounds() const { return iBound; } const G3D::AABox& getBounds() const { return iBound; }
static bool readFromFile(FILE* rf, ModelSpawn &spawn); static bool readFromFile(FILE* rf, ModelSpawn& spawn);
static bool writeToFile(FILE* rw, const ModelSpawn &spawn); static bool writeToFile(FILE* rw, const ModelSpawn& spawn);
}; };
class ModelInstance: public ModelSpawn class ModelInstance: public ModelSpawn
{ {
public: public:
ModelInstance(): iInvScale(0.0f), iModel(0) { } ModelInstance(): iInvScale(0.0f), iModel(0) { }
ModelInstance(const ModelSpawn &spawn, WorldModel* model); ModelInstance(const ModelSpawn& spawn, WorldModel* model);
void setUnloaded() { iModel = 0; } void setUnloaded() { iModel = 0; }
bool intersectRay(const G3D::Ray& pRay, float& pMaxDist, bool StopAtFirstHit) const; bool intersectRay(const G3D::Ray& pRay, float& pMaxDist, bool StopAtFirstHit) const;
void intersectPoint(const G3D::Vector3& p, AreaInfo &info) const; void intersectPoint(const G3D::Vector3& p, AreaInfo& info) const;
bool GetLocationInfo(const G3D::Vector3& p, LocationInfo &info) const; bool GetLocationInfo(const G3D::Vector3& p, LocationInfo& info) const;
bool GetLiquidLevel(const G3D::Vector3& p, LocationInfo &info, float &liqHeight) const; bool GetLiquidLevel(const G3D::Vector3& p, LocationInfo& info, float& liqHeight) const;
protected: protected:
G3D::Matrix3 iInvRot; G3D::Matrix3 iInvRot;
float iInvScale; float iInvScale;
WorldModel* iModel; WorldModel* iModel;
public: public:
WorldModel* getWorldModel(); WorldModel* getWorldModel();
}; };
} // namespace VMAP } // namespace VMAP

View File

@@ -19,7 +19,7 @@ template<> struct BoundsTrait<VMAP::GroupModel>
namespace VMAP namespace VMAP
{ {
bool IntersectTriangle(const MeshTriangle &tri, std::vector<Vector3>::const_iterator points, const G3D::Ray &ray, float &distance) bool IntersectTriangle(const MeshTriangle& tri, std::vector<Vector3>::const_iterator points, const G3D::Ray& ray, float& distance)
{ {
static const float EPS = 1e-5f; static const float EPS = 1e-5f;
@@ -30,7 +30,8 @@ namespace VMAP
const Vector3 p(ray.direction().cross(e2)); const Vector3 p(ray.direction().cross(e2));
const float a = e1.dot(p); const float a = e1.dot(p);
if (fabs(a) < EPS) { if (fabs(a) < EPS)
{
// Determinant is ill-conditioned; abort early // Determinant is ill-conditioned; abort early
return false; return false;
} }
@@ -39,7 +40,8 @@ namespace VMAP
const Vector3 s(ray.origin() - points[tri.idx0]); const Vector3 s(ray.origin() - points[tri.idx0]);
const float u = f * s.dot(p); const float u = f * s.dot(p);
if ((u < 0.0f) || (u > 1.0f)) { if ((u < 0.0f) || (u > 1.0f))
{
// We hit the plane of the m_geometry, but outside the m_geometry // We hit the plane of the m_geometry, but outside the m_geometry
return false; return false;
} }
@@ -47,7 +49,8 @@ namespace VMAP
const Vector3 q(s.cross(e1)); const Vector3 q(s.cross(e1));
const float v = f * ray.direction().dot(q); const float v = f * ray.direction().dot(q);
if ((v < 0.0f) || ((u + v) > 1.0f)) { if ((v < 0.0f) || ((u + v) > 1.0f))
{
// We hit the plane of the triangle, but outside the triangle // We hit the plane of the triangle, but outside the triangle
return false; return false;
} }
@@ -71,32 +74,32 @@ namespace VMAP
class TriBoundFunc class TriBoundFunc
{ {
public: public:
TriBoundFunc(std::vector<Vector3> &vert): vertices(vert.begin()) { } TriBoundFunc(std::vector<Vector3>& vert): vertices(vert.begin()) { }
void operator()(const MeshTriangle &tri, G3D::AABox &out) const void operator()(const MeshTriangle& tri, G3D::AABox& out) const
{ {
G3D::Vector3 lo = vertices[tri.idx0]; G3D::Vector3 lo = vertices[tri.idx0];
G3D::Vector3 hi = lo; G3D::Vector3 hi = lo;
lo = (lo.min(vertices[tri.idx1])).min(vertices[tri.idx2]); lo = (lo.min(vertices[tri.idx1])).min(vertices[tri.idx2]);
hi = (hi.max(vertices[tri.idx1])).max(vertices[tri.idx2]); hi = (hi.max(vertices[tri.idx1])).max(vertices[tri.idx2]);
out = G3D::AABox(lo, hi); out = G3D::AABox(lo, hi);
} }
protected: protected:
const std::vector<Vector3>::const_iterator vertices; const std::vector<Vector3>::const_iterator vertices;
}; };
// ===================== WmoLiquid ================================== // ===================== WmoLiquid ==================================
WmoLiquid::WmoLiquid(uint32 width, uint32 height, const Vector3 &corner, uint32 type): WmoLiquid::WmoLiquid(uint32 width, uint32 height, const Vector3& corner, uint32 type):
iTilesX(width), iTilesY(height), iCorner(corner), iType(type) iTilesX(width), iTilesY(height), iCorner(corner), iType(type)
{ {
iHeight = new float[(width+1)*(height+1)]; iHeight = new float[(width + 1) * (height + 1)];
iFlags = new uint8[width*height]; iFlags = new uint8[width * height];
} }
WmoLiquid::WmoLiquid(const WmoLiquid &other): iHeight(0), iFlags(0) WmoLiquid::WmoLiquid(const WmoLiquid& other): iHeight(0), iFlags(0)
{ {
*this = other; // use assignment operator... *this = other; // use assignment operator...
} }
@@ -107,7 +110,7 @@ namespace VMAP
delete[] iFlags; delete[] iFlags;
} }
WmoLiquid& WmoLiquid::operator=(const WmoLiquid &other) WmoLiquid& WmoLiquid::operator=(const WmoLiquid& other)
{ {
if (this == &other) if (this == &other)
return *this; return *this;
@@ -119,8 +122,8 @@ namespace VMAP
delete[] iFlags; delete[] iFlags;
if (other.iHeight) if (other.iHeight)
{ {
iHeight = new float[(iTilesX+1)*(iTilesY+1)]; iHeight = new float[(iTilesX + 1) * (iTilesY + 1)];
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;
@@ -134,20 +137,20 @@ namespace VMAP
return *this; return *this;
} }
bool WmoLiquid::GetLiquidHeight(const Vector3 &pos, float &liqHeight) const bool WmoLiquid::GetLiquidHeight(const Vector3& pos, float& liqHeight) const
{ {
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
@@ -170,14 +173,14 @@ namespace VMAP
const uint32 rowOffset = iTilesX + 1; const uint32 rowOffset = iTilesX + 1;
if (dx > dy) // case (a) if (dx > dy) // case (a)
{ {
float sx = iHeight[tx+1 + ty * rowOffset] - iHeight[tx + ty * rowOffset]; float sx = iHeight[tx + 1 + ty * rowOffset] - iHeight[tx + ty * rowOffset];
float sy = iHeight[tx+1 + (ty+1) * rowOffset] - iHeight[tx+1 + ty * rowOffset]; float sy = iHeight[tx + 1 + (ty + 1) * rowOffset] - iHeight[tx + 1 + ty * rowOffset];
liqHeight = iHeight[tx + ty * rowOffset] + dx * sx + dy * sy; liqHeight = iHeight[tx + ty * rowOffset] + dx * sx + dy * sy;
} }
else // case (b) else // case (b)
{ {
float sx = iHeight[tx+1 + (ty+1) * rowOffset] - iHeight[tx + (ty+1) * rowOffset]; float sx = iHeight[tx + 1 + (ty + 1) * rowOffset] - iHeight[tx + (ty + 1) * rowOffset];
float sy = iHeight[tx + (ty+1) * rowOffset] - iHeight[tx + ty * rowOffset]; float sy = iHeight[tx + (ty + 1) * rowOffset] - iHeight[tx + ty * rowOffset];
liqHeight = iHeight[tx + ty * rowOffset] + dx * sx + dy * sy; liqHeight = iHeight[tx + ty * rowOffset] + dx * sx + dy * sy;
} }
return true; return true;
@@ -186,23 +189,23 @@ namespace VMAP
uint32 WmoLiquid::GetFileSize() uint32 WmoLiquid::GetFileSize()
{ {
return 2 * sizeof(uint32) + return 2 * sizeof(uint32) +
sizeof(Vector3) + sizeof(Vector3) +
(iTilesX + 1)*(iTilesY + 1) * sizeof(float) + (iTilesX + 1) * (iTilesY + 1) * sizeof(float) +
iTilesX * iTilesY; iTilesX * iTilesY;
} }
bool WmoLiquid::writeToFile(FILE* wf) bool WmoLiquid::writeToFile(FILE* wf)
{ {
bool result = false; bool result = false;
if (fwrite(&iTilesX, sizeof(uint32), 1, wf) == 1 && if (fwrite(&iTilesX, sizeof(uint32), 1, wf) == 1 &&
fwrite(&iTilesY, sizeof(uint32), 1, wf) == 1 && fwrite(&iTilesY, sizeof(uint32), 1, wf) == 1 &&
fwrite(&iCorner, sizeof(Vector3), 1, wf) == 1 && fwrite(&iCorner, sizeof(Vector3), 1, wf) == 1 &&
fwrite(&iType, sizeof(uint32), 1, wf) == 1) fwrite(&iType, sizeof(uint32), 1, wf) == 1)
{ {
uint32 size = (iTilesX + 1) * (iTilesY + 1); uint32 size = (iTilesX + 1) * (iTilesY + 1);
if (fwrite(iHeight, sizeof(float), size, wf) == size) if (fwrite(iHeight, sizeof(float), size, wf) == size)
{ {
size = iTilesX*iTilesY; size = iTilesX * iTilesY;
result = fwrite(iFlags, sizeof(uint8), size, wf) == size; result = fwrite(iFlags, sizeof(uint8), size, wf) == size;
} }
} }
@@ -210,15 +213,15 @@ namespace VMAP
return result; return result;
} }
bool WmoLiquid::readFromFile(FILE* rf, WmoLiquid* &out) bool WmoLiquid::readFromFile(FILE* rf, WmoLiquid*& out)
{ {
bool result = false; bool result = false;
WmoLiquid* liquid = new WmoLiquid(); WmoLiquid* liquid = new WmoLiquid();
if (fread(&liquid->iTilesX, sizeof(uint32), 1, rf) == 1 && if (fread(&liquid->iTilesX, sizeof(uint32), 1, rf) == 1 &&
fread(&liquid->iTilesY, sizeof(uint32), 1, rf) == 1 && fread(&liquid->iTilesY, sizeof(uint32), 1, rf) == 1 &&
fread(&liquid->iCorner, sizeof(Vector3), 1, rf) == 1 && fread(&liquid->iCorner, sizeof(Vector3), 1, rf) == 1 &&
fread(&liquid->iType, sizeof(uint32), 1, rf) == 1) fread(&liquid->iType, sizeof(uint32), 1, rf) == 1)
{ {
uint32 size = (liquid->iTilesX + 1) * (liquid->iTilesY + 1); uint32 size = (liquid->iTilesX + 1) * (liquid->iTilesY + 1);
liquid->iHeight = new float[size]; liquid->iHeight = new float[size];
@@ -240,7 +243,7 @@ namespace VMAP
// ===================== GroupModel ================================== // ===================== GroupModel ==================================
GroupModel::GroupModel(const GroupModel &other): GroupModel::GroupModel(const GroupModel& other):
iBound(other.iBound), iMogpFlags(other.iMogpFlags), iGroupWMOID(other.iGroupWMOID), iBound(other.iBound), iMogpFlags(other.iMogpFlags), iGroupWMOID(other.iGroupWMOID),
vertices(other.vertices), triangles(other.triangles), meshTree(other.meshTree), iLiquid(0) vertices(other.vertices), triangles(other.triangles), meshTree(other.meshTree), iLiquid(0)
{ {
@@ -248,7 +251,7 @@ namespace VMAP
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)
{ {
vertices.swap(vert); vertices.swap(vert);
triangles.swap(tri); triangles.swap(tri);
@@ -268,7 +271,7 @@ namespace VMAP
// 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
@@ -278,7 +281,7 @@ namespace VMAP
// 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;
@@ -347,12 +350,12 @@ namespace VMAP
struct GModelRayCallback struct GModelRayCallback
{ {
GModelRayCallback(const std::vector<MeshTriangle> &tris, const std::vector<Vector3> &vert): GModelRayCallback(const std::vector<MeshTriangle>& tris, const std::vector<Vector3>& vert):
vertices(vert.begin()), triangles(tris.begin()), hit(false) { } vertices(vert.begin()), triangles(tris.begin()), hit(false) { }
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;
@@ -360,7 +363,7 @@ namespace VMAP
bool hit; bool hit;
}; };
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;
@@ -370,7 +373,7 @@ namespace VMAP
return callback.hit; return callback.hit;
} }
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;
@@ -384,7 +387,7 @@ namespace VMAP
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);
@@ -400,7 +403,7 @@ namespace VMAP
// ===================== WorldModel ================================== // ===================== WorldModel ==================================
void WorldModel::setGroupModels(std::vector<GroupModel> &models) void WorldModel::setGroupModels(std::vector<GroupModel>& models)
{ {
groupModels.swap(models); groupModels.swap(models);
groupTree.build(groupModels, BoundsTrait<GroupModel>::getBounds, 1); groupTree.build(groupModels, BoundsTrait<GroupModel>::getBounds, 1);
@@ -408,18 +411,18 @@ namespace VMAP
struct WModelRayCallBack struct WModelRayCallBack
{ {
WModelRayCallBack(const std::vector<GroupModel> &mod): models(mod.begin()), hit(false) { } WModelRayCallBack(const std::vector<GroupModel>& mod): models(mod.begin()), hit(false) { }
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;
bool hit; bool hit;
}; };
bool WorldModel::IntersectRay(const G3D::Ray &ray, float &distance, bool stopAtFirstHit) const bool WorldModel::IntersectRay(const G3D::Ray& ray, float& distance, bool stopAtFirstHit) const
{ {
// 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
@@ -431,44 +434,45 @@ namespace VMAP
return isc.hit; return isc.hit;
} }
class WModelAreaCallback { class WModelAreaCallback
public: {
WModelAreaCallback(const std::vector<GroupModel> &vals, const Vector3 &down): public:
prims(vals.begin()), hit(vals.end()), minVol(G3D::inf()), zDist(G3D::inf()), zVec(down) { } WModelAreaCallback(const std::vector<GroupModel>& vals, const Vector3& down):
std::vector<GroupModel>::const_iterator prims; prims(vals.begin()), hit(vals.end()), minVol(G3D::inf()), zDist(G3D::inf()), zVec(down) { }
std::vector<GroupModel>::const_iterator hit; std::vector<GroupModel>::const_iterator prims;
float minVol; std::vector<GroupModel>::const_iterator hit;
float zDist; float minVol;
Vector3 zVec; float zDist;
void operator()(const Vector3& point, uint32 entry) Vector3 zVec;
void operator()(const Vector3& point, uint32 entry)
{
float group_Z;
//float pVol = prims[entry].GetBound().volume();
//if (pVol < minVol)
//{
/* if (prims[entry].iBound.contains(point)) */
if (prims[entry].IsInsideObject(point, zVec, group_Z))
{ {
float group_Z; //minVol = pVol;
//float pVol = prims[entry].GetBound().volume(); //hit = prims + entry;
//if (pVol < minVol) if (group_Z < zDist)
//{ {
/* if (prims[entry].iBound.contains(point)) */ zDist = group_Z;
if (prims[entry].IsInsideObject(point, zVec, group_Z)) hit = prims + entry;
{ }
//minVol = pVol;
//hit = prims + entry;
if (group_Z < zDist)
{
zDist = group_Z;
hit = prims + entry;
}
#ifdef VMAP_DEBUG #ifdef VMAP_DEBUG
const GroupModel &gm = prims[entry]; const GroupModel& gm = prims[entry];
printf("%10u %8X %7.3f, %7.3f, %7.3f | %7.3f, %7.3f, %7.3f | z=%f, p_z=%f\n", gm.GetWmoID(), gm.GetMogpFlags(), printf("%10u %8X %7.3f, %7.3f, %7.3f | %7.3f, %7.3f, %7.3f | z=%f, p_z=%f\n", gm.GetWmoID(), gm.GetMogpFlags(),
gm.GetBound().low().x, gm.GetBound().low().y, gm.GetBound().low().z, gm.GetBound().low().x, gm.GetBound().low().y, gm.GetBound().low().z,
gm.GetBound().high().x, gm.GetBound().high().y, gm.GetBound().high().z, group_Z, point.z); gm.GetBound().high().x, gm.GetBound().high().y, gm.GetBound().high().z, group_Z, point.z);
#endif #endif
}
//}
//std::cout << "trying to intersect '" << prims[entry].name << "'\n";
} }
//}
//std::cout << "trying to intersect '" << prims[entry].name << "'\n";
}
}; };
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;
@@ -487,7 +491,7 @@ namespace VMAP
return false; return false;
} }
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;
@@ -503,7 +507,7 @@ namespace VMAP
return false; return false;
} }
bool WorldModel::writeFile(const std::string &filename) bool WorldModel::writeFile(const std::string& filename)
{ {
FILE* wf = fopen(filename.c_str(), "wb"); FILE* wf = fopen(filename.c_str(), "wb");
if (!wf) if (!wf)
@@ -517,14 +521,14 @@ namespace VMAP
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
@@ -536,7 +540,7 @@ namespace VMAP
return result; return result;
} }
bool WorldModel::readFile(const std::string &filename) bool WorldModel::readFile(const std::string& filename)
{ {
FILE* rf = fopen(filename.c_str(), "rb"); FILE* rf = fopen(filename.c_str(), "rb");
if (!rf) if (!rf)
@@ -560,7 +564,7 @@ namespace VMAP
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

View File

@@ -23,94 +23,94 @@ namespace VMAP
class MeshTriangle class MeshTriangle
{ {
public: public:
MeshTriangle() : idx0(0), idx1(0), idx2(0) { } MeshTriangle() : idx0(0), idx1(0), idx2(0) { }
MeshTriangle(uint32 na, uint32 nb, uint32 nc): idx0(na), idx1(nb), idx2(nc) { } MeshTriangle(uint32 na, uint32 nb, uint32 nc): idx0(na), idx1(nb), idx2(nc) { }
uint32 idx0; uint32 idx0;
uint32 idx1; uint32 idx1;
uint32 idx2; uint32 idx2;
}; };
class WmoLiquid class WmoLiquid
{ {
public: public:
WmoLiquid(uint32 width, uint32 height, const G3D::Vector3 &corner, uint32 type); WmoLiquid(uint32 width, uint32 height, const G3D::Vector3& corner, uint32 type);
WmoLiquid(const WmoLiquid &other); WmoLiquid(const WmoLiquid& other);
~WmoLiquid(); ~WmoLiquid();
WmoLiquid& operator=(const WmoLiquid &other); WmoLiquid& operator=(const WmoLiquid& other);
bool GetLiquidHeight(const G3D::Vector3 &pos, float &liqHeight) const; bool GetLiquidHeight(const G3D::Vector3& pos, float& liqHeight) const;
uint32 GetType() const { return iType; } uint32 GetType() const { return iType; }
float *GetHeightStorage() { return iHeight; } float* GetHeightStorage() { return iHeight; }
uint8 *GetFlagsStorage() { return iFlags; } uint8* GetFlagsStorage() { return iFlags; }
uint32 GetFileSize(); uint32 GetFileSize();
bool writeToFile(FILE* wf); bool writeToFile(FILE* wf);
static bool readFromFile(FILE* rf, WmoLiquid* &liquid); static bool readFromFile(FILE* rf, WmoLiquid*& liquid);
private: private:
WmoLiquid(): iTilesX(0), iTilesY(0), iType(0), iHeight(0), iFlags(0) { } WmoLiquid(): iTilesX(0), iTilesY(0), iType(0), iHeight(0), iFlags(0) { }
uint32 iTilesX; //!< number of tiles in x direction, each uint32 iTilesX; //!< number of tiles in x direction, each
uint32 iTilesY; uint32 iTilesY;
G3D::Vector3 iCorner; //!< the lower corner G3D::Vector3 iCorner; //!< the lower corner
uint32 iType; //!< liquid type uint32 iType; //!< liquid type
float *iHeight; //!< (tilesX + 1)*(tilesY + 1) height values float* iHeight; //!< (tilesX + 1)*(tilesY + 1) height values
uint8 *iFlags; //!< info if liquid tile is used uint8* iFlags; //!< info if liquid tile is used
public: public:
void getPosInfo(uint32 &tilesX, uint32 &tilesY, G3D::Vector3 &corner) const; void getPosInfo(uint32& tilesX, uint32& tilesY, G3D::Vector3& corner) const;
}; };
/*! holding additional info for WMO group files */ /*! holding additional info for WMO group files */
class GroupModel class GroupModel
{ {
public: public:
GroupModel(): iMogpFlags(0), iGroupWMOID(0), iLiquid(0) { } GroupModel(): iMogpFlags(0), iGroupWMOID(0), iLiquid(0) { }
GroupModel(const GroupModel &other); GroupModel(const GroupModel& other);
GroupModel(uint32 mogpFlags, uint32 groupWMOID, const G3D::AABox &bound): GroupModel(uint32 mogpFlags, uint32 groupWMOID, const G3D::AABox& bound):
iBound(bound), iMogpFlags(mogpFlags), iGroupWMOID(groupWMOID), iLiquid(0) { } iBound(bound), iMogpFlags(mogpFlags), iGroupWMOID(groupWMOID), iLiquid(0) { }
~GroupModel() { delete iLiquid; } ~GroupModel() { delete iLiquid; }
//! pass mesh data to object and create BIH. Passed vectors get get swapped with old geometry! //! pass mesh data to object and create BIH. Passed vectors get get swapped with old geometry!
void setMeshData(std::vector<G3D::Vector3> &vert, std::vector<MeshTriangle> &tri); void setMeshData(std::vector<G3D::Vector3>& vert, std::vector<MeshTriangle>& tri);
void setLiquidData(WmoLiquid*& liquid) { iLiquid = liquid; liquid = NULL; } void setLiquidData(WmoLiquid*& liquid) { iLiquid = liquid; liquid = NULL; }
bool IntersectRay(const G3D::Ray &ray, float &distance, bool stopAtFirstHit) const; bool IntersectRay(const G3D::Ray& ray, float& distance, bool stopAtFirstHit) const;
bool IsInsideObject(const G3D::Vector3 &pos, const G3D::Vector3 &down, float &z_dist) const; bool IsInsideObject(const G3D::Vector3& pos, const G3D::Vector3& down, float& z_dist) const;
bool GetLiquidLevel(const G3D::Vector3 &pos, float &liqHeight) const; bool GetLiquidLevel(const G3D::Vector3& pos, float& liqHeight) const;
uint32 GetLiquidType() const; uint32 GetLiquidType() const;
bool writeToFile(FILE* wf); bool writeToFile(FILE* wf);
bool readFromFile(FILE* rf); bool readFromFile(FILE* rf);
const G3D::AABox& GetBound() const { return iBound; } const G3D::AABox& GetBound() const { return iBound; }
uint32 GetMogpFlags() const { return iMogpFlags; } uint32 GetMogpFlags() const { return iMogpFlags; }
uint32 GetWmoID() const { return iGroupWMOID; } uint32 GetWmoID() const { return iGroupWMOID; }
protected: protected:
G3D::AABox iBound; G3D::AABox iBound;
uint32 iMogpFlags;// 0x8 outdor; 0x2000 indoor uint32 iMogpFlags;// 0x8 outdor; 0x2000 indoor
uint32 iGroupWMOID; uint32 iGroupWMOID;
std::vector<G3D::Vector3> vertices; std::vector<G3D::Vector3> vertices;
std::vector<MeshTriangle> triangles; std::vector<MeshTriangle> triangles;
BIH meshTree; BIH meshTree;
WmoLiquid* iLiquid; WmoLiquid* iLiquid;
public: public:
void getMeshData(std::vector<G3D::Vector3> &vertices, std::vector<MeshTriangle> &triangles, WmoLiquid* &liquid); void getMeshData(std::vector<G3D::Vector3>& vertices, std::vector<MeshTriangle>& triangles, WmoLiquid*& liquid);
}; };
/*! Holds a model (converted M2 or WMO) in its original coordinate space */ /*! Holds a model (converted M2 or WMO) in its original coordinate space */
class WorldModel class WorldModel
{ {
public: public:
WorldModel(): RootWMOID(0) { } WorldModel(): RootWMOID(0) { }
//! pass group models to WorldModel and create BIH. Passed vector is swapped with old geometry! //! pass group models to WorldModel and create BIH. Passed vector is swapped with old geometry!
void setGroupModels(std::vector<GroupModel> &models); void setGroupModels(std::vector<GroupModel>& models);
void setRootWmoID(uint32 id) { RootWMOID = id; } void setRootWmoID(uint32 id) { RootWMOID = id; }
bool IntersectRay(const G3D::Ray &ray, float &distance, bool stopAtFirstHit) const; bool IntersectRay(const G3D::Ray& ray, float& distance, bool stopAtFirstHit) const;
bool IntersectPoint(const G3D::Vector3 &p, const G3D::Vector3 &down, float &dist, AreaInfo &info) const; bool IntersectPoint(const G3D::Vector3& p, const G3D::Vector3& down, float& dist, AreaInfo& info) const;
bool GetLocationInfo(const G3D::Vector3 &p, const G3D::Vector3 &down, float &dist, LocationInfo &info) const; bool GetLocationInfo(const G3D::Vector3& p, const G3D::Vector3& down, float& dist, LocationInfo& info) const;
bool writeFile(const std::string &filename); bool writeFile(const std::string& filename);
bool readFile(const std::string &filename); bool readFile(const std::string& filename);
protected: protected:
uint32 RootWMOID; uint32 RootWMOID;
std::vector<GroupModel> groupModels; std::vector<GroupModel> groupModels;
BIH groupTree; BIH groupTree;
public: public:
void getGroupModels(std::vector<GroupModel> &groupModels); void getGroupModels(std::vector<GroupModel>& groupModels);
}; };
} // namespace VMAP } // namespace VMAP

View File

@@ -16,7 +16,7 @@ public:
explicit NodeArray() { memset(&_nodes, 0, sizeof(_nodes)); } explicit NodeArray() { memset(&_nodes, 0, sizeof(_nodes)); }
void AddNode(Node* n) void AddNode(Node* n)
{ {
for (uint8 i=0; i<9; ++i) for (uint8 i = 0; i < 9; ++i)
if (_nodes[i] == 0) if (_nodes[i] == 0)
{ {
_nodes[i] = n; _nodes[i] = n;
@@ -29,37 +29,41 @@ public:
}; };
template<class Node> template<class Node>
struct NodeCreator{ struct NodeCreator
static Node * makeNode(int /*x*/, int /*y*/) { return new Node();} {
static Node* makeNode(int /*x*/, int /*y*/) { return new Node();}
}; };
template<class T, template<class T,
class Node, class Node,
class NodeCreatorFunc = NodeCreator<Node>, class NodeCreatorFunc = NodeCreator<Node>,
/*class BoundsFunc = BoundsTrait<T>,*/ /*class BoundsFunc = BoundsTrait<T>,*/
class PositionFunc = PositionTrait<T> class PositionFunc = PositionTrait<T>
> >
class RegularGrid2D class RegularGrid2D
{ {
public: public:
enum{ enum
{
CELL_NUMBER = 64, CELL_NUMBER = 64,
}; };
#define HGRID_MAP_SIZE (533.33333f * 64.f) // shouldn't be changed #define HGRID_MAP_SIZE (533.33333f * 64.f) // shouldn't be changed
#define CELL_SIZE float(HGRID_MAP_SIZE/(float)CELL_NUMBER) #define CELL_SIZE float(HGRID_MAP_SIZE/(float)CELL_NUMBER)
typedef G3D::Table<const T*, NodeArray<Node> > MemberTable; typedef G3D::Table<const T*, NodeArray<Node> > MemberTable;
MemberTable memberTable; MemberTable memberTable;
Node* nodes[CELL_NUMBER][CELL_NUMBER]; Node* nodes[CELL_NUMBER][CELL_NUMBER];
RegularGrid2D(){ RegularGrid2D()
{
memset(nodes, 0, sizeof(nodes)); memset(nodes, 0, sizeof(nodes));
} }
~RegularGrid2D(){ ~RegularGrid2D()
{
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];
@@ -72,14 +76,14 @@ public:
pos[1] = value.getBounds().corner(1); pos[1] = value.getBounds().corner(1);
pos[2] = value.getBounds().corner(2); pos[2] = value.getBounds().corner(2);
pos[3] = value.getBounds().corner(3); pos[3] = value.getBounds().corner(3);
pos[4] = (pos[0] + pos[1])/2.0f; pos[4] = (pos[0] + pos[1]) / 2.0f;
pos[5] = (pos[1] + pos[2])/2.0f; pos[5] = (pos[1] + pos[2]) / 2.0f;
pos[6] = (pos[2] + pos[3])/2.0f; pos[6] = (pos[2] + pos[3]) / 2.0f;
pos[7] = (pos[3] + pos[0])/2.0f; pos[7] = (pos[3] + pos[0]) / 2.0f;
pos[8] = (pos[0] + pos[2])/2.0f; pos[8] = (pos[0] + pos[2]) / 2.0f;
NodeArray<Node> na; NodeArray<Node> na;
for (uint8 i=0; i<9; ++i) for (uint8 i = 0; i < 9; ++i)
{ {
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())
@@ -88,7 +92,7 @@ public:
na.AddNode(&node); na.AddNode(&node);
} }
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);
@@ -102,7 +106,7 @@ public:
void remove(const T& value) void remove(const T& value)
{ {
NodeArray<Node>& na = memberTable[&value]; NodeArray<Node>& na = memberTable[&value];
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);
@@ -132,7 +136,7 @@ public:
static Cell ComputeCell(float fx, float fy) static Cell ComputeCell(float fx, float fy)
{ {
Cell c = { int(fx * (1.f/CELL_SIZE) + (CELL_NUMBER/2)), int(fy * (1.f/CELL_SIZE) + (CELL_NUMBER/2)) }; Cell c = { int(fx * (1.f / CELL_SIZE) + (CELL_NUMBER / 2)), int(fy * (1.f / CELL_SIZE) + (CELL_NUMBER / 2)) };
return c; return c;
} }
@@ -185,26 +189,26 @@ public:
if (kx_inv >= 0) if (kx_inv >= 0)
{ {
stepX = 1; stepX = 1;
float x_border = (cell.x+1) * voxel; float x_border = (cell.x + 1) * voxel;
tMaxX = (x_border - bx) * kx_inv; tMaxX = (x_border - bx) * kx_inv;
} }
else else
{ {
stepX = -1; stepX = -1;
float x_border = (cell.x-1) * voxel; float x_border = (cell.x - 1) * voxel;
tMaxX = (x_border - bx) * kx_inv; tMaxX = (x_border - bx) * kx_inv;
} }
if (ky_inv >= 0) if (ky_inv >= 0)
{ {
stepY = 1; stepY = 1;
float y_border = (cell.y+1) * voxel; float y_border = (cell.y + 1) * voxel;
tMaxY = (y_border - by) * ky_inv; tMaxY = (y_border - by) * ky_inv;
} }
else else
{ {
stepY = -1; stepY = -1;
float y_border = (cell.y-1) * voxel; float y_border = (cell.y - 1) * voxel;
tMaxY = (y_border - by) * ky_inv; tMaxY = (y_border - by) * ky_inv;
} }

View File

@@ -17,6 +17,6 @@ namespace VMAP
const char GAMEOBJECT_MODELS[] = "GameObjectModels.dtree"; const char GAMEOBJECT_MODELS[] = "GameObjectModels.dtree";
// defined in TileAssembler.cpp currently... // defined in TileAssembler.cpp currently...
bool readChunk(FILE* rf, char *dest, const char *compare, uint32 len); bool readChunk(FILE* rf, char* dest, const char* compare, uint32 len);
} }
#endif #endif

View File

@@ -21,13 +21,15 @@ The collision detection is modified to return true, if we are inside an object.
namespace VMAP namespace VMAP
{ {
template<class TValue> template<class TValue>
class IntersectionCallBack { class IntersectionCallBack
{
public: public:
TValue* closestEntity; TValue* closestEntity;
G3D::Vector3 hitLocation; G3D::Vector3 hitLocation;
G3D::Vector3 hitNormal; G3D::Vector3 hitNormal;
void operator()(const G3D::Ray& ray, const TValue* entity, bool StopAtFirstHit, float& distance) { void operator()(const G3D::Ray& ray, const TValue* entity, bool StopAtFirstHit, float& distance)
{
entity->intersect(ray, distance, StopAtFirstHit, hitLocation, hitNormal); entity->intersect(ray, distance, StopAtFirstHit, hitLocation, hitNormal);
} }
}; };
@@ -116,7 +118,7 @@ namespace VMAP
{ {
location[i] = origin[i] + MaxT[WhichPlane] * dir[i]; location[i] = origin[i] + MaxT[WhichPlane] * dir[i];
if ((location[i] < MinB[i]) || if ((location[i] < MinB[i]) ||
(location[i] > MaxB[i])) (location[i] > MaxB[i]))
{ {
// On this plane we're outside the box extents, so // On this plane we're outside the box extents, so
// we miss the box // we miss the box

View File

@@ -6,22 +6,23 @@
#include "Common.h" #include "Common.h"
char const* localeNames[TOTAL_LOCALES] = { char const* localeNames[TOTAL_LOCALES] =
"enUS", {
"koKR", "enUS",
"frFR", "koKR",
"deDE", "frFR",
"zhCN", "deDE",
"zhTW", "zhCN",
"esES", "zhTW",
"esMX", "esES",
"ruRU" "esMX",
"ruRU"
}; };
LocaleConstant GetLocaleByName(const std::string& name) 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
@@ -30,8 +31,8 @@ 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

@@ -136,11 +136,11 @@ inline bool myisfinite(float f) { return isfinite(f) && !isnan(f); }
enum TimeConstants enum TimeConstants
{ {
MINUTE = 60, MINUTE = 60,
HOUR = MINUTE*60, HOUR = MINUTE * 60,
DAY = HOUR*24, DAY = HOUR * 24,
WEEK = DAY*7, WEEK = DAY * 7,
MONTH = DAY*30, MONTH = DAY * 30,
YEAR = MONTH*12, YEAR = MONTH * 12,
IN_MILLISECONDS = 1000 IN_MILLISECONDS = 1000
}; };

View File

@@ -36,35 +36,35 @@ namespace acore
template <class T> template <class T>
class CheckedBufferOutputIterator class CheckedBufferOutputIterator
{ {
public: public:
using iterator_category = std::output_iterator_tag; using iterator_category = std::output_iterator_tag;
using value_type = void; using value_type = void;
using pointer = T*; using pointer = T*;
using reference = T&; using reference = T&;
using difference_type = std::ptrdiff_t; using difference_type = std::ptrdiff_t;
CheckedBufferOutputIterator(T* buf, size_t n) : _buf(buf), _end(buf+n) {} CheckedBufferOutputIterator(T* buf, size_t n) : _buf(buf), _end(buf + n) {}
T& operator*() const { check(); return *_buf; } T& operator*() const { check(); return *_buf; }
CheckedBufferOutputIterator& operator++() { check(); ++_buf; return *this; } CheckedBufferOutputIterator& operator++() { check(); ++_buf; return *this; }
CheckedBufferOutputIterator operator++(int) { CheckedBufferOutputIterator v = *this; operator++(); return v; } CheckedBufferOutputIterator operator++(int) { CheckedBufferOutputIterator v = *this; operator++(); return v; }
size_t remaining() const { return (_end - _buf); } size_t remaining() const { return (_end - _buf); }
private: private:
T* _buf; T* _buf;
T* _end; T* _end;
void check() const void check() const
{ {
if (!(_buf < _end)) if (!(_buf < _end))
throw std::out_of_range("index"); throw std::out_of_range("index");
} }
}; };
namespace Containers namespace Containers
{ {
template<class T> template<class T>
void RandomResizeList(std::list<T> &list, uint32 size) void RandomResizeList(std::list<T>& list, uint32 size)
{ {
size_t list_size = list.size(); size_t list_size = list.size();
@@ -78,7 +78,7 @@ namespace acore
} }
template<class T, class Predicate> template<class T, class Predicate>
void RandomResizeList(std::list<T> &list, Predicate& predicate, uint32 size) void RandomResizeList(std::list<T>& list, Predicate& predicate, uint32 size)
{ {
//! First use predicate filter //! First use predicate filter
std::list<T> listCopy; std::list<T> listCopy;

View File

@@ -12,14 +12,14 @@
class ARC4 class ARC4
{ {
public: public:
ARC4(uint32 len); ARC4(uint32 len);
ARC4(uint8* seed, uint32 len); ARC4(uint8* seed, uint32 len);
~ARC4(); ~ARC4();
void Init(uint8* seed); void Init(uint8* seed);
void UpdateData(int len, uint8* data); void UpdateData(int len, uint8* data);
private: private:
EVP_CIPHER_CTX* m_ctx; EVP_CIPHER_CTX* m_ctx;
}; };
#endif #endif

View File

@@ -17,11 +17,11 @@ void AuthCrypt::Init(BigNumber* K)
{ {
uint8 ServerEncryptionKey[SEED_KEY_SIZE] = { 0xCC, 0x98, 0xAE, 0x04, 0xE8, 0x97, 0xEA, 0xCA, 0x12, 0xDD, 0xC0, 0x93, 0x42, 0x91, 0x53, 0x57 }; uint8 ServerEncryptionKey[SEED_KEY_SIZE] = { 0xCC, 0x98, 0xAE, 0x04, 0xE8, 0x97, 0xEA, 0xCA, 0x12, 0xDD, 0xC0, 0x93, 0x42, 0x91, 0x53, 0x57 };
HmacHash serverEncryptHmac(SEED_KEY_SIZE, (uint8*)ServerEncryptionKey); HmacHash serverEncryptHmac(SEED_KEY_SIZE, (uint8*)ServerEncryptionKey);
uint8 *encryptHash = serverEncryptHmac.ComputeHash(K); uint8* encryptHash = serverEncryptHmac.ComputeHash(K);
uint8 ServerDecryptionKey[SEED_KEY_SIZE] = { 0xC2, 0xB3, 0x72, 0x3C, 0xC6, 0xAE, 0xD9, 0xB5, 0x34, 0x3C, 0x53, 0xEE, 0x2F, 0x43, 0x67, 0xCE }; uint8 ServerDecryptionKey[SEED_KEY_SIZE] = { 0xC2, 0xB3, 0x72, 0x3C, 0xC6, 0xAE, 0xD9, 0xB5, 0x34, 0x3C, 0x53, 0xEE, 0x2F, 0x43, 0x67, 0xCE };
HmacHash clientDecryptHmac(SEED_KEY_SIZE, (uint8*)ServerDecryptionKey); HmacHash clientDecryptHmac(SEED_KEY_SIZE, (uint8*)ServerDecryptionKey);
uint8 *decryptHash = clientDecryptHmac.ComputeHash(K); uint8* decryptHash = clientDecryptHmac.ComputeHash(K);
//ARC4 _serverDecrypt(encryptHash); //ARC4 _serverDecrypt(encryptHash);
_clientDecrypt.Init(decryptHash); _clientDecrypt.Init(decryptHash);
@@ -43,7 +43,7 @@ void AuthCrypt::Init(BigNumber* K)
_initialized = true; _initialized = true;
} }
void AuthCrypt::DecryptRecv(uint8 *data, size_t len) void AuthCrypt::DecryptRecv(uint8* data, size_t len)
{ {
if (!_initialized) if (!_initialized)
return; return;
@@ -51,7 +51,7 @@ void AuthCrypt::DecryptRecv(uint8 *data, size_t len)
_clientDecrypt.UpdateData(len, data); _clientDecrypt.UpdateData(len, data);
} }
void AuthCrypt::EncryptSend(uint8 *data, size_t len) void AuthCrypt::EncryptSend(uint8* data, size_t len)
{ {
if (!_initialized) if (!_initialized)
return; return;

View File

@@ -13,18 +13,18 @@ class BigNumber;
class AuthCrypt class AuthCrypt
{ {
public: public:
AuthCrypt(); AuthCrypt();
void Init(BigNumber* K); void Init(BigNumber* K);
void DecryptRecv(uint8 *, size_t); void DecryptRecv(uint8*, size_t);
void EncryptSend(uint8 *, size_t); void EncryptSend(uint8*, size_t);
bool IsInitialized() const { return _initialized; } bool IsInitialized() const { return _initialized; }
private: private:
ARC4 _clientDecrypt; ARC4 _clientDecrypt;
ARC4 _serverEncrypt; ARC4 _serverEncrypt;
bool _initialized; bool _initialized;
}; };
#endif #endif

View File

@@ -87,7 +87,7 @@ BigNumber BigNumber::operator-=(BigNumber const& bn)
BigNumber BigNumber::operator*=(BigNumber const& bn) BigNumber BigNumber::operator*=(BigNumber const& bn)
{ {
BN_CTX *bnctx; BN_CTX* bnctx;
bnctx = BN_CTX_new(); bnctx = BN_CTX_new();
BN_mul(_bn, _bn, bn._bn, bnctx); BN_mul(_bn, _bn, bn._bn, bnctx);
@@ -98,7 +98,7 @@ BigNumber BigNumber::operator*=(BigNumber const& bn)
BigNumber BigNumber::operator/=(BigNumber const& bn) BigNumber BigNumber::operator/=(BigNumber const& bn)
{ {
BN_CTX *bnctx; BN_CTX* bnctx;
bnctx = BN_CTX_new(); bnctx = BN_CTX_new();
BN_div(_bn, NULL, _bn, bn._bn, bnctx); BN_div(_bn, NULL, _bn, bn._bn, bnctx);
@@ -109,7 +109,7 @@ BigNumber BigNumber::operator/=(BigNumber const& bn)
BigNumber BigNumber::operator%=(BigNumber const& bn) BigNumber BigNumber::operator%=(BigNumber const& bn)
{ {
BN_CTX *bnctx; BN_CTX* bnctx;
bnctx = BN_CTX_new(); bnctx = BN_CTX_new();
BN_mod(_bn, _bn, bn._bn, bnctx); BN_mod(_bn, _bn, bn._bn, bnctx);
@@ -121,7 +121,7 @@ BigNumber BigNumber::operator%=(BigNumber const& bn)
BigNumber BigNumber::Exp(BigNumber const& bn) BigNumber BigNumber::Exp(BigNumber const& bn)
{ {
BigNumber ret; BigNumber ret;
BN_CTX *bnctx; BN_CTX* bnctx;
bnctx = BN_CTX_new(); bnctx = BN_CTX_new();
BN_exp(ret._bn, _bn, bn._bn, bnctx); BN_exp(ret._bn, _bn, bn._bn, bnctx);
@@ -133,7 +133,7 @@ BigNumber BigNumber::Exp(BigNumber const& bn)
BigNumber BigNumber::ModExp(BigNumber const& bn1, BigNumber const& bn2) BigNumber BigNumber::ModExp(BigNumber const& bn1, BigNumber const& bn2)
{ {
BigNumber ret; BigNumber ret;
BN_CTX *bnctx; BN_CTX* bnctx;
bnctx = BN_CTX_new(); bnctx = BN_CTX_new();
BN_mod_exp(ret._bn, _bn, bn1._bn, bn2._bn, bnctx); BN_mod_exp(ret._bn, _bn, bn1._bn, bn2._bn, bnctx);
@@ -178,12 +178,12 @@ std::unique_ptr<uint8[]> BigNumber::AsByteArray(int32 minSize, bool littleEndian
return ret; return ret;
} }
char * BigNumber::AsHexStr() const char* BigNumber::AsHexStr() const
{ {
return BN_bn2hex(_bn); return BN_bn2hex(_bn);
} }
char * BigNumber::AsDecStr() const char* BigNumber::AsDecStr() const
{ {
return BN_bn2dec(_bn); return BN_bn2dec(_bn);
} }

View File

@@ -17,74 +17,74 @@ struct bignum_st;
class BigNumber class BigNumber
{ {
public: public:
BigNumber(); BigNumber();
BigNumber(BigNumber const& bn); BigNumber(BigNumber const& bn);
BigNumber(uint32); BigNumber(uint32);
~BigNumber(); ~BigNumber();
void SetDword(uint32); void SetDword(uint32);
void SetQword(uint64); void SetQword(uint64);
void SetBinary(uint8 const* bytes, int32 len); void SetBinary(uint8 const* bytes, int32 len);
void SetHexStr(char const* str); void SetHexStr(char const* str);
void SetRand(int32 numbits); void SetRand(int32 numbits);
BigNumber& operator=(BigNumber const& bn); BigNumber& operator=(BigNumber const& bn);
BigNumber operator+=(BigNumber const& bn); BigNumber operator+=(BigNumber const& bn);
BigNumber operator+(BigNumber const& bn) BigNumber operator+(BigNumber const& bn)
{ {
BigNumber t(*this); BigNumber t(*this);
return t += bn; return t += bn;
} }
BigNumber operator-=(BigNumber const& bn); BigNumber operator-=(BigNumber const& bn);
BigNumber operator-(BigNumber const& bn) BigNumber operator-(BigNumber const& bn)
{ {
BigNumber t(*this); BigNumber t(*this);
return t -= bn; return t -= bn;
} }
BigNumber operator*=(BigNumber const& bn); BigNumber operator*=(BigNumber const& bn);
BigNumber operator*(BigNumber const& bn) BigNumber operator*(BigNumber const& bn)
{ {
BigNumber t(*this); BigNumber t(*this);
return t *= bn; return t *= bn;
} }
BigNumber operator/=(BigNumber const& bn); BigNumber operator/=(BigNumber const& bn);
BigNumber operator/(BigNumber const& bn) BigNumber operator/(BigNumber const& bn)
{ {
BigNumber t(*this); BigNumber t(*this);
return t /= bn; return t /= bn;
} }
BigNumber operator%=(BigNumber const& bn); BigNumber operator%=(BigNumber const& bn);
BigNumber operator%(BigNumber const& bn) BigNumber operator%(BigNumber const& bn)
{ {
BigNumber t(*this); BigNumber t(*this);
return t %= bn; return t %= bn;
} }
bool isZero() const; bool isZero() const;
BigNumber ModExp(BigNumber const& bn1, BigNumber const& bn2); BigNumber ModExp(BigNumber const& bn1, BigNumber const& bn2);
BigNumber Exp(BigNumber const&); BigNumber Exp(BigNumber const&);
int32 GetNumBytes(void); int32 GetNumBytes(void);
struct bignum_st *BN() { return _bn; } struct bignum_st* BN() { return _bn; }
uint32 AsDword(); uint32 AsDword();
std::unique_ptr<uint8[]> AsByteArray(int32 minSize = 0, bool littleEndian = true); std::unique_ptr<uint8[]> AsByteArray(int32 minSize = 0, bool littleEndian = true);
char * AsHexStr() const; char* AsHexStr() const;
char * AsDecStr() const; char* AsDecStr() const;
private: private:
struct bignum_st *_bn; struct bignum_st* _bn;
}; };
#endif #endif

View File

@@ -12,7 +12,7 @@
#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER < 0x10100000L #if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER < 0x10100000L
HMAC_CTX* HMAC_CTX_new() HMAC_CTX* HMAC_CTX_new()
{ {
HMAC_CTX *ctx = new HMAC_CTX(); HMAC_CTX* ctx = new HMAC_CTX();
HMAC_CTX_init(ctx); HMAC_CTX_init(ctx);
return ctx; return ctx;
} }

View File

@@ -18,18 +18,18 @@ class BigNumber;
class HmacHash class HmacHash
{ {
public: public:
HmacHash(uint32 len, uint8* seed); HmacHash(uint32 len, uint8* seed);
~HmacHash(); ~HmacHash();
void UpdateData(std::string const& str); void UpdateData(std::string const& str);
void UpdateData(uint8 const* data, size_t len); void UpdateData(uint8 const* data, size_t len);
void Finalize(); void Finalize();
uint8* ComputeHash(BigNumber* bn); uint8* ComputeHash(BigNumber* bn);
uint8* GetDigest() { return m_digest; } uint8* GetDigest() { return m_digest; }
int GetLength() const { return SHA_DIGEST_LENGTH; } int GetLength() const { return SHA_DIGEST_LENGTH; }
private: private:
HMAC_CTX* m_ctx; HMAC_CTX* m_ctx;
uint8 m_digest[SHA_DIGEST_LENGTH]; uint8 m_digest[SHA_DIGEST_LENGTH];
}; };
#endif #endif

View File

@@ -19,7 +19,7 @@ static void lockingCallback(int mode, int type, char const* /*file*/, int /*line
else else
cryptoLocks[type]->unlock(); cryptoLocks[type]->unlock();
} }
static void threadIdCallback(CRYPTO_THREADID * id) static void threadIdCallback(CRYPTO_THREADID* id)
{ {
(void)id; (void)id;
CRYPTO_THREADID_set_numeric(id, std::hash<std::thread::id>()(std::this_thread::get_id())); CRYPTO_THREADID_set_numeric(id, std::hash<std::thread::id>()(std::this_thread::get_id()));

View File

@@ -19,12 +19,12 @@ SHA1Hash::~SHA1Hash()
SHA1_Init(&mC); SHA1_Init(&mC);
} }
void SHA1Hash::UpdateData(const uint8 *dta, int len) void SHA1Hash::UpdateData(const uint8* dta, int len)
{ {
SHA1_Update(&mC, dta, len); SHA1_Update(&mC, dta, len);
} }
void SHA1Hash::UpdateData(const std::string &str) void SHA1Hash::UpdateData(const std::string& str)
{ {
UpdateData((uint8 const*)str.c_str(), str.length()); UpdateData((uint8 const*)str.c_str(), str.length());
} }

View File

@@ -15,24 +15,24 @@ class BigNumber;
class SHA1Hash class SHA1Hash
{ {
public: public:
SHA1Hash(); SHA1Hash();
~SHA1Hash(); ~SHA1Hash();
void UpdateBigNumbers(BigNumber* bn0, ...); void UpdateBigNumbers(BigNumber* bn0, ...);
void UpdateData(const uint8 *dta, int len); void UpdateData(const uint8* dta, int len);
void UpdateData(const std::string &str); void UpdateData(const std::string& str);
void Initialize(); void Initialize();
void Finalize(); void Finalize();
uint8 *GetDigest(void) { return mDigest; }; uint8* GetDigest(void) { return mDigest; };
int GetLength(void) const { return SHA_DIGEST_LENGTH; }; int GetLength(void) const { return SHA_DIGEST_LENGTH; };
private: private:
SHA_CTX mC; SHA_CTX mC;
uint8 mDigest[SHA_DIGEST_LENGTH]; uint8 mDigest[SHA_DIGEST_LENGTH];
}; };
#endif #endif

View File

@@ -14,7 +14,7 @@ class SHA1Randx
public: public:
SHA1Randx(uint8* buff, uint32 size) SHA1Randx(uint8* buff, uint32 size)
{ {
uint32 taken = size/2; uint32 taken = size / 2;
sh.Initialize(); sh.Initialize();
sh.UpdateData(buff, taken); sh.UpdateData(buff, taken);

View File

@@ -84,7 +84,7 @@ bool DBCFileLoader::Load(char const* filename, char const* fmt)
} }
data = new unsigned char[recordSize * recordCount + stringSize]; data = new unsigned char[recordSize * recordCount + stringSize];
stringTable = data + recordSize*recordCount; stringTable = data + recordSize * recordCount;
if (fread(data, recordSize * recordCount + stringSize, 1, f) != 1) if (fread(data, recordSize * recordCount + stringSize, 1, f) != 1)
{ {
@@ -210,7 +210,7 @@ char* DBCFileLoader::AutoProduceData(char const* format, uint32& records, char**
else else
indexTable[y] = &dataTable[offset]; indexTable[y] = &dataTable[offset];
for (uint32 x=0; x < fieldCount; ++x) for (uint32 x = 0; x < fieldCount; ++x)
{ {
switch (format[x]) switch (format[x])
{ {
@@ -275,17 +275,17 @@ char* DBCFileLoader::AutoProduceStrings(char const* format, char* dataTable)
offset += sizeof(uint8); offset += sizeof(uint8);
break; break;
case FT_STRING: case FT_STRING:
{
// fill only not filled entries
char** slot = (char**)(&dataTable[offset]);
if (!*slot || !**slot)
{ {
const char * st = getRecord(y).getString(x); // fill only not filled entries
*slot = stringPool + (st - (char const*)stringTable); char** slot = (char**)(&dataTable[offset]);
if (!*slot || !** slot)
{
const char* st = getRecord(y).getString(x);
*slot = stringPool + (st - (char const*)stringTable);
}
offset += sizeof(char*);
break;
} }
offset += sizeof(char*);
break;
}
case FT_LOGIC: case FT_LOGIC:
ASSERT(false && "Attempted to load DBC files that does not have field types that match what is in the core. Check DBCfmt.h or your DBC files."); ASSERT(false && "Attempted to load DBC files that does not have field types that match what is in the core. Check DBCfmt.h or your DBC files.");
break; break;

View File

@@ -30,7 +30,7 @@ public:
DBCFileLoader(); DBCFileLoader();
~DBCFileLoader(); ~DBCFileLoader();
bool Load(const char *filename, const char *fmt); bool Load(const char* filename, const char* fmt);
class Record class Record
{ {
@@ -38,7 +38,7 @@ public:
float getFloat(size_t field) const float getFloat(size_t field) const
{ {
ASSERT(field < file.fieldCount); ASSERT(field < file.fieldCount);
float val = *reinterpret_cast<float*>(offset+file.GetOffset(field)); float val = *reinterpret_cast<float*>(offset + file.GetOffset(field));
EndianConvert(val); EndianConvert(val);
return val; return val;
} }
@@ -46,7 +46,7 @@ public:
uint32 getUInt(size_t field) const uint32 getUInt(size_t field) const
{ {
ASSERT(field < file.fieldCount); ASSERT(field < file.fieldCount);
uint32 val = *reinterpret_cast<uint32*>(offset+file.GetOffset(field)); uint32 val = *reinterpret_cast<uint32*>(offset + file.GetOffset(field));
EndianConvert(val); EndianConvert(val);
return val; return val;
} }
@@ -54,10 +54,10 @@ public:
uint8 getUInt8(size_t field) const uint8 getUInt8(size_t field) const
{ {
ASSERT(field < file.fieldCount); ASSERT(field < file.fieldCount);
return *reinterpret_cast<uint8*>(offset+file.GetOffset(field)); return *reinterpret_cast<uint8*>(offset + file.GetOffset(field));
} }
const char *getString(size_t field) const const char* getString(size_t field) const
{ {
ASSERT(field < file.fieldCount); ASSERT(field < file.fieldCount);
size_t stringOffset = getUInt(field); size_t stringOffset = getUInt(field);
@@ -66,9 +66,9 @@ public:
} }
private: private:
Record(DBCFileLoader &file_, unsigned char *offset_): offset(offset_), file(file_) { } Record(DBCFileLoader& file_, unsigned char* offset_): offset(offset_), file(file_) { }
unsigned char *offset; unsigned char* offset;
DBCFileLoader &file; DBCFileLoader& file;
friend class DBCFileLoader; friend class DBCFileLoader;
@@ -84,16 +84,16 @@ public:
bool IsLoaded() const { return data != nullptr; } bool IsLoaded() const { return data != nullptr; }
char* AutoProduceData(char const* fmt, uint32& count, char**& indexTable); char* AutoProduceData(char const* fmt, uint32& count, char**& indexTable);
char* AutoProduceStrings(char const* fmt, char* dataTable); char* AutoProduceStrings(char const* fmt, char* dataTable);
static uint32 GetFormatRecordSize(const char * format, int32 * index_pos = nullptr); static uint32 GetFormatRecordSize(const char* format, int32* index_pos = nullptr);
private: private:
uint32 recordSize; uint32 recordSize;
uint32 recordCount; uint32 recordCount;
uint32 fieldCount; uint32 fieldCount;
uint32 stringSize; uint32 stringSize;
uint32 *fieldsOffset; uint32* fieldsOffset;
unsigned char *data; unsigned char* data;
unsigned char *stringTable; unsigned char* stringTable;
DBCFileLoader(DBCFileLoader const& right) = delete; DBCFileLoader(DBCFileLoader const& right) = delete;
DBCFileLoader& operator=(DBCFileLoader const& right) = delete; DBCFileLoader& operator=(DBCFileLoader const& right) = delete;

View File

@@ -9,14 +9,14 @@
/*! Basic, ad-hoc queries. */ /*! Basic, ad-hoc queries. */
BasicStatementTask::BasicStatementTask(const char* sql) : BasicStatementTask::BasicStatementTask(const char* sql) :
m_has_result(false) m_has_result(false)
{ {
m_sql = strdup(sql); m_sql = strdup(sql);
} }
BasicStatementTask::BasicStatementTask(const char* sql, QueryResultFuture result) : BasicStatementTask::BasicStatementTask(const char* sql, QueryResultFuture result) :
m_has_result(true), m_has_result(true),
m_result(result) m_result(result)
{ {
m_sql = strdup(sql); m_sql = strdup(sql);
} }

View File

@@ -14,17 +14,17 @@ typedef ACE_Future<QueryResult> QueryResultFuture;
/*! Raw, ad-hoc query. */ /*! Raw, ad-hoc query. */
class BasicStatementTask : public SQLOperation class BasicStatementTask : public SQLOperation
{ {
public: public:
BasicStatementTask(const char* sql); BasicStatementTask(const char* sql);
BasicStatementTask(const char* sql, QueryResultFuture result); BasicStatementTask(const char* sql, QueryResultFuture result);
~BasicStatementTask(); ~BasicStatementTask();
bool Execute(); bool Execute();
private: private:
const char* m_sql; //- Raw query to be executed const char* m_sql; //- Raw query to be executed
bool m_has_result; bool m_has_result;
QueryResultFuture m_result; QueryResultFuture m_result;
}; };
#endif #endif

View File

@@ -11,8 +11,8 @@
#include "MySQLThreading.h" #include "MySQLThreading.h"
DatabaseWorker::DatabaseWorker(ACE_Activation_Queue* new_queue, MySQLConnection* con) : DatabaseWorker::DatabaseWorker(ACE_Activation_Queue* new_queue, MySQLConnection* con) :
m_queue(new_queue), m_queue(new_queue),
m_conn(con) m_conn(con)
{ {
/// Assign thread to task /// Assign thread to task
activate(); activate();
@@ -23,7 +23,7 @@ int DatabaseWorker::svc()
if (!m_queue) if (!m_queue)
return -1; return -1;
SQLOperation *request = NULL; SQLOperation* request = NULL;
while (1) while (1)
{ {
request = (SQLOperation*)(m_queue->dequeue()); request = (SQLOperation*)(m_queue->dequeue());

View File

@@ -14,17 +14,17 @@ class MySQLConnection;
class DatabaseWorker : protected ACE_Task_Base class DatabaseWorker : protected ACE_Task_Base
{ {
public: public:
DatabaseWorker(ACE_Activation_Queue* new_queue, MySQLConnection* con); DatabaseWorker(ACE_Activation_Queue* new_queue, MySQLConnection* con);
///- Inherited from ACE_Task_Base ///- Inherited from ACE_Task_Base
int svc(); int svc();
int wait() { return ACE_Task_Base::wait(); } int wait() { return ACE_Task_Base::wait(); }
private: private:
DatabaseWorker() : ACE_Task_Base() { } DatabaseWorker() : ACE_Task_Base() { }
ACE_Activation_Queue* m_queue; ACE_Activation_Queue* m_queue;
MySQLConnection* m_conn; MySQLConnection* m_conn;
}; };
#endif #endif

View File

@@ -12,8 +12,8 @@
template <class T> template <class T>
DatabaseWorkerPool<T>::DatabaseWorkerPool() : DatabaseWorkerPool<T>::DatabaseWorkerPool() :
_mqueue(new ACE_Message_Queue<ACE_SYNCH>(2*1024*1024, 2*1024*1024)), _mqueue(new ACE_Message_Queue<ACE_SYNCH>(2 * 1024 * 1024, 2 * 1024 * 1024)),
_queue(new ACE_Activation_Queue(_mqueue)) _queue(new ACE_Activation_Queue(_mqueue))
{ {
memset(_connectionCount, 0, sizeof(_connectionCount)); memset(_connectionCount, 0, sizeof(_connectionCount));
_connections.resize(IDX_SIZE); _connections.resize(IDX_SIZE);
@@ -29,7 +29,7 @@ bool DatabaseWorkerPool<T>::Open(const std::string& infoString, uint8 async_thre
_connectionInfo = MySQLConnectionInfo(infoString); _connectionInfo = MySQLConnectionInfo(infoString);
sLog->outSQLDriver("Opening DatabasePool '%s'. Asynchronous connections: %u, synchronous connections: %u.", sLog->outSQLDriver("Opening DatabasePool '%s'. Asynchronous connections: %u, synchronous connections: %u.",
GetDatabaseName(), async_threads, synch_threads); GetDatabaseName(), async_threads, synch_threads);
//! Open asynchronous connections (delayed operations) //! Open asynchronous connections (delayed operations)
_connections[IDX_ASYNC].resize(async_threads); _connections[IDX_ASYNC].resize(async_threads);
@@ -39,7 +39,7 @@ bool DatabaseWorkerPool<T>::Open(const std::string& infoString, uint8 async_thre
res &= t->Open(); res &= t->Open();
if (res) // only check mysql version if connection is valid if (res) // only check mysql version if connection is valid
WPFatal(mysql_get_server_version(t->GetHandle()) >= MIN_MYSQL_SERVER_VERSION, "AzerothCore does not support MySQL versions below 5.6"); WPFatal(mysql_get_server_version(t->GetHandle()) >= MIN_MYSQL_SERVER_VERSION, "AzerothCore does not support MySQL versions below 5.6");
_connections[IDX_ASYNC][i] = t; _connections[IDX_ASYNC][i] = t;
++_connectionCount[IDX_ASYNC]; ++_connectionCount[IDX_ASYNC];
} }
@@ -56,11 +56,11 @@ bool DatabaseWorkerPool<T>::Open(const std::string& infoString, uint8 async_thre
if (res) if (res)
sLog->outSQLDriver("DatabasePool '%s' opened successfully. %u total connections running.", GetDatabaseName(), sLog->outSQLDriver("DatabasePool '%s' opened successfully. %u total connections running.", GetDatabaseName(),
(_connectionCount[IDX_SYNCH] + _connectionCount[IDX_ASYNC])); (_connectionCount[IDX_SYNCH] + _connectionCount[IDX_ASYNC]));
else else
sLog->outError("DatabasePool %s NOT opened. There were errors opening the MySQL connections. Check your SQLDriverLogFile " sLog->outError("DatabasePool %s NOT opened. There were errors opening the MySQL connections. Check your SQLDriverLogFile "
"for specific errors.", GetDatabaseName()); "for specific errors.", GetDatabaseName());
return res; return res;
} }
@@ -84,7 +84,7 @@ void DatabaseWorkerPool<T>::Close()
} }
sLog->outSQLDriver("Asynchronous connections on DatabasePool '%s' terminated. Proceeding with synchronous connections.", sLog->outSQLDriver("Asynchronous connections on DatabasePool '%s' terminated. Proceeding with synchronous connections.",
GetDatabaseName()); GetDatabaseName());
//! Shut down the synchronous connections //! Shut down the synchronous connections
//! There's no need for locking the connection, because DatabaseWorkerPool<>::Close //! There's no need for locking the connection, because DatabaseWorkerPool<>::Close
@@ -212,7 +212,7 @@ SQLTransaction DatabaseWorkerPool<T>::BeginTransaction()
template <class T> template <class T>
void DatabaseWorkerPool<T>::CommitTransaction(SQLTransaction transaction) void DatabaseWorkerPool<T>::CommitTransaction(SQLTransaction transaction)
{ {
#ifdef ACORE_DEBUG #ifdef ACORE_DEBUG
//! Only analyze transaction weaknesses in Debug mode. //! Only analyze transaction weaknesses in Debug mode.
//! Ideally we catch the faults in Debug mode and then correct them, //! Ideally we catch the faults in Debug mode and then correct them,
//! so there's no need to waste these CPU cycles in Release mode. //! so there's no need to waste these CPU cycles in Release mode.
@@ -227,7 +227,7 @@ void DatabaseWorkerPool<T>::CommitTransaction(SQLTransaction transaction)
default: default:
break; break;
} }
#endif // ACORE_DEBUG #endif // ACORE_DEBUG
Enqueue(new TransactionTask(transaction)); Enqueue(new TransactionTask(transaction));
} }
@@ -311,7 +311,7 @@ T* DatabaseWorkerPool<T>::GetFreeConnection()
uint8 i = 0; uint8 i = 0;
size_t num_cons = _connectionCount[IDX_SYNCH]; size_t num_cons = _connectionCount[IDX_SYNCH];
T* t = nullptr; T* t = nullptr;
//! Block forever until a connection is free //! Block forever until a connection is free
for (;;) for (;;)
{ {

View File

@@ -34,211 +34,211 @@ class PingOperation : public SQLOperation
template <class T> template <class T>
class DatabaseWorkerPool class DatabaseWorkerPool
{ {
public: public:
/* Activity state */ /* Activity state */
DatabaseWorkerPool(); DatabaseWorkerPool();
~DatabaseWorkerPool() { } ~DatabaseWorkerPool() { }
bool Open(const std::string& infoString, uint8 async_threads, uint8 synch_threads); bool Open(const std::string& infoString, uint8 async_threads, uint8 synch_threads);
void Close(); void Close();
/** /**
Delayed one-way statement methods. Delayed one-way statement methods.
*/ */
//! Enqueues a one-way SQL operation in string format that will be executed asynchronously. //! Enqueues a one-way SQL operation in string format that will be executed asynchronously.
//! This method should only be used for queries that are only executed once, e.g during startup. //! This method should only be used for queries that are only executed once, e.g during startup.
void Execute(const char* sql); void Execute(const char* sql);
//! Enqueues a one-way SQL operation in string format -with variable args- that will be executed asynchronously. //! Enqueues a one-way SQL operation in string format -with variable args- that will be executed asynchronously.
//! This method should only be used for queries that are only executed once, e.g during startup. //! This method should only be used for queries that are only executed once, e.g during startup.
template<typename Format, typename... Args> template<typename Format, typename... Args>
void PExecute(Format&& sql, Args&&... args) void PExecute(Format&& sql, Args&& ... args)
{ {
if (acore::IsFormatEmptyOrNull(sql)) if (acore::IsFormatEmptyOrNull(sql))
return; return;
Execute(acore::StringFormat(std::forward<Format>(sql), std::forward<Args>(args)...).c_str()); Execute(acore::StringFormat(std::forward<Format>(sql), std::forward<Args>(args)...).c_str());
} }
//! Enqueues a one-way SQL operation in prepared statement format that will be executed asynchronously. //! Enqueues a one-way SQL operation in prepared statement format that will be executed asynchronously.
//! Statement must be prepared with CONNECTION_ASYNC flag. //! Statement must be prepared with CONNECTION_ASYNC flag.
void Execute(PreparedStatement* stmt); void Execute(PreparedStatement* stmt);
/** /**
Direct synchronous one-way statement methods. Direct synchronous one-way statement methods.
*/ */
//! Directly executes a one-way SQL operation in string format, that will block the calling thread until finished. //! Directly executes a one-way SQL operation in string format, that will block the calling thread until finished.
//! This method should only be used for queries that are only executed once, e.g during startup. //! This method should only be used for queries that are only executed once, e.g during startup.
void DirectExecute(const char* sql); void DirectExecute(const char* sql);
//! Directly executes a one-way SQL operation in string format -with variable args-, that will block the calling thread until finished. //! Directly executes a one-way SQL operation in string format -with variable args-, that will block the calling thread until finished.
//! This method should only be used for queries that are only executed once, e.g during startup. //! This method should only be used for queries that are only executed once, e.g during startup.
template<typename Format, typename... Args> template<typename Format, typename... Args>
void DirectPExecute(Format&& sql, Args&&... args) void DirectPExecute(Format&& sql, Args&& ... args)
{ {
if (acore::IsFormatEmptyOrNull(sql)) if (acore::IsFormatEmptyOrNull(sql))
return; return;
DirectExecute(acore::StringFormat(std::forward<Format>(sql), std::forward<Args>(args)...).c_str()); DirectExecute(acore::StringFormat(std::forward<Format>(sql), std::forward<Args>(args)...).c_str());
} }
//! Directly executes a one-way SQL operation in prepared statement format, that will block the calling thread until finished. //! Directly executes a one-way SQL operation in prepared statement format, that will block the calling thread until finished.
//! Statement must be prepared with the CONNECTION_SYNCH flag. //! Statement must be prepared with the CONNECTION_SYNCH flag.
void DirectExecute(PreparedStatement* stmt); void DirectExecute(PreparedStatement* stmt);
/** /**
Synchronous query (with resultset) methods. Synchronous query (with resultset) methods.
*/ */
//! Directly executes an SQL query in string format that will block the calling thread until finished. //! Directly executes an SQL query in string format that will block the calling thread until finished.
//! Returns reference counted auto pointer, no need for manual memory management in upper level code. //! Returns reference counted auto pointer, no need for manual memory management in upper level code.
QueryResult Query(const char* sql, T* conn = nullptr); QueryResult Query(const char* sql, T* conn = nullptr);
//! Directly executes an SQL query in string format -with variable args- that will block the calling thread until finished. //! Directly executes an SQL query in string format -with variable args- that will block the calling thread until finished.
//! Returns reference counted auto pointer, no need for manual memory management in upper level code. //! Returns reference counted auto pointer, no need for manual memory management in upper level code.
template<typename Format, typename... Args> template<typename Format, typename... Args>
QueryResult PQuery(Format&& sql, T* conn, Args&&... args) QueryResult PQuery(Format&& sql, T* conn, Args&& ... args)
{ {
if (acore::IsFormatEmptyOrNull(sql)) if (acore::IsFormatEmptyOrNull(sql))
return QueryResult(nullptr); return QueryResult(nullptr);
return Query(acore::StringFormat(std::forward<Format>(sql), std::forward<Args>(args)...).c_str(), conn); return Query(acore::StringFormat(std::forward<Format>(sql), std::forward<Args>(args)...).c_str(), conn);
} }
//! Directly executes an SQL query in string format -with variable args- that will block the calling thread until finished. //! Directly executes an SQL query in string format -with variable args- that will block the calling thread until finished.
//! Returns reference counted auto pointer, no need for manual memory management in upper level code. //! Returns reference counted auto pointer, no need for manual memory management in upper level code.
template<typename Format, typename... Args> template<typename Format, typename... Args>
QueryResult PQuery(Format&& sql, Args&&... args) QueryResult PQuery(Format&& sql, Args&& ... args)
{ {
if (acore::IsFormatEmptyOrNull(sql)) if (acore::IsFormatEmptyOrNull(sql))
return QueryResult(nullptr); return QueryResult(nullptr);
return Query(acore::StringFormat(std::forward<Format>(sql), std::forward<Args>(args)...).c_str()); return Query(acore::StringFormat(std::forward<Format>(sql), std::forward<Args>(args)...).c_str());
} }
//! Directly executes an SQL query in prepared format that will block the calling thread until finished. //! Directly executes an SQL query in prepared format that will block the calling thread until finished.
//! Returns reference counted auto pointer, no need for manual memory management in upper level code. //! Returns reference counted auto pointer, no need for manual memory management in upper level code.
//! Statement must be prepared with CONNECTION_SYNCH flag. //! Statement must be prepared with CONNECTION_SYNCH flag.
PreparedQueryResult Query(PreparedStatement* stmt); PreparedQueryResult Query(PreparedStatement* stmt);
/** /**
Asynchronous query (with resultset) methods. Asynchronous query (with resultset) methods.
*/ */
//! Enqueues a query in string format that will set the value of the QueryResultFuture return object as soon as the query is executed. //! Enqueues a query in string format that will set the value of the QueryResultFuture return object as soon as the query is executed.
//! The return value is then processed in ProcessQueryCallback methods. //! The return value is then processed in ProcessQueryCallback methods.
QueryResultFuture AsyncQuery(const char* sql); QueryResultFuture AsyncQuery(const char* sql);
//! Enqueues a query in string format -with variable args- that will set the value of the QueryResultFuture return object as soon as the query is executed. //! Enqueues a query in string format -with variable args- that will set the value of the QueryResultFuture return object as soon as the query is executed.
//! The return value is then processed in ProcessQueryCallback methods. //! The return value is then processed in ProcessQueryCallback methods.
template<typename Format, typename... Args> template<typename Format, typename... Args>
QueryResultFuture AsyncPQuery(Format&& sql, Args&&... args) QueryResultFuture AsyncPQuery(Format&& sql, Args&& ... args)
{ {
if (acore::IsFormatEmptyOrNull(sql)) if (acore::IsFormatEmptyOrNull(sql))
return QueryResult(nullptr); return QueryResult(nullptr);
return AsyncQuery(acore::StringFormat(std::forward<Format>(sql), std::forward<Args>(args)...).c_str()); return AsyncQuery(acore::StringFormat(std::forward<Format>(sql), std::forward<Args>(args)...).c_str());
} }
//! Enqueues a query in prepared format that will set the value of the PreparedQueryResultFuture return object as soon as the query is executed. //! Enqueues a query in prepared format that will set the value of the PreparedQueryResultFuture return object as soon as the query is executed.
//! The return value is then processed in ProcessQueryCallback methods. //! The return value is then processed in ProcessQueryCallback methods.
//! Statement must be prepared with CONNECTION_ASYNC flag. //! Statement must be prepared with CONNECTION_ASYNC flag.
PreparedQueryResultFuture AsyncQuery(PreparedStatement* stmt); PreparedQueryResultFuture AsyncQuery(PreparedStatement* stmt);
//! Enqueues a vector of SQL operations (can be both adhoc and prepared) that will set the value of the QueryResultHolderFuture //! Enqueues a vector of SQL operations (can be both adhoc and prepared) that will set the value of the QueryResultHolderFuture
//! return object as soon as the query is executed. //! return object as soon as the query is executed.
//! The return value is then processed in ProcessQueryCallback methods. //! The return value is then processed in ProcessQueryCallback methods.
//! Any prepared statements added to this holder need to be prepared with the CONNECTION_ASYNC flag. //! Any prepared statements added to this holder need to be prepared with the CONNECTION_ASYNC flag.
QueryResultHolderFuture DelayQueryHolder(SQLQueryHolder* holder); QueryResultHolderFuture DelayQueryHolder(SQLQueryHolder* holder);
/** /**
Transaction context methods. Transaction context methods.
*/ */
//! Begins an automanaged transaction pointer that will automatically rollback if not commited. (Autocommit=0) //! Begins an automanaged transaction pointer that will automatically rollback if not commited. (Autocommit=0)
SQLTransaction BeginTransaction(); SQLTransaction BeginTransaction();
//! Enqueues a collection of one-way SQL operations (can be both adhoc and prepared). The order in which these operations //! Enqueues a collection of one-way SQL operations (can be both adhoc and prepared). The order in which these operations
//! were appended to the transaction will be respected during execution. //! were appended to the transaction will be respected during execution.
void CommitTransaction(SQLTransaction transaction); void CommitTransaction(SQLTransaction transaction);
//! Directly executes a collection of one-way SQL operations (can be both adhoc and prepared). The order in which these operations //! Directly executes a collection of one-way SQL operations (can be both adhoc and prepared). The order in which these operations
//! were appended to the transaction will be respected during execution. //! were appended to the transaction will be respected during execution.
void DirectCommitTransaction(SQLTransaction& transaction); void DirectCommitTransaction(SQLTransaction& transaction);
//! Method used to execute prepared statements in a diverse context. //! Method used to execute prepared statements in a diverse context.
//! Will be wrapped in a transaction if valid object is present, otherwise executed standalone. //! Will be wrapped in a transaction if valid object is present, otherwise executed standalone.
void ExecuteOrAppend(SQLTransaction& trans, PreparedStatement* stmt); void ExecuteOrAppend(SQLTransaction& trans, PreparedStatement* stmt);
//! Method used to execute ad-hoc statements in a diverse context. //! Method used to execute ad-hoc statements in a diverse context.
//! Will be wrapped in a transaction if valid object is present, otherwise executed standalone. //! Will be wrapped in a transaction if valid object is present, otherwise executed standalone.
void ExecuteOrAppend(SQLTransaction& trans, const char* sql); void ExecuteOrAppend(SQLTransaction& trans, const char* sql);
/** /**
Other Other
*/ */
//! Automanaged (internally) pointer to a prepared statement object for usage in upper level code. //! Automanaged (internally) pointer to a prepared statement object for usage in upper level code.
//! Pointer is deleted in this->DirectExecute(PreparedStatement*), this->Query(PreparedStatement*) or PreparedStatementTask::~PreparedStatementTask. //! Pointer is deleted in this->DirectExecute(PreparedStatement*), this->Query(PreparedStatement*) or PreparedStatementTask::~PreparedStatementTask.
//! This object is not tied to the prepared statement on the MySQL context yet until execution. //! This object is not tied to the prepared statement on the MySQL context yet until execution.
PreparedStatement* GetPreparedStatement(uint32 index); PreparedStatement* GetPreparedStatement(uint32 index);
//! Apply escape string'ing for current collation. (utf8) //! Apply escape string'ing for current collation. (utf8)
unsigned long EscapeString(char* to, const char* from, unsigned long length) unsigned long EscapeString(char* to, const char* from, unsigned long length)
{ {
if (!to || !from || !length) if (!to || !from || !length)
return 0; return 0;
return mysql_real_escape_string(_connections[IDX_SYNCH][0]->GetHandle(), to, from, length); return mysql_real_escape_string(_connections[IDX_SYNCH][0]->GetHandle(), to, from, length);
} }
//! Keeps all our MySQL connections alive, prevent the server from disconnecting us. //! Keeps all our MySQL connections alive, prevent the server from disconnecting us.
void KeepAlive(); void KeepAlive();
char const* GetDatabaseName() const char const* GetDatabaseName() const
{ {
return _connectionInfo.database.c_str(); return _connectionInfo.database.c_str();
} }
void EscapeString(std::string& str) void EscapeString(std::string& str)
{ {
if (str.empty()) if (str.empty())
return; return;
char* buf = new char[str.size() * 2 + 1]; char* buf = new char[str.size() * 2 + 1];
EscapeString(buf, str.c_str(), str.size()); EscapeString(buf, str.c_str(), str.size());
str = buf; str = buf;
delete[] buf; delete[] buf;
} }
private: private:
void Enqueue(SQLOperation* op) void Enqueue(SQLOperation* op)
{ {
_queue->enqueue(op); _queue->enqueue(op);
} }
//! Gets a free connection in the synchronous connection pool. //! Gets a free connection in the synchronous connection pool.
//! Caller MUST call t->Unlock() after touching the MySQL context to prevent deadlocks. //! Caller MUST call t->Unlock() after touching the MySQL context to prevent deadlocks.
T* GetFreeConnection(); T* GetFreeConnection();
private: private:
enum _internalIndex enum _internalIndex
{ {
IDX_ASYNC, IDX_ASYNC,
IDX_SYNCH, IDX_SYNCH,
IDX_SIZE IDX_SIZE
}; };
ACE_Message_Queue<ACE_SYNCH>* _mqueue; ACE_Message_Queue<ACE_SYNCH>* _mqueue;
ACE_Activation_Queue* _queue; //! Queue shared by async worker threads. ACE_Activation_Queue* _queue; //! Queue shared by async worker threads.
std::vector<std::vector<T*>> _connections; std::vector<std::vector<T*>> _connections;
uint32 _connectionCount[2]; //! Counter of MySQL connections; uint32 _connectionCount[2]; //! Counter of MySQL connections;
MySQLConnectionInfo _connectionInfo; MySQLConnectionInfo _connectionInfo;
}; };
#endif #endif

View File

@@ -44,7 +44,7 @@ void Field::SetStructuredValue(char* newValue, enum_field_types newType)
if (newValue) if (newValue)
{ {
size_t size = strlen(newValue); size_t size = strlen(newValue);
data.value = new char [size+1]; data.value = new char [size + 1];
strcpy((char*)data.value, newValue); strcpy((char*)data.value, newValue);
data.length = size; data.length = size;
} }

View File

@@ -17,369 +17,396 @@ class Field
friend class ResultSet; friend class ResultSet;
friend class PreparedResultSet; friend class PreparedResultSet;
public: public:
bool GetBool() const // Wrapper, actually gets integer bool GetBool() const // Wrapper, actually gets integer
{
return (GetUInt8() == 1);
}
uint8 GetUInt8() const
{
if (!data.value)
return 0;
#ifdef ACORE_DEBUG
if (!IsType(MYSQL_TYPE_TINY))
{ {
return (GetUInt8() == 1); sLog->outSQLDriver("Warning: GetUInt8() on non-tinyint field. Using type: %s.", FieldTypeToString(data.type));
} return 0;
uint8 GetUInt8() const
{
if (!data.value)
return 0;
#ifdef ACORE_DEBUG
if (!IsType(MYSQL_TYPE_TINY))
{
sLog->outSQLDriver("Warning: GetUInt8() on non-tinyint field. Using type: %s.", FieldTypeToString(data.type));
return 0;
}
#endif
if (data.raw)
return *reinterpret_cast<uint8*>(data.value);
return static_cast<uint8>(atol((char*)data.value));
}
int8 GetInt8() const
{
if (!data.value)
return 0;
#ifdef ACORE_DEBUG
if (!IsType(MYSQL_TYPE_TINY))
{
sLog->outSQLDriver("Warning: GetInt8() on non-tinyint field. Using type: %s.", FieldTypeToString(data.type));
return 0;
}
#endif
if (data.raw)
return *reinterpret_cast<int8*>(data.value);
return static_cast<int8>(atol((char*)data.value));
}
#ifdef ELUNA
enum_field_types GetType() const
{
return data.type;
} }
#endif #endif
uint16 GetUInt16() const if (data.raw)
return *reinterpret_cast<uint8*>(data.value);
return static_cast<uint8>(atol((char*)data.value));
}
int8 GetInt8() const
{
if (!data.value)
return 0;
#ifdef ACORE_DEBUG
if (!IsType(MYSQL_TYPE_TINY))
{ {
if (!data.value) sLog->outSQLDriver("Warning: GetInt8() on non-tinyint field. Using type: %s.", FieldTypeToString(data.type));
return 0;
}
#endif
if (data.raw)
return *reinterpret_cast<int8*>(data.value);
return static_cast<int8>(atol((char*)data.value));
}
#ifdef ELUNA
enum_field_types GetType() const
{
return data.type;
}
#endif
uint16 GetUInt16() const
{
if (!data.value)
return 0;
#ifdef ACORE_DEBUG
if (!IsType(MYSQL_TYPE_SHORT) && !IsType(MYSQL_TYPE_YEAR))
{
sLog->outSQLDriver("Warning: GetUInt16() on non-smallint field. Using type: %s.", FieldTypeToString(data.type));
return 0;
}
#endif
if (data.raw)
return *reinterpret_cast<uint16*>(data.value);
return static_cast<uint16>(atol((char*)data.value));
}
int16 GetInt16() const
{
if (!data.value)
return 0;
#ifdef ACORE_DEBUG
if (!IsType(MYSQL_TYPE_SHORT) && !IsType(MYSQL_TYPE_YEAR))
{
sLog->outSQLDriver("Warning: GetInt16() on non-smallint field. Using type: %s.", FieldTypeToString(data.type));
return 0;
}
#endif
if (data.raw)
return *reinterpret_cast<int16*>(data.value);
return static_cast<int16>(atol((char*)data.value));
}
uint32 GetUInt32() const
{
if (!data.value)
return 0;
#ifdef ACORE_DEBUG
if (!IsType(MYSQL_TYPE_INT24) && !IsType(MYSQL_TYPE_LONG))
{
sLog->outSQLDriver("Warning: GetUInt32() on non-(medium)int field. Using type: %s.", FieldTypeToString(data.type));
return 0;
}
#endif
if (data.raw)
return *reinterpret_cast<uint32*>(data.value);
return static_cast<uint32>(atol((char*)data.value));
}
int32 GetInt32() const
{
if (!data.value)
return 0;
#ifdef ACORE_DEBUG
if (!IsType(MYSQL_TYPE_INT24) && !IsType(MYSQL_TYPE_LONG))
{
sLog->outSQLDriver("Warning: GetInt32() on non-(medium)int field. Using type: %s.", FieldTypeToString(data.type));
return 0;
}
#endif
if (data.raw)
return *reinterpret_cast<int32*>(data.value);
return static_cast<int32>(atol((char*)data.value));
}
uint64 GetUInt64() const
{
if (!data.value)
return 0;
#ifdef ACORE_DEBUG
if (!IsType(MYSQL_TYPE_LONGLONG) && !IsType(MYSQL_TYPE_BIT))
{
sLog->outSQLDriver("Warning: GetUInt64() on non-bigint field. Using type: %s.", FieldTypeToString(data.type));
return 0;
}
#endif
if (data.raw)
return *reinterpret_cast<uint64*>(data.value);
return static_cast<uint64>(atol((char*)data.value));
}
int64 GetInt64() const
{
if (!data.value)
return 0;
#ifdef ACORE_DEBUG
if (!IsType(MYSQL_TYPE_LONGLONG) && !IsType(MYSQL_TYPE_BIT))
{
sLog->outSQLDriver("Warning: GetInt64() on non-bigint field. Using type: %s.", FieldTypeToString(data.type));
return 0;
}
#endif
if (data.raw)
return *reinterpret_cast<int64*>(data.value);
return static_cast<int64>(strtol((char*)data.value, NULL, 10));
}
float GetFloat() const
{
if (!data.value)
return 0.0f;
#ifdef ACORE_DEBUG
if (!IsType(MYSQL_TYPE_FLOAT))
{
sLog->outSQLDriver("Warning: GetFloat() on non-float field. Using type: %s.", FieldTypeToString(data.type));
return 0.0f;
}
#endif
if (data.raw)
return *reinterpret_cast<float*>(data.value);
return static_cast<float>(atof((char*)data.value));
}
double GetDouble() const
{
if (!data.value)
return 0.0f;
#ifdef ACORE_DEBUG
if (!IsType(MYSQL_TYPE_DOUBLE))
{
sLog->outSQLDriver("Warning: GetDouble() on non-double field. Using type: %s.", FieldTypeToString(data.type));
return 0.0f;
}
#endif
if (data.raw)
return *reinterpret_cast<double*>(data.value);
return static_cast<double>(atof((char*)data.value));
}
char const* GetCString() const
{
if (!data.value)
return NULL;
#ifdef ACORE_DEBUG
if (IsNumeric())
{
sLog->outSQLDriver("Error: GetCString() on numeric field. Using type: %s.", FieldTypeToString(data.type));
return NULL;
}
#endif
return static_cast<char const*>(data.value);
}
std::string GetString() const
{
if (!data.value)
return "";
if (data.raw)
{
char const* string = GetCString();
if (!string)
string = "";
return std::string(string, data.length);
}
return std::string((char*)data.value);
}
bool IsNull() const
{
return data.value == NULL;
}
protected:
Field();
~Field();
#if defined(__GNUC__)
#pragma pack(1)
#else
#pragma pack(push, 1)
#endif
struct
{
uint32 length; // Length (prepared strings only)
void* value; // Actual data in memory
enum_field_types type; // Field type
bool raw; // Raw bytes? (Prepared statement or ad hoc)
} data;
#if defined(__GNUC__)
#pragma pack()
#else
#pragma pack(pop)
#endif
void SetByteValue(void const* newValue, size_t const newSize, enum_field_types newType, uint32 length);
void SetStructuredValue(char* newValue, enum_field_types newType);
void CleanUp()
{
delete[] ((char*)data.value);
data.value = NULL;
}
static size_t SizeForType(MYSQL_FIELD* field)
{
switch (field->type)
{
case MYSQL_TYPE_NULL:
return 0; return 0;
case MYSQL_TYPE_TINY:
return 1;
case MYSQL_TYPE_YEAR:
case MYSQL_TYPE_SHORT:
return 2;
case MYSQL_TYPE_INT24:
case MYSQL_TYPE_LONG:
case MYSQL_TYPE_FLOAT:
return 4;
case MYSQL_TYPE_DOUBLE:
case MYSQL_TYPE_LONGLONG:
case MYSQL_TYPE_BIT:
return 8;
#ifdef ACORE_DEBUG case MYSQL_TYPE_TIMESTAMP:
if (!IsType(MYSQL_TYPE_SHORT) && !IsType(MYSQL_TYPE_YEAR)) case MYSQL_TYPE_DATE:
{ case MYSQL_TYPE_TIME:
sLog->outSQLDriver("Warning: GetUInt16() on non-smallint field. Using type: %s.", FieldTypeToString(data.type)); case MYSQL_TYPE_DATETIME:
return sizeof(MYSQL_TIME);
case MYSQL_TYPE_TINY_BLOB:
case MYSQL_TYPE_MEDIUM_BLOB:
case MYSQL_TYPE_LONG_BLOB:
case MYSQL_TYPE_BLOB:
case MYSQL_TYPE_STRING:
case MYSQL_TYPE_VAR_STRING:
return field->max_length + 1;
case MYSQL_TYPE_DECIMAL:
case MYSQL_TYPE_NEWDECIMAL:
return 64;
case MYSQL_TYPE_GEOMETRY:
/*
Following types are not sent over the wire:
MYSQL_TYPE_ENUM:
MYSQL_TYPE_SET:
*/
default:
sLog->outSQLDriver("SQL::SizeForType(): invalid field type %u", uint32(field->type));
return 0; return 0;
}
#endif
if (data.raw)
return *reinterpret_cast<uint16*>(data.value);
return static_cast<uint16>(atol((char*)data.value));
} }
}
int16 GetInt16() const bool IsType(enum_field_types type) const
{
return data.type == type;
}
bool IsNumeric() const
{
return (data.type == MYSQL_TYPE_TINY ||
data.type == MYSQL_TYPE_SHORT ||
data.type == MYSQL_TYPE_INT24 ||
data.type == MYSQL_TYPE_LONG ||
data.type == MYSQL_TYPE_FLOAT ||
data.type == MYSQL_TYPE_DOUBLE ||
data.type == MYSQL_TYPE_LONGLONG );
}
private:
#ifdef ACORE_DEBUG
static char const* FieldTypeToString(enum_field_types type)
{
switch (type)
{ {
if (!data.value) case MYSQL_TYPE_BIT:
return 0; return "BIT";
case MYSQL_TYPE_BLOB:
#ifdef ACORE_DEBUG return "BLOB";
if (!IsType(MYSQL_TYPE_SHORT) && !IsType(MYSQL_TYPE_YEAR)) case MYSQL_TYPE_DATE:
{ return "DATE";
sLog->outSQLDriver("Warning: GetInt16() on non-smallint field. Using type: %s.", FieldTypeToString(data.type)); case MYSQL_TYPE_DATETIME:
return 0; return "DATETIME";
} case MYSQL_TYPE_NEWDECIMAL:
#endif return "NEWDECIMAL";
case MYSQL_TYPE_DECIMAL:
if (data.raw) return "DECIMAL";
return *reinterpret_cast<int16*>(data.value); case MYSQL_TYPE_DOUBLE:
return static_cast<int16>(atol((char*)data.value)); return "DOUBLE";
case MYSQL_TYPE_ENUM:
return "ENUM";
case MYSQL_TYPE_FLOAT:
return "FLOAT";
case MYSQL_TYPE_GEOMETRY:
return "GEOMETRY";
case MYSQL_TYPE_INT24:
return "INT24";
case MYSQL_TYPE_LONG:
return "LONG";
case MYSQL_TYPE_LONGLONG:
return "LONGLONG";
case MYSQL_TYPE_LONG_BLOB:
return "LONG_BLOB";
case MYSQL_TYPE_MEDIUM_BLOB:
return "MEDIUM_BLOB";
case MYSQL_TYPE_NEWDATE:
return "NEWDATE";
case MYSQL_TYPE_NULL:
return "NULL";
case MYSQL_TYPE_SET:
return "SET";
case MYSQL_TYPE_SHORT:
return "SHORT";
case MYSQL_TYPE_STRING:
return "STRING";
case MYSQL_TYPE_TIME:
return "TIME";
case MYSQL_TYPE_TIMESTAMP:
return "TIMESTAMP";
case MYSQL_TYPE_TINY:
return "TINY";
case MYSQL_TYPE_TINY_BLOB:
return "TINY_BLOB";
case MYSQL_TYPE_VAR_STRING:
return "VAR_STRING";
case MYSQL_TYPE_YEAR:
return "YEAR";
default:
return "-Unknown-";
} }
}
uint32 GetUInt32() const #endif
{
if (!data.value)
return 0;
#ifdef ACORE_DEBUG
if (!IsType(MYSQL_TYPE_INT24) && !IsType(MYSQL_TYPE_LONG))
{
sLog->outSQLDriver("Warning: GetUInt32() on non-(medium)int field. Using type: %s.", FieldTypeToString(data.type));
return 0;
}
#endif
if (data.raw)
return *reinterpret_cast<uint32*>(data.value);
return static_cast<uint32>(atol((char*)data.value));
}
int32 GetInt32() const
{
if (!data.value)
return 0;
#ifdef ACORE_DEBUG
if (!IsType(MYSQL_TYPE_INT24) && !IsType(MYSQL_TYPE_LONG))
{
sLog->outSQLDriver("Warning: GetInt32() on non-(medium)int field. Using type: %s.", FieldTypeToString(data.type));
return 0;
}
#endif
if (data.raw)
return *reinterpret_cast<int32*>(data.value);
return static_cast<int32>(atol((char*)data.value));
}
uint64 GetUInt64() const
{
if (!data.value)
return 0;
#ifdef ACORE_DEBUG
if (!IsType(MYSQL_TYPE_LONGLONG) && !IsType(MYSQL_TYPE_BIT))
{
sLog->outSQLDriver("Warning: GetUInt64() on non-bigint field. Using type: %s.", FieldTypeToString(data.type));
return 0;
}
#endif
if (data.raw)
return *reinterpret_cast<uint64*>(data.value);
return static_cast<uint64>(atol((char*)data.value));
}
int64 GetInt64() const
{
if (!data.value)
return 0;
#ifdef ACORE_DEBUG
if (!IsType(MYSQL_TYPE_LONGLONG) && !IsType(MYSQL_TYPE_BIT))
{
sLog->outSQLDriver("Warning: GetInt64() on non-bigint field. Using type: %s.", FieldTypeToString(data.type));
return 0;
}
#endif
if (data.raw)
return *reinterpret_cast<int64*>(data.value);
return static_cast<int64>(strtol((char*)data.value, NULL, 10));
}
float GetFloat() const
{
if (!data.value)
return 0.0f;
#ifdef ACORE_DEBUG
if (!IsType(MYSQL_TYPE_FLOAT))
{
sLog->outSQLDriver("Warning: GetFloat() on non-float field. Using type: %s.", FieldTypeToString(data.type));
return 0.0f;
}
#endif
if (data.raw)
return *reinterpret_cast<float*>(data.value);
return static_cast<float>(atof((char*)data.value));
}
double GetDouble() const
{
if (!data.value)
return 0.0f;
#ifdef ACORE_DEBUG
if (!IsType(MYSQL_TYPE_DOUBLE))
{
sLog->outSQLDriver("Warning: GetDouble() on non-double field. Using type: %s.", FieldTypeToString(data.type));
return 0.0f;
}
#endif
if (data.raw)
return *reinterpret_cast<double*>(data.value);
return static_cast<double>(atof((char*)data.value));
}
char const* GetCString() const
{
if (!data.value)
return NULL;
#ifdef ACORE_DEBUG
if (IsNumeric())
{
sLog->outSQLDriver("Error: GetCString() on numeric field. Using type: %s.", FieldTypeToString(data.type));
return NULL;
}
#endif
return static_cast<char const*>(data.value);
}
std::string GetString() const
{
if (!data.value)
return "";
if (data.raw)
{
char const* string = GetCString();
if (!string)
string = "";
return std::string(string, data.length);
}
return std::string((char*)data.value);
}
bool IsNull() const
{
return data.value == NULL;
}
protected:
Field();
~Field();
#if defined(__GNUC__)
#pragma pack(1)
#else
#pragma pack(push, 1)
#endif
struct
{
uint32 length; // Length (prepared strings only)
void* value; // Actual data in memory
enum_field_types type; // Field type
bool raw; // Raw bytes? (Prepared statement or ad hoc)
} data;
#if defined(__GNUC__)
#pragma pack()
#else
#pragma pack(pop)
#endif
void SetByteValue(void const* newValue, size_t const newSize, enum_field_types newType, uint32 length);
void SetStructuredValue(char* newValue, enum_field_types newType);
void CleanUp()
{
delete[] ((char*)data.value);
data.value = NULL;
}
static size_t SizeForType(MYSQL_FIELD* field)
{
switch (field->type)
{
case MYSQL_TYPE_NULL:
return 0;
case MYSQL_TYPE_TINY:
return 1;
case MYSQL_TYPE_YEAR:
case MYSQL_TYPE_SHORT:
return 2;
case MYSQL_TYPE_INT24:
case MYSQL_TYPE_LONG:
case MYSQL_TYPE_FLOAT:
return 4;
case MYSQL_TYPE_DOUBLE:
case MYSQL_TYPE_LONGLONG:
case MYSQL_TYPE_BIT:
return 8;
case MYSQL_TYPE_TIMESTAMP:
case MYSQL_TYPE_DATE:
case MYSQL_TYPE_TIME:
case MYSQL_TYPE_DATETIME:
return sizeof(MYSQL_TIME);
case MYSQL_TYPE_TINY_BLOB:
case MYSQL_TYPE_MEDIUM_BLOB:
case MYSQL_TYPE_LONG_BLOB:
case MYSQL_TYPE_BLOB:
case MYSQL_TYPE_STRING:
case MYSQL_TYPE_VAR_STRING:
return field->max_length + 1;
case MYSQL_TYPE_DECIMAL:
case MYSQL_TYPE_NEWDECIMAL:
return 64;
case MYSQL_TYPE_GEOMETRY:
/*
Following types are not sent over the wire:
MYSQL_TYPE_ENUM:
MYSQL_TYPE_SET:
*/
default:
sLog->outSQLDriver("SQL::SizeForType(): invalid field type %u", uint32(field->type));
return 0;
}
}
bool IsType(enum_field_types type) const
{
return data.type == type;
}
bool IsNumeric() const
{
return (data.type == MYSQL_TYPE_TINY ||
data.type == MYSQL_TYPE_SHORT ||
data.type == MYSQL_TYPE_INT24 ||
data.type == MYSQL_TYPE_LONG ||
data.type == MYSQL_TYPE_FLOAT ||
data.type == MYSQL_TYPE_DOUBLE ||
data.type == MYSQL_TYPE_LONGLONG );
}
private:
#ifdef ACORE_DEBUG
static char const* FieldTypeToString(enum_field_types type)
{
switch (type)
{
case MYSQL_TYPE_BIT: return "BIT";
case MYSQL_TYPE_BLOB: return "BLOB";
case MYSQL_TYPE_DATE: return "DATE";
case MYSQL_TYPE_DATETIME: return "DATETIME";
case MYSQL_TYPE_NEWDECIMAL: return "NEWDECIMAL";
case MYSQL_TYPE_DECIMAL: return "DECIMAL";
case MYSQL_TYPE_DOUBLE: return "DOUBLE";
case MYSQL_TYPE_ENUM: return "ENUM";
case MYSQL_TYPE_FLOAT: return "FLOAT";
case MYSQL_TYPE_GEOMETRY: return "GEOMETRY";
case MYSQL_TYPE_INT24: return "INT24";
case MYSQL_TYPE_LONG: return "LONG";
case MYSQL_TYPE_LONGLONG: return "LONGLONG";
case MYSQL_TYPE_LONG_BLOB: return "LONG_BLOB";
case MYSQL_TYPE_MEDIUM_BLOB: return "MEDIUM_BLOB";
case MYSQL_TYPE_NEWDATE: return "NEWDATE";
case MYSQL_TYPE_NULL: return "NULL";
case MYSQL_TYPE_SET: return "SET";
case MYSQL_TYPE_SHORT: return "SHORT";
case MYSQL_TYPE_STRING: return "STRING";
case MYSQL_TYPE_TIME: return "TIME";
case MYSQL_TYPE_TIMESTAMP: return "TIMESTAMP";
case MYSQL_TYPE_TINY: return "TINY";
case MYSQL_TYPE_TINY_BLOB: return "TINY_BLOB";
case MYSQL_TYPE_VAR_STRING: return "VAR_STRING";
case MYSQL_TYPE_YEAR: return "YEAR";
default: return "-Unknown-";
}
}
#endif
}; };
#endif #endif

View File

@@ -148,8 +148,8 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_DEL_GUILD_MEMBER, "DELETE FROM guild_member WHERE guid = ?", CONNECTION_ASYNC); // 0: uint32 PrepareStatement(CHAR_DEL_GUILD_MEMBER, "DELETE FROM guild_member WHERE guid = ?", CONNECTION_ASYNC); // 0: uint32
PrepareStatement(CHAR_DEL_GUILD_MEMBERS, "DELETE FROM guild_member WHERE guildid = ?", CONNECTION_ASYNC); // 0: uint32 PrepareStatement(CHAR_DEL_GUILD_MEMBERS, "DELETE FROM guild_member WHERE guildid = ?", CONNECTION_ASYNC); // 0: uint32
PrepareStatement(CHAR_SEL_GUILD_MEMBER_EXTENDED, "SELECT g.guildid, g.name, gr.rname, gm.pnote, gm.offnote " PrepareStatement(CHAR_SEL_GUILD_MEMBER_EXTENDED, "SELECT g.guildid, g.name, gr.rname, gm.pnote, gm.offnote "
"FROM guild g JOIN guild_member gm ON g.guildid = gm.guildid " "FROM guild g JOIN guild_member gm ON g.guildid = gm.guildid "
"JOIN guild_rank gr ON g.guildid = gr.guildid AND gm.`rank` = gr.rid WHERE gm.guid = ?", CONNECTION_BOTH); "JOIN guild_rank gr ON g.guildid = gr.guildid AND gm.`rank` = gr.rid WHERE gm.guid = ?", CONNECTION_BOTH);
// 0: uint32, 1: uint8, 3: string, 4: uint32, 5: uint32 // 0: uint32, 1: uint8, 3: string, 4: uint32, 5: uint32
PrepareStatement(CHAR_INS_GUILD_RANK, "INSERT INTO guild_rank (guildid, rid, rname, rights, BankMoneyPerDay) VALUES (?, ?, ?, ?, ?)", CONNECTION_ASYNC); PrepareStatement(CHAR_INS_GUILD_RANK, "INSERT INTO guild_rank (guildid, rid, rname, rights, BankMoneyPerDay) VALUES (?, ?, ?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_GUILD_RANKS, "DELETE FROM guild_rank WHERE guildid = ?", CONNECTION_ASYNC); // 0: uint32 PrepareStatement(CHAR_DEL_GUILD_RANKS, "DELETE FROM guild_rank WHERE guildid = ?", CONNECTION_ASYNC); // 0: uint32
@@ -403,7 +403,7 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_DEL_CHAR_AURA_FROZEN, "DELETE FROM character_aura WHERE spell = 9454 AND guid = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_DEL_CHAR_AURA_FROZEN, "DELETE FROM character_aura WHERE spell = 9454 AND guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_CHAR_INVENTORY_COUNT_ITEM, "SELECT COUNT(itemEntry) FROM character_inventory ci INNER JOIN item_instance ii ON ii.guid = ci.item WHERE itemEntry = ?", CONNECTION_SYNCH); PrepareStatement(CHAR_SEL_CHAR_INVENTORY_COUNT_ITEM, "SELECT COUNT(itemEntry) FROM character_inventory ci INNER JOIN item_instance ii ON ii.guid = ci.item WHERE itemEntry = ?", CONNECTION_SYNCH);
PrepareStatement(CHAR_SEL_MAIL_COUNT_ITEM, "SELECT COUNT(itemEntry) FROM mail_items mi INNER JOIN item_instance ii ON ii.guid = mi.item_guid WHERE itemEntry = ?", CONNECTION_SYNCH); PrepareStatement(CHAR_SEL_MAIL_COUNT_ITEM, "SELECT COUNT(itemEntry) FROM mail_items mi INNER JOIN item_instance ii ON ii.guid = mi.item_guid WHERE itemEntry = ?", CONNECTION_SYNCH);
PrepareStatement(CHAR_SEL_AUCTIONHOUSE_COUNT_ITEM,"SELECT COUNT(itemEntry) FROM auctionhouse ah INNER JOIN item_instance ii ON ii.guid = ah.itemguid WHERE itemEntry = ?", CONNECTION_SYNCH); PrepareStatement(CHAR_SEL_AUCTIONHOUSE_COUNT_ITEM, "SELECT COUNT(itemEntry) FROM auctionhouse ah INNER JOIN item_instance ii ON ii.guid = ah.itemguid WHERE itemEntry = ?", CONNECTION_SYNCH);
PrepareStatement(CHAR_SEL_GUILD_BANK_COUNT_ITEM, "SELECT COUNT(itemEntry) FROM guild_bank_item gbi INNER JOIN item_instance ii ON ii.guid = gbi.item_guid WHERE itemEntry = ?", CONNECTION_SYNCH); PrepareStatement(CHAR_SEL_GUILD_BANK_COUNT_ITEM, "SELECT COUNT(itemEntry) FROM guild_bank_item gbi INNER JOIN item_instance ii ON ii.guid = gbi.item_guid WHERE itemEntry = ?", CONNECTION_SYNCH);
PrepareStatement(CHAR_SEL_CHAR_INVENTORY_ITEM_BY_ENTRY, "SELECT ci.item, cb.slot AS bag, ci.slot, ci.guid, c.account, c.name FROM characters c " PrepareStatement(CHAR_SEL_CHAR_INVENTORY_ITEM_BY_ENTRY, "SELECT ci.item, cb.slot AS bag, ci.slot, ci.guid, c.account, c.name FROM characters c "
"INNER JOIN character_inventory ci ON ci.guid = c.guid " "INNER JOIN character_inventory ci ON ci.guid = c.guid "

View File

@@ -12,13 +12,13 @@
class CharacterDatabaseConnection : public MySQLConnection class CharacterDatabaseConnection : public MySQLConnection
{ {
public: public:
//- Constructors for sync and async connections //- Constructors for sync and async connections
CharacterDatabaseConnection(MySQLConnectionInfo& connInfo) : MySQLConnection(connInfo) {} CharacterDatabaseConnection(MySQLConnectionInfo& connInfo) : MySQLConnection(connInfo) {}
CharacterDatabaseConnection(ACE_Activation_Queue* q, MySQLConnectionInfo& connInfo) : MySQLConnection(q, connInfo) {} CharacterDatabaseConnection(ACE_Activation_Queue* q, MySQLConnectionInfo& connInfo) : MySQLConnection(q, connInfo) {}
//- Loads database type specific prepared statements //- Loads database type specific prepared statements
void DoPrepareStatements(); void DoPrepareStatements();
}; };
typedef DatabaseWorkerPool<CharacterDatabaseConnection> CharacterDatabaseWorkerPool; typedef DatabaseWorkerPool<CharacterDatabaseConnection> CharacterDatabaseWorkerPool;

View File

@@ -12,13 +12,13 @@
class LoginDatabaseConnection : public MySQLConnection class LoginDatabaseConnection : public MySQLConnection
{ {
public: public:
//- Constructors for sync and async connections //- Constructors for sync and async connections
LoginDatabaseConnection(MySQLConnectionInfo& connInfo) : MySQLConnection(connInfo) { } LoginDatabaseConnection(MySQLConnectionInfo& connInfo) : MySQLConnection(connInfo) { }
LoginDatabaseConnection(ACE_Activation_Queue* q, MySQLConnectionInfo& connInfo) : MySQLConnection(q, connInfo) { } LoginDatabaseConnection(ACE_Activation_Queue* q, MySQLConnectionInfo& connInfo) : MySQLConnection(q, connInfo) { }
//- Loads database type specific prepared statements //- Loads database type specific prepared statements
void DoPrepareStatements(); void DoPrepareStatements();
}; };
typedef DatabaseWorkerPool<LoginDatabaseConnection> LoginDatabaseWorkerPool; typedef DatabaseWorkerPool<LoginDatabaseConnection> LoginDatabaseWorkerPool;

View File

@@ -12,13 +12,13 @@
class WorldDatabaseConnection : public MySQLConnection class WorldDatabaseConnection : public MySQLConnection
{ {
public: public:
//- Constructors for sync and async connections //- Constructors for sync and async connections
WorldDatabaseConnection(MySQLConnectionInfo& connInfo) : MySQLConnection(connInfo) { } WorldDatabaseConnection(MySQLConnectionInfo& connInfo) : MySQLConnection(connInfo) { }
WorldDatabaseConnection(ACE_Activation_Queue* q, MySQLConnectionInfo& connInfo) : MySQLConnection(q, connInfo) { } WorldDatabaseConnection(ACE_Activation_Queue* q, MySQLConnectionInfo& connInfo) : MySQLConnection(q, connInfo) { }
//- Loads database type specific prepared statements //- Loads database type specific prepared statements
void DoPrepareStatements(); void DoPrepareStatements();
}; };
typedef DatabaseWorkerPool<WorldDatabaseConnection> WorldDatabaseWorkerPool; typedef DatabaseWorkerPool<WorldDatabaseConnection> WorldDatabaseWorkerPool;

View File

@@ -24,23 +24,23 @@
#endif #endif
MySQLConnection::MySQLConnection(MySQLConnectionInfo& connInfo) : MySQLConnection::MySQLConnection(MySQLConnectionInfo& connInfo) :
m_reconnecting(false), m_reconnecting(false),
m_prepareError(false), m_prepareError(false),
m_queue(NULL), m_queue(NULL),
m_worker(NULL), m_worker(NULL),
m_Mysql(NULL), m_Mysql(NULL),
m_connectionInfo(connInfo), m_connectionInfo(connInfo),
m_connectionFlags(CONNECTION_SYNCH) m_connectionFlags(CONNECTION_SYNCH)
{ {
} }
MySQLConnection::MySQLConnection(ACE_Activation_Queue* queue, MySQLConnectionInfo& connInfo) : MySQLConnection::MySQLConnection(ACE_Activation_Queue* queue, MySQLConnectionInfo& connInfo) :
m_reconnecting(false), m_reconnecting(false),
m_prepareError(false), m_prepareError(false),
m_queue(queue), m_queue(queue),
m_Mysql(NULL), m_Mysql(NULL),
m_connectionInfo(connInfo), m_connectionInfo(connInfo),
m_connectionFlags(CONNECTION_ASYNC) m_connectionFlags(CONNECTION_ASYNC)
{ {
m_worker = new DatabaseWorker(m_queue, this); m_worker = new DatabaseWorker(m_queue, this);
} }
@@ -63,7 +63,7 @@ void MySQLConnection::Close()
bool MySQLConnection::Open() bool MySQLConnection::Open()
{ {
MYSQL *mysqlInit; MYSQL* mysqlInit;
mysqlInit = mysql_init(NULL); mysqlInit = mysql_init(NULL);
if (!mysqlInit) if (!mysqlInit)
{ {
@@ -77,7 +77,7 @@ bool MySQLConnection::Open()
mysql_options(mysqlInit, MYSQL_SET_CHARSET_NAME, "utf8"); mysql_options(mysqlInit, MYSQL_SET_CHARSET_NAME, "utf8");
//mysql_options(mysqlInit, MYSQL_OPT_READ_TIMEOUT, (char const*)&timeout); //mysql_options(mysqlInit, MYSQL_OPT_READ_TIMEOUT, (char const*)&timeout);
#ifdef _WIN32 #ifdef _WIN32
if (m_connectionInfo.host == ".") // named pipe use option (Windows) if (m_connectionInfo.host == ".") // named pipe use option (Windows)
{ {
unsigned int opt = MYSQL_PROTOCOL_PIPE; unsigned int opt = MYSQL_PROTOCOL_PIPE;
@@ -90,7 +90,7 @@ bool MySQLConnection::Open()
port = atoi(m_connectionInfo.port_or_socket.c_str()); port = atoi(m_connectionInfo.port_or_socket.c_str());
unix_socket = 0; unix_socket = 0;
} }
#else #else
if (m_connectionInfo.host == ".") // socket use option (Unix/Linux) if (m_connectionInfo.host == ".") // socket use option (Unix/Linux)
{ {
unsigned int opt = MYSQL_PROTOCOL_SOCKET; unsigned int opt = MYSQL_PROTOCOL_SOCKET;
@@ -104,22 +104,23 @@ bool MySQLConnection::Open()
port = atoi(m_connectionInfo.port_or_socket.c_str()); port = atoi(m_connectionInfo.port_or_socket.c_str());
unix_socket = 0; unix_socket = 0;
} }
#endif #endif
// Possible improvement for future: make ATTEMPTS and SECONDS configurable values // Possible improvement for future: make ATTEMPTS and SECONDS configurable values
uint32 const ATTEMPTS = 180; uint32 const ATTEMPTS = 180;
uint32 count = 0; uint32 count = 0;
do { do
{
m_Mysql = mysql_real_connect( m_Mysql = mysql_real_connect(
mysqlInit, mysqlInit,
m_connectionInfo.host.c_str(), m_connectionInfo.host.c_str(),
m_connectionInfo.user.c_str(), m_connectionInfo.user.c_str(),
m_connectionInfo.password.c_str(), m_connectionInfo.password.c_str(),
m_connectionInfo.database.c_str(), m_connectionInfo.database.c_str(),
port, port,
unix_socket, unix_socket,
0); 0);
if (m_Mysql) if (m_Mysql)
{ {
@@ -250,7 +251,7 @@ bool MySQLConnection::Execute(PreparedStatement* stmt)
} }
} }
bool MySQLConnection::_Query(PreparedStatement* stmt, MYSQL_RES **pResult, uint64* pRowCount, uint32* pFieldCount) bool MySQLConnection::_Query(PreparedStatement* stmt, MYSQL_RES** pResult, uint64* pRowCount, uint32* pFieldCount)
{ {
if (!m_Mysql) if (!m_Mysql)
return false; return false;
@@ -287,7 +288,7 @@ bool MySQLConnection::_Query(PreparedStatement* stmt, MYSQL_RES **pResult, uint6
{ {
uint32 lErrno = mysql_errno(m_Mysql); uint32 lErrno = mysql_errno(m_Mysql);
sLog->outSQLDriver("SQL(p): %s\n [ERROR]: [%u] %s", sLog->outSQLDriver("SQL(p): %s\n [ERROR]: [%u] %s",
m_mStmt->getQueryString(m_queries[index].first).c_str(), lErrno, mysql_stmt_error(msql_STMT)); m_mStmt->getQueryString(m_queries[index].first).c_str(), lErrno, mysql_stmt_error(msql_STMT));
if (_HandleMySQLErrno(lErrno)) // If it returns true, an error was handled successfully (i.e. reconnection) if (_HandleMySQLErrno(lErrno)) // If it returns true, an error was handled successfully (i.e. reconnection)
return _Query(stmt, pResult, pRowCount, pFieldCount); // Try again return _Query(stmt, pResult, pRowCount, pFieldCount); // Try again
@@ -315,8 +316,8 @@ ResultSet* MySQLConnection::Query(const char* sql)
if (!sql) if (!sql)
return NULL; return NULL;
MYSQL_RES *result = NULL; MYSQL_RES* result = NULL;
MYSQL_FIELD *fields = NULL; MYSQL_FIELD* fields = NULL;
uint64 rowCount = 0; uint64 rowCount = 0;
uint32 fieldCount = 0; uint32 fieldCount = 0;
@@ -326,7 +327,7 @@ ResultSet* MySQLConnection::Query(const char* sql)
return new ResultSet(result, fields, rowCount, fieldCount); return new ResultSet(result, fields, rowCount, fieldCount);
} }
bool MySQLConnection::_Query(const char *sql, MYSQL_RES **pResult, MYSQL_FIELD **pFields, uint64* pRowCount, uint32* pFieldCount) bool MySQLConnection::_Query(const char* sql, MYSQL_RES** pResult, MYSQL_FIELD** pFields, uint64* pRowCount, uint32* pFieldCount)
{ {
if (!m_Mysql) if (!m_Mysql)
return false; return false;
@@ -401,29 +402,29 @@ bool MySQLConnection::ExecuteTransaction(SQLTransaction& transaction)
switch (itr->type) switch (itr->type)
{ {
case SQL_ELEMENT_PREPARED: case SQL_ELEMENT_PREPARED:
{
PreparedStatement* stmt = data.element.stmt;
ASSERT(stmt);
if (!Execute(stmt))
{ {
sLog->outSQLDriver("[Warning] Transaction aborted. %u queries not executed.", (uint32)queries.size()); PreparedStatement* stmt = data.element.stmt;
RollbackTransaction(); ASSERT(stmt);
return false; if (!Execute(stmt))
{
sLog->outSQLDriver("[Warning] Transaction aborted. %u queries not executed.", (uint32)queries.size());
RollbackTransaction();
return false;
}
} }
} break;
break;
case SQL_ELEMENT_RAW: case SQL_ELEMENT_RAW:
{
const char* sql = data.element.query;
ASSERT(sql);
if (!Execute(sql))
{ {
sLog->outSQLDriver("[Warning] Transaction aborted. %u queries not executed.", (uint32)queries.size()); const char* sql = data.element.query;
RollbackTransaction(); ASSERT(sql);
return false; if (!Execute(sql))
{
sLog->outSQLDriver("[Warning] Transaction aborted. %u queries not executed.", (uint32)queries.size());
RollbackTransaction();
return false;
}
} }
} break;
break;
} }
} }
@@ -442,7 +443,7 @@ MySQLPreparedStatement* MySQLConnection::GetPreparedStatement(uint32 index)
MySQLPreparedStatement* ret = m_stmts[index]; MySQLPreparedStatement* ret = m_stmts[index];
if (!ret) if (!ret)
sLog->outSQLDriver("ERROR: Could not fetch prepared statement %u on database `%s`, connection type: %s.", sLog->outSQLDriver("ERROR: Could not fetch prepared statement %u on database `%s`, connection type: %s.",
index, m_connectionInfo.database.c_str(), (m_connectionFlags & CONNECTION_ASYNC) ? "asynchronous" : "synchronous"); index, m_connectionInfo.database.c_str(), (m_connectionFlags & CONNECTION_ASYNC) ? "asynchronous" : "synchronous");
return ret; return ret;
} }
@@ -490,7 +491,7 @@ void MySQLConnection::PrepareStatement(uint32 index, const char* sql, Connection
PreparedResultSet* MySQLConnection::Query(PreparedStatement* stmt) PreparedResultSet* MySQLConnection::Query(PreparedStatement* stmt)
{ {
MYSQL_RES *result = NULL; MYSQL_RES* result = NULL;
uint64 rowCount = 0; uint64 rowCount = 0;
uint32 fieldCount = 0; uint32 fieldCount = 0;
@@ -514,27 +515,27 @@ bool MySQLConnection::_HandleMySQLErrno(uint32 errNo)
#if !(MARIADB_VERSION_ID >= 100200) #if !(MARIADB_VERSION_ID >= 100200)
case CR_INVALID_CONN_HANDLE: case CR_INVALID_CONN_HANDLE:
#endif #endif
{
m_reconnecting = true;
uint64 oldThreadId = mysql_thread_id(GetHandle());
mysql_close(GetHandle());
if (this->Open()) // Don't remove 'this' pointer unless you want to skip loading all prepared statements....
{ {
sLog->outSQLDriver("Connection to the MySQL server is active."); m_reconnecting = true;
if (oldThreadId != mysql_thread_id(GetHandle())) uint64 oldThreadId = mysql_thread_id(GetHandle());
sLog->outSQLDriver("Successfully reconnected to %s @%s:%s (%s).", mysql_close(GetHandle());
m_connectionInfo.database.c_str(), m_connectionInfo.host.c_str(), m_connectionInfo.port_or_socket.c_str(), if (this->Open()) // Don't remove 'this' pointer unless you want to skip loading all prepared statements....
(m_connectionFlags & CONNECTION_ASYNC) ? "asynchronous" : "synchronous"); {
sLog->outSQLDriver("Connection to the MySQL server is active.");
if (oldThreadId != mysql_thread_id(GetHandle()))
sLog->outSQLDriver("Successfully reconnected to %s @%s:%s (%s).",
m_connectionInfo.database.c_str(), m_connectionInfo.host.c_str(), m_connectionInfo.port_or_socket.c_str(),
(m_connectionFlags & CONNECTION_ASYNC) ? "asynchronous" : "synchronous");
m_reconnecting = false; m_reconnecting = false;
return true; return true;
}
uint32 lErrno = mysql_errno(GetHandle()); // It's possible this attempted reconnect throws 2006 at us. To prevent crazy recursive calls, sleep here.
std::this_thread::sleep_for(3s); // Sleep 3 seconds
return _HandleMySQLErrno(lErrno); // Call self (recursive)
} }
uint32 lErrno = mysql_errno(GetHandle()); // It's possible this attempted reconnect throws 2006 at us. To prevent crazy recursive calls, sleep here.
std::this_thread::sleep_for(3s); // Sleep 3 seconds
return _HandleMySQLErrno(lErrno); // Call self (recursive)
}
case ER_LOCK_DEADLOCK: case ER_LOCK_DEADLOCK:
return false; // Implemented in TransactionTask::Execute and DatabaseWorkerPool<T>::DirectCommitTransaction return false; // Implemented in TransactionTask::Execute and DatabaseWorkerPool<T>::DirectCommitTransaction
// Query related errors - skip query // Query related errors - skip query

View File

@@ -58,69 +58,69 @@ class MySQLConnection
template <class T> friend class DatabaseWorkerPool; template <class T> friend class DatabaseWorkerPool;
friend class PingOperation; friend class PingOperation;
public: public:
MySQLConnection(MySQLConnectionInfo& connInfo); //! Constructor for synchronous connections. MySQLConnection(MySQLConnectionInfo& connInfo); //! Constructor for synchronous connections.
MySQLConnection(ACE_Activation_Queue* queue, MySQLConnectionInfo& connInfo); //! Constructor for asynchronous connections. MySQLConnection(ACE_Activation_Queue* queue, MySQLConnectionInfo& connInfo); //! Constructor for asynchronous connections.
virtual ~MySQLConnection(); virtual ~MySQLConnection();
virtual bool Open(); virtual bool Open();
void Close(); void Close();
public: public:
bool Execute(const char* sql); bool Execute(const char* sql);
bool Execute(PreparedStatement* stmt); bool Execute(PreparedStatement* stmt);
ResultSet* Query(const char* sql); ResultSet* Query(const char* sql);
PreparedResultSet* Query(PreparedStatement* stmt); PreparedResultSet* Query(PreparedStatement* stmt);
bool _Query(const char *sql, MYSQL_RES **pResult, MYSQL_FIELD **pFields, uint64* pRowCount, uint32* pFieldCount); bool _Query(const char* sql, MYSQL_RES** pResult, MYSQL_FIELD** pFields, uint64* pRowCount, uint32* pFieldCount);
bool _Query(PreparedStatement* stmt, MYSQL_RES **pResult, uint64* pRowCount, uint32* pFieldCount); bool _Query(PreparedStatement* stmt, MYSQL_RES** pResult, uint64* pRowCount, uint32* pFieldCount);
void BeginTransaction(); void BeginTransaction();
void RollbackTransaction(); void RollbackTransaction();
void CommitTransaction(); void CommitTransaction();
bool ExecuteTransaction(SQLTransaction& transaction); bool ExecuteTransaction(SQLTransaction& transaction);
operator bool () const { return m_Mysql != NULL; } operator bool () const { return m_Mysql != NULL; }
void Ping() { mysql_ping(m_Mysql); } void Ping() { mysql_ping(m_Mysql); }
uint32 GetLastError() { return mysql_errno(m_Mysql); } uint32 GetLastError() { return mysql_errno(m_Mysql); }
protected: protected:
bool LockIfReady() bool LockIfReady()
{ {
/// Tries to acquire lock. If lock is acquired by another thread /// Tries to acquire lock. If lock is acquired by another thread
/// the calling parent will just try another connection /// the calling parent will just try another connection
return m_Mutex.tryacquire() != -1; return m_Mutex.tryacquire() != -1;
} }
void Unlock() void Unlock()
{ {
/// Called by parent databasepool. Will let other threads access this connection /// Called by parent databasepool. Will let other threads access this connection
m_Mutex.release(); m_Mutex.release();
} }
MYSQL* GetHandle() { return m_Mysql; } MYSQL* GetHandle() { return m_Mysql; }
MySQLPreparedStatement* GetPreparedStatement(uint32 index); MySQLPreparedStatement* GetPreparedStatement(uint32 index);
void PrepareStatement(uint32 index, const char* sql, ConnectionFlags flags); void PrepareStatement(uint32 index, const char* sql, ConnectionFlags flags);
bool PrepareStatements(); bool PrepareStatements();
virtual void DoPrepareStatements() = 0; virtual void DoPrepareStatements() = 0;
protected: protected:
std::vector<MySQLPreparedStatement*> m_stmts; //! PreparedStatements storage std::vector<MySQLPreparedStatement*> m_stmts; //! PreparedStatements storage
PreparedStatementMap m_queries; //! Query storage PreparedStatementMap m_queries; //! Query storage
bool m_reconnecting; //! Are we reconnecting? bool m_reconnecting; //! Are we reconnecting?
bool m_prepareError; //! Was there any error while preparing statements? bool m_prepareError; //! Was there any error while preparing statements?
private: private:
bool _HandleMySQLErrno(uint32 errNo); bool _HandleMySQLErrno(uint32 errNo);
private: private:
ACE_Activation_Queue* m_queue; //! Queue shared with other asynchronous connections. ACE_Activation_Queue* m_queue; //! Queue shared with other asynchronous connections.
DatabaseWorker* m_worker; //! Core worker task. DatabaseWorker* m_worker; //! Core worker task.
MYSQL * m_Mysql; //! MySQL Handle. MYSQL* m_Mysql; //! MySQL Handle.
MySQLConnectionInfo& m_connectionInfo; //! Connection info (used for logging) MySQLConnectionInfo& m_connectionInfo; //! Connection info (used for logging)
ConnectionFlags m_connectionFlags; //! Connection flags (for preparing relevant statements) ConnectionFlags m_connectionFlags; //! Connection flags (for preparing relevant statements)
ACE_Thread_Mutex m_Mutex; ACE_Thread_Mutex m_Mutex;
}; };
#endif #endif

View File

@@ -11,37 +11,37 @@
class MySQL class MySQL
{ {
public: public:
/*! Create a thread on the MySQL server to mirrior the calling thread, /*! Create a thread on the MySQL server to mirrior the calling thread,
initializes thread-specific variables and allows thread-specific initializes thread-specific variables and allows thread-specific
operations without concurrence from other threads. operations without concurrence from other threads.
This should only be called if multiple core threads are running This should only be called if multiple core threads are running
on the same MySQL connection. Seperate MySQL connections implicitly on the same MySQL connection. Seperate MySQL connections implicitly
create a mirror thread. create a mirror thread.
*/ */
static void Thread_Init() static void Thread_Init()
{ {
mysql_thread_init(); mysql_thread_init();
} }
/*! Shuts down MySQL thread and frees resources, should only be called /*! Shuts down MySQL thread and frees resources, should only be called
when we terminate. MySQL threads and connections are not configurable when we terminate. MySQL threads and connections are not configurable
during runtime. during runtime.
*/ */
static void Thread_End() static void Thread_End()
{ {
mysql_thread_end(); mysql_thread_end();
} }
static void Library_Init() static void Library_Init()
{ {
mysql_library_init(-1, NULL, NULL); mysql_library_init(-1, NULL, NULL);
} }
static void Library_End() static void Library_End()
{ {
mysql_library_end(); mysql_library_end();
} }
}; };
#endif #endif

View File

@@ -9,8 +9,8 @@
#include "Log.h" #include "Log.h"
PreparedStatement::PreparedStatement(uint32 index) : PreparedStatement::PreparedStatement(uint32 index) :
m_stmt(NULL), m_stmt(NULL),
m_index(index) m_index(index)
{ {
} }
@@ -68,17 +68,17 @@ void PreparedStatement::BindParameters()
break; break;
} }
} }
#ifdef _DEBUG #ifdef _DEBUG
if (i < m_stmt->m_paramCount) if (i < m_stmt->m_paramCount)
sLog->outSQLDriver("[WARNING]: BindParameters() for statement %u did not bind all allocated parameters", m_index); sLog->outSQLDriver("[WARNING]: BindParameters() for statement %u did not bind all allocated parameters", m_index);
#endif #endif
} }
//- Bind to buffer //- Bind to buffer
void PreparedStatement::setBool(const uint8 index, const bool value) void PreparedStatement::setBool(const uint8 index, const bool value)
{ {
if (index >= statement_data.size()) if (index >= statement_data.size())
statement_data.resize(index+1); statement_data.resize(index + 1);
statement_data[index].data.boolean = value; statement_data[index].data.boolean = value;
statement_data[index].type = TYPE_BOOL; statement_data[index].type = TYPE_BOOL;
@@ -87,7 +87,7 @@ void PreparedStatement::setBool(const uint8 index, const bool value)
void PreparedStatement::setUInt8(const uint8 index, const uint8 value) void PreparedStatement::setUInt8(const uint8 index, const uint8 value)
{ {
if (index >= statement_data.size()) if (index >= statement_data.size())
statement_data.resize(index+1); statement_data.resize(index + 1);
statement_data[index].data.ui8 = value; statement_data[index].data.ui8 = value;
statement_data[index].type = TYPE_UI8; statement_data[index].type = TYPE_UI8;
@@ -96,7 +96,7 @@ void PreparedStatement::setUInt8(const uint8 index, const uint8 value)
void PreparedStatement::setUInt16(const uint8 index, const uint16 value) void PreparedStatement::setUInt16(const uint8 index, const uint16 value)
{ {
if (index >= statement_data.size()) if (index >= statement_data.size())
statement_data.resize(index+1); statement_data.resize(index + 1);
statement_data[index].data.ui16 = value; statement_data[index].data.ui16 = value;
statement_data[index].type = TYPE_UI16; statement_data[index].type = TYPE_UI16;
@@ -105,7 +105,7 @@ void PreparedStatement::setUInt16(const uint8 index, const uint16 value)
void PreparedStatement::setUInt32(const uint8 index, const uint32 value) void PreparedStatement::setUInt32(const uint8 index, const uint32 value)
{ {
if (index >= statement_data.size()) if (index >= statement_data.size())
statement_data.resize(index+1); statement_data.resize(index + 1);
statement_data[index].data.ui32 = value; statement_data[index].data.ui32 = value;
statement_data[index].type = TYPE_UI32; statement_data[index].type = TYPE_UI32;
@@ -114,7 +114,7 @@ void PreparedStatement::setUInt32(const uint8 index, const uint32 value)
void PreparedStatement::setUInt64(const uint8 index, const uint64 value) void PreparedStatement::setUInt64(const uint8 index, const uint64 value)
{ {
if (index >= statement_data.size()) if (index >= statement_data.size())
statement_data.resize(index+1); statement_data.resize(index + 1);
statement_data[index].data.ui64 = value; statement_data[index].data.ui64 = value;
statement_data[index].type = TYPE_UI64; statement_data[index].type = TYPE_UI64;
@@ -123,7 +123,7 @@ void PreparedStatement::setUInt64(const uint8 index, const uint64 value)
void PreparedStatement::setInt8(const uint8 index, const int8 value) void PreparedStatement::setInt8(const uint8 index, const int8 value)
{ {
if (index >= statement_data.size()) if (index >= statement_data.size())
statement_data.resize(index+1); statement_data.resize(index + 1);
statement_data[index].data.i8 = value; statement_data[index].data.i8 = value;
statement_data[index].type = TYPE_I8; statement_data[index].type = TYPE_I8;
@@ -132,7 +132,7 @@ void PreparedStatement::setInt8(const uint8 index, const int8 value)
void PreparedStatement::setInt16(const uint8 index, const int16 value) void PreparedStatement::setInt16(const uint8 index, const int16 value)
{ {
if (index >= statement_data.size()) if (index >= statement_data.size())
statement_data.resize(index+1); statement_data.resize(index + 1);
statement_data[index].data.i16 = value; statement_data[index].data.i16 = value;
statement_data[index].type = TYPE_I16; statement_data[index].type = TYPE_I16;
@@ -141,7 +141,7 @@ void PreparedStatement::setInt16(const uint8 index, const int16 value)
void PreparedStatement::setInt32(const uint8 index, const int32 value) void PreparedStatement::setInt32(const uint8 index, const int32 value)
{ {
if (index >= statement_data.size()) if (index >= statement_data.size())
statement_data.resize(index+1); statement_data.resize(index + 1);
statement_data[index].data.i32 = value; statement_data[index].data.i32 = value;
statement_data[index].type = TYPE_I32; statement_data[index].type = TYPE_I32;
@@ -150,7 +150,7 @@ void PreparedStatement::setInt32(const uint8 index, const int32 value)
void PreparedStatement::setInt64(const uint8 index, const int64 value) void PreparedStatement::setInt64(const uint8 index, const int64 value)
{ {
if (index >= statement_data.size()) if (index >= statement_data.size())
statement_data.resize(index+1); statement_data.resize(index + 1);
statement_data[index].data.i64 = value; statement_data[index].data.i64 = value;
statement_data[index].type = TYPE_I64; statement_data[index].type = TYPE_I64;
@@ -159,7 +159,7 @@ void PreparedStatement::setInt64(const uint8 index, const int64 value)
void PreparedStatement::setFloat(const uint8 index, const float value) void PreparedStatement::setFloat(const uint8 index, const float value)
{ {
if (index >= statement_data.size()) if (index >= statement_data.size())
statement_data.resize(index+1); statement_data.resize(index + 1);
statement_data[index].data.f = value; statement_data[index].data.f = value;
statement_data[index].type = TYPE_FLOAT; statement_data[index].type = TYPE_FLOAT;
@@ -168,7 +168,7 @@ void PreparedStatement::setFloat(const uint8 index, const float value)
void PreparedStatement::setDouble(const uint8 index, const double value) void PreparedStatement::setDouble(const uint8 index, const double value)
{ {
if (index >= statement_data.size()) if (index >= statement_data.size())
statement_data.resize(index+1); statement_data.resize(index + 1);
statement_data[index].data.d = value; statement_data[index].data.d = value;
statement_data[index].type = TYPE_DOUBLE; statement_data[index].type = TYPE_DOUBLE;
@@ -177,7 +177,7 @@ void PreparedStatement::setDouble(const uint8 index, const double value)
void PreparedStatement::setString(const uint8 index, const std::string& value) void PreparedStatement::setString(const uint8 index, const std::string& value)
{ {
if (index >= statement_data.size()) if (index >= statement_data.size())
statement_data.resize(index+1); statement_data.resize(index + 1);
statement_data[index].str = value; statement_data[index].str = value;
statement_data[index].type = TYPE_STRING; statement_data[index].type = TYPE_STRING;
@@ -186,15 +186,15 @@ void PreparedStatement::setString(const uint8 index, const std::string& value)
void PreparedStatement::setNull(const uint8 index) void PreparedStatement::setNull(const uint8 index)
{ {
if (index >= statement_data.size()) if (index >= statement_data.size())
statement_data.resize(index+1); statement_data.resize(index + 1);
statement_data[index].type = TYPE_NULL; statement_data[index].type = TYPE_NULL;
} }
MySQLPreparedStatement::MySQLPreparedStatement(MYSQL_STMT* stmt) : MySQLPreparedStatement::MySQLPreparedStatement(MYSQL_STMT* stmt) :
m_stmt(NULL), m_stmt(NULL),
m_Mstmt(stmt), m_Mstmt(stmt),
m_bind(NULL) m_bind(NULL)
{ {
/// Initialize variable parameters /// Initialize variable parameters
m_paramCount = mysql_stmt_param_count(stmt); m_paramCount = mysql_stmt_param_count(stmt);
@@ -221,7 +221,7 @@ MySQLPreparedStatement::~MySQLPreparedStatement()
void MySQLPreparedStatement::ClearParameters() void MySQLPreparedStatement::ClearParameters()
{ {
for (uint32 i=0; i < m_paramCount; ++i) for (uint32 i = 0; i < m_paramCount; ++i)
{ {
delete m_bind[i].length; delete m_bind[i].length;
m_bind[i].length = NULL; m_bind[i].length = NULL;
@@ -339,12 +339,12 @@ void MySQLPreparedStatement::setString(const uint8 index, const char* value)
MYSQL_BIND* param = &m_bind[index]; MYSQL_BIND* param = &m_bind[index];
size_t len = strlen(value) + 1; size_t len = strlen(value) + 1;
param->buffer_type = MYSQL_TYPE_VAR_STRING; param->buffer_type = MYSQL_TYPE_VAR_STRING;
delete [] static_cast<char *>(param->buffer); delete [] static_cast<char*>(param->buffer);
param->buffer = new char[len]; param->buffer = new char[len];
param->buffer_length = len; param->buffer_length = len;
param->is_null_value = 0; param->is_null_value = 0;
delete param->length; delete param->length;
param->length = new unsigned long(len-1); param->length = new unsigned long(len - 1);
memcpy(param->buffer, value, len); memcpy(param->buffer, value, len);
} }
@@ -355,7 +355,7 @@ void MySQLPreparedStatement::setNull(const uint8 index)
m_paramsSet[index] = true; m_paramsSet[index] = true;
MYSQL_BIND* param = &m_bind[index]; MYSQL_BIND* param = &m_bind[index];
param->buffer_type = MYSQL_TYPE_NULL; param->buffer_type = MYSQL_TYPE_NULL;
delete [] static_cast<char *>(param->buffer); delete [] static_cast<char*>(param->buffer);
param->buffer = NULL; param->buffer = NULL;
param->buffer_length = 0; param->buffer_length = 0;
param->is_null_value = 1; param->is_null_value = 1;
@@ -366,7 +366,7 @@ void MySQLPreparedStatement::setNull(const uint8 index)
void MySQLPreparedStatement::setValue(MYSQL_BIND* param, enum_field_types type, const void* value, uint32 len, bool isUnsigned) void MySQLPreparedStatement::setValue(MYSQL_BIND* param, enum_field_types type, const void* value, uint32 len, bool isUnsigned)
{ {
param->buffer_type = type; param->buffer_type = type;
delete [] static_cast<char *>(param->buffer); delete [] static_cast<char*>(param->buffer);
param->buffer = new char[len]; param->buffer = new char[len];
param->buffer_length = 0; param->buffer_length = 0;
param->is_null_value = 0; param->is_null_value = 0;
@@ -439,15 +439,15 @@ std::string MySQLPreparedStatement::getQueryString(std::string const& sqlPattern
//- Execution //- Execution
PreparedStatementTask::PreparedStatementTask(PreparedStatement* stmt) : PreparedStatementTask::PreparedStatementTask(PreparedStatement* stmt) :
m_stmt(stmt), m_stmt(stmt),
m_has_result(false) m_has_result(false)
{ {
} }
PreparedStatementTask::PreparedStatementTask(PreparedStatement* stmt, PreparedQueryResultFuture result) : PreparedStatementTask::PreparedStatementTask(PreparedStatement* stmt, PreparedQueryResultFuture result) :
m_stmt(stmt), m_stmt(stmt),
m_has_result(true), m_has_result(true),
m_result(result) m_result(result)
{ {
} }

View File

@@ -65,31 +65,31 @@ class PreparedStatement
friend class MySQLPreparedStatement; friend class MySQLPreparedStatement;
friend class MySQLConnection; friend class MySQLConnection;
public: public:
explicit PreparedStatement(uint32 index); explicit PreparedStatement(uint32 index);
~PreparedStatement(); ~PreparedStatement();
void setBool(const uint8 index, const bool value); void setBool(const uint8 index, const bool value);
void setUInt8(const uint8 index, const uint8 value); void setUInt8(const uint8 index, const uint8 value);
void setUInt16(const uint8 index, const uint16 value); void setUInt16(const uint8 index, const uint16 value);
void setUInt32(const uint8 index, const uint32 value); void setUInt32(const uint8 index, const uint32 value);
void setUInt64(const uint8 index, const uint64 value); void setUInt64(const uint8 index, const uint64 value);
void setInt8(const uint8 index, const int8 value); void setInt8(const uint8 index, const int8 value);
void setInt16(const uint8 index, const int16 value); void setInt16(const uint8 index, const int16 value);
void setInt32(const uint8 index, const int32 value); void setInt32(const uint8 index, const int32 value);
void setInt64(const uint8 index, const int64 value); void setInt64(const uint8 index, const int64 value);
void setFloat(const uint8 index, const float value); void setFloat(const uint8 index, const float value);
void setDouble(const uint8 index, const double value); void setDouble(const uint8 index, const double value);
void setString(const uint8 index, const std::string& value); void setString(const uint8 index, const std::string& value);
void setNull(const uint8 index); void setNull(const uint8 index);
protected: protected:
void BindParameters(); void BindParameters();
protected: protected:
MySQLPreparedStatement* m_stmt; MySQLPreparedStatement* m_stmt;
uint32 m_index; uint32 m_index;
std::vector<PreparedStatementData> statement_data; //- Buffer of parameters, not tied to MySQL in any way yet std::vector<PreparedStatementData> statement_data; //- Buffer of parameters, not tied to MySQL in any way yet
}; };
//- Class of which the instances are unique per MySQLConnection //- Class of which the instances are unique per MySQLConnection
@@ -100,40 +100,40 @@ class MySQLPreparedStatement
friend class MySQLConnection; friend class MySQLConnection;
friend class PreparedStatement; friend class PreparedStatement;
public: public:
MySQLPreparedStatement(MYSQL_STMT* stmt); MySQLPreparedStatement(MYSQL_STMT* stmt);
~MySQLPreparedStatement(); ~MySQLPreparedStatement();
void setBool(const uint8 index, const bool value); void setBool(const uint8 index, const bool value);
void setUInt8(const uint8 index, const uint8 value); void setUInt8(const uint8 index, const uint8 value);
void setUInt16(const uint8 index, const uint16 value); void setUInt16(const uint8 index, const uint16 value);
void setUInt32(const uint8 index, const uint32 value); void setUInt32(const uint8 index, const uint32 value);
void setUInt64(const uint8 index, const uint64 value); void setUInt64(const uint8 index, const uint64 value);
void setInt8(const uint8 index, const int8 value); void setInt8(const uint8 index, const int8 value);
void setInt16(const uint8 index, const int16 value); void setInt16(const uint8 index, const int16 value);
void setInt32(const uint8 index, const int32 value); void setInt32(const uint8 index, const int32 value);
void setInt64(const uint8 index, const int64 value); void setInt64(const uint8 index, const int64 value);
void setFloat(const uint8 index, const float value); void setFloat(const uint8 index, const float value);
void setDouble(const uint8 index, const double value); void setDouble(const uint8 index, const double value);
void setString(const uint8 index, const char* value); void setString(const uint8 index, const char* value);
void setNull(const uint8 index); void setNull(const uint8 index);
protected: protected:
MYSQL_STMT* GetSTMT() { return m_Mstmt; } MYSQL_STMT* GetSTMT() { return m_Mstmt; }
MYSQL_BIND* GetBind() { return m_bind; } MYSQL_BIND* GetBind() { return m_bind; }
PreparedStatement* m_stmt; PreparedStatement* m_stmt;
void ClearParameters(); void ClearParameters();
bool CheckValidIndex(uint8 index); bool CheckValidIndex(uint8 index);
std::string getQueryString(std::string const& sqlPattern) const; std::string getQueryString(std::string const& sqlPattern) const;
private: private:
void setValue(MYSQL_BIND* param, enum_field_types type, const void* value, uint32 len, bool isUnsigned); void setValue(MYSQL_BIND* param, enum_field_types type, const void* value, uint32 len, bool isUnsigned);
private: private:
MYSQL_STMT* m_Mstmt; MYSQL_STMT* m_Mstmt;
uint32 m_paramCount; uint32 m_paramCount;
std::vector<bool> m_paramsSet; std::vector<bool> m_paramsSet;
MYSQL_BIND* m_bind; MYSQL_BIND* m_bind;
}; };
typedef ACE_Future<PreparedQueryResult> PreparedQueryResultFuture; typedef ACE_Future<PreparedQueryResult> PreparedQueryResultFuture;
@@ -141,16 +141,16 @@ typedef ACE_Future<PreparedQueryResult> PreparedQueryResultFuture;
//- Lower-level class, enqueuable operation //- Lower-level class, enqueuable operation
class PreparedStatementTask : public SQLOperation class PreparedStatementTask : public SQLOperation
{ {
public: public:
PreparedStatementTask(PreparedStatement* stmt); PreparedStatementTask(PreparedStatement* stmt);
PreparedStatementTask(PreparedStatement* stmt, PreparedQueryResultFuture result); PreparedStatementTask(PreparedStatement* stmt, PreparedQueryResultFuture result);
~PreparedStatementTask(); ~PreparedStatementTask();
bool Execute(); bool Execute();
protected: protected:
PreparedStatement* m_stmt; PreparedStatement* m_stmt;
bool m_has_result; bool m_has_result;
PreparedQueryResultFuture m_result; PreparedQueryResultFuture m_result;
}; };
#endif #endif

View File

@@ -9,7 +9,7 @@
#include "PreparedStatement.h" #include "PreparedStatement.h"
#include "Log.h" #include "Log.h"
bool SQLQueryHolder::SetQuery(size_t index, const char *sql) bool SQLQueryHolder::SetQuery(size_t index, const char* sql)
{ {
if (m_queries.size() <= index) if (m_queries.size() <= index)
{ {
@@ -29,7 +29,7 @@ bool SQLQueryHolder::SetQuery(size_t index, const char *sql)
return true; return true;
} }
bool SQLQueryHolder::SetPQuery(size_t index, const char *format, ...) bool SQLQueryHolder::SetPQuery(size_t index, const char* format, ...)
{ {
if (!format) if (!format)
{ {
@@ -165,7 +165,7 @@ bool SQLQueryHolderTask::Execute()
return false; return false;
/// we can do this, we are friends /// we can do this, we are friends
std::vector<SQLQueryHolder::SQLResultPair> &queries = m_holder->m_queries; std::vector<SQLQueryHolder::SQLResultPair>& queries = m_holder->m_queries;
for (size_t i = 0; i < queries.size(); i++) for (size_t i = 0; i < queries.size(); i++)
{ {
@@ -175,19 +175,19 @@ bool SQLQueryHolderTask::Execute()
switch (data->type) switch (data->type)
{ {
case SQL_ELEMENT_RAW: case SQL_ELEMENT_RAW:
{ {
char const* sql = data->element.query; char const* sql = data->element.query;
if (sql) if (sql)
m_holder->SetResult(i, m_conn->Query(sql)); m_holder->SetResult(i, m_conn->Query(sql));
break; break;
} }
case SQL_ELEMENT_PREPARED: case SQL_ELEMENT_PREPARED:
{ {
PreparedStatement* stmt = data->element.stmt; PreparedStatement* stmt = data->element.stmt;
if (stmt) if (stmt)
m_holder->SetPreparedResult(i, m_conn->Query(stmt)); m_holder->SetPreparedResult(i, m_conn->Query(stmt));
break; break;
} }
} }
} }
} }

View File

@@ -12,34 +12,34 @@
class SQLQueryHolder class SQLQueryHolder
{ {
friend class SQLQueryHolderTask; friend class SQLQueryHolderTask;
private: private:
typedef std::pair<SQLElementData, SQLResultSetUnion> SQLResultPair; typedef std::pair<SQLElementData, SQLResultSetUnion> SQLResultPair;
std::vector<SQLResultPair> m_queries; std::vector<SQLResultPair> m_queries;
public: public:
SQLQueryHolder() { } SQLQueryHolder() { }
~SQLQueryHolder(); ~SQLQueryHolder();
bool SetQuery(size_t index, const char *sql); bool SetQuery(size_t index, const char* sql);
bool SetPQuery(size_t index, const char *format, ...) ATTR_PRINTF(3, 4); bool SetPQuery(size_t index, const char* format, ...) ATTR_PRINTF(3, 4);
bool SetPreparedQuery(size_t index, PreparedStatement* stmt); bool SetPreparedQuery(size_t index, PreparedStatement* stmt);
void SetSize(size_t size); void SetSize(size_t size);
QueryResult GetResult(size_t index); QueryResult GetResult(size_t index);
PreparedQueryResult GetPreparedResult(size_t index); PreparedQueryResult GetPreparedResult(size_t index);
void SetResult(size_t index, ResultSet* result); void SetResult(size_t index, ResultSet* result);
void SetPreparedResult(size_t index, PreparedResultSet* result); void SetPreparedResult(size_t index, PreparedResultSet* result);
}; };
typedef ACE_Future<SQLQueryHolder*> QueryResultHolderFuture; typedef ACE_Future<SQLQueryHolder*> QueryResultHolderFuture;
class SQLQueryHolderTask : public SQLOperation class SQLQueryHolderTask : public SQLOperation
{ {
private: private:
SQLQueryHolder * m_holder; SQLQueryHolder* m_holder;
QueryResultHolderFuture m_result; QueryResultHolderFuture m_result;
public: public:
SQLQueryHolderTask(SQLQueryHolder *holder, QueryResultHolderFuture res) SQLQueryHolderTask(SQLQueryHolder* holder, QueryResultHolderFuture res)
: m_holder(holder), m_result(res){ }; : m_holder(holder), m_result(res) { };
bool Execute(); bool Execute();
}; };

View File

@@ -7,25 +7,25 @@
#include "DatabaseEnv.h" #include "DatabaseEnv.h"
#include "Log.h" #include "Log.h"
ResultSet::ResultSet(MYSQL_RES *result, MYSQL_FIELD *fields, uint64 rowCount, uint32 fieldCount) : ResultSet::ResultSet(MYSQL_RES* result, MYSQL_FIELD* fields, uint64 rowCount, uint32 fieldCount) :
_rowCount(rowCount), _rowCount(rowCount),
_fieldCount(fieldCount), _fieldCount(fieldCount),
_result(result), _result(result),
_fields(fields) _fields(fields)
{ {
_currentRow = new Field[_fieldCount]; _currentRow = new Field[_fieldCount];
ASSERT(_currentRow); ASSERT(_currentRow);
} }
PreparedResultSet::PreparedResultSet(MYSQL_STMT* stmt, MYSQL_RES *result, uint64 rowCount, uint32 fieldCount) : PreparedResultSet::PreparedResultSet(MYSQL_STMT* stmt, MYSQL_RES* result, uint64 rowCount, uint32 fieldCount) :
m_rowCount(rowCount), m_rowCount(rowCount),
m_rowPosition(0), m_rowPosition(0),
m_fieldCount(fieldCount), m_fieldCount(fieldCount),
m_rBind(NULL), m_rBind(NULL),
m_stmt(stmt), m_stmt(stmt),
m_res(result), m_res(result),
m_isNull(NULL), m_isNull(NULL),
m_length(NULL) m_length(NULL)
{ {
if (!m_res) if (!m_res)
return; return;
@@ -94,9 +94,9 @@ m_length(NULL)
{ {
if (!*m_rBind[fIndex].is_null) if (!*m_rBind[fIndex].is_null)
m_rows[uint32(m_rowPosition)][fIndex].SetByteValue( m_rBind[fIndex].buffer, m_rows[uint32(m_rowPosition)][fIndex].SetByteValue( m_rBind[fIndex].buffer,
m_rBind[fIndex].buffer_length, m_rBind[fIndex].buffer_length,
m_rBind[fIndex].buffer_type, m_rBind[fIndex].buffer_type,
*m_rBind[fIndex].length ); *m_rBind[fIndex].length );
else else
switch (m_rBind[fIndex].buffer_type) switch (m_rBind[fIndex].buffer_type)
{ {
@@ -106,16 +106,16 @@ m_length(NULL)
case MYSQL_TYPE_BLOB: case MYSQL_TYPE_BLOB:
case MYSQL_TYPE_STRING: case MYSQL_TYPE_STRING:
case MYSQL_TYPE_VAR_STRING: case MYSQL_TYPE_VAR_STRING:
m_rows[uint32(m_rowPosition)][fIndex].SetByteValue( "", m_rows[uint32(m_rowPosition)][fIndex].SetByteValue( "",
m_rBind[fIndex].buffer_length, m_rBind[fIndex].buffer_length,
m_rBind[fIndex].buffer_type, m_rBind[fIndex].buffer_type,
*m_rBind[fIndex].length ); *m_rBind[fIndex].length );
break; break;
default: default:
m_rows[uint32(m_rowPosition)][fIndex].SetByteValue( 0, m_rows[uint32(m_rowPosition)][fIndex].SetByteValue( 0,
m_rBind[fIndex].buffer_length, m_rBind[fIndex].buffer_length,
m_rBind[fIndex].buffer_type, m_rBind[fIndex].buffer_type,
*m_rBind[fIndex].length ); *m_rBind[fIndex].length );
} }
} }
m_rowPosition++; m_rowPosition++;

View File

@@ -14,7 +14,7 @@
#include "Field.h" #include "Field.h"
#ifdef _WIN32 #ifdef _WIN32
#include <winsock2.h> #include <winsock2.h>
#endif #endif
#include <mysql.h> #include <mysql.h>
@@ -24,76 +24,76 @@ typedef bool my_bool;
class ResultSet class ResultSet
{ {
public: public:
ResultSet(MYSQL_RES* result, MYSQL_FIELD* fields, uint64 rowCount, uint32 fieldCount); ResultSet(MYSQL_RES* result, MYSQL_FIELD* fields, uint64 rowCount, uint32 fieldCount);
~ResultSet(); ~ResultSet();
bool NextRow(); bool NextRow();
uint64 GetRowCount() const { return _rowCount; } uint64 GetRowCount() const { return _rowCount; }
uint32 GetFieldCount() const { return _fieldCount; } uint32 GetFieldCount() const { return _fieldCount; }
#ifdef ELUNA #ifdef ELUNA
std::string GetFieldName(uint32 index) const; std::string GetFieldName(uint32 index) const;
#endif #endif
Field* Fetch() const { return _currentRow; } Field* Fetch() const { return _currentRow; }
const Field & operator [] (uint32 index) const const Field& operator [] (uint32 index) const
{ {
ASSERT(index < _fieldCount); ASSERT(index < _fieldCount);
return _currentRow[index]; return _currentRow[index];
} }
protected: protected:
uint64 _rowCount; uint64 _rowCount;
Field* _currentRow; Field* _currentRow;
uint32 _fieldCount; uint32 _fieldCount;
private: private:
void CleanUp(); void CleanUp();
MYSQL_RES* _result; MYSQL_RES* _result;
MYSQL_FIELD* _fields; MYSQL_FIELD* _fields;
}; };
typedef acore::AutoPtr<ResultSet, ACE_Thread_Mutex> QueryResult; typedef acore::AutoPtr<ResultSet, ACE_Thread_Mutex> QueryResult;
class PreparedResultSet class PreparedResultSet
{ {
public: public:
PreparedResultSet(MYSQL_STMT* stmt, MYSQL_RES* result, uint64 rowCount, uint32 fieldCount); PreparedResultSet(MYSQL_STMT* stmt, MYSQL_RES* result, uint64 rowCount, uint32 fieldCount);
~PreparedResultSet(); ~PreparedResultSet();
bool NextRow(); bool NextRow();
uint64 GetRowCount() const { return m_rowCount; } uint64 GetRowCount() const { return m_rowCount; }
uint32 GetFieldCount() const { return m_fieldCount; } uint32 GetFieldCount() const { return m_fieldCount; }
Field* Fetch() const Field* Fetch() const
{ {
ASSERT(m_rowPosition < m_rowCount); ASSERT(m_rowPosition < m_rowCount);
return m_rows[uint32(m_rowPosition)]; return m_rows[uint32(m_rowPosition)];
} }
const Field & operator [] (uint32 index) const const Field& operator [] (uint32 index) const
{ {
ASSERT(m_rowPosition < m_rowCount); ASSERT(m_rowPosition < m_rowCount);
ASSERT(index < m_fieldCount); ASSERT(index < m_fieldCount);
return m_rows[uint32(m_rowPosition)][index]; return m_rows[uint32(m_rowPosition)][index];
} }
protected: protected:
std::vector<Field*> m_rows; std::vector<Field*> m_rows;
uint64 m_rowCount; uint64 m_rowCount;
uint64 m_rowPosition; uint64 m_rowPosition;
uint32 m_fieldCount; uint32 m_fieldCount;
private: private:
MYSQL_BIND* m_rBind; MYSQL_BIND* m_rBind;
MYSQL_STMT* m_stmt; MYSQL_STMT* m_stmt;
MYSQL_RES* m_res; MYSQL_RES* m_res;
my_bool* m_isNull; my_bool* m_isNull;
unsigned long* m_length; unsigned long* m_length;
void FreeBindBuffer(); void FreeBindBuffer();
void CleanUp(); void CleanUp();
bool _NextRow(); bool _NextRow();
}; };

View File

@@ -47,17 +47,17 @@ class MySQLConnection;
class SQLOperation : public ACE_Method_Request class SQLOperation : public ACE_Method_Request
{ {
public: public:
SQLOperation(): m_conn(NULL) { } SQLOperation(): m_conn(NULL) { }
virtual int call() virtual int call()
{ {
Execute(); Execute();
return 0; return 0;
} }
virtual bool Execute() = 0; virtual bool Execute() = 0;
virtual void SetConnection(MySQLConnection* con) { m_conn = con; } virtual void SetConnection(MySQLConnection* con) { m_conn = con; }
MySQLConnection* m_conn; MySQLConnection* m_conn;
}; };
#endif #endif

View File

@@ -44,15 +44,15 @@ void Transaction::Cleanup()
while (!m_queries.empty()) while (!m_queries.empty())
{ {
SQLElementData const &data = m_queries.front(); SQLElementData const& data = m_queries.front();
switch (data.type) switch (data.type)
{ {
case SQL_ELEMENT_PREPARED: case SQL_ELEMENT_PREPARED:
delete data.element.stmt; delete data.element.stmt;
break; break;
case SQL_ELEMENT_RAW: case SQL_ELEMENT_RAW:
free((void*)(data.element.query)); free((void*)(data.element.query));
break; break;
} }
m_queries.pop_front(); m_queries.pop_front();

View File

@@ -21,22 +21,22 @@ class Transaction
template <typename T> template <typename T>
friend class DatabaseWorkerPool; friend class DatabaseWorkerPool;
public: public:
Transaction() : _cleanedUp(false) { } Transaction() : _cleanedUp(false) { }
~Transaction() { Cleanup(); } ~Transaction() { Cleanup(); }
void Append(PreparedStatement* statement); void Append(PreparedStatement* statement);
void Append(const char* sql); void Append(const char* sql);
void PAppend(const char* sql, ...); void PAppend(const char* sql, ...);
size_t GetSize() const { return m_queries.size(); } size_t GetSize() const { return m_queries.size(); }
protected: protected:
void Cleanup(); void Cleanup();
std::list<SQLElementData> m_queries; std::list<SQLElementData> m_queries;
private: private:
bool _cleanedUp; bool _cleanedUp;
}; };
typedef acore::AutoPtr<Transaction, ACE_Thread_Mutex> SQLTransaction; typedef acore::AutoPtr<Transaction, ACE_Thread_Mutex> SQLTransaction;
@@ -47,14 +47,14 @@ class TransactionTask : public SQLOperation
template <class T> friend class DatabaseWorkerPool; template <class T> friend class DatabaseWorkerPool;
friend class DatabaseWorker; friend class DatabaseWorker;
public: public:
TransactionTask(SQLTransaction trans) : m_trans(trans) { } ; TransactionTask(SQLTransaction trans) : m_trans(trans) { } ;
~TransactionTask(){ }; ~TransactionTask() { };
protected: protected:
bool Execute(); bool Execute();
SQLTransaction m_trans; SQLTransaction m_trans;
}; };
#endif #endif

View File

@@ -57,73 +57,73 @@ namespace
namespace acore namespace acore
{ {
void Assert(char const* file, int line, char const* function, std::string const& debugInfo, char const* message) void Assert(char const* file, int line, char const* function, std::string const& debugInfo, char const* message)
{ {
std::string formattedMessage = acore::StringFormat("\n%s:%i in %s ASSERTION FAILED:\n %s\n", file, line, function, message) + debugInfo + '\n'; std::string formattedMessage = acore::StringFormat("\n%s:%i in %s ASSERTION FAILED:\n %s\n", file, line, function, message) + debugInfo + '\n';
fprintf(stderr, "%s", formattedMessage.c_str()); fprintf(stderr, "%s", formattedMessage.c_str());
fflush(stderr); fflush(stderr);
Crash(formattedMessage.c_str()); Crash(formattedMessage.c_str());
} }
void Assert(char const* file, int line, char const* function, std::string const& debugInfo, char const* message, char const* format, ...) void Assert(char const* file, int line, char const* function, std::string const& debugInfo, char const* message, char const* format, ...)
{ {
va_list args; va_list args;
va_start(args, format); va_start(args, format);
std::string formattedMessage = acore::StringFormat("\n%s:%i in %s ASSERTION FAILED:\n %s\n", file, line, function, message) + FormatAssertionMessage(format, args) + '\n' + debugInfo + '\n'; std::string formattedMessage = acore::StringFormat("\n%s:%i in %s ASSERTION FAILED:\n %s\n", file, line, function, message) + FormatAssertionMessage(format, args) + '\n' + debugInfo + '\n';
va_end(args); va_end(args);
fprintf(stderr, "%s", formattedMessage.c_str()); fprintf(stderr, "%s", formattedMessage.c_str());
fflush(stderr); fflush(stderr);
Crash(formattedMessage.c_str()); Crash(formattedMessage.c_str());
} }
void Fatal(char const* file, int line, char const* function, char const* message, ...) void Fatal(char const* file, int line, char const* function, char const* message, ...)
{ {
va_list args; va_list args;
va_start(args, message); va_start(args, message);
std::string formattedMessage = acore::StringFormat("\n%s:%i in %s FATAL ERROR:\n", file, line, function) + FormatAssertionMessage(message, args) + '\n'; std::string formattedMessage = acore::StringFormat("\n%s:%i in %s FATAL ERROR:\n", file, line, function) + FormatAssertionMessage(message, args) + '\n';
va_end(args); va_end(args);
fprintf(stderr, "%s", formattedMessage.c_str()); fprintf(stderr, "%s", formattedMessage.c_str());
fflush(stderr); fflush(stderr);
std::this_thread::sleep_for(std::chrono::seconds(10)); std::this_thread::sleep_for(std::chrono::seconds(10));
Crash(formattedMessage.c_str()); Crash(formattedMessage.c_str());
} }
void Error(char const* file, int line, char const* function, char const* message) void Error(char const* file, int line, char const* function, char const* message)
{ {
std::string formattedMessage = acore::StringFormat("\n%s:%i in %s ERROR:\n %s\n", file, line, function, message); std::string formattedMessage = acore::StringFormat("\n%s:%i in %s ERROR:\n %s\n", file, line, function, message);
fprintf(stderr, "%s", formattedMessage.c_str()); fprintf(stderr, "%s", formattedMessage.c_str());
fflush(stderr); fflush(stderr);
Crash(formattedMessage.c_str()); Crash(formattedMessage.c_str());
} }
void Warning(char const* file, int line, char const* function, char const* message) void Warning(char const* file, int line, char const* function, char const* message)
{ {
fprintf(stderr, "\n%s:%i in %s WARNING:\n %s\n", fprintf(stderr, "\n%s:%i in %s WARNING:\n %s\n",
file, line, function, message); file, line, function, message);
} }
void Abort(char const* file, int line, char const* function) void Abort(char const* file, int line, char const* function)
{ {
std::string formattedMessage = acore::StringFormat("\n%s:%i in %s ABORTED.\n", file, line, function); std::string formattedMessage = acore::StringFormat("\n%s:%i in %s ABORTED.\n", file, line, function);
fprintf(stderr, "%s", formattedMessage.c_str()); fprintf(stderr, "%s", formattedMessage.c_str());
fflush(stderr); fflush(stderr);
Crash(formattedMessage.c_str()); Crash(formattedMessage.c_str());
} }
void AbortHandler(int sigval) void AbortHandler(int sigval)
{ {
// nothing useful to log here, no way to pass args // nothing useful to log here, no way to pass args
std::string formattedMessage = acore::StringFormat("Caught signal %i\n", sigval); std::string formattedMessage = acore::StringFormat("Caught signal %i\n", sigval);
fprintf(stderr, "%s", formattedMessage.c_str()); fprintf(stderr, "%s", formattedMessage.c_str());
fflush(stderr); fflush(stderr);
Crash(formattedMessage.c_str()); Crash(formattedMessage.c_str());
} }
} // namespace acore } // namespace acore

View File

@@ -33,13 +33,13 @@ inline LPTSTR ErrorMessage(DWORD dw)
{ {
LPVOID lpMsgBuf; LPVOID lpMsgBuf;
DWORD formatResult = FormatMessage( DWORD formatResult = FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM, FORMAT_MESSAGE_FROM_SYSTEM,
NULL, NULL,
dw, dw,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf, (LPTSTR) &lpMsgBuf,
0, NULL); 0, NULL);
if (formatResult != 0) if (formatResult != 0)
return (LPTSTR)lpMsgBuf; return (LPTSTR)lpMsgBuf;
else else
@@ -110,7 +110,7 @@ WheatyExceptionReport::~WheatyExceptionReport()
// Entry point where control comes on an unhandled exception // Entry point where control comes on an unhandled exception
//=========================================================== //===========================================================
LONG WINAPI WheatyExceptionReport::WheatyUnhandledExceptionFilter( LONG WINAPI WheatyExceptionReport::WheatyUnhandledExceptionFilter(
PEXCEPTION_POINTERS pExceptionInfo) PEXCEPTION_POINTERS pExceptionInfo)
{ {
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
@@ -141,26 +141,26 @@ PEXCEPTION_POINTERS pExceptionInfo)
SYSTEMTIME systime; SYSTEMTIME systime;
GetLocalTime(&systime); GetLocalTime(&systime);
sprintf(m_szDumpFileName, "%s\\%s_%s_[%u-%u_%u-%u-%u].dmp", sprintf(m_szDumpFileName, "%s\\%s_%s_[%u-%u_%u-%u-%u].dmp",
crash_folder_path, GitRevision::GetHash(), pos, systime.wDay, systime.wMonth, systime.wHour, systime.wMinute, systime.wSecond); crash_folder_path, GitRevision::GetHash(), pos, systime.wDay, systime.wMonth, systime.wHour, systime.wMinute, systime.wSecond);
sprintf(m_szLogFileName, "%s\\%s_%s_[%u-%u_%u-%u-%u].txt", sprintf(m_szLogFileName, "%s\\%s_%s_[%u-%u_%u-%u-%u].txt",
crash_folder_path, GitRevision::GetHash(), pos, systime.wDay, systime.wMonth, systime.wHour, systime.wMinute, systime.wSecond); crash_folder_path, GitRevision::GetHash(), pos, systime.wDay, systime.wMonth, systime.wHour, systime.wMinute, systime.wSecond);
m_hDumpFile = CreateFile(m_szDumpFileName, m_hDumpFile = CreateFile(m_szDumpFileName,
GENERIC_WRITE, GENERIC_WRITE,
0, 0,
0, 0,
OPEN_ALWAYS, OPEN_ALWAYS,
FILE_FLAG_WRITE_THROUGH, FILE_FLAG_WRITE_THROUGH,
0); 0);
m_hReportFile = CreateFile(m_szLogFileName, m_hReportFile = CreateFile(m_szLogFileName,
GENERIC_WRITE, GENERIC_WRITE,
0, 0,
0, 0,
OPEN_ALWAYS, OPEN_ALWAYS,
FILE_FLAG_WRITE_THROUGH, FILE_FLAG_WRITE_THROUGH,
0); 0);
if (m_hDumpFile) if (m_hDumpFile)
{ {
@@ -183,7 +183,7 @@ PEXCEPTION_POINTERS pExceptionInfo)
} }
MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(),
m_hDumpFile, MiniDumpWithIndirectlyReferencedMemory, &info, &additionalStreamInfo, 0); m_hDumpFile, MiniDumpWithIndirectlyReferencedMemory, &info, &additionalStreamInfo, 0);
CloseHandle(m_hDumpFile); CloseHandle(m_hDumpFile);
} }
@@ -217,13 +217,13 @@ BOOL WheatyExceptionReport::_GetProcessorName(TCHAR* sProcessorName, DWORD maxco
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"), NULL, NULL, lRet = ::RegQueryValueEx(hKey, _T("ProcessorNameString"), NULL, NULL,
(LPBYTE)szTmp, &cntBytes); (LPBYTE)szTmp, &cntBytes);
if (lRet != ERROR_SUCCESS) if (lRet != ERROR_SUCCESS)
return FALSE; return FALSE;
::RegCloseKey(hKey); ::RegCloseKey(hKey);
@@ -271,150 +271,150 @@ BOOL WheatyExceptionReport::_GetWindowsVersion(TCHAR* szVersion, DWORD cntMax)
{ {
// Windows NT product family. // Windows NT product family.
case VER_PLATFORM_WIN32_NT: case VER_PLATFORM_WIN32_NT:
{ {
#if WINVER < 0x0500 #if WINVER < 0x0500
BYTE suiteMask = osvi.wReserved[0]; BYTE suiteMask = osvi.wReserved[0];
BYTE productType = osvi.wReserved[1]; BYTE productType = osvi.wReserved[1];
#else #else
WORD suiteMask = osvi.wSuiteMask; WORD suiteMask = osvi.wSuiteMask;
BYTE productType = osvi.wProductType; BYTE productType = osvi.wProductType;
#endif // WINVER < 0x0500 #endif // WINVER < 0x0500
// Test for the specific product family. // Test for the specific product family.
if (osvi.dwMajorVersion == 10) if (osvi.dwMajorVersion == 10)
{
if (productType == VER_NT_WORKSTATION)
_tcsncat(szVersion, _T("Windows 10 "), cntMax);
else
_tcsncat(szVersion, _T("Windows Server 2016 "), cntMax);
}
else if (osvi.dwMajorVersion == 6)
{
if (productType == VER_NT_WORKSTATION)
{ {
if (osvi.dwMinorVersion == 3) if (productType == VER_NT_WORKSTATION)
_tcsncat(szVersion, _T("Windows 8.1 "), cntMax); _tcsncat(szVersion, _T("Windows 10 "), cntMax);
else
_tcsncat(szVersion, _T("Windows Server 2016 "), cntMax);
}
else if (osvi.dwMajorVersion == 6)
{
if (productType == VER_NT_WORKSTATION)
{
if (osvi.dwMinorVersion == 3)
_tcsncat(szVersion, _T("Windows 8.1 "), cntMax);
else if (osvi.dwMinorVersion == 2)
_tcsncat(szVersion, _T("Windows 8 "), cntMax);
else if (osvi.dwMinorVersion == 1)
_tcsncat(szVersion, _T("Windows 7 "), cntMax);
else
_tcsncat(szVersion, _T("Windows Vista "), cntMax);
}
else if (osvi.dwMinorVersion == 3)
_tcsncat(szVersion, _T("Windows Server 2012 R2 "), cntMax);
else if (osvi.dwMinorVersion == 2) else if (osvi.dwMinorVersion == 2)
_tcsncat(szVersion, _T("Windows 8 "), cntMax); _tcsncat(szVersion, _T("Windows Server 2012 "), cntMax);
else if (osvi.dwMinorVersion == 1) else if (osvi.dwMinorVersion == 1)
_tcsncat(szVersion, _T("Windows 7 "), cntMax); _tcsncat(szVersion, _T("Windows Server 2008 R2 "), cntMax);
else else
_tcsncat(szVersion, _T("Windows Vista "), cntMax); _tcsncat(szVersion, _T("Windows Server 2008 "), cntMax);
} }
else if (osvi.dwMinorVersion == 3) else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2)
_tcsncat(szVersion, _T("Windows Server 2012 R2 "), cntMax); _tcsncat(szVersion, _T("Microsoft Windows Server 2003 "), cntMax);
else if (osvi.dwMinorVersion == 2) else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1)
_tcsncat(szVersion, _T("Windows Server 2012 "), cntMax); _tcsncat(szVersion, _T("Microsoft Windows XP "), cntMax);
else if (osvi.dwMinorVersion == 1) else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0)
_tcsncat(szVersion, _T("Windows Server 2008 R2 "), cntMax); _tcsncat(szVersion, _T("Microsoft Windows 2000 "), cntMax);
else else if (osvi.dwMajorVersion <= 4)
_tcsncat(szVersion, _T("Windows Server 2008 "), cntMax); _tcsncat(szVersion, _T("Microsoft Windows NT "), cntMax);
}
else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2)
_tcsncat(szVersion, _T("Microsoft Windows Server 2003 "), cntMax);
else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1)
_tcsncat(szVersion, _T("Microsoft Windows XP "), cntMax);
else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0)
_tcsncat(szVersion, _T("Microsoft Windows 2000 "), cntMax);
else if (osvi.dwMajorVersion <= 4)
_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)
{
// Test for the workstation type.
if (productType == VER_NT_WORKSTATION)
{ {
if (osvi.dwMajorVersion == 4) // Test for the workstation type.
_tcsncat(szVersion, _T("Workstation 4.0 "), cntMax); if (productType == VER_NT_WORKSTATION)
else if (suiteMask & VER_SUITE_PERSONAL) {
_tcsncat(szVersion, _T("Home Edition "), cntMax); if (osvi.dwMajorVersion == 4)
else if (suiteMask & VER_SUITE_EMBEDDEDNT) _tcsncat(szVersion, _T("Workstation 4.0 "), cntMax);
_tcsncat(szVersion, _T("Embedded "), cntMax); else if (suiteMask & VER_SUITE_PERSONAL)
_tcsncat(szVersion, _T("Home Edition "), cntMax);
else if (suiteMask & VER_SUITE_EMBEDDEDNT)
_tcsncat(szVersion, _T("Embedded "), cntMax);
else
_tcsncat(szVersion, _T("Professional "), cntMax);
}
// Test for the server type.
else if (productType == VER_NT_SERVER)
{
if (osvi.dwMajorVersion == 6 || osvi.dwMajorVersion == 10)
{
if (suiteMask & VER_SUITE_SMALLBUSINESS_RESTRICTED)
_tcsncat(szVersion, _T("Essentials "), cntMax);
else if (suiteMask & VER_SUITE_DATACENTER)
_tcsncat(szVersion, _T("Datacenter "), cntMax);
else if (suiteMask & VER_SUITE_ENTERPRISE)
_tcsncat(szVersion, _T("Enterprise "), cntMax);
else
_tcsncat(szVersion, _T("Standard "), cntMax);
}
else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2)
{
if (suiteMask & VER_SUITE_DATACENTER)
_tcsncat(szVersion, _T("Datacenter Edition "), cntMax);
else if (suiteMask & VER_SUITE_ENTERPRISE)
_tcsncat(szVersion, _T("Enterprise Edition "), cntMax);
else if (suiteMask == VER_SUITE_BLADE)
_tcsncat(szVersion, _T("Web Edition "), cntMax);
else
_tcsncat(szVersion, _T("Standard Edition "), cntMax);
}
else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0)
{
if (suiteMask & VER_SUITE_DATACENTER)
_tcsncat(szVersion, _T("Datacenter Server "), cntMax);
else if (suiteMask & VER_SUITE_ENTERPRISE)
_tcsncat(szVersion, _T("Advanced Server "), cntMax);
else
_tcsncat(szVersion, _T("Server "), cntMax);
}
else // Windows NT 4.0
{
if (suiteMask & VER_SUITE_ENTERPRISE)
_tcsncat(szVersion, _T("Server 4.0, Enterprise Edition "), cntMax);
else
_tcsncat(szVersion, _T("Server 4.0 "), cntMax);
}
}
}
// Display service pack (if any) and build number.
if (osvi.dwMajorVersion == 4 && _tcsicmp(szCSDVersion, _T("Service Pack 6")) == 0)
{
HKEY hKey;
LONG lRet;
// Test for SP6 versus SP6a.
lRet = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Hotfix\\Q246009"), 0, KEY_QUERY_VALUE, &hKey);
if (lRet == ERROR_SUCCESS)
{
_stprintf(wszTmp, _T("Service Pack 6a (Version %d.%d, Build %d)"),
osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber & 0xFFFF);
_tcsncat(szVersion, wszTmp, cntMax);
}
else // Windows NT 4.0 prior to SP6a
{
_stprintf(wszTmp, _T("%s (Version %d.%d, Build %d)"),
szCSDVersion, osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber & 0xFFFF);
_tcsncat(szVersion, wszTmp, cntMax);
}
::RegCloseKey(hKey);
}
else // Windows NT 3.51 and earlier or Windows 2000 and later
{
if (!_tcslen(szCSDVersion))
_stprintf(wszTmp, _T("(Version %d.%d, Build %d)"),
osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber & 0xFFFF);
else else
_tcsncat(szVersion, _T("Professional "), cntMax); _stprintf(wszTmp, _T("%s (Version %d.%d, Build %d)"),
} szCSDVersion, osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber & 0xFFFF);
// Test for the server type.
else if (productType == VER_NT_SERVER)
{
if (osvi.dwMajorVersion == 6 || osvi.dwMajorVersion == 10)
{
if (suiteMask & VER_SUITE_SMALLBUSINESS_RESTRICTED)
_tcsncat(szVersion, _T("Essentials "), cntMax);
else if (suiteMask & VER_SUITE_DATACENTER)
_tcsncat(szVersion, _T("Datacenter "), cntMax);
else if (suiteMask & VER_SUITE_ENTERPRISE)
_tcsncat(szVersion, _T("Enterprise "), cntMax);
else
_tcsncat(szVersion, _T("Standard "), cntMax);
}
else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2)
{
if (suiteMask & VER_SUITE_DATACENTER)
_tcsncat(szVersion, _T("Datacenter Edition "), cntMax);
else if (suiteMask & VER_SUITE_ENTERPRISE)
_tcsncat(szVersion, _T("Enterprise Edition "), cntMax);
else if (suiteMask == VER_SUITE_BLADE)
_tcsncat(szVersion, _T("Web Edition "), cntMax);
else
_tcsncat(szVersion, _T("Standard Edition "), cntMax);
}
else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0)
{
if (suiteMask & VER_SUITE_DATACENTER)
_tcsncat(szVersion, _T("Datacenter Server "), cntMax);
else if (suiteMask & VER_SUITE_ENTERPRISE)
_tcsncat(szVersion, _T("Advanced Server "), cntMax);
else
_tcsncat(szVersion, _T("Server "), cntMax);
}
else // Windows NT 4.0
{
if (suiteMask & VER_SUITE_ENTERPRISE)
_tcsncat(szVersion, _T("Server 4.0, Enterprise Edition "), cntMax);
else
_tcsncat(szVersion, _T("Server 4.0 "), cntMax);
}
}
}
// Display service pack (if any) and build number.
if (osvi.dwMajorVersion == 4 && _tcsicmp(szCSDVersion, _T("Service Pack 6")) == 0)
{
HKEY hKey;
LONG lRet;
// Test for SP6 versus SP6a.
lRet = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Hotfix\\Q246009"), 0, KEY_QUERY_VALUE, &hKey);
if (lRet == ERROR_SUCCESS)
{
_stprintf(wszTmp, _T("Service Pack 6a (Version %d.%d, Build %d)"),
osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber & 0xFFFF);
_tcsncat(szVersion, wszTmp, cntMax); _tcsncat(szVersion, wszTmp, cntMax);
} }
else // Windows NT 4.0 prior to SP6a break;
{
_stprintf(wszTmp, _T("%s (Version %d.%d, Build %d)"),
szCSDVersion, osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber & 0xFFFF);
_tcsncat(szVersion, wszTmp, cntMax);
}
::RegCloseKey(hKey);
} }
else // Windows NT 3.51 and earlier or Windows 2000 and later
{
if (!_tcslen(szCSDVersion))
_stprintf(wszTmp, _T("(Version %d.%d, Build %d)"),
osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber & 0xFFFF);
else
_stprintf(wszTmp, _T("%s (Version %d.%d, Build %d)"),
szCSDVersion, osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber & 0xFFFF);
_tcsncat(szVersion, wszTmp, cntMax);
}
break;
}
default: default:
_stprintf(wszTmp, _T("%s (Version %d.%d, Build %d)"), _stprintf(wszTmp, _T("%s (Version %d.%d, Build %d)"),
szCSDVersion, osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber & 0xFFFF); szCSDVersion, osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber & 0xFFFF);
_tcsncat(szVersion, wszTmp, cntMax); _tcsncat(szVersion, wszTmp, cntMax);
break; break;
} }
@@ -434,10 +434,10 @@ void WheatyExceptionReport::PrintSystemInfo()
Log(_T("//=====================================================\r\n")); Log(_T("//=====================================================\r\n"));
if (_GetProcessorName(sString, countof(sString))) if (_GetProcessorName(sString, countof(sString)))
Log(_T("*** Hardware ***\r\nProcessor: %s\r\nNumber Of Processors: %d\r\nPhysical Memory: %d KB (Available: %d KB)\r\nCommit Charge Limit: %d KB\r\n"), Log(_T("*** Hardware ***\r\nProcessor: %s\r\nNumber Of Processors: %d\r\nPhysical Memory: %d KB (Available: %d KB)\r\nCommit Charge Limit: %d KB\r\n"),
sString, SystemInfo.dwNumberOfProcessors, MemoryStatus.dwTotalPhys/0x400, MemoryStatus.dwAvailPhys/0x400, MemoryStatus.dwTotalPageFile/0x400); sString, SystemInfo.dwNumberOfProcessors, MemoryStatus.dwTotalPhys / 0x400, MemoryStatus.dwAvailPhys / 0x400, MemoryStatus.dwTotalPageFile / 0x400);
else else
Log(_T("*** Hardware ***\r\nProcessor: <unknown>\r\nNumber Of Processors: %d\r\nPhysical Memory: %d KB (Available: %d KB)\r\nCommit Charge Limit: %d KB\r\n"), Log(_T("*** Hardware ***\r\nProcessor: <unknown>\r\nNumber Of Processors: %d\r\nPhysical Memory: %d KB (Available: %d KB)\r\nCommit Charge Limit: %d KB\r\n"),
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);
@@ -448,48 +448,48 @@ void WheatyExceptionReport::PrintSystemInfo()
//=========================================================================== //===========================================================================
void WheatyExceptionReport::printTracesForAllThreads(bool bWriteVariables) void WheatyExceptionReport::printTracesForAllThreads(bool bWriteVariables)
{ {
THREADENTRY32 te32; THREADENTRY32 te32;
DWORD dwOwnerPID = GetCurrentProcessId(); DWORD dwOwnerPID = GetCurrentProcessId();
m_hProcess = GetCurrentProcess(); m_hProcess = GetCurrentProcess();
// 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);
// Retrieve information about the first thread, // Retrieve information about the first thread,
// and exit if unsuccessful // and exit if unsuccessful
if (!Thread32First(hThreadSnap, &te32)) if (!Thread32First(hThreadSnap, &te32))
{
CloseHandle(hThreadSnap); // Must clean up the
// snapshot object!
return;
}
// Now walk the thread list of the system,
// and display information about each thread
// associated with the specified process
do
{
if (te32.th32OwnerProcessID == dwOwnerPID)
{ {
CONTEXT context; CloseHandle(hThreadSnap); // Must clean up the
context.ContextFlags = 0xffffffff; // snapshot object!
HANDLE threadHandle = OpenThread(THREAD_GET_CONTEXT | THREAD_QUERY_INFORMATION, false, te32.th32ThreadID); return;
if (threadHandle)
{
if (GetThreadContext(threadHandle, &context))
WriteStackDetails(&context, bWriteVariables, threadHandle);
CloseHandle(threadHandle);
}
} }
} while (Thread32Next(hThreadSnap, &te32));
// Don't forget to clean up the snapshot object. // Now walk the thread list of the system,
CloseHandle(hThreadSnap); // and display information about each thread
// associated with the specified process
do
{
if (te32.th32OwnerProcessID == dwOwnerPID)
{
CONTEXT context;
context.ContextFlags = 0xffffffff;
HANDLE threadHandle = OpenThread(THREAD_GET_CONTEXT | THREAD_QUERY_INFORMATION, false, te32.th32ThreadID);
if (threadHandle)
{
if (GetThreadContext(threadHandle, &context))
WriteStackDetails(&context, bWriteVariables, threadHandle);
CloseHandle(threadHandle);
}
}
} while (Thread32Next(hThreadSnap, &te32));
// Don't forget to clean up the snapshot object.
CloseHandle(hThreadSnap);
} }
//=========================================================================== //===========================================================================
@@ -497,7 +497,7 @@ void WheatyExceptionReport::printTracesForAllThreads(bool bWriteVariables)
// WheatyUnhandledExceptionFilter // WheatyUnhandledExceptionFilter
//=========================================================================== //===========================================================================
void WheatyExceptionReport::GenerateExceptionReport( void WheatyExceptionReport::GenerateExceptionReport(
PEXCEPTION_POINTERS pExceptionInfo) PEXCEPTION_POINTERS pExceptionInfo)
{ {
__try __try
{ {
@@ -526,9 +526,9 @@ PEXCEPTION_POINTERS pExceptionInfo)
DWORD section; DWORD section;
DWORD_PTR offset; DWORD_PTR offset;
GetLogicalAddress(pExceptionRecord->ExceptionAddress, GetLogicalAddress(pExceptionRecord->ExceptionAddress,
szFaultingModule, szFaultingModule,
sizeof(szFaultingModule), sizeof(szFaultingModule),
section, offset); section, offset);
#ifdef _M_IX86 #ifdef _M_IX86
Log(_T("Fault address: %08X %02X:%08X %s\r\n"), Log(_T("Fault address: %08X %02X:%08X %s\r\n"),
@@ -612,11 +612,11 @@ PEXCEPTION_POINTERS pExceptionInfo)
//====================================================================== //======================================================================
LPTSTR WheatyExceptionReport::GetExceptionString(DWORD dwCode) LPTSTR WheatyExceptionReport::GetExceptionString(DWORD dwCode)
{ {
#define EXCEPTION(x) case EXCEPTION_##x: return _T(#x); #define EXCEPTION(x) case EXCEPTION_##x: return _T(#x);
switch (dwCode) switch (dwCode)
{ {
EXCEPTION(ACCESS_VIOLATION) EXCEPTION(ACCESS_VIOLATION)
EXCEPTION(DATATYPE_MISALIGNMENT) EXCEPTION(DATATYPE_MISALIGNMENT)
EXCEPTION(BREAKPOINT) EXCEPTION(BREAKPOINT)
EXCEPTION(SINGLE_STEP) EXCEPTION(SINGLE_STEP)
@@ -646,8 +646,8 @@ LPTSTR WheatyExceptionReport::GetExceptionString(DWORD dwCode)
static TCHAR szBuffer[512] = { 0 }; static TCHAR szBuffer[512] = { 0 };
FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_HMODULE, FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_HMODULE,
GetModuleHandle(_T("NTDLL.DLL")), GetModuleHandle(_T("NTDLL.DLL")),
dwCode, 0, szBuffer, sizeof(szBuffer), 0); dwCode, 0, szBuffer, sizeof(szBuffer), 0);
return szBuffer; return szBuffer;
} }
@@ -660,7 +660,7 @@ LPTSTR WheatyExceptionReport::GetExceptionString(DWORD dwCode)
// by the len parameter (in characters!) // by the len parameter (in characters!)
//============================================================================= //=============================================================================
BOOL WheatyExceptionReport::GetLogicalAddress( BOOL WheatyExceptionReport::GetLogicalAddress(
PVOID addr, PTSTR szModule, DWORD len, DWORD& section, DWORD_PTR& offset) PVOID addr, PTSTR szModule, DWORD len, DWORD& section, DWORD_PTR& offset)
{ {
MEMORY_BASIC_INFORMATION mbi; MEMORY_BASIC_INFORMATION mbi;
@@ -688,12 +688,12 @@ PVOID addr, PTSTR szModule, DWORD len, DWORD& section, DWORD_PTR& offset)
// Iterate through the section table, looking for the one that encompasses // Iterate through the section table, looking for the one that encompasses
// the linear address. // the linear address.
for (unsigned i = 0; for (unsigned i = 0;
i < pNtHdr->FileHeader.NumberOfSections; i < pNtHdr->FileHeader.NumberOfSections;
i++, pSection++) i++, pSection++)
{ {
DWORD_PTR sectionStart = pSection->VirtualAddress; DWORD_PTR sectionStart = pSection->VirtualAddress;
DWORD_PTR sectionEnd = sectionStart DWORD_PTR sectionEnd = sectionStart
+ DWORD_PTR(std::max(pSection->SizeOfRawData, pSection->Misc.VirtualSize)); + DWORD_PTR(std::max(pSection->SizeOfRawData, pSection->Misc.VirtualSize));
// Is the address in this section??? // Is the address in this section???
if ((rva >= sectionStart) && (rva <= sectionEnd)) if ((rva >= sectionStart) && (rva <= sectionEnd))
@@ -701,7 +701,7 @@ PVOID addr, PTSTR szModule, DWORD len, DWORD& section, DWORD_PTR& offset)
// Yes, address is in the section. Calculate section and offset, // Yes, address is in the section. Calculate section and offset,
// and store in the "section" & "offset" params, which were // and store in the "section" & "offset" params, which were
// passed by reference. // passed by reference.
section = i+1; section = i + 1;
offset = rva - sectionStart; offset = rva - sectionStart;
return TRUE; return TRUE;
} }
@@ -725,8 +725,8 @@ struct CSymbolInfoPackage : public SYMBOL_INFO_PACKAGE
// Walks the stack, and writes the results to the report file // Walks the stack, and writes the results to the report file
//============================================================ //============================================================
void WheatyExceptionReport::WriteStackDetails( void WheatyExceptionReport::WriteStackDetails(
PCONTEXT pContext, PCONTEXT pContext,
bool bWriteVariables, HANDLE pThreadHandle) // true if local/params should be output bool bWriteVariables, HANDLE pThreadHandle) // true if local/params should be output
{ {
Log(_T("\r\nCall stack:\r\n")); Log(_T("\r\nCall stack:\r\n"));
@@ -738,7 +738,7 @@ bool bWriteVariables, HANDLE pThreadHandle)
STACKFRAME64 sf; STACKFRAME64 sf;
memset(&sf, 0, sizeof(sf)); memset(&sf, 0, sizeof(sf));
#ifdef _M_IX86 #ifdef _M_IX86
// Initialize the STACKFRAME structure for the first call. This is only // Initialize the STACKFRAME structure for the first call. This is only
// necessary for Intel CPUs, and isn't mentioned in the documentation. // necessary for Intel CPUs, and isn't mentioned in the documentation.
sf.AddrPC.Offset = pContext->Eip; sf.AddrPC.Offset = pContext->Eip;
@@ -749,7 +749,7 @@ bool bWriteVariables, HANDLE pThreadHandle)
sf.AddrFrame.Mode = AddrModeFlat; sf.AddrFrame.Mode = AddrModeFlat;
dwMachineType = IMAGE_FILE_MACHINE_I386; dwMachineType = IMAGE_FILE_MACHINE_I386;
#endif #endif
#ifdef _M_X64 #ifdef _M_X64
sf.AddrPC.Offset = pContext->Rip; sf.AddrPC.Offset = pContext->Rip;
@@ -765,14 +765,14 @@ bool bWriteVariables, HANDLE pThreadHandle)
{ {
// Get the next stack frame // Get the next stack frame
if (! StackWalk64(dwMachineType, if (! StackWalk64(dwMachineType,
m_hProcess, m_hProcess,
pThreadHandle != NULL ? pThreadHandle : GetCurrentThread(), pThreadHandle != NULL ? pThreadHandle : GetCurrentThread(),
&sf, &sf,
pContext, pContext,
0, 0,
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.
@@ -789,10 +789,10 @@ bool bWriteVariables, HANDLE pThreadHandle)
// Get the name of the function for this stack frame entry // Get the name of the function for this stack frame entry
CSymbolInfoPackage sip; CSymbolInfoPackage sip;
if (SymFromAddr( if (SymFromAddr(
m_hProcess, // Process handle of the current process m_hProcess, // Process handle of the current process
sf.AddrPC.Offset, // Symbol address sf.AddrPC.Offset, // Symbol address
&symDisplacement, // Address of the variable that will receive the displacement &symDisplacement, // Address of the variable that will receive the displacement
&sip.si)) // Address of the SYMBOL_INFO structure (inside "sip" object) &sip.si)) // Address of the SYMBOL_INFO structure (inside "sip" object)
{ {
Log(_T("%hs+%I64X"), sip.si.Name, symDisplacement); Log(_T("%hs+%I64X"), sip.si.Name, symDisplacement);
@@ -804,7 +804,7 @@ bool bWriteVariables, HANDLE pThreadHandle)
DWORD_PTR offset = 0; DWORD_PTR offset = 0;
GetLogicalAddress((PVOID)sf.AddrPC.Offset, GetLogicalAddress((PVOID)sf.AddrPC.Offset,
szModule, sizeof(szModule), section, offset); szModule, sizeof(szModule), section, offset);
#ifdef _M_IX86 #ifdef _M_IX86
Log(_T("%04X:%08X %s"), section, offset, szModule); Log(_T("%04X:%08X %s"), section, offset, szModule);
#endif #endif
@@ -817,7 +817,7 @@ bool bWriteVariables, HANDLE pThreadHandle)
IMAGEHLP_LINE64 lineInfo = { sizeof(IMAGEHLP_LINE64) }; IMAGEHLP_LINE64 lineInfo = { sizeof(IMAGEHLP_LINE64) };
DWORD dwLineDisplacement; DWORD dwLineDisplacement;
if (SymGetLineFromAddr64(m_hProcess, sf.AddrPC.Offset, if (SymGetLineFromAddr64(m_hProcess, sf.AddrPC.Offset,
&dwLineDisplacement, &lineInfo)) &dwLineDisplacement, &lineInfo))
{ {
Log(_T(" %s line %u"), lineInfo.FileName, lineInfo.LineNumber); Log(_T(" %s line %u"), lineInfo.FileName, lineInfo.LineNumber);
} }
@@ -847,9 +847,9 @@ bool bWriteVariables, HANDLE pThreadHandle)
BOOL CALLBACK BOOL CALLBACK
WheatyExceptionReport::EnumerateSymbolsCallback( WheatyExceptionReport::EnumerateSymbolsCallback(
PSYMBOL_INFO pSymInfo, PSYMBOL_INFO pSymInfo,
ULONG /*SymbolSize*/, ULONG /*SymbolSize*/,
PVOID UserContext) PVOID UserContext)
{ {
__try __try
{ {
@@ -871,8 +871,8 @@ PVOID UserContext)
// values. // values.
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
bool WheatyExceptionReport::FormatSymbolValue( bool WheatyExceptionReport::FormatSymbolValue(
PSYMBOL_INFO pSym, PSYMBOL_INFO pSym,
STACKFRAME64 * sf) STACKFRAME64* sf)
{ {
// 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
@@ -883,7 +883,8 @@ STACKFRAME64 * sf)
if (pSym->Flags & IMAGEHLP_SYMBOL_INFO_REGRELATIVE) if (pSym->Flags & IMAGEHLP_SYMBOL_INFO_REGRELATIVE)
{ {
// if (pSym->Register == 8) // EBP is the value 8 (in DBGHELP 5.1) // if (pSym->Register == 8) // EBP is the value 8 (in DBGHELP 5.1)
{ // This may change!!! {
// This may change!!!
#ifdef _M_IX86 #ifdef _M_IX86
pVariable = sf->AddrFrame.Offset; pVariable = sf->AddrFrame.Offset;
#elif _M_X64 #elif _M_X64
@@ -942,14 +943,14 @@ STACKFRAME64 * sf)
// bHandled = false, so that FormatSymbolValue() will format them. // bHandled = false, so that FormatSymbolValue() will format them.
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
void WheatyExceptionReport::DumpTypeIndex( void WheatyExceptionReport::DumpTypeIndex(
DWORD64 modBase, DWORD64 modBase,
DWORD dwTypeIndex, DWORD dwTypeIndex,
DWORD_PTR offset, DWORD_PTR offset,
bool & bHandled, bool& bHandled,
char const* Name, char const* Name,
char* /*suffix*/, char* /*suffix*/,
bool newSymbol, bool newSymbol,
bool logChildren) bool logChildren)
{ {
bHandled = false; bHandled = false;
@@ -962,9 +963,9 @@ bool logChildren)
// 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.
WCHAR * pwszTypeName; WCHAR* pwszTypeName;
if (SymGetTypeInfo(m_hProcess, modBase, dwTypeIndex, TI_GET_SYMNAME, if (SymGetTypeInfo(m_hProcess, modBase, dwTypeIndex, TI_GET_SYMNAME,
&pwszTypeName)) &pwszTypeName))
{ {
// handle special cases // handle special cases
if (wcscmp(pwszTypeName, L"std::basic_string<char,std::char_traits<char>,std::allocator<char> >") == 0) if (wcscmp(pwszTypeName, L"std::basic_string<char,std::char_traits<char>,std::allocator<char> >") == 0)
@@ -1085,17 +1086,17 @@ bool logChildren)
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 != NULL && Name[0] != '\0') if (Name != NULL && 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;
case SymTagArrayType: case SymTagArrayType:
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;
default: default:
break; break;
@@ -1109,7 +1110,7 @@ bool logChildren)
BasicType basicType = btNoType; BasicType basicType = btNoType;
DumpTypeIndex(modBase, innerTypeID, DumpTypeIndex(modBase, innerTypeID,
offset, bHandled, Name, "", false, false); offset, bHandled, Name, "", false, false);
// Set Value back to an empty string since the Array object itself has no value, only its elements have // Set Value back to an empty string since the Array object itself has no value, only its elements have
std::string firstElementValue = symbolDetails.top().Value; std::string firstElementValue = symbolDetails.top().Value;
@@ -1196,16 +1197,16 @@ bool logChildren)
// TI_FINDCHILDREN_PARAMS struct has. Use derivation to accomplish this. // TI_FINDCHILDREN_PARAMS struct has. Use derivation to accomplish this.
struct FINDCHILDREN : TI_FINDCHILDREN_PARAMS struct FINDCHILDREN : TI_FINDCHILDREN_PARAMS
{ {
ULONG MoreChildIds[1024*2]; ULONG MoreChildIds[1024 * 2];
FINDCHILDREN(){Count = sizeof(MoreChildIds) / sizeof(MoreChildIds[0]);} FINDCHILDREN() {Count = sizeof(MoreChildIds) / sizeof(MoreChildIds[0]);}
} children; } children;
children.Count = dwChildrenCount; children.Count = dwChildrenCount;
children.Start= 0; children.Start = 0;
// Get the array of TypeIds, one for each child type // Get the array of TypeIds, one for each child type
if (!SymGetTypeInfo(m_hProcess, modBase, dwTypeIndex, TI_FINDCHILDREN, if (!SymGetTypeInfo(m_hProcess, modBase, dwTypeIndex, TI_FINDCHILDREN,
&children)) &children))
{ {
return; return;
} }
@@ -1217,17 +1218,17 @@ bool logChildren)
SymGetTypeInfo(m_hProcess, modBase, children.ChildId[i], TI_GET_SYMTAG, &symTag); SymGetTypeInfo(m_hProcess, modBase, children.ChildId[i], TI_GET_SYMTAG, &symTag);
if (symTag == SymTagFunction || if (symTag == SymTagFunction ||
symTag == SymTagEnum || symTag == SymTagEnum ||
symTag == SymTagTypedef || symTag == SymTagTypedef ||
symTag == SymTagVTable) symTag == SymTagVTable)
continue; continue;
// Ignore static fields // Ignore static fields
DWORD dataKind; DWORD dataKind;
SymGetTypeInfo(m_hProcess, modBase, children.ChildId[i], TI_GET_DATAKIND, &dataKind); SymGetTypeInfo(m_hProcess, modBase, children.ChildId[i], TI_GET_DATAKIND, &dataKind);
if (dataKind == DataIsStaticLocal || if (dataKind == DataIsStaticLocal ||
dataKind == DataIsGlobal || dataKind == DataIsGlobal ||
dataKind == DataIsStaticMember) dataKind == DataIsStaticMember)
continue; continue;
@@ -1245,14 +1246,14 @@ bool logChildren)
// Get the offset of the child member, relative to its parent // Get the offset of the child member, relative to its parent
DWORD dwMemberOffset; DWORD dwMemberOffset;
SymGetTypeInfo(m_hProcess, modBase, children.ChildId[i], SymGetTypeInfo(m_hProcess, modBase, children.ChildId[i],
TI_GET_OFFSET, &dwMemberOffset); TI_GET_OFFSET, &dwMemberOffset);
// Calculate the address of the member // Calculate the address of the member
DWORD_PTR dwFinalOffset = offset + dwMemberOffset; DWORD_PTR dwFinalOffset = offset + dwMemberOffset;
DumpTypeIndex(modBase, DumpTypeIndex(modBase,
children.ChildId[i], children.ChildId[i],
dwFinalOffset, bHandled2, ""/*Name */, "", true, true); dwFinalOffset, bHandled2, ""/*Name */, "", true, true);
// If the child wasn't a UDT, format it appropriately // If the child wasn't a UDT, format it appropriately
if (!bHandled2) if (!bHandled2)
@@ -1264,7 +1265,7 @@ bool logChildren)
// SymGetTypeInfo(TI_GET_TYPEID) call below. // SymGetTypeInfo(TI_GET_TYPEID) call below.
DWORD typeId; DWORD typeId;
SymGetTypeInfo(m_hProcess, modBase, children.ChildId[i], SymGetTypeInfo(m_hProcess, modBase, children.ChildId[i],
TI_GET_TYPEID, &typeId); TI_GET_TYPEID, &typeId);
// Get the size of the child member // Get the size of the child member
ULONG64 length; ULONG64 length;
@@ -1282,39 +1283,39 @@ bool logChildren)
return; return;
} }
void WheatyExceptionReport::FormatOutputValue(char * pszCurrBuffer, void WheatyExceptionReport::FormatOutputValue(char* pszCurrBuffer,
BasicType basicType, BasicType basicType,
DWORD64 length, DWORD64 length,
PVOID pAddress, PVOID pAddress,
size_t bufferSize, size_t bufferSize,
size_t countOverride) size_t countOverride)
{ {
__try __try
{ {
switch (basicType) switch (basicType)
{ {
case btChar: case btChar:
{ {
// 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)
@@ -1333,19 +1334,19 @@ size_t countOverride)
if (basicType == btFloat) if (basicType == btFloat)
{ {
pszCurrBuffer += sprintf(pszCurrBuffer, "%f", pszCurrBuffer += sprintf(pszCurrBuffer, "%f",
*(double *)pAddress); *(double*)pAddress);
} }
else else
pszCurrBuffer += sprintf(pszCurrBuffer, "0x%I64X", pszCurrBuffer += sprintf(pszCurrBuffer, "0x%I64X",
*(DWORD64*)pAddress); *(DWORD64*)pAddress);
} }
else else
{ {
#if _WIN64 #if _WIN64
pszCurrBuffer += sprintf(pszCurrBuffer, "0x%I64X", (DWORD64)pAddress); pszCurrBuffer += sprintf(pszCurrBuffer, "0x%I64X", (DWORD64)pAddress);
#else #else
pszCurrBuffer += sprintf(pszCurrBuffer, "0x%X", (DWORD)pAddress); pszCurrBuffer += sprintf(pszCurrBuffer, "0x%X", (DWORD)pAddress);
#endif #endif
} }
break; break;
} }
@@ -1365,7 +1366,7 @@ WheatyExceptionReport::GetBasicType(DWORD typeIndex, DWORD64 modBase)
{ {
BasicType basicType; BasicType basicType;
if (SymGetTypeInfo(m_hProcess, modBase, typeIndex, if (SymGetTypeInfo(m_hProcess, modBase, typeIndex,
TI_GET_BASETYPE, &basicType)) TI_GET_BASETYPE, &basicType))
{ {
return basicType; return basicType;
} }
@@ -1376,7 +1377,7 @@ WheatyExceptionReport::GetBasicType(DWORD typeIndex, DWORD64 modBase)
if (SymGetTypeInfo(m_hProcess, modBase, typeIndex, TI_GET_TYPEID, &typeId)) if (SymGetTypeInfo(m_hProcess, modBase, typeIndex, TI_GET_TYPEID, &typeId))
{ {
if (SymGetTypeInfo(m_hProcess, modBase, typeId, TI_GET_BASETYPE, if (SymGetTypeInfo(m_hProcess, modBase, typeId, TI_GET_BASETYPE,
&basicType)) &basicType))
{ {
return basicType; return basicType;
} }
@@ -1401,12 +1402,12 @@ DWORD_PTR WheatyExceptionReport::DereferenceUnsafePointer(DWORD_PTR address)
// Helper function that writes to the report file, and allows the user to use // Helper function that writes to the report file, and allows the user to use
// printf style formating // printf style formating
//============================================================================ //============================================================================
int __cdecl WheatyExceptionReport::Log(const TCHAR * format, ...) int __cdecl WheatyExceptionReport::Log(const TCHAR* format, ...)
{ {
int retValue; int retValue;
va_list argptr; va_list argptr;
va_start(argptr, format); va_start(argptr, format);
if (stackOverflowException) if (stackOverflowException)
retValue = HeapLog(format, argptr); retValue = HeapLog(format, argptr);
else else
@@ -1417,7 +1418,7 @@ int __cdecl WheatyExceptionReport::Log(const TCHAR * format, ...)
return retValue; return retValue;
} }
int __cdecl WheatyExceptionReport::StackLog(const TCHAR * format, va_list argptr) int __cdecl WheatyExceptionReport::StackLog(const TCHAR* format, va_list argptr)
{ {
int retValue; int retValue;
DWORD cbWritten; DWORD cbWritten;
@@ -1429,7 +1430,7 @@ int __cdecl WheatyExceptionReport::StackLog(const TCHAR * format, va_list argptr
return retValue; return retValue;
} }
int __cdecl WheatyExceptionReport::HeapLog(const TCHAR * format, va_list argptr) int __cdecl WheatyExceptionReport::HeapLog(const TCHAR* format, va_list argptr)
{ {
int retValue = 0; int retValue = 0;
DWORD cbWritten; DWORD cbWritten;

View File

@@ -103,7 +103,7 @@ struct SymbolPair
bool operator<(SymbolPair const& other) const bool operator<(SymbolPair const& other) const
{ {
return _offset < other._offset || return _offset < other._offset ||
(_offset == other._offset && _type < other._type); (_offset == other._offset && _type < other._type);
} }
DWORD _type; DWORD _type;
@@ -133,69 +133,69 @@ struct SymbolDetail
class WheatyExceptionReport class WheatyExceptionReport
{ {
public: public:
WheatyExceptionReport(); WheatyExceptionReport();
~WheatyExceptionReport(); ~WheatyExceptionReport();
// entry point where control comes on an unhandled exception // entry point where control comes on an unhandled exception
static LONG WINAPI WheatyUnhandledExceptionFilter( static LONG WINAPI WheatyUnhandledExceptionFilter(
PEXCEPTION_POINTERS pExceptionInfo); PEXCEPTION_POINTERS pExceptionInfo);
static void __cdecl WheatyCrtHandler(wchar_t const* expression, wchar_t const* function, wchar_t const* file, unsigned int line, uintptr_t pReserved); static void __cdecl WheatyCrtHandler(wchar_t const* expression, wchar_t const* function, wchar_t const* file, unsigned int line, uintptr_t pReserved);
static void printTracesForAllThreads(bool); static void printTracesForAllThreads(bool);
private: private:
// where report info is extracted and generated // where report info is extracted and generated
static void GenerateExceptionReport(PEXCEPTION_POINTERS pExceptionInfo); static void GenerateExceptionReport(PEXCEPTION_POINTERS pExceptionInfo);
static void PrintSystemInfo(); static void PrintSystemInfo();
static BOOL _GetWindowsVersion(TCHAR* szVersion, DWORD cntMax); static BOOL _GetWindowsVersion(TCHAR* szVersion, DWORD cntMax);
static BOOL _GetProcessorName(TCHAR* sProcessorName, DWORD maxcount); static BOOL _GetProcessorName(TCHAR* sProcessorName, DWORD maxcount);
// Helper functions // Helper functions
static LPTSTR GetExceptionString(DWORD dwCode); static LPTSTR GetExceptionString(DWORD dwCode);
static BOOL GetLogicalAddress(PVOID addr, PTSTR szModule, DWORD len, static BOOL GetLogicalAddress(PVOID addr, PTSTR szModule, DWORD len,
DWORD& section, DWORD_PTR& offset); DWORD& section, DWORD_PTR& offset);
static void WriteStackDetails(PCONTEXT pContext, bool bWriteVariables, HANDLE pThreadHandle); static void WriteStackDetails(PCONTEXT pContext, bool bWriteVariables, HANDLE pThreadHandle);
static BOOL CALLBACK EnumerateSymbolsCallback(PSYMBOL_INFO, ULONG, PVOID); static BOOL CALLBACK EnumerateSymbolsCallback(PSYMBOL_INFO, ULONG, PVOID);
static bool FormatSymbolValue(PSYMBOL_INFO, STACKFRAME64 *); static bool FormatSymbolValue(PSYMBOL_INFO, STACKFRAME64*);
static void DumpTypeIndex(DWORD64, DWORD, DWORD_PTR, bool &, char const*, char*, bool, bool); static void DumpTypeIndex(DWORD64, DWORD, DWORD_PTR, bool&, char const*, char*, bool, bool);
static void FormatOutputValue(char * pszCurrBuffer, BasicType basicType, DWORD64 length, PVOID pAddress, size_t bufferSize, size_t countOverride = 0); static void FormatOutputValue(char* pszCurrBuffer, BasicType basicType, DWORD64 length, PVOID pAddress, size_t bufferSize, size_t countOverride = 0);
static BasicType GetBasicType(DWORD typeIndex, DWORD64 modBase); static BasicType GetBasicType(DWORD typeIndex, DWORD64 modBase);
static DWORD_PTR DereferenceUnsafePointer(DWORD_PTR address); static DWORD_PTR DereferenceUnsafePointer(DWORD_PTR address);
static int __cdecl Log(const TCHAR * format, ...); static int __cdecl Log(const TCHAR* format, ...);
static int __cdecl StackLog(const TCHAR * format, va_list argptr); static int __cdecl StackLog(const TCHAR* format, va_list argptr);
static int __cdecl HeapLog(const TCHAR * format, va_list argptr); static int __cdecl HeapLog(const TCHAR* format, va_list argptr);
static bool StoreSymbol(DWORD type , DWORD_PTR offset); static bool StoreSymbol(DWORD type, DWORD_PTR offset);
static void ClearSymbols(); static void ClearSymbols();
// Variables used by the class // Variables used by the class
static TCHAR m_szLogFileName[MAX_PATH]; static TCHAR m_szLogFileName[MAX_PATH];
static TCHAR m_szDumpFileName[MAX_PATH]; static TCHAR m_szDumpFileName[MAX_PATH];
static LPTOP_LEVEL_EXCEPTION_FILTER m_previousFilter; static LPTOP_LEVEL_EXCEPTION_FILTER m_previousFilter;
static _invalid_parameter_handler m_previousCrtHandler; static _invalid_parameter_handler m_previousCrtHandler;
static HANDLE m_hReportFile; static HANDLE m_hReportFile;
static HANDLE m_hDumpFile; static HANDLE m_hDumpFile;
static HANDLE m_hProcess; static HANDLE m_hProcess;
static SymbolPairs symbols; static SymbolPairs symbols;
static std::stack<SymbolDetail> symbolDetails; static std::stack<SymbolDetail> symbolDetails;
static bool stackOverflowException; static bool stackOverflowException;
static bool alreadyCrashed; static bool alreadyCrashed;
static std::mutex alreadyCrashedLock; static std::mutex alreadyCrashedLock;
typedef NTSTATUS(NTAPI* pRtlGetVersion)(PRTL_OSVERSIONINFOW lpVersionInformation); typedef NTSTATUS(NTAPI* pRtlGetVersion)(PRTL_OSVERSIONINFOW lpVersionInformation);
static pRtlGetVersion RtlGetVersion; static pRtlGetVersion RtlGetVersion;
static void PushSymbolDetail(); static void PushSymbolDetail();
static void PopSymbolDetail(); static void PopSymbolDetail();
static void PrintSymbolDetail(); static void PrintSymbolDetail();
}; };

View File

@@ -41,9 +41,9 @@ private:
template<class T> template<class T>
class Permissible class Permissible
{ {
public: public:
virtual ~Permissible() { } virtual ~Permissible() { }
virtual int Permit(const T *) const = 0; virtual int Permit(const T*) const = 0;
}; };
#endif #endif

View File

@@ -15,218 +15,236 @@ class LinkedListHead;
class LinkedListElement class LinkedListElement
{ {
private: private:
friend class LinkedListHead; friend class LinkedListHead;
LinkedListElement* iNext; LinkedListElement* iNext;
LinkedListElement* iPrev; LinkedListElement* iPrev;
public: public:
LinkedListElement(): iNext(NULL), iPrev(NULL) { } LinkedListElement(): iNext(NULL), iPrev(NULL) { }
~LinkedListElement() { delink(); } ~LinkedListElement() { delink(); }
bool hasNext() const { return(iNext && iNext->iNext != NULL); } bool hasNext() const { return(iNext && iNext->iNext != NULL); }
bool hasPrev() const { return(iPrev && iPrev->iPrev != NULL); } bool hasPrev() const { return(iPrev && iPrev->iPrev != NULL); }
bool isInList() const { return(iNext != NULL && iPrev != NULL); } bool isInList() const { return(iNext != NULL && iPrev != NULL); }
LinkedListElement * next() { return hasNext() ? iNext : NULL; } LinkedListElement* next() { return hasNext() ? iNext : NULL; }
LinkedListElement const* next() const { return hasNext() ? iNext : NULL; } LinkedListElement const* next() const { return hasNext() ? iNext : NULL; }
LinkedListElement * prev() { return hasPrev() ? iPrev : NULL; } LinkedListElement* prev() { return hasPrev() ? iPrev : NULL; }
LinkedListElement const* prev() const { return hasPrev() ? iPrev : NULL; } LinkedListElement const* prev() const { return hasPrev() ? iPrev : NULL; }
LinkedListElement * nocheck_next() { return iNext; } LinkedListElement* nocheck_next() { return iNext; }
LinkedListElement const* nocheck_next() const { return iNext; } LinkedListElement const* nocheck_next() const { return iNext; }
LinkedListElement * nocheck_prev() { return iPrev; } LinkedListElement* nocheck_prev() { return iPrev; }
LinkedListElement const* nocheck_prev() const { return iPrev; } LinkedListElement const* nocheck_prev() const { return iPrev; }
void delink() void delink()
{
if (isInList())
{ {
if (isInList()) iNext->iPrev = iPrev;
{ iPrev->iNext = iNext;
iNext->iPrev = iPrev; iPrev->iNext = iNext; iNext = NULL; iPrev = NULL; iNext = NULL;
} iPrev = NULL;
} }
}
void insertBefore(LinkedListElement* pElem) void insertBefore(LinkedListElement* pElem)
{ {
pElem->iNext = this; pElem->iNext = this;
pElem->iPrev = iPrev; pElem->iPrev = iPrev;
iPrev->iNext = pElem; iPrev->iNext = pElem;
iPrev = pElem; iPrev = pElem;
} }
void insertAfter(LinkedListElement* pElem) void insertAfter(LinkedListElement* pElem)
{ {
pElem->iPrev = this; pElem->iPrev = this;
pElem->iNext = iNext; pElem->iNext = iNext;
iNext->iPrev = pElem; iNext->iPrev = pElem;
iNext = pElem; iNext = pElem;
} }
}; };
//============================================ //============================================
class LinkedListHead class LinkedListHead
{ {
private: private:
LinkedListElement iFirst; LinkedListElement iFirst;
LinkedListElement iLast; LinkedListElement iLast;
uint32 iSize; uint32 iSize;
public: public:
LinkedListHead(): iSize(0) LinkedListHead(): iSize(0)
{
// create empty list
iFirst.iNext = &iLast;
iLast.iPrev = &iFirst;
}
bool isEmpty() const { return(!iFirst.iNext->isInList()); }
LinkedListElement* getFirst() { return(isEmpty() ? NULL : iFirst.iNext); }
LinkedListElement const* getFirst() const { return(isEmpty() ? NULL : iFirst.iNext); }
LinkedListElement* getLast() { return(isEmpty() ? NULL : iLast.iPrev); }
LinkedListElement const* getLast() const { return(isEmpty() ? NULL : iLast.iPrev); }
void insertFirst(LinkedListElement* pElem)
{
iFirst.insertAfter(pElem);
}
void insertLast(LinkedListElement* pElem)
{
iLast.insertBefore(pElem);
}
uint32 getSize() const
{
if (!iSize)
{ {
// create empty list uint32 result = 0;
LinkedListElement const* e = getFirst();
iFirst.iNext = &iLast; while (e)
iLast.iPrev = &iFirst;
}
bool isEmpty() const { return(!iFirst.iNext->isInList()); }
LinkedListElement * getFirst() { return(isEmpty() ? NULL : iFirst.iNext); }
LinkedListElement const* getFirst() const { return(isEmpty() ? NULL : iFirst.iNext); }
LinkedListElement * getLast() { return(isEmpty() ? NULL : iLast.iPrev); }
LinkedListElement const* getLast() const { return(isEmpty() ? NULL : iLast.iPrev); }
void insertFirst(LinkedListElement* pElem)
{
iFirst.insertAfter(pElem);
}
void insertLast(LinkedListElement* pElem)
{
iLast.insertBefore(pElem);
}
uint32 getSize() const
{
if (!iSize)
{ {
uint32 result = 0; ++result;
LinkedListElement const* e = getFirst(); e = e->next();
while (e)
{
++result;
e = e->next();
}
return result;
} }
else return result;
return iSize; }
else
return iSize;
}
void incSize() { ++iSize; }
void decSize() { --iSize; }
template<class _Ty>
class Iterator
{
public:
typedef std::bidirectional_iterator_tag iterator_category;
typedef _Ty value_type;
typedef ptrdiff_t difference_type;
typedef ptrdiff_t distance_type;
typedef _Ty* pointer;
typedef _Ty const* const_pointer;
typedef _Ty& reference;
typedef _Ty const& const_reference;
Iterator() : _Ptr(0)
{
// construct with null node pointer
} }
void incSize() { ++iSize; } Iterator(pointer _Pnode) : _Ptr(_Pnode)
void decSize() { --iSize; }
template<class _Ty>
class Iterator
{ {
public: // construct with node pointer _Pnode
typedef std::bidirectional_iterator_tag iterator_category; }
typedef _Ty value_type;
typedef ptrdiff_t difference_type;
typedef ptrdiff_t distance_type;
typedef _Ty* pointer;
typedef _Ty const* const_pointer;
typedef _Ty& reference;
typedef _Ty const & const_reference;
Iterator() : _Ptr(0) Iterator& operator=(Iterator const& _Right)
{ // construct with null node pointer {
} _Ptr = _Right._Ptr;
return *this;
}
Iterator(pointer _Pnode) : _Ptr(_Pnode) Iterator& operator=(const_pointer const& _Right)
{ // construct with node pointer _Pnode {
} _Ptr = pointer(_Right);
return *this;
}
Iterator& operator=(Iterator const &_Right) reference operator*()
{ {
_Ptr = _Right._Ptr; // return designated value
return *this; return *_Ptr;
} }
Iterator& operator=(const_pointer const &_Right) pointer operator->()
{ {
_Ptr = pointer(_Right); // return pointer to class object
return *this; return _Ptr;
} }
reference operator*() Iterator& operator++()
{ // return designated value {
return *_Ptr; // preincrement
} _Ptr = _Ptr->next();
return (*this);
}
pointer operator->() Iterator operator++(int)
{ // return pointer to class object {
return _Ptr; // postincrement
} iterator _Tmp = *this;
++*this;
return (_Tmp);
}
Iterator& operator++() Iterator& operator--()
{ // preincrement {
_Ptr = _Ptr->next(); // predecrement
return (*this); _Ptr = _Ptr->prev();
} return (*this);
}
Iterator operator++(int) Iterator operator--(int)
{ // postincrement {
iterator _Tmp = *this; // postdecrement
++*this; iterator _Tmp = *this;
return (_Tmp); --*this;
} return (_Tmp);
}
Iterator& operator--() bool operator==(Iterator const& _Right) const
{ // predecrement {
_Ptr = _Ptr->prev(); // test for iterator equality
return (*this); return (_Ptr == _Right._Ptr);
} }
Iterator operator--(int) bool operator!=(Iterator const& _Right) const
{ // postdecrement {
iterator _Tmp = *this; // test for iterator inequality
--*this; return (!(*this == _Right));
return (_Tmp); }
}
bool operator==(Iterator const &_Right) const bool operator==(pointer const& _Right) const
{ // test for iterator equality {
return (_Ptr == _Right._Ptr); // test for pointer equality
} return (_Ptr != _Right);
}
bool operator!=(Iterator const &_Right) const bool operator!=(pointer const& _Right) const
{ // test for iterator inequality {
return (!(*this == _Right)); // test for pointer equality
} return (!(*this == _Right));
}
bool operator==(pointer const &_Right) const bool operator==(const_reference _Right) const
{ // test for pointer equality {
return (_Ptr != _Right); // test for reference equality
} return (_Ptr == &_Right);
}
bool operator!=(pointer const &_Right) const bool operator!=(const_reference _Right) const
{ // test for pointer equality {
return (!(*this == _Right)); // test for reference equality
} return (_Ptr != &_Right);
}
bool operator==(const_reference _Right) const pointer _Mynode()
{ // test for reference equality {
return (_Ptr == &_Right); // return node pointer
} return (_Ptr);
}
bool operator!=(const_reference _Right) const protected:
{ // test for reference equality pointer _Ptr; // pointer to node
return (_Ptr != &_Right); };
}
pointer _Mynode() typedef Iterator<LinkedListElement> iterator;
{ // return node pointer
return (_Ptr);
}
protected:
pointer _Ptr; // pointer to node
};
typedef Iterator<LinkedListElement> iterator;
}; };
//============================================ //============================================

View File

@@ -13,30 +13,30 @@
template <class TO, class FROM> class RefManager : public LinkedListHead template <class TO, class FROM> class RefManager : public LinkedListHead
{ {
public: public:
typedef LinkedListHead::Iterator< Reference<TO, FROM> > iterator; typedef LinkedListHead::Iterator< Reference<TO, FROM> > iterator;
RefManager() { } RefManager() { }
virtual ~RefManager() { clearReferences(); } virtual ~RefManager() { clearReferences(); }
Reference<TO, FROM>* getFirst() { return ((Reference<TO, FROM>*) LinkedListHead::getFirst()); } Reference<TO, FROM>* getFirst() { return ((Reference<TO, FROM>*) LinkedListHead::getFirst()); }
Reference<TO, FROM> const* getFirst() const { return ((Reference<TO, FROM> const*) LinkedListHead::getFirst()); } Reference<TO, FROM> const* getFirst() const { return ((Reference<TO, FROM> const*) LinkedListHead::getFirst()); }
Reference<TO, FROM>* getLast() { return ((Reference<TO, FROM>*) LinkedListHead::getLast()); } Reference<TO, FROM>* getLast() { return ((Reference<TO, FROM>*) LinkedListHead::getLast()); }
Reference<TO, FROM> const* getLast() const { return ((Reference<TO, FROM> const*) LinkedListHead::getLast()); } Reference<TO, FROM> const* getLast() const { return ((Reference<TO, FROM> const*) LinkedListHead::getLast()); }
iterator begin() { return iterator(getFirst()); } iterator begin() { return iterator(getFirst()); }
iterator end() { return iterator(NULL); } iterator end() { return iterator(NULL); }
iterator rbegin() { return iterator(getLast()); } iterator rbegin() { return iterator(getLast()); }
iterator rend() { return iterator(NULL); } iterator rend() { return iterator(NULL); }
void clearReferences() void clearReferences()
{
LinkedListElement* ref;
while ((ref = getFirst()) != NULL)
{ {
LinkedListElement* ref; ((Reference<TO, FROM>*) ref)->invalidate();
while ((ref = getFirst()) != NULL) ref->delink(); // the delink might be already done by invalidate(), but doing it here again does not hurt and insures an empty list
{
((Reference<TO, FROM>*) ref)->invalidate();
ref->delink(); // the delink might be already done by invalidate(), but doing it here again does not hurt and insures an empty list
}
} }
}
}; };
//===================================================== //=====================================================

View File

@@ -14,74 +14,74 @@
template <class TO, class FROM> class Reference : public LinkedListElement template <class TO, class FROM> class Reference : public LinkedListElement
{ {
private: private:
TO* iRefTo; TO* iRefTo;
FROM* iRefFrom; FROM* iRefFrom;
protected: protected:
// Tell our refTo (target) object that we have a link // Tell our refTo (target) object that we have a link
virtual void targetObjectBuildLink() = 0; virtual void targetObjectBuildLink() = 0;
// Tell our refTo (taget) object, that the link is cut // Tell our refTo (taget) object, that the link is cut
virtual void targetObjectDestroyLink() = 0; virtual void targetObjectDestroyLink() = 0;
// Tell our refFrom (source) object, that the link is cut (Target destroyed) // Tell our refFrom (source) object, that the link is cut (Target destroyed)
virtual void sourceObjectDestroyLink() = 0; virtual void sourceObjectDestroyLink() = 0;
public: public:
Reference() { iRefTo = NULL; iRefFrom = NULL; } Reference() { iRefTo = NULL; iRefFrom = NULL; }
virtual ~Reference() { } virtual ~Reference() { }
// Create new link // Create new link
void link(TO* toObj, FROM* fromObj) void link(TO* toObj, FROM* fromObj)
{
ASSERT(fromObj); // fromObj MUST not be NULL
if (isValid())
unlink();
if (toObj != NULL)
{ {
ASSERT(fromObj); // fromObj MUST not be NULL iRefTo = toObj;
if (isValid()) iRefFrom = fromObj;
unlink(); targetObjectBuildLink();
if (toObj != NULL)
{
iRefTo = toObj;
iRefFrom = fromObj;
targetObjectBuildLink();
}
} }
}
// We don't need the reference anymore. Call comes from the refFrom object // We don't need the reference anymore. Call comes from the refFrom object
// Tell our refTo object, that the link is cut // Tell our refTo object, that the link is cut
void unlink() void unlink()
{ {
targetObjectDestroyLink(); targetObjectDestroyLink();
delink(); delink();
iRefTo = NULL; iRefTo = NULL;
iRefFrom = NULL; iRefFrom = NULL;
} }
// Link is invalid due to destruction of referenced target object. Call comes from the refTo object // Link is invalid due to destruction of referenced target object. Call comes from the refTo object
// Tell our refFrom object, that the link is cut // Tell our refFrom object, that the link is cut
void invalidate() // the iRefFrom MUST remain!! void invalidate() // the iRefFrom MUST remain!!
{ {
sourceObjectDestroyLink(); sourceObjectDestroyLink();
delink(); delink();
iRefTo = NULL; iRefTo = NULL;
} }
bool isValid() const // Only check the iRefTo bool isValid() const // Only check the iRefTo
{ {
return iRefTo != NULL; return iRefTo != NULL;
} }
Reference<TO, FROM> * next() { return((Reference<TO, FROM> *) LinkedListElement::next()); } Reference<TO, FROM>* next() { return((Reference<TO, FROM>*) LinkedListElement::next()); }
Reference<TO, FROM> const* next() const { return((Reference<TO, FROM> const*) LinkedListElement::next()); } Reference<TO, FROM> const* next() const { return((Reference<TO, FROM> const*) LinkedListElement::next()); }
Reference<TO, FROM> * prev() { return((Reference<TO, FROM> *) LinkedListElement::prev()); } Reference<TO, FROM>* prev() { return((Reference<TO, FROM>*) LinkedListElement::prev()); }
Reference<TO, FROM> const* prev() const { return((Reference<TO, FROM> const*) LinkedListElement::prev()); } Reference<TO, FROM> const* prev() const { return((Reference<TO, FROM> const*) LinkedListElement::prev()); }
Reference<TO, FROM> * nocheck_next() { return((Reference<TO, FROM> *) LinkedListElement::nocheck_next()); } Reference<TO, FROM>* nocheck_next() { return((Reference<TO, FROM>*) LinkedListElement::nocheck_next()); }
Reference<TO, FROM> const* nocheck_next() const { return((Reference<TO, FROM> const*) LinkedListElement::nocheck_next()); } Reference<TO, FROM> const* nocheck_next() const { return((Reference<TO, FROM> const*) LinkedListElement::nocheck_next()); }
Reference<TO, FROM> * nocheck_prev() { return((Reference<TO, FROM> *) LinkedListElement::nocheck_prev()); } Reference<TO, FROM>* nocheck_prev() { return((Reference<TO, FROM>*) LinkedListElement::nocheck_prev()); }
Reference<TO, FROM> const* nocheck_prev() const { return((Reference<TO, FROM> const*) LinkedListElement::nocheck_prev()); } Reference<TO, FROM> const* nocheck_prev() const { return((Reference<TO, FROM> const*) LinkedListElement::nocheck_prev()); }
TO* operator ->() const { return iRefTo; } TO* operator ->() const { return iRefTo; }
TO* getTarget() const { return iRefTo; } TO* getTarget() const { return iRefTo; }
FROM* GetSource() const { return iRefFrom; } FROM* GetSource() const { return iRefFrom; }
}; };
//===================================================== //=====================================================

View File

@@ -18,81 +18,81 @@
template<class T, class Key = std::string> template<class T, class Key = std::string>
class ObjectRegistry class ObjectRegistry
{ {
public: public:
typedef std::map<Key, T *> RegistryMapType; typedef std::map<Key, T*> RegistryMapType;
/// Returns a registry item /// Returns a registry item
const T* GetRegistryItem(Key key) const const T* GetRegistryItem(Key key) const
{
typename RegistryMapType::const_iterator iter = i_registeredObjects.find(key);
return( iter == i_registeredObjects.end() ? NULL : iter->second );
}
static ObjectRegistry<T, Key>* instance()
{
static ObjectRegistry<T, Key>* instance = new ObjectRegistry<T, Key>();
return instance;
}
/// Inserts a registry item
bool InsertItem(T* obj, Key key, bool override = false)
{
typename RegistryMapType::iterator iter = i_registeredObjects.find(key);
if ( iter != i_registeredObjects.end() )
{ {
typename RegistryMapType::const_iterator iter = i_registeredObjects.find(key); if ( !override )
return( iter == i_registeredObjects.end() ? NULL : iter->second ); return false;
delete iter->second;
i_registeredObjects.erase(iter);
} }
static ObjectRegistry<T, Key>* instance() i_registeredObjects[key] = obj;
{ return true;
static ObjectRegistry<T, Key>* instance = new ObjectRegistry<T, Key>(); }
return instance;
}
/// Inserts a registry item /// Removes a registry item
bool InsertItem(T *obj, Key key, bool override = false) void RemoveItem(Key key, bool delete_object = true)
{
typename RegistryMapType::iterator iter = i_registeredObjects.find(key);
if ( iter != i_registeredObjects.end() )
{ {
typename RegistryMapType::iterator iter = i_registeredObjects.find(key); if ( delete_object )
if ( iter != i_registeredObjects.end() )
{
if ( !override )
return false;
delete iter->second; delete iter->second;
i_registeredObjects.erase(iter); i_registeredObjects.erase(iter);
}
i_registeredObjects[key] = obj;
return true;
} }
}
/// Removes a registry item /// Returns true if registry contains an item
void RemoveItem(Key key, bool delete_object = true) bool HasItem(Key key) const
{ {
typename RegistryMapType::iterator iter = i_registeredObjects.find(key); return (i_registeredObjects.find(key) != i_registeredObjects.end());
if ( iter != i_registeredObjects.end() ) }
{
if ( delete_object )
delete iter->second;
i_registeredObjects.erase(iter);
}
}
/// Returns true if registry contains an item /// Inefficiently return a vector of registered items
bool HasItem(Key key) const unsigned int GetRegisteredItems(std::vector<Key>& l) const
{ {
return (i_registeredObjects.find(key) != i_registeredObjects.end()); unsigned int sz = l.size();
} l.resize(sz + i_registeredObjects.size());
for (typename RegistryMapType::const_iterator iter = i_registeredObjects.begin(); iter != i_registeredObjects.end(); ++iter)
l[sz++] = iter->first;
return i_registeredObjects.size();
}
/// Inefficiently return a vector of registered items /// Return the map of registered items
unsigned int GetRegisteredItems(std::vector<Key> &l) const RegistryMapType const& GetRegisteredItems() const
{ {
unsigned int sz = l.size(); return i_registeredObjects;
l.resize(sz + i_registeredObjects.size()); }
for (typename RegistryMapType::const_iterator iter = i_registeredObjects.begin(); iter != i_registeredObjects.end(); ++iter)
l[sz++] = iter->first;
return i_registeredObjects.size();
}
/// Return the map of registered items ObjectRegistry() { }
RegistryMapType const &GetRegisteredItems() const ~ObjectRegistry()
{ {
return i_registeredObjects; for (typename RegistryMapType::iterator iter = i_registeredObjects.begin(); iter != i_registeredObjects.end(); ++iter)
} delete iter->second;
i_registeredObjects.clear();
ObjectRegistry() { } }
~ObjectRegistry() private:
{ RegistryMapType i_registeredObjects;
for (typename RegistryMapType::iterator iter=i_registeredObjects.begin(); iter != i_registeredObjects.end(); ++iter)
delete iter->second;
i_registeredObjects.clear();
}
private:
RegistryMapType i_registeredObjects;
}; };
#endif #endif

View File

@@ -85,28 +85,28 @@ template<class H, class T> struct ContainerList<TypeList<H, T> >
template<class OBJECT_TYPES> template<class OBJECT_TYPES>
class TypeMapContainer class TypeMapContainer
{ {
public: public:
template<class SPECIFIC_TYPE> size_t Count() const { return acore::Count(i_elements, (SPECIFIC_TYPE*)NULL); } template<class SPECIFIC_TYPE> size_t Count() const { return acore::Count(i_elements, (SPECIFIC_TYPE*)NULL); }
/// inserts a specific object into the container /// inserts a specific object into the container
template<class SPECIFIC_TYPE> bool insert(SPECIFIC_TYPE *obj) template<class SPECIFIC_TYPE> bool insert(SPECIFIC_TYPE* obj)
{ {
SPECIFIC_TYPE* t = acore::Insert(i_elements, obj); SPECIFIC_TYPE* t = acore::Insert(i_elements, obj);
return (t != NULL); return (t != NULL);
} }
/// Removes the object from the container, and returns the removed object /// Removes the object from the container, and returns the removed object
//template<class SPECIFIC_TYPE> bool remove(SPECIFIC_TYPE* obj) //template<class SPECIFIC_TYPE> bool remove(SPECIFIC_TYPE* obj)
//{ //{
// SPECIFIC_TYPE* t = acore::Remove(i_elements, obj); // SPECIFIC_TYPE* t = acore::Remove(i_elements, obj);
// return (t != NULL); // return (t != NULL);
//} //}
ContainerMapList<OBJECT_TYPES> & GetElements(void) { return i_elements; } ContainerMapList<OBJECT_TYPES>& GetElements(void) { return i_elements; }
const ContainerMapList<OBJECT_TYPES> & GetElements(void) const { return i_elements;} const ContainerMapList<OBJECT_TYPES>& GetElements(void) const { return i_elements;}
private: private:
ContainerMapList<OBJECT_TYPES> i_elements; ContainerMapList<OBJECT_TYPES> i_elements;
}; };
#endif #endif

View File

@@ -21,54 +21,54 @@ namespace acore
{ {
/* ContainerMapList Helpers */ /* ContainerMapList Helpers */
// count functions // count functions
template<class SPECIFIC_TYPE> size_t Count(const ContainerMapList<SPECIFIC_TYPE> &elements, SPECIFIC_TYPE* /*fake*/) template<class SPECIFIC_TYPE> size_t Count(const ContainerMapList<SPECIFIC_TYPE>& elements, SPECIFIC_TYPE* /*fake*/)
{ {
return elements._element.getSize(); return elements._element.getSize();
} }
template<class SPECIFIC_TYPE> size_t Count(const ContainerMapList<TypeNull> &/*elements*/, SPECIFIC_TYPE* /*fake*/) template<class SPECIFIC_TYPE> size_t Count(const ContainerMapList<TypeNull>& /*elements*/, SPECIFIC_TYPE* /*fake*/)
{ {
return 0; return 0;
} }
template<class SPECIFIC_TYPE, class T> size_t Count(const ContainerMapList<T> &/*elements*/, SPECIFIC_TYPE* /*fake*/) template<class SPECIFIC_TYPE, class T> size_t Count(const ContainerMapList<T>& /*elements*/, SPECIFIC_TYPE* /*fake*/)
{ {
return 0; return 0;
} }
template<class SPECIFIC_TYPE, class T> size_t Count(const ContainerMapList<TypeList<SPECIFIC_TYPE, T> >&elements, SPECIFIC_TYPE* fake) template<class SPECIFIC_TYPE, class T> size_t Count(const ContainerMapList<TypeList<SPECIFIC_TYPE, T> >& elements, SPECIFIC_TYPE* fake)
{ {
return Count(elements._elements, fake); return Count(elements._elements, fake);
} }
template<class SPECIFIC_TYPE, class H, class T> size_t Count(const ContainerMapList<TypeList<H, T> >&elements, SPECIFIC_TYPE* fake) template<class SPECIFIC_TYPE, class H, class T> size_t Count(const ContainerMapList<TypeList<H, T> >& elements, SPECIFIC_TYPE* fake)
{ {
return Count(elements._TailElements, fake); return Count(elements._TailElements, fake);
} }
// non-const insert functions // non-const insert functions
template<class SPECIFIC_TYPE> SPECIFIC_TYPE* Insert(ContainerMapList<SPECIFIC_TYPE> &elements, SPECIFIC_TYPE *obj) template<class SPECIFIC_TYPE> SPECIFIC_TYPE* Insert(ContainerMapList<SPECIFIC_TYPE>& elements, SPECIFIC_TYPE* obj)
{ {
//elements._element[hdl] = obj; //elements._element[hdl] = obj;
obj->AddToGrid(elements._element); obj->AddToGrid(elements._element);
return obj; return obj;
} }
template<class SPECIFIC_TYPE> SPECIFIC_TYPE* Insert(ContainerMapList<TypeNull> &/*elements*/, SPECIFIC_TYPE * /*obj*/) template<class SPECIFIC_TYPE> SPECIFIC_TYPE* Insert(ContainerMapList<TypeNull>& /*elements*/, SPECIFIC_TYPE* /*obj*/)
{ {
return NULL; return NULL;
} }
// this is a missed // this is a missed
template<class SPECIFIC_TYPE, class T> SPECIFIC_TYPE* Insert(ContainerMapList<T> &/*elements*/, SPECIFIC_TYPE * /*obj*/) template<class SPECIFIC_TYPE, class T> SPECIFIC_TYPE* Insert(ContainerMapList<T>& /*elements*/, SPECIFIC_TYPE* /*obj*/)
{ {
return NULL; // a missed return NULL; // a missed
} }
// Recursion // Recursion
template<class SPECIFIC_TYPE, class H, class T> SPECIFIC_TYPE* Insert(ContainerMapList<TypeList<H, T> >&elements, SPECIFIC_TYPE *obj) template<class SPECIFIC_TYPE, class H, class T> SPECIFIC_TYPE* Insert(ContainerMapList<TypeList<H, T> >& elements, SPECIFIC_TYPE* obj)
{ {
SPECIFIC_TYPE* t= Insert(elements._elements, obj); SPECIFIC_TYPE* t = Insert(elements._elements, obj);
return (t != NULL ? t : Insert(elements._TailElements, obj)); return (t != NULL ? t : Insert(elements._TailElements, obj));
} }

View File

@@ -47,48 +47,48 @@ namespace acore
// } // }
// non-const find functions // non-const find functions
template<class SPECIFIC_TYPE> CountedPtr<SPECIFIC_TYPE>& Find(ContainerMapList<SPECIFIC_TYPE> &elements, OBJECT_HANDLE hdl, CountedPtr<SPECIFIC_TYPE>* /*fake*/) template<class SPECIFIC_TYPE> CountedPtr<SPECIFIC_TYPE>& Find(ContainerMapList<SPECIFIC_TYPE>& elements, OBJECT_HANDLE hdl, CountedPtr<SPECIFIC_TYPE>* /*fake*/)
{ {
typename std::map<OBJECT_HANDLE, CountedPtr<SPECIFIC_TYPE> >::iterator iter = elements._element.find(hdl); typename std::map<OBJECT_HANDLE, CountedPtr<SPECIFIC_TYPE> >::iterator iter = elements._element.find(hdl);
return (iter == elements._element.end() ? NullPtr<SPECIFIC_TYPE>((SPECIFIC_TYPE*)NULL) : iter->second); return (iter == elements._element.end() ? NullPtr<SPECIFIC_TYPE>((SPECIFIC_TYPE*)NULL) : iter->second);
}; };
template<class SPECIFIC_TYPE> CountedPtr<SPECIFIC_TYPE>& Find(ContainerMapList<TypeNull> &elements, OBJECT_HANDLE hdl, CountedPtr<SPECIFIC_TYPE>* /*fake*/) template<class SPECIFIC_TYPE> CountedPtr<SPECIFIC_TYPE>& Find(ContainerMapList<TypeNull>& elements, OBJECT_HANDLE hdl, CountedPtr<SPECIFIC_TYPE>* /*fake*/)
{ {
return NullPtr<SPECIFIC_TYPE>((SPECIFIC_TYPE*)NULL);// terminate recursion return NullPtr<SPECIFIC_TYPE>((SPECIFIC_TYPE*)NULL);// terminate recursion
} }
template<class SPECIFIC_TYPE, class T> CountedPtr<SPECIFIC_TYPE>& Find(ContainerMapList<T> &elements, OBJECT_HANDLE hdl, CountedPtr<SPECIFIC_TYPE>* /*fake*/) template<class SPECIFIC_TYPE, class T> CountedPtr<SPECIFIC_TYPE>& Find(ContainerMapList<T>& elements, OBJECT_HANDLE hdl, CountedPtr<SPECIFIC_TYPE>* /*fake*/)
{ {
return NullPtr<SPECIFIC_TYPE>((SPECIFIC_TYPE*)NULL);// this is a missed return NullPtr<SPECIFIC_TYPE>((SPECIFIC_TYPE*)NULL);// this is a missed
} }
template<class SPECIFIC_TYPE, class H, class T> CountedPtr<SPECIFIC_TYPE>& Find(ContainerMapList<TypeList<H, T> >&elements, OBJECT_HANDLE hdl, CountedPtr<SPECIFIC_TYPE>* fake) template<class SPECIFIC_TYPE, class H, class T> CountedPtr<SPECIFIC_TYPE>& Find(ContainerMapList<TypeList<H, T> >& elements, OBJECT_HANDLE hdl, CountedPtr<SPECIFIC_TYPE>* fake)
{ {
CountedPtr<SPECIFIC_TYPE> &t = Find(elements._elements, hdl, fake); CountedPtr<SPECIFIC_TYPE>& t = Find(elements._elements, hdl, fake);
return (!t ? Find(elements._TailElements, hdl, fake) : t); return (!t ? Find(elements._TailElements, hdl, fake) : t);
} }
// const find functions // const find functions
template<class SPECIFIC_TYPE> const CountedPtr<SPECIFIC_TYPE>& Find(const ContainerMapList<SPECIFIC_TYPE> &elements, OBJECT_HANDLE hdl, CountedPtr<SPECIFIC_TYPE>* /*fake*/) template<class SPECIFIC_TYPE> const CountedPtr<SPECIFIC_TYPE>& Find(const ContainerMapList<SPECIFIC_TYPE>& elements, OBJECT_HANDLE hdl, CountedPtr<SPECIFIC_TYPE>* /*fake*/)
{ {
typename CountedPtr<SPECIFIC_TYPE>::iterator iter = elements._element.find(hdl); typename CountedPtr<SPECIFIC_TYPE>::iterator iter = elements._element.find(hdl);
return (iter == elements._element.end() ? NullPtr<SPECIFIC_TYPE>((SPECIFIC_TYPE*)NULL) : iter->second); return (iter == elements._element.end() ? NullPtr<SPECIFIC_TYPE>((SPECIFIC_TYPE*)NULL) : iter->second);
}; };
template<class SPECIFIC_TYPE> const CountedPtr<SPECIFIC_TYPE>& Find(const ContainerMapList<TypeNull> &elements, OBJECT_HANDLE hdl, CountedPtr<SPECIFIC_TYPE>* /*fake*/) template<class SPECIFIC_TYPE> const CountedPtr<SPECIFIC_TYPE>& Find(const ContainerMapList<TypeNull>& elements, OBJECT_HANDLE hdl, CountedPtr<SPECIFIC_TYPE>* /*fake*/)
{ {
return NullPtr<SPECIFIC_TYPE>((SPECIFIC_TYPE*)NULL); return NullPtr<SPECIFIC_TYPE>((SPECIFIC_TYPE*)NULL);
} }
template<class SPECIFIC_TYPE, class T> const CountedPtr<SPECIFIC_TYPE>& Find(const ContainerMapList<T> &elements, OBJECT_HANDLE hdl, CountedPtr<SPECIFIC_TYPE>* /*fake*/) template<class SPECIFIC_TYPE, class T> const CountedPtr<SPECIFIC_TYPE>& Find(const ContainerMapList<T>& elements, OBJECT_HANDLE hdl, CountedPtr<SPECIFIC_TYPE>* /*fake*/)
{ {
return NullPtr<SPECIFIC_TYPE>((SPECIFIC_TYPE*)NULL); return NullPtr<SPECIFIC_TYPE>((SPECIFIC_TYPE*)NULL);
} }
template<class SPECIFIC_TYPE, class H, class T> CountedPtr<SPECIFIC_TYPE>& Find(const ContainerMapList<TypeList<H, T> >&elements, OBJECT_HANDLE hdl, CountedPtr<SPECIFIC_TYPE>* fake) template<class SPECIFIC_TYPE, class H, class T> CountedPtr<SPECIFIC_TYPE>& Find(const ContainerMapList<TypeList<H, T> >& elements, OBJECT_HANDLE hdl, CountedPtr<SPECIFIC_TYPE>* fake)
{ {
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);
@@ -96,32 +96,32 @@ namespace acore
} }
// non-const insert functions // non-const insert functions
template<class SPECIFIC_TYPE> CountedPtr<SPECIFIC_TYPE>& Insert(ContainerMapList<SPECIFIC_TYPE> &elements, CountedPtr<SPECIFIC_TYPE> &obj, OBJECT_HANDLE hdl) template<class SPECIFIC_TYPE> CountedPtr<SPECIFIC_TYPE>& Insert(ContainerMapList<SPECIFIC_TYPE>& elements, CountedPtr<SPECIFIC_TYPE>& obj, OBJECT_HANDLE hdl)
{ {
elements._element[hdl] = obj; elements._element[hdl] = obj;
return obj; return obj;
}; };
template<class SPECIFIC_TYPE> CountedPtr<SPECIFIC_TYPE>& Insert(ContainerMapList<TypeNull> &elements, CountedPtr<SPECIFIC_TYPE> &obj, OBJECT_HANDLE hdl) template<class SPECIFIC_TYPE> CountedPtr<SPECIFIC_TYPE>& Insert(ContainerMapList<TypeNull>& elements, CountedPtr<SPECIFIC_TYPE>& obj, OBJECT_HANDLE hdl)
{ {
return NullPtr<SPECIFIC_TYPE>((SPECIFIC_TYPE*)NULL); return NullPtr<SPECIFIC_TYPE>((SPECIFIC_TYPE*)NULL);
} }
// this is a missed // this is a missed
template<class SPECIFIC_TYPE, class T> CountedPtr<SPECIFIC_TYPE>& Insert(ContainerMapList<T> &elements, CountedPtr<SPECIFIC_TYPE> &obj, OBJECT_HANDLE hdl) template<class SPECIFIC_TYPE, class T> CountedPtr<SPECIFIC_TYPE>& Insert(ContainerMapList<T>& elements, CountedPtr<SPECIFIC_TYPE>& obj, OBJECT_HANDLE hdl)
{ {
return NullPtr<SPECIFIC_TYPE>((SPECIFIC_TYPE*)NULL);// a missed return NullPtr<SPECIFIC_TYPE>((SPECIFIC_TYPE*)NULL);// a missed
} }
// Recursion // Recursion
template<class SPECIFIC_TYPE, class H, class T> CountedPtr<SPECIFIC_TYPE>& Insert(ContainerMapList<TypeList<H, T> >&elements, CountedPtr<SPECIFIC_TYPE> &obj, OBJECT_HANDLE hdl) template<class SPECIFIC_TYPE, class H, class T> CountedPtr<SPECIFIC_TYPE>& Insert(ContainerMapList<TypeList<H, T> >& elements, CountedPtr<SPECIFIC_TYPE>& obj, OBJECT_HANDLE hdl)
{ {
CountedPtr<SPECIFIC_TYPE> &t= Insert(elements._elements, obj, hdl); CountedPtr<SPECIFIC_TYPE>& t = Insert(elements._elements, obj, hdl);
return (!t ? Insert(elements._TailElements, obj, hdl) : t); return (!t ? Insert(elements._TailElements, obj, hdl) : t);
} }
// non-const remove method // non-const remove method
template<class SPECIFIC_TYPE> bool Remove(ContainerMapList<SPECIFIC_TYPE> &elements, CountedPtr<SPECIFIC_TYPE> &obj, OBJECT_HANDLE hdl) template<class SPECIFIC_TYPE> bool Remove(ContainerMapList<SPECIFIC_TYPE>& elements, CountedPtr<SPECIFIC_TYPE>& obj, OBJECT_HANDLE hdl)
{ {
typename std::map<OBJECT_HANDLE, CountedPtr<SPECIFIC_TYPE> >::iterator iter = elements._element.find(hdl); typename std::map<OBJECT_HANDLE, CountedPtr<SPECIFIC_TYPE> >::iterator iter = elements._element.find(hdl);
if ( iter != elements._element.end() ) if ( iter != elements._element.end() )
@@ -133,18 +133,18 @@ namespace acore
return false; // found... terminate the search return false; // found... terminate the search
} }
template<class SPECIFIC_TYPE> bool Remove(ContainerMapList<TypeNull> &elements, CountedPtr<SPECIFIC_TYPE> &obj, OBJECT_HANDLE hdl) template<class SPECIFIC_TYPE> bool Remove(ContainerMapList<TypeNull>& elements, CountedPtr<SPECIFIC_TYPE>& obj, OBJECT_HANDLE hdl)
{ {
return false; return false;
} }
// this is a missed // this is a missed
template<class SPECIFIC_TYPE, class T> bool Remove(ContainerMapList<T> &elements, CountedPtr<SPECIFIC_TYPE> &obj, OBJECT_HANDLE hdl) template<class SPECIFIC_TYPE, class T> bool Remove(ContainerMapList<T>& elements, CountedPtr<SPECIFIC_TYPE>& obj, OBJECT_HANDLE hdl)
{ {
return false; return false;
} }
template<class SPECIFIC_TYPE, class T, class H> bool Remove(ContainerMapList<TypeList<H, T> > &elements, CountedPtr<SPECIFIC_TYPE> &obj, OBJECT_HANDLE hdl) template<class SPECIFIC_TYPE, class T, class H> bool Remove(ContainerMapList<TypeList<H, T> >& elements, CountedPtr<SPECIFIC_TYPE>& obj, OBJECT_HANDLE hdl)
{ {
// The head element is bad // The head element is bad
bool t = Remove(elements._elements, obj, hdl); bool t = Remove(elements._elements, obj, hdl);

View File

@@ -20,58 +20,58 @@
template<class T, class Y> class TypeContainerVisitor; template<class T, class Y> class TypeContainerVisitor;
// visitor helper // visitor helper
template<class VISITOR, class TYPE_CONTAINER> void VisitorHelper(VISITOR &v, TYPE_CONTAINER &c) template<class VISITOR, class TYPE_CONTAINER> void VisitorHelper(VISITOR& v, TYPE_CONTAINER& c)
{ {
v.Visit(c); v.Visit(c);
} }
// terminate condition for container list // terminate condition for container list
template<class VISITOR> void VisitorHelper(VISITOR &/*v*/, ContainerList<TypeNull> &/*c*/) { } template<class VISITOR> void VisitorHelper(VISITOR& /*v*/, ContainerList<TypeNull>& /*c*/) { }
template<class VISITOR, class T> void VisitorHelper(VISITOR &v, ContainerList<T> &c) template<class VISITOR, class T> void VisitorHelper(VISITOR& v, ContainerList<T>& c)
{ {
v.Visit(c._element); v.Visit(c._element);
} }
// recursion for container list // recursion for container list
template<class VISITOR, class H, class T> void VisitorHelper(VISITOR &v, ContainerList<TypeList<H, T> > &c) template<class VISITOR, class H, class T> void VisitorHelper(VISITOR& v, ContainerList<TypeList<H, T> >& c)
{ {
VisitorHelper(v, c._elements); VisitorHelper(v, c._elements);
VisitorHelper(v, c._TailElements); VisitorHelper(v, c._TailElements);
} }
// terminate condition container map list // terminate condition container map list
template<class VISITOR> void VisitorHelper(VISITOR &/*v*/, ContainerMapList<TypeNull> &/*c*/) { } template<class VISITOR> void VisitorHelper(VISITOR& /*v*/, ContainerMapList<TypeNull>& /*c*/) { }
template<class VISITOR, class T> void VisitorHelper(VISITOR &v, ContainerMapList<T> &c) template<class VISITOR, class T> void VisitorHelper(VISITOR& v, ContainerMapList<T>& c)
{ {
v.Visit(c._element); v.Visit(c._element);
} }
// recursion container map list // recursion container map list
template<class VISITOR, class H, class T> void VisitorHelper(VISITOR &v, ContainerMapList<TypeList<H, T> > &c) template<class VISITOR, class H, class T> void VisitorHelper(VISITOR& v, ContainerMapList<TypeList<H, T> >& c)
{ {
VisitorHelper(v, c._elements); VisitorHelper(v, c._elements);
VisitorHelper(v, c._TailElements); VisitorHelper(v, c._TailElements);
} }
// array list // array list
template<class VISITOR, class T> void VisitorHelper(VISITOR &v, ContainerArrayList<T> &c) template<class VISITOR, class T> void VisitorHelper(VISITOR& v, ContainerArrayList<T>& c)
{ {
v.Visit(c._element); v.Visit(c._element);
} }
template<class VISITOR> void VisitorHelper(VISITOR &/*v*/, ContainerArrayList<TypeNull> &/*c*/) { } template<class VISITOR> void VisitorHelper(VISITOR& /*v*/, ContainerArrayList<TypeNull>& /*c*/) { }
// recursion // recursion
template<class VISITOR, class H, class T> void VisitorHelper(VISITOR &v, ContainerArrayList<TypeList<H, T> > &c) template<class VISITOR, class H, class T> void VisitorHelper(VISITOR& v, ContainerArrayList<TypeList<H, T> >& c)
{ {
VisitorHelper(v, c._elements); VisitorHelper(v, c._elements);
VisitorHelper(v, c._TailElements); VisitorHelper(v, c._TailElements);
} }
// for TypeMapContainer // for TypeMapContainer
template<class VISITOR, class OBJECT_TYPES> void VisitorHelper(VISITOR &v, TypeMapContainer<OBJECT_TYPES> &c) template<class VISITOR, class OBJECT_TYPES> void VisitorHelper(VISITOR& v, TypeMapContainer<OBJECT_TYPES>& c)
{ {
VisitorHelper(v, c.GetElements()); VisitorHelper(v, c.GetElements());
} }
@@ -79,21 +79,21 @@ template<class VISITOR, class OBJECT_TYPES> void VisitorHelper(VISITOR &v, TypeM
template<class VISITOR, class TYPE_CONTAINER> template<class VISITOR, class TYPE_CONTAINER>
class TypeContainerVisitor class TypeContainerVisitor
{ {
public: public:
TypeContainerVisitor(VISITOR &v) : i_visitor(v) { } TypeContainerVisitor(VISITOR& v) : i_visitor(v) { }
void Visit(TYPE_CONTAINER &c) void Visit(TYPE_CONTAINER& c)
{ {
VisitorHelper(i_visitor, c); VisitorHelper(i_visitor, c);
} }
void Visit(const TYPE_CONTAINER &c) const void Visit(const TYPE_CONTAINER& c) const
{ {
VisitorHelper(i_visitor, c); VisitorHelper(i_visitor, c);
} }
private: private:
VISITOR &i_visitor; VISITOR& i_visitor;
}; };
#endif #endif

View File

@@ -71,7 +71,7 @@ Log* Log::instance()
return &instance; return &instance;
} }
void Log::SetLogLevel(char *Level) void Log::SetLogLevel(char* Level)
{ {
int32 NewLevel = atoi((char*)Level); int32 NewLevel = atoi((char*)Level);
if (NewLevel < 0) if (NewLevel < 0)
@@ -81,7 +81,7 @@ void Log::SetLogLevel(char *Level)
outString("LogLevel is %u", m_logLevel); outString("LogLevel is %u", m_logLevel);
} }
void Log::SetLogFileLevel(char *Level) void Log::SetLogFileLevel(char* Level)
{ {
int32 NewLevel = atoi((char*)Level); int32 NewLevel = atoi((char*)Level);
if (NewLevel < 0) if (NewLevel < 0)
@@ -126,7 +126,7 @@ void Log::Initialize()
bool m_gmlog_timestamp = sConfigMgr->GetBoolDefault("GmLogTimestamp", false, false); bool m_gmlog_timestamp = sConfigMgr->GetBoolDefault("GmLogTimestamp", false, false);
size_t dot_pos = m_gmlog_filename_format.find_last_of('.'); size_t dot_pos = m_gmlog_filename_format.find_last_of('.');
if (dot_pos!=m_gmlog_filename_format.npos) if (dot_pos != m_gmlog_filename_format.npos)
{ {
if (m_gmlog_timestamp) if (m_gmlog_timestamp)
m_gmlog_filename_format.insert(dot_pos, m_logsTimestamp); m_gmlog_filename_format.insert(dot_pos, m_logsTimestamp);
@@ -151,7 +151,7 @@ void Log::Initialize()
chatLogfile = openLogFile("ChatLogFile", "ChatLogTimestamp", "a"); chatLogfile = openLogFile("ChatLogFile", "ChatLogTimestamp", "a");
sqlLogFile = openLogFile("SQLDriverLogFile", NULL, "a"); sqlLogFile = openLogFile("SQLDriverLogFile", NULL, "a");
sqlDevLogFile = openLogFile("SQLDeveloperLogFile", NULL, "a"); sqlDevLogFile = openLogFile("SQLDeveloperLogFile", NULL, "a");
miscLogFile = fopen((m_logsDir+"Misc.log").c_str(), "a"); miscLogFile = fopen((m_logsDir + "Misc.log").c_str(), "a");
// Main log file settings // Main log file settings
m_logLevel = sConfigMgr->GetIntDefault("LogLevel", LOGL_NORMAL, false); m_logLevel = sConfigMgr->GetIntDefault("LogLevel", LOGL_NORMAL, false);
@@ -184,20 +184,20 @@ void Log::ReloadConfig()
FILE* Log::openLogFile(char const* configFileName, char const* configTimeStampFlag, char const* mode) FILE* Log::openLogFile(char const* configFileName, char const* configTimeStampFlag, char const* mode)
{ {
std::string logfn=sConfigMgr->GetStringDefault(configFileName, "", false); std::string logfn = sConfigMgr->GetStringDefault(configFileName, "", false);
if (logfn.empty()) if (logfn.empty())
return NULL; return NULL;
if (configTimeStampFlag && sConfigMgr->GetBoolDefault(configTimeStampFlag, false, false)) if (configTimeStampFlag && sConfigMgr->GetBoolDefault(configTimeStampFlag, false, false))
{ {
size_t dot_pos = logfn.find_last_of("."); size_t dot_pos = logfn.find_last_of(".");
if (dot_pos!=logfn.npos) if (dot_pos != logfn.npos)
logfn.insert(dot_pos, m_logsTimestamp); logfn.insert(dot_pos, m_logsTimestamp);
else else
logfn += m_logsTimestamp; logfn += m_logsTimestamp;
} }
return fopen((m_logsDir+logfn).c_str(), mode); return fopen((m_logsDir + logfn).c_str(), mode);
} }
FILE* Log::openGmlogPerAccount(uint32 account) FILE* Log::openGmlogPerAccount(uint32 account)
@@ -220,7 +220,7 @@ void Log::outTimestamp(FILE* file)
// HH hour (2 digits 00-23) // HH hour (2 digits 00-23)
// MM minutes (2 digits 00-59) // MM minutes (2 digits 00-59)
// SS seconds (2 digits 00-59) // SS seconds (2 digits 00-59)
fprintf(file, "%-4d-%02d-%02d %02d:%02d:%02d ", aTm->tm_year+1900, aTm->tm_mon+1, aTm->tm_mday, aTm->tm_hour, aTm->tm_min, aTm->tm_sec); fprintf(file, "%-4d-%02d-%02d %02d:%02d:%02d ", aTm->tm_year + 1900, aTm->tm_mon + 1, aTm->tm_mday, aTm->tm_hour, aTm->tm_min, aTm->tm_sec);
} }
void Log::InitColors(const std::string& str) void Log::InitColors(const std::string& str)
@@ -254,7 +254,7 @@ void Log::InitColors(const std::string& str)
void Log::SetColor(bool stdout_stream, ColorTypes color) void Log::SetColor(bool stdout_stream, ColorTypes color)
{ {
#if AC_PLATFORM == AC_PLATFORM_WINDOWS #if AC_PLATFORM == AC_PLATFORM_WINDOWS
static WORD WinColorFG[Colors] = static WORD WinColorFG[Colors] =
{ {
0, // BLACK 0, // BLACK
@@ -265,41 +265,41 @@ void Log::SetColor(bool stdout_stream, ColorTypes color)
FOREGROUND_RED | FOREGROUND_BLUE, // MAGENTA FOREGROUND_RED | FOREGROUND_BLUE, // MAGENTA
FOREGROUND_GREEN | FOREGROUND_BLUE, // CYAN FOREGROUND_GREEN | FOREGROUND_BLUE, // CYAN
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE, // WHITE FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE, // WHITE
// YELLOW // YELLOW
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY,
// RED_BOLD // RED_BOLD
FOREGROUND_RED | FOREGROUND_INTENSITY, FOREGROUND_RED | FOREGROUND_INTENSITY,
// GREEN_BOLD // GREEN_BOLD
FOREGROUND_GREEN | FOREGROUND_INTENSITY, FOREGROUND_GREEN | FOREGROUND_INTENSITY,
FOREGROUND_BLUE | FOREGROUND_INTENSITY, // BLUE_BOLD FOREGROUND_BLUE | FOREGROUND_INTENSITY, // BLUE_BOLD
// MAGENTA_BOLD // MAGENTA_BOLD
FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY, FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY,
// CYAN_BOLD // CYAN_BOLD
FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY, FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY,
// WHITE_BOLD // WHITE_BOLD
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY
}; };
HANDLE hConsole = GetStdHandle(stdout_stream ? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE ); HANDLE hConsole = GetStdHandle(stdout_stream ? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE );
SetConsoleTextAttribute(hConsole, WinColorFG[color]); SetConsoleTextAttribute(hConsole, WinColorFG[color]);
#else #else
enum ANSITextAttr enum ANSITextAttr
{ {
TA_NORMAL=0, TA_NORMAL = 0,
TA_BOLD=1, TA_BOLD = 1,
TA_BLINK=5, TA_BLINK = 5,
TA_REVERSE=7 TA_REVERSE = 7
}; };
enum ANSIFgTextAttr enum ANSIFgTextAttr
{ {
FG_BLACK=30, FG_RED, FG_GREEN, FG_BROWN, FG_BLUE, FG_BLACK = 30, FG_RED, FG_GREEN, FG_BROWN, FG_BLUE,
FG_MAGENTA, FG_CYAN, FG_WHITE, FG_YELLOW FG_MAGENTA, FG_CYAN, FG_WHITE, FG_YELLOW
}; };
enum ANSIBgTextAttr enum ANSIBgTextAttr
{ {
BG_BLACK=40, BG_RED, BG_GREEN, BG_BROWN, BG_BLUE, BG_BLACK = 40, BG_RED, BG_GREEN, BG_BROWN, BG_BLUE,
BG_MAGENTA, BG_CYAN, BG_WHITE BG_MAGENTA, BG_CYAN, BG_WHITE
}; };
@@ -322,18 +322,18 @@ void Log::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 < Colors ? ";1" : "")); fprintf((stdout_stream ? stdout : stderr), "\x1b[%d%sm", UnixColorFG[color], (color >= YELLOW && color < Colors ? ";1" : ""));
#endif #endif
} }
void Log::ResetColor(bool stdout_stream) void Log::ResetColor(bool stdout_stream)
{ {
#if AC_PLATFORM == AC_PLATFORM_WINDOWS #if AC_PLATFORM == AC_PLATFORM_WINDOWS
HANDLE hConsole = GetStdHandle(stdout_stream ? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE ); HANDLE hConsole = GetStdHandle(stdout_stream ? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE );
SetConsoleTextAttribute(hConsole, FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED ); SetConsoleTextAttribute(hConsole, FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED );
#else #else
fprintf(( stdout_stream ? stdout : stderr ), "\x1b[0m"); fprintf(( stdout_stream ? stdout : stderr ), "\x1b[0m");
#endif #endif
} }
std::string Log::GetTimestampStr() std::string Log::GetTimestampStr()
@@ -348,7 +348,7 @@ std::string Log::GetTimestampStr()
// MM minutes (2 digits 00-59) // MM minutes (2 digits 00-59)
// SS seconds (2 digits 00-59) // SS seconds (2 digits 00-59)
char buf[20]; char buf[20];
int ret = snprintf(buf, 20, "%04d-%02d-%02d_%02d-%02d-%02d", aTm.tm_year+1900, aTm.tm_mon+1, aTm.tm_mday, aTm.tm_hour, aTm.tm_min, aTm.tm_sec); int ret = snprintf(buf, 20, "%04d-%02d-%02d_%02d-%02d-%02d", aTm.tm_year + 1900, aTm.tm_mon + 1, aTm.tm_mday, aTm.tm_hour, aTm.tm_min, aTm.tm_sec);
if (ret < 0) if (ret < 0)
{ {
@@ -358,7 +358,7 @@ std::string Log::GetTimestampStr()
return std::string(buf); return std::string(buf);
} }
void Log::outDB(LogTypes type, const char * str) void Log::outDB(LogTypes type, const char* str)
{ {
if(!str || std::string(str).empty() || type >= MAX_LOG_TYPES) if(!str || std::string(str).empty() || type >= MAX_LOG_TYPES)
return; return;
@@ -367,10 +367,10 @@ void Log::outDB(LogTypes type, const char * str)
LoginDatabase.EscapeString(new_str); LoginDatabase.EscapeString(new_str);
LoginDatabase.PExecute("INSERT INTO logs (time, realm, type, string) " LoginDatabase.PExecute("INSERT INTO logs (time, realm, type, string) "
"VALUES (" UI64FMTD ", %u, %u, '%s');", uint64(time(0)), realm, (uint32)type, new_str.c_str()); "VALUES (" UI64FMTD ", %u, %u, '%s');", uint64(time(0)), realm, (uint32)type, new_str.c_str());
} }
void Log::outString(const char * str, ...) void Log::outString(const char* str, ...)
{ {
if (!str) if (!str)
return; return;
@@ -423,7 +423,7 @@ void Log::outString()
fflush(stdout); fflush(stdout);
} }
void Log::outCrash(const char * err, ...) void Log::outCrash(const char* err, ...)
{ {
if (!err) if (!err)
return; return;
@@ -466,7 +466,7 @@ void Log::outCrash(const char * err, ...)
fflush(stderr); fflush(stderr);
} }
void Log::outError(const char * err, ...) void Log::outError(const char* err, ...)
{ {
if (!err) if (!err)
return; return;
@@ -537,7 +537,7 @@ void Log::outSQLDriver(const char* str, ...)
fflush(stdout); fflush(stdout);
} }
void Log::outErrorDb(const char * err, ...) void Log::outErrorDb(const char* err, ...)
{ {
if (!err) if (!err)
return; return;
@@ -592,7 +592,7 @@ void Log::outErrorDb(const char * err, ...)
fflush(stderr); fflush(stderr);
} }
void Log::outBasic(const char * str, ...) void Log::outBasic(const char* str, ...)
{ {
if (!str) if (!str)
return; return;
@@ -636,7 +636,7 @@ void Log::outBasic(const char * str, ...)
fflush(stdout); fflush(stdout);
} }
void Log::outDetail(const char * str, ...) void Log::outDetail(const char* str, ...)
{ {
if (!str) if (!str)
return; return;
@@ -708,7 +708,7 @@ void Log::outSQLDev(const char* str, ...)
fflush(stdout); fflush(stdout);
} }
void Log::outDebug(DebugLogFilters f, const char * str, ...) void Log::outDebug(DebugLogFilters f, const char* str, ...)
{ {
if (!(m_DebugLogMask & f)) if (!(m_DebugLogMask & f))
return; return;
@@ -756,7 +756,7 @@ void Log::outDebug(DebugLogFilters f, const char * str, ...)
fflush(stdout); fflush(stdout);
} }
void Log::outStaticDebug(const char * str, ...) void Log::outStaticDebug(const char* str, ...)
{ {
if (!str) if (!str)
return; return;
@@ -801,7 +801,7 @@ void Log::outStaticDebug(const char * str, ...)
fflush(stdout); fflush(stdout);
} }
void Log::outStringInLine(const char * str, ...) void Log::outStringInLine(const char* str, ...)
{ {
if (!str) if (!str)
return; return;
@@ -820,7 +820,7 @@ void Log::outStringInLine(const char * str, ...)
} }
} }
void Log::outCommand(uint32 account, const char * str, ...) void Log::outCommand(uint32 account, const char* str, ...)
{ {
if (!str) if (!str)
return; return;
@@ -890,7 +890,7 @@ void Log::outCommand(uint32 account, const char * str, ...)
fflush(stdout); fflush(stdout);
} }
void Log::outChar(const char * str, ...) void Log::outChar(const char* str, ...)
{ {
if (!str) if (!str)
return; return;
@@ -917,7 +917,7 @@ void Log::outChar(const char * str, ...)
} }
} }
void Log::outCharDump(const char * str, uint32 account_id, uint32 guid, const char * name) void Log::outCharDump(const char* str, uint32 account_id, uint32 guid, const char* name)
{ {
FILE* file = NULL; FILE* file = NULL;
if (m_charLog_Dump_Separate) if (m_charLog_Dump_Separate)
@@ -933,14 +933,14 @@ void Log::outCharDump(const char * str, uint32 account_id, uint32 guid, const ch
if (file) if (file)
{ {
fprintf(file, "== START DUMP == (account: %u guid: %u name: %s )\n%s\n== END DUMP ==\n", fprintf(file, "== START DUMP == (account: %u guid: %u name: %s )\n%s\n== END DUMP ==\n",
account_id, guid, name, str); account_id, guid, name, str);
fflush(file); fflush(file);
if (m_charLog_Dump_Separate) if (m_charLog_Dump_Separate)
fclose(file); fclose(file);
} }
} }
void Log::outChat(const char * str, ...) void Log::outChat(const char* str, ...)
{ {
if (!str) if (!str)
return; return;
@@ -967,7 +967,7 @@ void Log::outChat(const char * str, ...)
} }
} }
void Log::outRemote(const char * str, ...) void Log::outRemote(const char* str, ...)
{ {
if (!str) if (!str)
return; return;
@@ -994,7 +994,7 @@ void Log::outRemote(const char * str, ...)
} }
} }
void Log::outMisc(const char * str, ...) void Log::outMisc(const char* str, ...)
{ {
if (!str) if (!str)
return; return;

View File

@@ -58,7 +58,7 @@ enum LogTypes
LOG_TYPE_CRASH = 9, LOG_TYPE_CRASH = 9,
LOG_TYPE_CHAT = 10, LOG_TYPE_CHAT = 10,
LOG_TYPE_PERF = 11, LOG_TYPE_PERF = 11,
LOG_TYPE_MULTITH= 12, LOG_TYPE_MULTITH = 12,
MAX_LOG_TYPES MAX_LOG_TYPES
}; };
@@ -70,7 +70,7 @@ enum LogLevel
LOGL_DEBUG LOGL_DEBUG
}; };
const int LogLevels = int(LOGL_DEBUG)+1; const int LogLevels = int(LOGL_DEBUG) + 1;
enum ColorTypes enum ColorTypes
{ {
@@ -91,110 +91,110 @@ enum ColorTypes
WHITE WHITE
}; };
const int Colors = int(WHITE)+1; const int Colors = int(WHITE) + 1;
class Log class Log
{ {
private: private:
Log(); Log();
~Log(); ~Log();
Log(Log const&) = delete; Log(Log const&) = delete;
Log(Log&&) = delete; Log(Log&&) = delete;
Log& operator=(Log const&) = delete; Log& operator=(Log const&) = delete;
Log& operator=(Log&&) = delete; Log& operator=(Log&&) = delete;
public: public:
static Log* instance(); static Log* instance();
void Initialize();
void ReloadConfig(); void Initialize();
void InitColors(const std::string& init_str); void ReloadConfig();
void SetColor(bool stdout_stream, ColorTypes color);
void ResetColor(bool stdout_stream);
void outDB(LogTypes type, const char * str); void InitColors(const std::string& init_str);
void outString(const char * str, ...) ATTR_PRINTF(2, 3); void SetColor(bool stdout_stream, ColorTypes color);
void outString(); void ResetColor(bool stdout_stream);
void outStringInLine(const char * str, ...) ATTR_PRINTF(2, 3);
void outError(const char * err, ...) ATTR_PRINTF(2, 3);
void outCrash(const char * err, ...) ATTR_PRINTF(2, 3);
void outBasic(const char * str, ...) ATTR_PRINTF(2, 3);
void outDetail(const char * str, ...) ATTR_PRINTF(2, 3);
void outSQLDev(const char * str, ...) ATTR_PRINTF(2, 3);
void outDebug(DebugLogFilters f, const char* str, ...) ATTR_PRINTF(3, 4);
void outStaticDebug(const char * str, ...) ATTR_PRINTF(2, 3);
void outErrorDb(const char * str, ...) ATTR_PRINTF(2, 3);
void outChar(const char * str, ...) ATTR_PRINTF(2, 3);
void outCommand(uint32 account, const char * str, ...) ATTR_PRINTF(3, 4);
void outChat(const char * str, ...) ATTR_PRINTF(2, 3);
void outRemote(const char * str, ...) ATTR_PRINTF(2, 3);
void outSQLDriver(const char* str, ...) ATTR_PRINTF(2, 3);
void outMisc(const char * str, ...) ATTR_PRINTF(2, 3); // pussywizard
void outCharDump(const char * str, uint32 account_id, uint32 guid, const char * name);
static void outTimestamp(FILE* file); void outDB(LogTypes type, const char* str);
static std::string GetTimestampStr(); void outString(const char* str, ...) ATTR_PRINTF(2, 3);
void outString();
void outStringInLine(const char* str, ...) ATTR_PRINTF(2, 3);
void outError(const char* err, ...) ATTR_PRINTF(2, 3);
void outCrash(const char* err, ...) ATTR_PRINTF(2, 3);
void outBasic(const char* str, ...) ATTR_PRINTF(2, 3);
void outDetail(const char* str, ...) ATTR_PRINTF(2, 3);
void outSQLDev(const char* str, ...) ATTR_PRINTF(2, 3);
void outDebug(DebugLogFilters f, const char* str, ...) ATTR_PRINTF(3, 4);
void outStaticDebug(const char* str, ...) ATTR_PRINTF(2, 3);
void outErrorDb(const char* str, ...) ATTR_PRINTF(2, 3);
void outChar(const char* str, ...) ATTR_PRINTF(2, 3);
void outCommand(uint32 account, const char* str, ...) ATTR_PRINTF(3, 4);
void outChat(const char* str, ...) ATTR_PRINTF(2, 3);
void outRemote(const char* str, ...) ATTR_PRINTF(2, 3);
void outSQLDriver(const char* str, ...) ATTR_PRINTF(2, 3);
void outMisc(const char* str, ...) ATTR_PRINTF(2, 3); // pussywizard
void outCharDump(const char* str, uint32 account_id, uint32 guid, const char* name);
void SetLogLevel(char * Level); static void outTimestamp(FILE* file);
void SetLogFileLevel(char * Level); static std::string GetTimestampStr();
void SetSQLDriverQueryLogging(bool newStatus) { m_sqlDriverQueryLogging = newStatus; }
void SetRealmID(uint32 id) { realm = id; }
bool IsOutDebug() const { return m_logLevel > 2 || (m_logFileLevel > 2 && logfile); } void SetLogLevel(char* Level);
bool IsOutCharDump() const { return m_charLog_Dump; } void SetLogFileLevel(char* Level);
void SetSQLDriverQueryLogging(bool newStatus) { m_sqlDriverQueryLogging = newStatus; }
void SetRealmID(uint32 id) { realm = id; }
bool GetLogDB() const { return m_enableLogDB; } bool IsOutDebug() const { return m_logLevel > 2 || (m_logFileLevel > 2 && logfile); }
void SetLogDB(bool enable) { m_enableLogDB = enable; } bool IsOutCharDump() const { return m_charLog_Dump; }
bool GetSQLDriverQueryLogging() const { return m_sqlDriverQueryLogging; }
private:
FILE* openLogFile(char const* configFileName, char const* configTimeStampFlag, char const* mode);
FILE* openGmlogPerAccount(uint32 account);
FILE* raLogfile; bool GetLogDB() const { return m_enableLogDB; }
FILE* logfile; void SetLogDB(bool enable) { m_enableLogDB = enable; }
FILE* gmLogfile; bool GetSQLDriverQueryLogging() const { return m_sqlDriverQueryLogging; }
FILE* charLogfile; private:
FILE* dberLogfile; FILE* openLogFile(char const* configFileName, char const* configTimeStampFlag, char const* mode);
FILE* chatLogfile; FILE* openGmlogPerAccount(uint32 account);
FILE* sqlLogFile;
FILE* sqlDevLogFile;
FILE* miscLogFile;
// cache values for after initilization use (like gm log per account case) FILE* raLogfile;
std::string m_logsDir; FILE* logfile;
std::string m_logsTimestamp; FILE* gmLogfile;
FILE* charLogfile;
FILE* dberLogfile;
FILE* chatLogfile;
FILE* sqlLogFile;
FILE* sqlDevLogFile;
FILE* miscLogFile;
// gm log control // cache values for after initilization use (like gm log per account case)
bool m_gmlog_per_account; std::string m_logsDir;
std::string m_gmlog_filename_format; std::string m_logsTimestamp;
bool m_enableLogDB; // gm log control
uint32 realm; bool m_gmlog_per_account;
std::string m_gmlog_filename_format;
// log coloring bool m_enableLogDB;
bool m_colored; uint32 realm;
ColorTypes m_colors[4];
// log levels: // log coloring
// false: errors only, true: full query logging bool m_colored;
bool m_sqlDriverQueryLogging; ColorTypes m_colors[4];
// log levels: // log levels:
// 0 minimum/string, 1 basic/error, 2 detail, 3 full/debug // false: errors only, true: full query logging
uint8 m_dbLogLevel; bool m_sqlDriverQueryLogging;
uint8 m_logLevel;
uint8 m_logFileLevel;
bool m_dbChar;
bool m_dbRA;
bool m_dbGM;
bool m_dbChat;
bool m_charLog_Dump;
bool m_charLog_Dump_Separate;
std::string m_dumpsDir;
DebugLogFilters m_DebugLogMask; // log levels:
// 0 minimum/string, 1 basic/error, 2 detail, 3 full/debug
uint8 m_dbLogLevel;
uint8 m_logLevel;
uint8 m_logFileLevel;
bool m_dbChar;
bool m_dbRA;
bool m_dbGM;
bool m_dbChat;
bool m_charLog_Dump;
bool m_charLog_Dump_Separate;
std::string m_dumpsDir;
DebugLogFilters m_DebugLogMask;
}; };
#define sLog Log::instance() #define sLog Log::instance()

View File

@@ -12,7 +12,7 @@
#include <sstream> #include <sstream>
ByteBufferPositionException::ByteBufferPositionException(bool add, size_t pos, ByteBufferPositionException::ByteBufferPositionException(bool add, size_t pos,
size_t size, size_t valueSize) size_t size, size_t valueSize)
{ {
std::ostringstream ss; std::ostringstream ss;
@@ -24,7 +24,7 @@ ByteBufferPositionException::ByteBufferPositionException(bool add, size_t pos,
} }
ByteBufferSourceException::ByteBufferSourceException(size_t pos, size_t size, ByteBufferSourceException::ByteBufferSourceException(size_t pos, size_t size,
size_t valueSize) size_t valueSize)
{ {
std::ostringstream ss; std::ostringstream ss;

View File

@@ -27,7 +27,7 @@ public:
char const* what() const throw() { return msg_.c_str(); } char const* what() const throw() { return msg_.c_str(); }
protected: protected:
std::string & message() throw() { return msg_; } std::string& message() throw() { return msg_; }
private: private:
std::string msg_; std::string msg_;
@@ -51,466 +51,466 @@ public:
class ByteBuffer class ByteBuffer
{ {
public: public:
const static size_t DEFAULT_SIZE = 0x1000; const static size_t DEFAULT_SIZE = 0x1000;
// constructor // constructor
ByteBuffer() : _rpos(0), _wpos(0) ByteBuffer() : _rpos(0), _wpos(0)
{
_storage.reserve(DEFAULT_SIZE);
}
ByteBuffer(size_t reserve) : _rpos(0), _wpos(0)
{
_storage.reserve(reserve);
}
// copy constructor
ByteBuffer(const ByteBuffer& buf) : _rpos(buf._rpos), _wpos(buf._wpos),
_storage(buf._storage)
{
}
/* requried as of C++ 11 */
#if __cplusplus >= 201103L
ByteBuffer(ByteBuffer&&) = default;
ByteBuffer& operator=(const ByteBuffer&) = default;
ByteBuffer& operator=(ByteBuffer&&) = default;
#endif
void clear()
{
_storage.clear();
_rpos = _wpos = 0;
}
template <typename T> void append(T value)
{
EndianConvert(value);
append((uint8*)&value, sizeof(value));
}
template <typename T> void put(size_t pos, T value)
{
EndianConvert(value);
put(pos, (uint8*)&value, sizeof(value));
}
ByteBuffer& operator<<(uint8 value)
{
append<uint8>(value);
return *this;
}
ByteBuffer& operator<<(uint16 value)
{
append<uint16>(value);
return *this;
}
ByteBuffer& operator<<(uint32 value)
{
append<uint32>(value);
return *this;
}
ByteBuffer& operator<<(uint64 value)
{
append<uint64>(value);
return *this;
}
// signed as in 2e complement
ByteBuffer& operator<<(int8 value)
{
append<int8>(value);
return *this;
}
ByteBuffer& operator<<(int16 value)
{
append<int16>(value);
return *this;
}
ByteBuffer& operator<<(int32 value)
{
append<int32>(value);
return *this;
}
ByteBuffer& operator<<(int64 value)
{
append<int64>(value);
return *this;
}
// floating points
ByteBuffer& operator<<(float value)
{
append<float>(value);
return *this;
}
ByteBuffer& operator<<(double value)
{
append<double>(value);
return *this;
}
ByteBuffer& operator<<(const std::string& value)
{
if (size_t len = value.length())
append((uint8 const*)value.c_str(), len);
append((uint8)0);
return *this;
}
ByteBuffer& operator<<(const char* str)
{
if (size_t len = (str ? strlen(str) : 0))
append((uint8 const*)str, len);
append((uint8)0);
return *this;
}
ByteBuffer& operator>>(bool& value)
{
value = (read<char>() > 0);
return *this;
}
ByteBuffer& operator>>(uint8& value)
{
value = read<uint8>();
return *this;
}
ByteBuffer& operator>>(uint16& value)
{
value = read<uint16>();
return *this;
}
ByteBuffer& operator>>(uint32& value)
{
value = read<uint32>();
return *this;
}
ByteBuffer& operator>>(uint64& value)
{
value = read<uint64>();
return *this;
}
//signed as in 2e complement
ByteBuffer& operator>>(int8& value)
{
value = read<int8>();
return *this;
}
ByteBuffer& operator>>(int16& value)
{
value = read<int16>();
return *this;
}
ByteBuffer& operator>>(int32& value)
{
value = read<int32>();
return *this;
}
ByteBuffer& operator>>(int64& value)
{
value = read<int64>();
return *this;
}
ByteBuffer& operator>>(float& value)
{
value = read<float>();
if (!myisfinite(value))
{ {
_storage.reserve(DEFAULT_SIZE); value = 0.0f;
//throw ByteBufferException();
} }
return *this;
}
ByteBuffer(size_t reserve) : _rpos(0), _wpos(0) ByteBuffer& operator>>(double& value)
{
value = read<double>();
if (!myisfinite(value))
{ {
_storage.reserve(reserve); value = 0.0f;
//throw ByteBufferException();
} }
return *this;
}
// copy constructor ByteBuffer& operator>>(std::string& value)
ByteBuffer(const ByteBuffer &buf) : _rpos(buf._rpos), _wpos(buf._wpos), {
_storage(buf._storage) value.clear();
while (rpos() < size()) // prevent crash at wrong string format in packet
{ {
char c = read<char>();
if (c == 0)
break;
value += c;
} }
/* requried as of C++ 11 */ return *this;
#if __cplusplus >= 201103L }
ByteBuffer(ByteBuffer&&) = default;
ByteBuffer& operator=(const ByteBuffer&) = default;
ByteBuffer& operator=(ByteBuffer&&) = default;
#endif
void clear() uint8& operator[](size_t const pos)
{ {
_storage.clear(); if (pos >= size())
_rpos = _wpos = 0; throw ByteBufferPositionException(false, pos, 1, size());
} return _storage[pos];
}
template <typename T> void append(T value) uint8 const& operator[](size_t const pos) const
{ {
EndianConvert(value); if (pos >= size())
append((uint8 *)&value, sizeof(value)); throw ByteBufferPositionException(false, pos, 1, size());
} return _storage[pos];
}
template <typename T> void put(size_t pos, T value) size_t rpos() const { return _rpos; }
{
EndianConvert(value);
put(pos, (uint8 *)&value, sizeof(value));
}
ByteBuffer &operator<<(uint8 value) size_t rpos(size_t rpos_)
{ {
append<uint8>(value); _rpos = rpos_;
return *this; return _rpos;
} }
ByteBuffer &operator<<(uint16 value) void rfinish()
{ {
append<uint16>(value); _rpos = wpos();
return *this; }
}
ByteBuffer &operator<<(uint32 value) size_t wpos() const { return _wpos; }
{
append<uint32>(value);
return *this;
}
ByteBuffer &operator<<(uint64 value) size_t wpos(size_t wpos_)
{ {
append<uint64>(value); _wpos = wpos_;
return *this; return _wpos;
} }
// signed as in 2e complement template<typename T>
ByteBuffer &operator<<(int8 value) void read_skip() { read_skip(sizeof(T)); }
{
append<int8>(value);
return *this;
}
ByteBuffer &operator<<(int16 value) void read_skip(size_t skip)
{ {
append<int16>(value); if (_rpos + skip > size())
return *this; throw ByteBufferPositionException(false, _rpos, skip, size());
} _rpos += skip;
}
ByteBuffer &operator<<(int32 value) template <typename T> T read()
{ {
append<int32>(value); T r = read<T>(_rpos);
return *this; _rpos += sizeof(T);
} return r;
}
ByteBuffer &operator<<(int64 value) template <typename T> T read(size_t pos) const
{ {
append<int64>(value); if (pos + sizeof(T) > size())
return *this; throw ByteBufferPositionException(false, pos, sizeof(T), size());
} T val = *((T const*)&_storage[pos]);
EndianConvert(val);
return val;
}
// floating points void read(uint8* dest, size_t len)
ByteBuffer &operator<<(float value) {
{ if (_rpos + len > size())
append<float>(value); throw ByteBufferPositionException(false, _rpos, len, size());
return *this; std::memcpy(dest, &_storage[_rpos], len);
} _rpos += len;
}
ByteBuffer &operator<<(double value) void readPackGUID(uint64& guid)
{ {
append<double>(value); if (rpos() + 1 > size())
return *this; throw ByteBufferPositionException(false, _rpos, 1, size());
}
ByteBuffer &operator<<(const std::string &value) guid = 0;
{
if (size_t len = value.length())
append((uint8 const*)value.c_str(), len);
append((uint8)0);
return *this;
}
ByteBuffer &operator<<(const char *str) uint8 guidmark = 0;
{ (*this) >> guidmark;
if (size_t len = (str ? strlen(str) : 0))
append((uint8 const*)str, len);
append((uint8)0);
return *this;
}
ByteBuffer &operator>>(bool &value) for (int i = 0; i < 8; ++i)
{ {
value = (read<char>() > 0); if (guidmark & (uint8(1) << i))
return *this;
}
ByteBuffer &operator>>(uint8 &value)
{
value = read<uint8>();
return *this;
}
ByteBuffer &operator>>(uint16 &value)
{
value = read<uint16>();
return *this;
}
ByteBuffer &operator>>(uint32 &value)
{
value = read<uint32>();
return *this;
}
ByteBuffer &operator>>(uint64 &value)
{
value = read<uint64>();
return *this;
}
//signed as in 2e complement
ByteBuffer &operator>>(int8 &value)
{
value = read<int8>();
return *this;
}
ByteBuffer &operator>>(int16 &value)
{
value = read<int16>();
return *this;
}
ByteBuffer &operator>>(int32 &value)
{
value = read<int32>();
return *this;
}
ByteBuffer &operator>>(int64 &value)
{
value = read<int64>();
return *this;
}
ByteBuffer &operator>>(float &value)
{
value = read<float>();
if (!myisfinite(value))
{ {
value = 0.0f; if (rpos() + 1 > size())
//throw ByteBufferException(); throw ByteBufferPositionException(false, _rpos, 1, size());
}
return *this;
}
ByteBuffer &operator>>(double &value) uint8 bit;
{ (*this) >> bit;
value = read<double>(); guid |= (uint64(bit) << (i * 8));
if (!myisfinite(value))
{
value = 0.0f;
//throw ByteBufferException();
}
return *this;
}
ByteBuffer &operator>>(std::string& value)
{
value.clear();
while (rpos() < size()) // prevent crash at wrong string format in packet
{
char c = read<char>();
if (c == 0)
break;
value += c;
}
return *this;
}
uint8& operator[](size_t const pos)
{
if (pos >= size())
throw ByteBufferPositionException(false, pos, 1, size());
return _storage[pos];
}
uint8 const& operator[](size_t const pos) const
{
if (pos >= size())
throw ByteBufferPositionException(false, pos, 1, size());
return _storage[pos];
}
size_t rpos() const { return _rpos; }
size_t rpos(size_t rpos_)
{
_rpos = rpos_;
return _rpos;
}
void rfinish()
{
_rpos = wpos();
}
size_t wpos() const { return _wpos; }
size_t wpos(size_t wpos_)
{
_wpos = wpos_;
return _wpos;
}
template<typename T>
void read_skip() { read_skip(sizeof(T)); }
void read_skip(size_t skip)
{
if (_rpos + skip > size())
throw ByteBufferPositionException(false, _rpos, skip, size());
_rpos += skip;
}
template <typename T> T read()
{
T r = read<T>(_rpos);
_rpos += sizeof(T);
return r;
}
template <typename T> T read(size_t pos) const
{
if (pos + sizeof(T) > size())
throw ByteBufferPositionException(false, pos, sizeof(T), size());
T val = *((T const*)&_storage[pos]);
EndianConvert(val);
return val;
}
void read(uint8 *dest, size_t len)
{
if (_rpos + len > size())
throw ByteBufferPositionException(false, _rpos, len, size());
std::memcpy(dest, &_storage[_rpos], len);
_rpos += len;
}
void readPackGUID(uint64& guid)
{
if (rpos() + 1 > size())
throw ByteBufferPositionException(false, _rpos, 1, size());
guid = 0;
uint8 guidmark = 0;
(*this) >> guidmark;
for (int i = 0; i < 8; ++i)
{
if (guidmark & (uint8(1) << i))
{
if (rpos() + 1 > size())
throw ByteBufferPositionException(false, _rpos, 1, size());
uint8 bit;
(*this) >> bit;
guid |= (uint64(bit) << (i * 8));
}
} }
} }
}
uint32 ReadPackedTime() uint32 ReadPackedTime()
{
uint32 packedDate = read<uint32>();
tm lt = tm();
lt.tm_min = packedDate & 0x3F;
lt.tm_hour = (packedDate >> 6) & 0x1F;
//lt.tm_wday = (packedDate >> 11) & 7;
lt.tm_mday = ((packedDate >> 14) & 0x3F) + 1;
lt.tm_mon = (packedDate >> 20) & 0xF;
lt.tm_year = ((packedDate >> 24) & 0x1F) + 100;
return uint32(mktime(&lt));
}
ByteBuffer& ReadPackedTime(uint32& time)
{
time = ReadPackedTime();
return *this;
}
uint8* contents()
{
if (_storage.empty())
throw ByteBufferException();
return &_storage[0];
}
const uint8* contents() const
{
if (_storage.empty())
throw ByteBufferException();
return &_storage[0];
}
size_t size() const { return _storage.size(); }
bool empty() const { return _storage.empty(); }
void resize(size_t newsize)
{
_storage.resize(newsize, 0);
_rpos = 0;
_wpos = size();
}
void reserve(size_t ressize)
{
if (ressize > size())
_storage.reserve(ressize);
}
void append(const char* src, size_t cnt)
{
return append((const uint8*)src, cnt);
}
template<class T> void append(const T* src, size_t cnt)
{
return append((const uint8*)src, cnt * sizeof(T));
}
void append(const uint8* src, size_t cnt)
{
if (!cnt)
throw ByteBufferSourceException(_wpos, size(), cnt);
if (!src)
throw ByteBufferSourceException(_wpos, size(), cnt);
ASSERT(size() < 10000000);
size_t newsize = _wpos + cnt;
if (_storage.capacity() < newsize) // pussywizard
{ {
uint32 packedDate = read<uint32>(); if (newsize < 100)
tm lt = tm(); _storage.reserve(300);
else if (newsize < 750)
lt.tm_min = packedDate & 0x3F; _storage.reserve(2500);
lt.tm_hour = (packedDate >> 6) & 0x1F; else if (newsize < 6000)
//lt.tm_wday = (packedDate >> 11) & 7; _storage.reserve(10000);
lt.tm_mday = ((packedDate >> 14) & 0x3F) + 1; else
lt.tm_mon = (packedDate >> 20) & 0xF; _storage.reserve(400000);
lt.tm_year = ((packedDate >> 24) & 0x1F) + 100;
return uint32(mktime(&lt));
} }
ByteBuffer& ReadPackedTime(uint32& time) if (_storage.size() < newsize)
_storage.resize(newsize);
memcpy(&_storage[_wpos], src, cnt);
_wpos = newsize;
}
void append(const ByteBuffer& buffer)
{
if (buffer.wpos())
append(buffer.contents(), buffer.wpos());
}
// can be used in SMSG_MONSTER_MOVE opcode
void appendPackXYZ(float x, float y, float z)
{
uint32 packed = 0;
packed |= ((int)(x / 0.25f) & 0x7FF);
packed |= ((int)(y / 0.25f) & 0x7FF) << 11;
packed |= ((int)(z / 0.25f) & 0x3FF) << 22;
*this << packed;
}
void appendPackGUID(uint64 guid)
{
uint8 packGUID[8 + 1];
packGUID[0] = 0;
size_t size = 1;
for (uint8 i = 0; guid != 0; ++i)
{ {
time = ReadPackedTime(); if (guid & 0xFF)
return *this;
}
uint8 * contents()
{
if (_storage.empty())
throw ByteBufferException();
return &_storage[0];
}
const uint8 *contents() const
{
if (_storage.empty())
throw ByteBufferException();
return &_storage[0];
}
size_t size() const { return _storage.size(); }
bool empty() const { return _storage.empty(); }
void resize(size_t newsize)
{
_storage.resize(newsize, 0);
_rpos = 0;
_wpos = size();
}
void reserve(size_t ressize)
{
if (ressize > size())
_storage.reserve(ressize);
}
void append(const char *src, size_t cnt)
{
return append((const uint8 *)src, cnt);
}
template<class T> void append(const T *src, size_t cnt)
{
return append((const uint8 *)src, cnt * sizeof(T));
}
void append(const uint8 *src, size_t cnt)
{
if (!cnt)
throw ByteBufferSourceException(_wpos, size(), cnt);
if (!src)
throw ByteBufferSourceException(_wpos, size(), cnt);
ASSERT(size() < 10000000);
size_t newsize = _wpos + cnt;
if (_storage.capacity() < newsize) // pussywizard
{ {
if (newsize < 100) packGUID[0] |= uint8(1 << i);
_storage.reserve(300); packGUID[size] = uint8(guid & 0xFF);
else if (newsize < 750) ++size;
_storage.reserve(2500);
else if (newsize < 6000)
_storage.reserve(10000);
else
_storage.reserve(400000);
} }
if (_storage.size() < newsize) guid >>= 8;
_storage.resize(newsize);
memcpy(&_storage[_wpos], src, cnt);
_wpos = newsize;
} }
append(packGUID, size);
}
void append(const ByteBuffer& buffer) void AppendPackedTime(time_t time)
{ {
if (buffer.wpos()) tm lt;
append(buffer.contents(), buffer.wpos()); localtime_r(&time, &lt);
} append<uint32>((lt.tm_year - 100) << 24 | lt.tm_mon << 20 | (lt.tm_mday - 1) << 14 | lt.tm_wday << 11 | lt.tm_hour << 6 | lt.tm_min);
}
// can be used in SMSG_MONSTER_MOVE opcode void put(size_t pos, const uint8* src, size_t cnt)
void appendPackXYZ(float x, float y, float z) {
{ if (pos + cnt > size())
uint32 packed = 0; throw ByteBufferPositionException(true, pos, cnt, size());
packed |= ((int)(x / 0.25f) & 0x7FF);
packed |= ((int)(y / 0.25f) & 0x7FF) << 11;
packed |= ((int)(z / 0.25f) & 0x3FF) << 22;
*this << packed;
}
void appendPackGUID(uint64 guid) if (!src)
{ throw ByteBufferSourceException(_wpos, size(), cnt);
uint8 packGUID[8+1];
packGUID[0] = 0;
size_t size = 1;
for (uint8 i = 0;guid != 0;++i)
{
if (guid & 0xFF)
{
packGUID[0] |= uint8(1 << i);
packGUID[size] = uint8(guid & 0xFF);
++size;
}
guid >>= 8; std::memcpy(&_storage[pos], src, cnt);
} }
append(packGUID, size);
}
void AppendPackedTime(time_t time) void hexlike(bool outString = false) const;
{
tm lt;
localtime_r(&time, &lt);
append<uint32>((lt.tm_year - 100) << 24 | lt.tm_mon << 20 | (lt.tm_mday - 1) << 14 | lt.tm_wday << 11 | lt.tm_hour << 6 | lt.tm_min);
}
void put(size_t pos, const uint8 *src, size_t cnt) protected:
{ size_t _rpos, _wpos;
if (pos + cnt > size()) std::vector<uint8> _storage;
throw ByteBufferPositionException(true, pos, cnt, size());
if (!src)
throw ByteBufferSourceException(_wpos, size(), cnt);
std::memcpy(&_storage[pos], src, cnt);
}
void hexlike(bool outString = false) const;
protected:
size_t _rpos, _wpos;
std::vector<uint8> _storage;
}; };
template <typename T> template <typename T>
inline ByteBuffer &operator<<(ByteBuffer &b, std::vector<T> v) inline ByteBuffer& operator<<(ByteBuffer& b, std::vector<T> v)
{ {
b << (uint32)v.size(); b << (uint32)v.size();
for (typename std::vector<T>::iterator i = v.begin(); i != v.end(); ++i) for (typename std::vector<T>::iterator i = v.begin(); i != v.end(); ++i)
@@ -521,7 +521,7 @@ inline ByteBuffer &operator<<(ByteBuffer &b, std::vector<T> v)
} }
template <typename T> template <typename T>
inline ByteBuffer &operator>>(ByteBuffer &b, std::vector<T> &v) inline ByteBuffer& operator>>(ByteBuffer& b, std::vector<T>& v)
{ {
uint32 vsize; uint32 vsize;
b >> vsize; b >> vsize;
@@ -536,7 +536,7 @@ inline ByteBuffer &operator>>(ByteBuffer &b, std::vector<T> &v)
} }
template <typename T> template <typename T>
inline ByteBuffer &operator<<(ByteBuffer &b, std::list<T> v) inline ByteBuffer& operator<<(ByteBuffer& b, std::list<T> v)
{ {
b << (uint32)v.size(); b << (uint32)v.size();
for (typename std::list<T>::iterator i = v.begin(); i != v.end(); ++i) for (typename std::list<T>::iterator i = v.begin(); i != v.end(); ++i)
@@ -547,7 +547,7 @@ inline ByteBuffer &operator<<(ByteBuffer &b, std::list<T> v)
} }
template <typename T> template <typename T>
inline ByteBuffer &operator>>(ByteBuffer &b, std::list<T> &v) inline ByteBuffer& operator>>(ByteBuffer& b, std::list<T>& v)
{ {
uint32 vsize; uint32 vsize;
b >> vsize; b >> vsize;
@@ -562,7 +562,7 @@ inline ByteBuffer &operator>>(ByteBuffer &b, std::list<T> &v)
} }
template <typename K, typename V> template <typename K, typename V>
inline ByteBuffer &operator<<(ByteBuffer &b, std::map<K, V> &m) inline ByteBuffer& operator<<(ByteBuffer& b, std::map<K, V>& m)
{ {
b << (uint32)m.size(); b << (uint32)m.size();
for (typename std::map<K, V>::iterator i = m.begin(); i != m.end(); ++i) for (typename std::map<K, V>::iterator i = m.begin(); i != m.end(); ++i)
@@ -573,7 +573,7 @@ inline ByteBuffer &operator<<(ByteBuffer &b, std::map<K, V> &m)
} }
template <typename K, typename V> template <typename K, typename V>
inline ByteBuffer &operator>>(ByteBuffer &b, std::map<K, V> &m) inline ByteBuffer& operator>>(ByteBuffer& b, std::map<K, V>& m)
{ {
uint32 msize; uint32 msize;
b >> msize; b >> msize;

View File

@@ -12,34 +12,34 @@
class WorldPacket : public ByteBuffer class WorldPacket : public ByteBuffer
{ {
public: public:
// just container for later use // just container for later use
WorldPacket() : ByteBuffer(0), m_opcode(0) WorldPacket() : ByteBuffer(0), m_opcode(0)
{ {
} }
explicit WorldPacket(uint16 opcode, size_t res=200) : ByteBuffer(res), m_opcode(opcode) { } explicit WorldPacket(uint16 opcode, size_t res = 200) : ByteBuffer(res), m_opcode(opcode) { }
// copy constructor // copy constructor
WorldPacket(const WorldPacket &packet) : ByteBuffer(packet), m_opcode(packet.m_opcode) WorldPacket(const WorldPacket& packet) : ByteBuffer(packet), m_opcode(packet.m_opcode)
{ {
} }
/* requried as of C++ 11 */ /* requried as of C++ 11 */
#if __cplusplus >= 201103L #if __cplusplus >= 201103L
WorldPacket(WorldPacket&&) = default; WorldPacket(WorldPacket&&) = default;
WorldPacket& operator=(const WorldPacket&) = default; WorldPacket& operator=(const WorldPacket&) = default;
WorldPacket& operator=(WorldPacket&&) = default; WorldPacket& operator=(WorldPacket&&) = default;
#endif #endif
void Initialize(uint16 opcode, size_t newres=200) void Initialize(uint16 opcode, size_t newres = 200)
{ {
clear(); clear();
_storage.reserve(newres); _storage.reserve(newres);
m_opcode = opcode; m_opcode = opcode;
} }
uint16 GetOpcode() const { return m_opcode; } uint16 GetOpcode() const { return m_opcode; }
void SetOpcode(uint16 opcode) { m_opcode = opcode; } void SetOpcode(uint16 opcode) { m_opcode = opcode; }
protected: protected:
uint16 m_opcode; uint16 m_opcode;
}; };
#endif #endif

View File

@@ -23,277 +23,277 @@ typedef ACE_Future<PreparedQueryResult> PreparedQueryResultFuture;
template <typename Result, typename ParamType, bool chain = false> template <typename Result, typename ParamType, bool chain = false>
class QueryCallback class QueryCallback
{ {
public: public:
QueryCallback() : _param(), _stage(chain ? 0 : CALLBACK_STAGE_INVALID) {} QueryCallback() : _param(), _stage(chain ? 0 : CALLBACK_STAGE_INVALID) {}
//! The parameter of this function should be a resultset returned from either .AsyncQuery or .AsyncPQuery //! The parameter of this function should be a resultset returned from either .AsyncQuery or .AsyncPQuery
void SetFutureResult(ACE_Future<Result> value) void SetFutureResult(ACE_Future<Result> value)
{ {
_result = value; _result = value;
} }
ACE_Future<Result> GetFutureResult() ACE_Future<Result> GetFutureResult()
{ {
return _result; return _result;
} }
int IsReady() int IsReady()
{ {
return _result.ready(); return _result.ready();
} }
void GetResult(Result& res) void GetResult(Result& res)
{ {
_result.get(res); _result.get(res);
} }
void FreeResult() void FreeResult()
{ {
_result.cancel(); _result.cancel();
} }
void SetParam(ParamType value) void SetParam(ParamType value)
{ {
_param = value; _param = value;
} }
ParamType GetParam() ParamType GetParam()
{ {
return _param; return _param;
} }
//! Resets the stage of the callback chain //! Resets the stage of the callback chain
void ResetStage() void ResetStage()
{ {
if (!chain) if (!chain)
return; return;
_stage = 0; _stage = 0;
} }
//! Advances the callback chain to the next stage, so upper level code can act on its results accordingly //! Advances the callback chain to the next stage, so upper level code can act on its results accordingly
void NextStage() void NextStage()
{ {
if (!chain) if (!chain)
return; return;
++_stage; ++_stage;
} }
//! Returns the callback stage (or CALLBACK_STAGE_INVALID if invalid) //! Returns the callback stage (or CALLBACK_STAGE_INVALID if invalid)
uint8 GetStage() uint8 GetStage()
{ {
return _stage; return _stage;
} }
//! Resets all underlying variables (param, result and stage) //! Resets all underlying variables (param, result and stage)
void Reset() void Reset()
{ {
SetParam(NULL); SetParam(NULL);
FreeResult(); FreeResult();
ResetStage(); ResetStage();
} }
private: private:
ACE_Future<Result> _result; ACE_Future<Result> _result;
ParamType _param; ParamType _param;
uint8 _stage; uint8 _stage;
}; };
template <typename Result, typename ParamType1, typename ParamType2, bool chain = false> template <typename Result, typename ParamType1, typename ParamType2, bool chain = false>
class QueryCallback_2 class QueryCallback_2
{ {
public: public:
QueryCallback_2() : _stage(chain ? 0 : CALLBACK_STAGE_INVALID) {} QueryCallback_2() : _stage(chain ? 0 : CALLBACK_STAGE_INVALID) {}
//! The parameter of this function should be a resultset returned from either .AsyncQuery or .AsyncPQuery //! The parameter of this function should be a resultset returned from either .AsyncQuery or .AsyncPQuery
void SetFutureResult(ACE_Future<Result> value) void SetFutureResult(ACE_Future<Result> value)
{ {
_result = value; _result = value;
} }
ACE_Future<Result> GetFutureResult() ACE_Future<Result> GetFutureResult()
{ {
return _result; return _result;
} }
int IsReady() int IsReady()
{ {
return _result.ready(); return _result.ready();
} }
void GetResult(Result& res) void GetResult(Result& res)
{ {
_result.get(res); _result.get(res);
} }
void FreeResult() void FreeResult()
{ {
_result.cancel(); _result.cancel();
} }
void SetFirstParam(ParamType1 value) void SetFirstParam(ParamType1 value)
{ {
_param_1 = value; _param_1 = value;
} }
void SetSecondParam(ParamType2 value) void SetSecondParam(ParamType2 value)
{ {
_param_2 = value; _param_2 = value;
} }
ParamType1 GetFirstParam() ParamType1 GetFirstParam()
{ {
return _param_1; return _param_1;
} }
ParamType2 GetSecondParam() ParamType2 GetSecondParam()
{ {
return _param_2; return _param_2;
} }
//! Resets the stage of the callback chain //! Resets the stage of the callback chain
void ResetStage() void ResetStage()
{ {
if (!chain) if (!chain)
return; return;
_stage = 0; _stage = 0;
} }
//! Advances the callback chain to the next stage, so upper level code can act on its results accordingly //! Advances the callback chain to the next stage, so upper level code can act on its results accordingly
void NextStage() void NextStage()
{ {
if (!chain) if (!chain)
return; return;
++_stage; ++_stage;
} }
//! Returns the callback stage (or CALLBACK_STAGE_INVALID if invalid) //! Returns the callback stage (or CALLBACK_STAGE_INVALID if invalid)
uint8 GetStage() uint8 GetStage()
{ {
return _stage; return _stage;
} }
//! Resets all underlying variables (param, result and stage) //! Resets all underlying variables (param, result and stage)
void Reset() void Reset()
{ {
SetFirstParam(0); SetFirstParam(0);
SetSecondParam(NULL); SetSecondParam(NULL);
FreeResult(); FreeResult();
ResetStage(); ResetStage();
} }
private: private:
ACE_Future<Result> _result; ACE_Future<Result> _result;
ParamType1 _param_1; ParamType1 _param_1;
ParamType2 _param_2; ParamType2 _param_2;
uint8 _stage; uint8 _stage;
}; };
template <typename Result, typename ParamType1, typename ParamType2, typename ParamType3, bool chain = false> template <typename Result, typename ParamType1, typename ParamType2, typename ParamType3, bool chain = false>
class QueryCallback_3 class QueryCallback_3
{ {
public: public:
QueryCallback_3() : _stage(chain ? 0 : CALLBACK_STAGE_INVALID) {} QueryCallback_3() : _stage(chain ? 0 : CALLBACK_STAGE_INVALID) {}
//! The parameter of this function should be a resultset returned from either .AsyncQuery or .AsyncPQuery //! The parameter of this function should be a resultset returned from either .AsyncQuery or .AsyncPQuery
void SetFutureResult(ACE_Future<Result> value) void SetFutureResult(ACE_Future<Result> value)
{ {
_result = value; _result = value;
} }
ACE_Future<Result> GetFutureResult() ACE_Future<Result> GetFutureResult()
{ {
return _result; return _result;
} }
int IsReady() int IsReady()
{ {
return _result.ready(); return _result.ready();
} }
void GetResult(Result& res) void GetResult(Result& res)
{ {
_result.get(res); _result.get(res);
} }
void FreeResult() void FreeResult()
{ {
_result.cancel(); _result.cancel();
} }
void SetFirstParam(ParamType1 value) void SetFirstParam(ParamType1 value)
{ {
_param_1 = value; _param_1 = value;
} }
void SetSecondParam(ParamType2 value) void SetSecondParam(ParamType2 value)
{ {
_param_2 = value; _param_2 = value;
} }
void SetThirdParam(ParamType3 value) void SetThirdParam(ParamType3 value)
{ {
_param_3 = value; _param_3 = value;
} }
ParamType1 GetFirstParam() ParamType1 GetFirstParam()
{ {
return _param_1; return _param_1;
} }
ParamType2 GetSecondParam() ParamType2 GetSecondParam()
{ {
return _param_2; return _param_2;
} }
ParamType3 GetThirdParam() ParamType3 GetThirdParam()
{ {
return _param_3; return _param_3;
} }
//! Resets the stage of the callback chain //! Resets the stage of the callback chain
void ResetStage() void ResetStage()
{ {
if (!chain) if (!chain)
return; return;
_stage = 0; _stage = 0;
} }
//! Advances the callback chain to the next stage, so upper level code can act on its results accordingly //! Advances the callback chain to the next stage, so upper level code can act on its results accordingly
void NextStage() void NextStage()
{ {
if (!chain) if (!chain)
return; return;
++_stage; ++_stage;
} }
//! Returns the callback stage (or CALLBACK_STAGE_INVALID if invalid) //! Returns the callback stage (or CALLBACK_STAGE_INVALID if invalid)
uint8 GetStage() uint8 GetStage()
{ {
return _stage; return _stage;
} }
//! Resets all underlying variables (param, result and stage) //! Resets all underlying variables (param, result and stage)
void Reset() void Reset()
{ {
SetFirstParam(NULL); SetFirstParam(NULL);
SetSecondParam(NULL); SetSecondParam(NULL);
SetThirdParam(NULL); SetThirdParam(NULL);
FreeResult(); FreeResult();
ResetStage(); ResetStage();
} }
private: private:
ACE_Future<Result> _result; ACE_Future<Result> _result;
ParamType1 _param_1; ParamType1 _param_1;
ParamType2 _param_2; ParamType2 _param_2;
ParamType3 _param_3; ParamType3 _param_3;
uint8 _stage; uint8 _stage;
}; };
#endif #endif

View File

@@ -10,7 +10,7 @@ DelayExecutor* DelayExecutor::instance()
} }
DelayExecutor::DelayExecutor() DelayExecutor::DelayExecutor()
: pre_svc_hook_(0), post_svc_hook_(0), activated_(false), mqueue_(1*1024*1024, 1*1024*1024), queue_(&mqueue_) : pre_svc_hook_(0), post_svc_hook_(0), activated_(false), mqueue_(1 * 1024 * 1024, 1 * 1024 * 1024), queue_(&mqueue_)
{ {
} }

View File

@@ -7,33 +7,33 @@
class DelayExecutor : protected ACE_Task_Base class DelayExecutor : protected ACE_Task_Base
{ {
public: public:
DelayExecutor(); DelayExecutor();
virtual ~DelayExecutor(); virtual ~DelayExecutor();
static DelayExecutor* instance(); static DelayExecutor* instance();
int execute(ACE_Method_Request* new_req); int execute(ACE_Method_Request* new_req);
int start(int num_threads = 1, ACE_Method_Request* pre_svc_hook = NULL, ACE_Method_Request* post_svc_hook = NULL); int start(int num_threads = 1, ACE_Method_Request* pre_svc_hook = NULL, ACE_Method_Request* post_svc_hook = NULL);
int deactivate(); int deactivate();
bool activated(); bool activated();
virtual int svc(); virtual int svc();
private: private:
ACE_Method_Request* pre_svc_hook_; ACE_Method_Request* pre_svc_hook_;
ACE_Method_Request* post_svc_hook_; ACE_Method_Request* post_svc_hook_;
bool activated_; bool activated_;
ACE_Message_Queue<ACE_SYNCH> mqueue_; ACE_Message_Queue<ACE_SYNCH> mqueue_;
ACE_Activation_Queue queue_; ACE_Activation_Queue queue_;
void activated(bool s); void activated(bool s);
}; };
#endif // _M_DELAY_EXECUTOR_H #endif // _M_DELAY_EXECUTOR_H

View File

@@ -15,8 +15,8 @@
namespace ACE_Based namespace ACE_Based
{ {
template <class T, class LockType, typename StorageType=std::deque<T> > template <class T, class LockType, typename StorageType = std::deque<T> >
class LockedQueue class LockedQueue
{ {
//! Lock access to the queue. //! Lock access to the queue.
LockType _lock; LockType _lock;
@@ -27,120 +27,120 @@ namespace ACE_Based
//! Cancellation flag. //! Cancellation flag.
volatile bool _canceled; volatile bool _canceled;
public: public:
//! Create a LockedQueue. //! Create a LockedQueue.
LockedQueue() LockedQueue()
: _canceled(false) : _canceled(false)
{ {
} }
//! Destroy a LockedQueue. //! Destroy a LockedQueue.
virtual ~LockedQueue() virtual ~LockedQueue()
{ {
} }
//! Adds an item to the queue. //! Adds an item to the queue.
void add(const T& item) void add(const T& item)
{ {
lock(); lock();
//ASSERT(!this->_canceled); //ASSERT(!this->_canceled);
// throw Cancellation_Exception(); // throw Cancellation_Exception();
_queue.push_back(item); _queue.push_back(item);
unlock();
}
//! Gets the next result in the queue, if any.
bool next(T& result)
{
// ACE_Guard<LockType> g(this->_lock);
ACE_GUARD_RETURN (LockType, g, this->_lock, false);
if (_queue.empty())
return false;
//ASSERT (!_queue.empty() || !this->_canceled);
// throw Cancellation_Exception();
result = _queue.front();
_queue.pop_front();
return true;
}
template<class Checker>
bool next(T& result, Checker& check)
{
ACE_Guard<LockType> g(this->_lock);
if (_queue.empty())
return false;
result = _queue.front();
if (!check.Process(result))
return false;
_queue.pop_front();
return true;
}
//! Peeks at the top of the queue. Check if the queue is empty before calling! Remember to unlock after use if autoUnlock == false.
T& peek(bool autoUnlock = false)
{
lock();
T& result = _queue.front();
if (autoUnlock)
unlock(); unlock();
}
//! Gets the next result in the queue, if any. return result;
bool next(T& result) }
{
// ACE_Guard<LockType> g(this->_lock);
ACE_GUARD_RETURN (LockType, g, this->_lock, false);
if (_queue.empty()) //! Cancels the queue.
return false; void cancel()
{
lock();
//ASSERT (!_queue.empty() || !this->_canceled); _canceled = true;
// throw Cancellation_Exception();
result = _queue.front();
_queue.pop_front();
return true; unlock();
} }
template<class Checker> //! Checks if the queue is cancelled.
bool next(T& result, Checker& check) bool cancelled()
{ {
ACE_Guard<LockType> g(this->_lock); ACE_Guard<LockType> g(this->_lock);
return _canceled;
}
if (_queue.empty()) //! Locks the queue for access.
return false; void lock()
{
this->_lock.acquire();
}
result = _queue.front(); //! Unlocks the queue.
if (!check.Process(result)) void unlock()
return false; {
this->_lock.release();
}
_queue.pop_front(); ///! Calls pop_front of the queue
return true; void pop_front()
} {
ACE_GUARD (LockType, g, this->_lock);
_queue.pop_front();
}
//! Peeks at the top of the queue. Check if the queue is empty before calling! Remember to unlock after use if autoUnlock == false. ///! Checks if we're empty or not with locks held
T& peek(bool autoUnlock = false) bool empty()
{ {
lock(); ACE_GUARD_RETURN (LockType, g, this->_lock, false);
return _queue.empty();
T& result = _queue.front(); }
if (autoUnlock)
unlock();
return result;
}
//! Cancels the queue.
void cancel()
{
lock();
_canceled = true;
unlock();
}
//! Checks if the queue is cancelled.
bool cancelled()
{
ACE_Guard<LockType> g(this->_lock);
return _canceled;
}
//! Locks the queue for access.
void lock()
{
this->_lock.acquire();
}
//! Unlocks the queue.
void unlock()
{
this->_lock.release();
}
///! Calls pop_front of the queue
void pop_front()
{
ACE_GUARD (LockType, g, this->_lock);
_queue.pop_front();
}
///! Checks if we're empty or not with locks held
bool empty()
{
ACE_GUARD_RETURN (LockType, g, this->_lock, false);
return _queue.empty();
}
}; };
} }
#endif #endif

View File

@@ -95,7 +95,7 @@ private:
typename std::enable_if<std::is_pointer<E>::value>::type DeleteQueuedObject(E& obj) { delete obj; } typename std::enable_if<std::is_pointer<E>::value>::type DeleteQueuedObject(E& obj) { delete obj; }
template<typename E = T> template<typename E = T>
typename std::enable_if<!std::is_pointer<E>::value>::type DeleteQueuedObject(E const& /*packet*/) { } typename std::enable_if < !std::is_pointer<E>::value >::type DeleteQueuedObject(E const& /*packet*/) { }
}; };
#endif #endif

View File

@@ -88,13 +88,27 @@ void Thread::setPriority(Priority priority)
switch (priority) switch (priority)
{ {
#ifdef WIN32 #ifdef WIN32
case Priority_Realtime: _ok = SetThreadPriority(handle, THREAD_PRIORITY_TIME_CRITICAL); break; case Priority_Realtime:
case Priority_Highest: _ok = SetThreadPriority(handle, THREAD_PRIORITY_HIGHEST); break; _ok = SetThreadPriority(handle, THREAD_PRIORITY_TIME_CRITICAL);
case Priority_High: _ok = SetThreadPriority(handle, THREAD_PRIORITY_ABOVE_NORMAL); break; break;
case Priority_Normal: _ok = SetThreadPriority(handle, THREAD_PRIORITY_NORMAL); break; case Priority_Highest:
case Priority_Low: _ok = SetThreadPriority(handle, THREAD_PRIORITY_BELOW_NORMAL); break; _ok = SetThreadPriority(handle, THREAD_PRIORITY_HIGHEST);
case Priority_Lowest: _ok = SetThreadPriority(handle, THREAD_PRIORITY_LOWEST); break; break;
case Priority_Idle: _ok = SetThreadPriority(handle, THREAD_PRIORITY_IDLE); break; case Priority_High:
_ok = SetThreadPriority(handle, THREAD_PRIORITY_ABOVE_NORMAL);
break;
case Priority_Normal:
_ok = SetThreadPriority(handle, THREAD_PRIORITY_NORMAL);
break;
case Priority_Low:
_ok = SetThreadPriority(handle, THREAD_PRIORITY_BELOW_NORMAL);
break;
case Priority_Lowest:
_ok = SetThreadPriority(handle, THREAD_PRIORITY_LOWEST);
break;
case Priority_Idle:
_ok = SetThreadPriority(handle, THREAD_PRIORITY_IDLE);
break;
#endif #endif
default: default:
break; break;

View File

@@ -17,18 +17,18 @@ namespace acore
{ {
class Runnable class Runnable
{ {
public: public:
virtual ~Runnable() {} virtual ~Runnable() {}
virtual void run() = 0; virtual void run() = 0;
void incReference() { ++m_refs; } void incReference() { ++m_refs; }
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;
}; };
enum Priority enum Priority
@@ -44,28 +44,28 @@ namespace acore
class Thread class Thread
{ {
public: public:
Thread(); Thread();
explicit Thread(Runnable* instance); explicit Thread(Runnable* instance);
~Thread(); ~Thread();
bool wait(); bool wait();
void destroy(); void destroy();
void setPriority(Priority type); void setPriority(Priority type);
static void Sleep(unsigned long msecs); static void Sleep(unsigned long msecs);
static std::thread::id currentId(); static std::thread::id currentId();
private: private:
Thread(const Thread&); Thread(const Thread&);
Thread& operator=(const Thread&); Thread& operator=(const Thread&);
static void ThreadTask(void* param); static void ThreadTask(void* param);
Runnable* const m_task; Runnable* const m_task;
std::thread::id m_iThreadId; std::thread::id m_iThreadId;
std::thread m_ThreadImp; std::thread m_ThreadImp;
}; };
} }
#endif #endif

View File

@@ -19,120 +19,120 @@ namespace acore
template<typename MUTEX> template<typename MUTEX>
class GeneralLock class GeneralLock
{ {
public: public:
GeneralLock(MUTEX& m) GeneralLock(MUTEX& m)
: i_mutex(m) : i_mutex(m)
{ {
i_mutex.lock(); i_mutex.lock();
} }
~GeneralLock() ~GeneralLock()
{ {
i_mutex.unlock(); i_mutex.unlock();
} }
private: private:
GeneralLock(const GeneralLock&); GeneralLock(const GeneralLock&);
GeneralLock& operator=(const GeneralLock&); GeneralLock& operator=(const GeneralLock&);
MUTEX& i_mutex; MUTEX& i_mutex;
}; };
template<class T> template<class T>
class SingleThreaded class SingleThreaded
{ {
public: public:
struct Lock // empty object struct Lock // empty object
{
Lock()
{ {
Lock() }
{ Lock(const T&)
} {
Lock(const T&) }
{
}
Lock(const SingleThreaded<T>&) // for single threaded we ignore this Lock(const SingleThreaded<T>&) // for single threaded we ignore this
{ {
} }
}; };
}; };
template<class T, class MUTEX> template<class T, class MUTEX>
class ObjectLevelLockable class ObjectLevelLockable
{ {
public:
ObjectLevelLockable()
: i_mtx()
{
}
friend class Lock;
class Lock
{
public: public:
ObjectLevelLockable() Lock(ObjectLevelLockable<T, MUTEX>& host)
: i_mtx() : i_lock(host.i_mtx)
{ {
} }
friend class Lock;
class Lock
{
public:
Lock(ObjectLevelLockable<T, MUTEX>& host)
: i_lock(host.i_mtx)
{
}
private:
GeneralLock<MUTEX> i_lock;
};
private: private:
// prevent the compiler creating a copy construct GeneralLock<MUTEX> i_lock;
ObjectLevelLockable(const ObjectLevelLockable<T, MUTEX>&); };
ObjectLevelLockable<T, MUTEX>& operator=(const ObjectLevelLockable<T, MUTEX>&);
MUTEX i_mtx; private:
// prevent the compiler creating a copy construct
ObjectLevelLockable(const ObjectLevelLockable<T, MUTEX>&);
ObjectLevelLockable<T, MUTEX>& operator=(const ObjectLevelLockable<T, MUTEX>&);
MUTEX i_mtx;
}; };
template<class T, class MUTEX> template<class T, class MUTEX>
class ClassLevelLockable class ClassLevelLockable
{ {
public:
ClassLevelLockable()
{
}
friend class Lock;
class Lock
{
public: public:
ClassLevelLockable() Lock(const T& /*host*/)
{ {
ClassLevelLockable<T, MUTEX>::si_mtx.lock();
} }
friend class Lock; Lock(const ClassLevelLockable<T, MUTEX>&)
class Lock
{ {
public: ClassLevelLockable<T, MUTEX>::si_mtx.lock();
}
Lock(const T& /*host*/) Lock()
{ {
ClassLevelLockable<T, MUTEX>::si_mtx.lock(); ClassLevelLockable<T, MUTEX>::si_mtx.lock();
} }
Lock(const ClassLevelLockable<T, MUTEX>&) ~Lock()
{ {
ClassLevelLockable<T, MUTEX>::si_mtx.lock(); ClassLevelLockable<T, MUTEX>::si_mtx.unlock();
} }
};
Lock() private:
{
ClassLevelLockable<T, MUTEX>::si_mtx.lock();
}
~Lock() static MUTEX si_mtx;
{
ClassLevelLockable<T, MUTEX>::si_mtx.unlock();
}
};
private:
static MUTEX si_mtx;
}; };
} }

View File

@@ -17,18 +17,18 @@
namespace ByteConverter namespace ByteConverter
{ {
template<size_t T> template<size_t T>
inline void convert(char *val) inline void convert(char* val)
{ {
std::swap(*val, *(val + T - 1)); std::swap(*val, *(val + T - 1));
convert<T - 2>(val + 1); convert < T - 2 > (val + 1);
} }
template<> inline void convert<0>(char *) { } template<> inline void convert<0>(char*) { }
template<> inline void convert<1>(char *) { } // ignore central byte template<> inline void convert<1>(char*) { } // ignore central byte
template<typename T> inline void apply(T *val) template<typename T> inline void apply(T* val)
{ {
convert<sizeof(T)>((char *)(val)); convert<sizeof(T)>((char*)(val));
} }
} }

View File

@@ -26,7 +26,8 @@ public:
/** /**
* Returns a pointer to object of requested type stored with given key or nullptr * Returns a pointer to object of requested type stored with given key or nullptr
*/ */
template<class T> T* Get(std::string const & k) const { template<class T> T* Get(std::string const& k) const
{
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;
@@ -36,13 +37,14 @@ public:
return dynamic_cast<T*>(it->second.get()); return dynamic_cast<T*>(it->second.get());
return nullptr; return nullptr;
} }
/** /**
* Returns a pointer to object of requested type stored with given key * Returns a pointer to object of requested type stored with given key
* or default constructs one and returns that one * or default constructs one and returns that one
*/ */
template<class T, typename std::enable_if<std::is_default_constructible<T>::value, int>::type = 0> template<class T, typename std::enable_if<std::is_default_constructible<T>::value, int>::type = 0>
T* GetDefault(std::string const & k) { T * GetDefault(std::string const& k)
{
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;
@@ -50,16 +52,16 @@ public:
Container.emplace(k, std::unique_ptr<T>(v)); Container.emplace(k, std::unique_ptr<T>(v));
return v; return v;
} }
/** /**
* Stores a new object that inherits the Base class with the given key * Stores a new object that inherits the Base class with the given key
*/ */
void Set(std::string const & k, Base* v) { Container[k] = std::unique_ptr<Base>(v); } void Set(std::string const& k, Base* v) { Container[k] = std::unique_ptr<Base>(v); }
/** /**
* Removes objects with given key and returns true if one was removed, false otherwise * Removes objects with given key and returns true if one was removed, false otherwise
*/ */
bool Erase(std::string const & k) { return Container.erase(k) != 0; } bool Erase(std::string const& k) { return Container.erase(k) != 0; }
private: private:
std::unordered_map<std::string, std::unique_ptr<Base>> Container; std::unordered_map<std::string, std::unique_ptr<Base>> Container;

View File

@@ -15,51 +15,51 @@
class BasicEvent class BasicEvent
{ {
public: public:
BasicEvent() BasicEvent()
{ {
to_Abort = false; to_Abort = false;
m_addTime = 0; m_addTime = 0;
m_execTime = 0; m_execTime = 0;
} }
virtual ~BasicEvent() { } // override destructor to perform some actions on event removal virtual ~BasicEvent() { } // override destructor to perform some actions on event removal
// this method executes when the event is triggered // this method executes when the event is triggered
// return false if event does not want to be deleted // return false if event does not want to be deleted
// e_time is execution time, p_time is update interval // e_time is execution time, p_time is update interval
virtual bool Execute(uint64 /*e_time*/, uint32 /*p_time*/) { return true; } virtual bool Execute(uint64 /*e_time*/, uint32 /*p_time*/) { return true; }
virtual bool IsDeletable() const { return true; } // this event can be safely deleted virtual bool IsDeletable() const { return true; } // this event can be safely deleted
virtual void Abort(uint64 /*e_time*/) { } // this method executes when the event is aborted virtual void Abort(uint64 /*e_time*/) { } // this method executes when the event is aborted
bool to_Abort; // set by externals when the event is aborted, aborted events don't execute bool to_Abort; // set by externals when the event is aborted, aborted events don't execute
// and get Abort call when deleted // and get Abort call when deleted
// these can be used for time offset control // these can be used for time offset control
uint64 m_addTime; // time when the event was added to queue, filled by event handler uint64 m_addTime; // time when the event was added to queue, filled by event handler
uint64 m_execTime; // planned time of next execution, filled by event handler uint64 m_execTime; // planned time of next execution, filled by event handler
}; };
typedef std::multimap<uint64, BasicEvent*> EventList; typedef std::multimap<uint64, BasicEvent*> EventList;
class EventProcessor class EventProcessor
{ {
public: public:
EventProcessor(); EventProcessor();
~EventProcessor(); ~EventProcessor();
void Update(uint32 p_time); void Update(uint32 p_time);
void KillAllEvents(bool force); void KillAllEvents(bool force);
void AddEvent(BasicEvent* Event, uint64 e_time, bool set_addtime = true); void AddEvent(BasicEvent* Event, uint64 e_time, bool set_addtime = true);
uint64 CalculateTime(uint64 t_offset) const; uint64 CalculateTime(uint64 t_offset) const;
// Xinef: calculates next queue tick time // Xinef: calculates next queue tick time
uint64 CalculateQueueTime(uint64 delay) const; uint64 CalculateQueueTime(uint64 delay) const;
protected: protected:
uint64 m_time; uint64 m_time;
EventList m_events; EventList m_events;
bool m_aborting; bool m_aborting;
}; };
#endif #endif

View File

@@ -25,7 +25,7 @@
#endif #endif
#endif #endif
extern int main(int argc, char ** argv); extern int main(int argc, char** argv);
extern char serviceLongName[]; extern char serviceLongName[];
extern char serviceName[]; extern char serviceName[];
extern char serviceDescription[]; extern char serviceDescription[];
@@ -36,7 +36,7 @@ SERVICE_STATUS serviceStatus;
SERVICE_STATUS_HANDLE serviceStatusHandle = 0; SERVICE_STATUS_HANDLE serviceStatusHandle = 0;
typedef WINADVAPI BOOL (WINAPI *CSD_T)(SC_HANDLE, DWORD, LPCVOID); typedef WINADVAPI BOOL (WINAPI* CSD_T)(SC_HANDLE, DWORD, LPCVOID);
bool WinServiceInstall() bool WinServiceInstall()
{ {
@@ -45,24 +45,24 @@ bool WinServiceInstall()
if (serviceControlManager) if (serviceControlManager)
{ {
char path[_MAX_PATH + 10]; char path[_MAX_PATH + 10];
if (GetModuleFileName( 0, path, sizeof(path)/sizeof(path[0]) ) > 0) if (GetModuleFileName( 0, path, sizeof(path) / sizeof(path[0]) ) > 0)
{ {
SC_HANDLE service; SC_HANDLE service;
std::strcat(path, " --service"); std::strcat(path, " --service");
service = CreateService(serviceControlManager, service = CreateService(serviceControlManager,
serviceName, // name of service serviceName, // name of service
serviceLongName, // service name to display serviceLongName, // service name to display
SERVICE_ALL_ACCESS, // desired access SERVICE_ALL_ACCESS, // desired access
// service type // service type
SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS, SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
SERVICE_AUTO_START, // start type SERVICE_AUTO_START, // start type
SERVICE_ERROR_IGNORE, // error control type SERVICE_ERROR_IGNORE, // error control type
path, // service's binary path, // service's binary
0, // no load ordering group 0, // no load ordering group
0, // no tag identifier 0, // no tag identifier
0, // no dependencies 0, // no dependencies
0, // LocalSystem account 0, // LocalSystem account
0); // no password 0); // no password
if (service) if (service)
{ {
HMODULE advapi32 = GetModuleHandle("ADVAPI32.DLL"); HMODULE advapi32 = GetModuleHandle("ADVAPI32.DLL");
@@ -95,7 +95,7 @@ bool WinServiceInstall()
ZeroMemory(&sfa, sizeof(SERVICE_FAILURE_ACTIONS)); ZeroMemory(&sfa, sizeof(SERVICE_FAILURE_ACTIONS));
sfa.lpsaActions = _action; sfa.lpsaActions = _action;
sfa.cActions = 1; sfa.cActions = 1;
sfa.dwResetPeriod =INFINITE; sfa.dwResetPeriod = INFINITE;
ChangeService_Config2( ChangeService_Config2(
service, // handle to service service, // handle to service
SERVICE_CONFIG_FAILURE_ACTIONS, // information level SERVICE_CONFIG_FAILURE_ACTIONS, // information level
@@ -117,7 +117,7 @@ bool WinServiceUninstall()
if (serviceControlManager) if (serviceControlManager)
{ {
SC_HANDLE service = OpenService(serviceControlManager, SC_HANDLE service = OpenService(serviceControlManager,
serviceName, SERVICE_QUERY_STATUS | DELETE); serviceName, SERVICE_QUERY_STATUS | DELETE);
if (service) if (service)
{ {
SERVICE_STATUS serviceStatus2; SERVICE_STATUS serviceStatus2;
@@ -173,7 +173,7 @@ void WINAPI ServiceControlHandler(DWORD controlCode)
SetServiceStatus(serviceStatusHandle, &serviceStatus); SetServiceStatus(serviceStatusHandle, &serviceStatus);
} }
void WINAPI ServiceMain(DWORD argc, char *argv[]) void WINAPI ServiceMain(DWORD argc, char* argv[])
{ {
// initialise service status // initialise service status
serviceStatus.dwServiceType = SERVICE_WIN32; serviceStatus.dwServiceType = SERVICE_WIN32;
@@ -191,7 +191,7 @@ void WINAPI ServiceMain(DWORD argc, char *argv[])
char path[_MAX_PATH + 1]; char path[_MAX_PATH + 1];
unsigned int i, last_slash = 0; unsigned int i, last_slash = 0;
GetModuleFileName(0, path, sizeof(path)/sizeof(path[0])); GetModuleFileName(0, path, sizeof(path) / sizeof(path[0]));
for (i = 0; i < std::strlen(path); i++) for (i = 0; i < std::strlen(path); i++)
{ {

View File

@@ -12,9 +12,9 @@
namespace acore namespace acore
{ {
/// Handle termination signals /// Handle termination signals
class SignalHandler : public ACE_Event_Handler class SignalHandler : public ACE_Event_Handler
{ {
public: public:
int handle_signal(int SigNum, siginfo_t* = NULL, ucontext_t* = NULL) int handle_signal(int SigNum, siginfo_t* = NULL, ucontext_t* = NULL)
{ {
@@ -22,7 +22,7 @@ class SignalHandler : public ACE_Event_Handler
return 0; return 0;
} }
virtual void HandleSignal(int /*SigNum*/) { }; virtual void HandleSignal(int /*SigNum*/) { };
}; };
} }

View File

@@ -50,158 +50,158 @@ inline uint32 GetMSTimeDiffToNow(uint32 oldMSTime)
struct IntervalTimer struct IntervalTimer
{ {
public: public:
IntervalTimer() IntervalTimer()
: _interval(0), _current(0) : _interval(0), _current(0)
{ {
} }
void Update(time_t diff) void Update(time_t diff)
{ {
_current += diff; _current += diff;
if (_current < 0) if (_current < 0)
_current = 0; _current = 0;
} }
bool Passed() bool Passed()
{ {
return _current >= _interval; return _current >= _interval;
} }
void Reset() void Reset()
{ {
if (_current >= _interval) if (_current >= _interval)
_current %= _interval; _current %= _interval;
} }
void SetCurrent(time_t current) void SetCurrent(time_t current)
{ {
_current = current; _current = current;
} }
void SetInterval(time_t interval) void SetInterval(time_t interval)
{ {
_interval = interval; _interval = interval;
} }
time_t GetInterval() const time_t GetInterval() const
{ {
return _interval; return _interval;
} }
time_t GetCurrent() const time_t GetCurrent() const
{ {
return _current; return _current;
} }
private: private:
time_t _interval; time_t _interval;
time_t _current; time_t _current;
}; };
struct TimeTracker struct TimeTracker
{ {
public: public:
TimeTracker(time_t expiry) TimeTracker(time_t expiry)
: i_expiryTime(expiry) : i_expiryTime(expiry)
{ {
} }
void Update(time_t diff) void Update(time_t diff)
{ {
i_expiryTime -= diff; i_expiryTime -= diff;
} }
bool Passed() const bool Passed() const
{ {
return i_expiryTime <= 0; return i_expiryTime <= 0;
} }
void Reset(time_t interval) void Reset(time_t interval)
{ {
i_expiryTime = interval; i_expiryTime = interval;
} }
time_t GetExpiry() const time_t GetExpiry() const
{ {
return i_expiryTime; return i_expiryTime;
} }
private: private:
time_t i_expiryTime; time_t i_expiryTime;
}; };
struct TimeTrackerSmall struct TimeTrackerSmall
{ {
public: public:
TimeTrackerSmall(uint32 expiry = 0) TimeTrackerSmall(uint32 expiry = 0)
: i_expiryTime(expiry) : i_expiryTime(expiry)
{ {
} }
void Update(int32 diff) void Update(int32 diff)
{ {
i_expiryTime -= diff; i_expiryTime -= diff;
} }
bool Passed() const bool Passed() const
{ {
return i_expiryTime <= 0; return i_expiryTime <= 0;
} }
void Reset(uint32 interval) void Reset(uint32 interval)
{ {
i_expiryTime = interval; i_expiryTime = interval;
} }
int32 GetExpiry() const int32 GetExpiry() const
{ {
return i_expiryTime; return i_expiryTime;
} }
private: private:
int32 i_expiryTime; int32 i_expiryTime;
}; };
struct PeriodicTimer struct PeriodicTimer
{ {
public: public:
PeriodicTimer(int32 period, int32 start_time) PeriodicTimer(int32 period, int32 start_time)
: i_period(period), i_expireTime(start_time) : i_period(period), i_expireTime(start_time)
{ {
} }
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;
} }
void SetPeriodic(int32 period, int32 start_time) void SetPeriodic(int32 period, int32 start_time)
{ {
i_expireTime = start_time; i_expireTime = start_time;
i_period = period; i_period = period;
} }
// Tracker interface // Tracker interface
void TUpdate(int32 diff) { i_expireTime -= diff; } void TUpdate(int32 diff) { i_expireTime -= diff; }
bool TPassed() const { return i_expireTime <= 0; } bool TPassed() const { return i_expireTime <= 0; }
void TReset(int32 diff, int32 period) { i_expireTime += period > diff ? period : diff; } void TReset(int32 diff, int32 period) { i_expireTime += period > diff ? period : diff; }
private: private:
int32 i_period; int32 i_period;
int32 i_expireTime; int32 i_expireTime;
}; };
#endif #endif

View File

@@ -68,7 +68,7 @@ SFMTEngine& SFMTEngine::Instance()
return engine; return engine;
} }
Tokenizer::Tokenizer(const std::string &src, const char sep, uint32 vectorReserve) Tokenizer::Tokenizer(const std::string& src, const char sep, uint32 vectorReserve)
{ {
m_str = new char[src.length() + 1]; m_str = new char[src.length() + 1];
memcpy(m_str, src.c_str(), src.length() + 1); memcpy(m_str, src.c_str(), src.length() + 1);
@@ -141,7 +141,7 @@ time_t GetLocalHourTimestamp(time_t time, uint8 hour, bool onlyAfterTime)
return hourLocal; return hourLocal;
} }
void stripLineInvisibleChars(std::string &str) void stripLineInvisibleChars(std::string& str)
{ {
static std::string const invChars = " \t\7\n"; static std::string const invChars = " \t\7\n";
@@ -150,7 +150,7 @@ void stripLineInvisibleChars(std::string &str)
bool space = false; bool space = false;
for (size_t pos = 0; pos < str.size(); ++pos) for (size_t pos = 0; pos < str.size(); ++pos)
{ {
if (invChars.find(str[pos])!=std::string::npos) if (invChars.find(str[pos]) != std::string::npos)
{ {
if (!space) if (!space)
{ {
@@ -160,7 +160,7 @@ 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;
@@ -170,7 +170,7 @@ void stripLineInvisibleChars(std::string &str)
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();
} }
@@ -194,8 +194,8 @@ std::string secsToTimeString(uint64 timeInSecs, bool shortText)
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;
} }
@@ -205,8 +205,8 @@ int32 MoneyStringToMoney(const std::string& moneyString)
int32 money = 0; int32 money = 0;
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, ' ');
@@ -241,22 +241,31 @@ uint32 TimeStringToSecs(const std::string& timestring)
{ {
if (isdigit(*itr)) if (isdigit(*itr))
{ {
buffer*=10; buffer *= 10;
buffer+= (*itr)-'0'; buffer += (*itr) - '0';
} }
else else
{ {
switch (*itr) switch (*itr)
{ {
case 'd': multiplier = DAY; break; case 'd':
case 'h': multiplier = HOUR; break; multiplier = DAY;
case 'm': multiplier = MINUTE; break; break;
case 's': multiplier = 1; break; case 'h':
default : return 0; //bad format multiplier = HOUR;
break;
case 'm':
multiplier = MINUTE;
break;
case 's':
multiplier = 1;
break;
default :
return 0; //bad format
} }
buffer*=multiplier; buffer *= multiplier;
secs+=buffer; secs += buffer;
buffer=0; buffer = 0;
} }
} }
@@ -274,7 +283,7 @@ std::string TimeToTimestampStr(time_t t)
// MM minutes (2 digits 00-59) // MM minutes (2 digits 00-59)
// SS seconds (2 digits 00-59) // SS seconds (2 digits 00-59)
char buf[20]; char buf[20];
int ret = snprintf(buf, 20, "%04d-%02d-%02d_%02d-%02d-%02d", aTm.tm_year+1900, aTm.tm_mon+1, aTm.tm_mday, aTm.tm_hour, aTm.tm_min, aTm.tm_sec); int ret = snprintf(buf, 20, "%04d-%02d-%02d_%02d-%02d-%02d", aTm.tm_year + 1900, aTm.tm_mon + 1, aTm.tm_mday, aTm.tm_hour, aTm.tm_min, aTm.tm_sec);
if (ret < 0) if (ret < 0)
{ {
@@ -349,7 +358,7 @@ size_t utf8length(std::string& utf8str)
{ {
try try
{ {
return utf8::distance(utf8str.c_str(), utf8str.c_str()+utf8str.size()); return utf8::distance(utf8str.c_str(), utf8str.c_str() + utf8str.size());
} }
catch(std::exception const&) catch(std::exception const&)
{ {
@@ -362,16 +371,16 @@ void utf8truncate(std::string& utf8str, size_t len)
{ {
try try
{ {
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);
utf8::utf8to16(utf8str.c_str(), utf8str.c_str()+utf8str.size(), &wstr[0]); utf8::utf8to16(utf8str.c_str(), utf8str.c_str() + utf8str.size(), &wstr[0]);
wstr.resize(len); wstr.resize(len);
char* oend = utf8::utf16to8(wstr.c_str(), wstr.c_str()+wstr.size(), &utf8str[0]); char* oend = utf8::utf16to8(wstr.c_str(), wstr.c_str() + wstr.size(), &utf8str[0]);
utf8str.resize(oend-(&utf8str[0])); // remove unused tail utf8str.resize(oend - (&utf8str[0])); // remove unused tail
} }
catch(std::exception const&) catch(std::exception const&)
{ {
@@ -384,7 +393,7 @@ bool Utf8toWStr(char const* utf8str, size_t csize, wchar_t* wstr, size_t& wsize)
try try
{ {
acore::CheckedBufferOutputIterator<wchar_t> out(wstr, wsize); acore::CheckedBufferOutputIterator<wchar_t> out(wstr, wsize);
out = utf8::utf8to16(utf8str, utf8str+csize, out); out = utf8::utf8to16(utf8str, utf8str + csize, out);
wsize -= out.remaining(); // remaining unused space wsize -= out.remaining(); // remaining unused space
wstr[wsize] = L'\0'; wstr[wsize] = L'\0';
} }
@@ -418,7 +427,7 @@ bool Utf8toWStr(const std::string& utf8str, std::wstring& wstr)
wstr.clear(); wstr.clear();
try try
{ {
utf8::utf8to16(utf8str.c_str(), utf8str.c_str()+utf8str.size(), std::back_inserter(wstr)); utf8::utf8to16(utf8str.c_str(), utf8str.c_str() + utf8str.size(), std::back_inserter(wstr));
} }
catch(std::exception const&) catch(std::exception const&)
{ {
@@ -434,12 +443,12 @@ bool WStrToUtf8(wchar_t* wstr, size_t size, std::string& utf8str)
try try
{ {
std::string utf8str2; std::string utf8str2;
utf8str2.resize(size*4); // allocate for most long case utf8str2.resize(size * 4); // allocate for most long case
if (size) if (size)
{ {
char* oend = utf8::utf16to8(wstr, wstr+size, &utf8str2[0]); char* oend = utf8::utf16to8(wstr, wstr + size, &utf8str2[0]);
utf8str2.resize(oend-(&utf8str2[0])); // remove unused tail utf8str2.resize(oend - (&utf8str2[0])); // remove unused tail
} }
utf8str = utf8str2; utf8str = utf8str2;
} }
@@ -457,12 +466,12 @@ bool WStrToUtf8(std::wstring const& wstr, std::string& utf8str)
try try
{ {
std::string utf8str2; std::string utf8str2;
utf8str2.resize(wstr.size()*4); // allocate for most long case utf8str2.resize(wstr.size() * 4); // allocate for most long case
if (wstr.size()) if (wstr.size())
{ {
char* oend = utf8::utf16to8(wstr.c_str(), wstr.c_str()+wstr.size(), &utf8str2[0]); char* oend = utf8::utf16to8(wstr.c_str(), wstr.c_str() + wstr.size(), &utf8str2[0]);
utf8str2.resize(oend-(&utf8str2[0])); // remove unused tail utf8str2.resize(oend - (&utf8str2[0])); // remove unused tail
} }
utf8str = utf8str2; utf8str = utf8str2;
} }
@@ -512,13 +521,14 @@ std::wstring GetMainPartOfName(std::wstring const& wname, uint32 declension)
static std::wstring const j_End = { wchar_t(0x0439), wchar_t(0x0000) }; static std::wstring const j_End = { wchar_t(0x0439), wchar_t(0x0000) };
static std::array<std::array<std::wstring const*, 7>, 6> const dropEnds = {{ static std::array<std::array<std::wstring const*, 7>, 6> const dropEnds = {{
{ &a_End, &o_End, &ya_End, &ie_End, &soft_End, &j_End, nullptr }, { &a_End, &o_End, &ya_End, &ie_End, &soft_End, &j_End, nullptr },
{ &a_End, &ya_End, &yeru_End, &i_End, nullptr, nullptr, nullptr }, { &a_End, &ya_End, &yeru_End, &i_End, nullptr, nullptr, nullptr },
{ &ie_End, &u_End, &yu_End, &i_End, nullptr, nullptr, nullptr }, { &ie_End, &u_End, &yu_End, &i_End, nullptr, nullptr, nullptr },
{ &u_End, &yu_End, &o_End, &ie_End, &soft_End, &ya_End, &a_End }, { &u_End, &yu_End, &o_End, &ie_End, &soft_End, &ya_End, &a_End },
{ &oj_End, &io_j_End, &ie_j_End, &o_m_End, &io_m_End, &ie_m_End, &yu_End }, { &oj_End, &io_j_End, &ie_j_End, &o_m_End, &io_m_End, &ie_m_End, &yu_End },
{ &ie_End, &i_End, nullptr, nullptr, nullptr, nullptr, nullptr } { &ie_End, &i_End, nullptr, nullptr, nullptr, nullptr, nullptr }
}}; }
};
std::size_t const thisLen = wname.length(); std::size_t const thisLen = wname.length();
std::array<std::wstring const*, 7> const& endings = dropEnds[declension]; std::array<std::wstring const*, 7> const& endings = dropEnds[declension];
@@ -529,8 +539,8 @@ std::wstring GetMainPartOfName(std::wstring const& wname, uint32 declension)
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;
@@ -584,7 +594,7 @@ bool Utf8FitTo(const std::string& str, std::wstring const& search)
return true; return true;
} }
void utf8printf(FILE* out, const char *str, ...) void utf8printf(FILE* out, const char* str, ...)
{ {
va_list ap; va_list ap;
va_start(ap, str); va_start(ap, str);
@@ -592,7 +602,7 @@ void utf8printf(FILE* out, const char *str, ...)
va_end(ap); va_end(ap);
} }
void vutf8printf(FILE* out, const char *str, va_list* ap) void vutf8printf(FILE* out, const char* str, va_list* ap)
{ {
#if AC_PLATFORM == AC_PLATFORM_WINDOWS #if AC_PLATFORM == AC_PLATFORM_WINDOWS
char temp_buf[32 * 1024]; char temp_buf[32 * 1024];
@@ -601,9 +611,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);
CharToOemBuffW(&wtemp_buf[0], &temp_buf[0], uint32(wtemp_len + 1)); CharToOemBuffW(&wtemp_buf[0], &temp_buf[0], uint32(wtemp_len + 1));
@@ -683,5 +693,5 @@ bool StringToBool(std::string const& str)
bool StringContainsStringI(std::string const& haystack, std::string const& needle) bool StringContainsStringI(std::string const& haystack, std::string const& needle)
{ {
return haystack.end() != return haystack.end() !=
std::search(haystack.begin(), haystack.end(), needle.begin(), needle.end(), [](char c1, char c2) { return std::toupper(c1) == std::toupper(c2); }); std::search(haystack.begin(), haystack.end(), needle.begin(), needle.end(), [](char c1, char c2) { return std::toupper(c1) == std::toupper(c2); });
} }

Some files were not shown because too many files have changed in this diff Show More