mirror of
https://git.suyu.dev/suyu/suyu.git
synced 2024-12-22 00:10:57 +01:00
convert tabs to spaces
This commit is contained in:
parent
4860480c36
commit
c9b5b89e21
47 changed files with 4913 additions and 4913 deletions
|
@ -1,18 +1,18 @@
|
||||||
set(SRCS src/break_points.cpp
|
set(SRCS src/break_points.cpp
|
||||||
src/console_listener.cpp
|
src/console_listener.cpp
|
||||||
src/extended_trace.cpp
|
src/extended_trace.cpp
|
||||||
src/file_search.cpp
|
src/file_search.cpp
|
||||||
src/file_util.cpp
|
src/file_util.cpp
|
||||||
src/hash.cpp
|
src/hash.cpp
|
||||||
src/log_manager.cpp
|
src/log_manager.cpp
|
||||||
src/math_util.cpp
|
src/math_util.cpp
|
||||||
src/mem_arena.cpp
|
src/mem_arena.cpp
|
||||||
src/memory_util.cpp
|
src/memory_util.cpp
|
||||||
src/misc.cpp
|
src/misc.cpp
|
||||||
src/msg_handler.cpp
|
src/msg_handler.cpp
|
||||||
src/string_util.cpp
|
src/string_util.cpp
|
||||||
src/thread.cpp
|
src/thread.cpp
|
||||||
src/timer.cpp
|
src/timer.cpp
|
||||||
src/version.cpp)
|
src/version.cpp)
|
||||||
|
|
||||||
add_library(common STATIC ${SRCS})
|
add_library(common STATIC ${SRCS})
|
||||||
|
|
|
@ -25,42 +25,42 @@ namespace Common
|
||||||
{
|
{
|
||||||
|
|
||||||
inline void AtomicAdd(volatile u32& target, u32 value) {
|
inline void AtomicAdd(volatile u32& target, u32 value) {
|
||||||
__sync_add_and_fetch(&target, value);
|
__sync_add_and_fetch(&target, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void AtomicAnd(volatile u32& target, u32 value) {
|
inline void AtomicAnd(volatile u32& target, u32 value) {
|
||||||
__sync_and_and_fetch(&target, value);
|
__sync_and_and_fetch(&target, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void AtomicDecrement(volatile u32& target) {
|
inline void AtomicDecrement(volatile u32& target) {
|
||||||
__sync_add_and_fetch(&target, -1);
|
__sync_add_and_fetch(&target, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void AtomicIncrement(volatile u32& target) {
|
inline void AtomicIncrement(volatile u32& target) {
|
||||||
__sync_add_and_fetch(&target, 1);
|
__sync_add_and_fetch(&target, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline u32 AtomicLoad(volatile u32& src) {
|
inline u32 AtomicLoad(volatile u32& src) {
|
||||||
return src; // 32-bit reads are always atomic.
|
return src; // 32-bit reads are always atomic.
|
||||||
}
|
}
|
||||||
inline u32 AtomicLoadAcquire(volatile u32& src) {
|
inline u32 AtomicLoadAcquire(volatile u32& src) {
|
||||||
//keep the compiler from caching any memory references
|
//keep the compiler from caching any memory references
|
||||||
u32 result = src; // 32-bit reads are always atomic.
|
u32 result = src; // 32-bit reads are always atomic.
|
||||||
//__sync_synchronize(); // TODO: May not be necessary.
|
//__sync_synchronize(); // TODO: May not be necessary.
|
||||||
// Compiler instruction only. x86 loads always have acquire semantics.
|
// Compiler instruction only. x86 loads always have acquire semantics.
|
||||||
__asm__ __volatile__ ( "":::"memory" );
|
__asm__ __volatile__ ( "":::"memory" );
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void AtomicOr(volatile u32& target, u32 value) {
|
inline void AtomicOr(volatile u32& target, u32 value) {
|
||||||
__sync_or_and_fetch(&target, value);
|
__sync_or_and_fetch(&target, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void AtomicStore(volatile u32& dest, u32 value) {
|
inline void AtomicStore(volatile u32& dest, u32 value) {
|
||||||
dest = value; // 32-bit writes are always atomic.
|
dest = value; // 32-bit writes are always atomic.
|
||||||
}
|
}
|
||||||
inline void AtomicStoreRelease(volatile u32& dest, u32 value) {
|
inline void AtomicStoreRelease(volatile u32& dest, u32 value) {
|
||||||
__sync_lock_test_and_set(&dest, value); // TODO: Wrong! This function is has acquire semantics.
|
__sync_lock_test_and_set(&dest, value); // TODO: Wrong! This function is has acquire semantics.
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,40 +31,40 @@ namespace Common
|
||||||
{
|
{
|
||||||
|
|
||||||
inline void AtomicAdd(volatile u32& target, u32 value) {
|
inline void AtomicAdd(volatile u32& target, u32 value) {
|
||||||
InterlockedExchangeAdd((volatile LONG*)&target, (LONG)value);
|
InterlockedExchangeAdd((volatile LONG*)&target, (LONG)value);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void AtomicAnd(volatile u32& target, u32 value) {
|
inline void AtomicAnd(volatile u32& target, u32 value) {
|
||||||
_InterlockedAnd((volatile LONG*)&target, (LONG)value);
|
_InterlockedAnd((volatile LONG*)&target, (LONG)value);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void AtomicIncrement(volatile u32& target) {
|
inline void AtomicIncrement(volatile u32& target) {
|
||||||
InterlockedIncrement((volatile LONG*)&target);
|
InterlockedIncrement((volatile LONG*)&target);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void AtomicDecrement(volatile u32& target) {
|
inline void AtomicDecrement(volatile u32& target) {
|
||||||
InterlockedDecrement((volatile LONG*)&target);
|
InterlockedDecrement((volatile LONG*)&target);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline u32 AtomicLoad(volatile u32& src) {
|
inline u32 AtomicLoad(volatile u32& src) {
|
||||||
return src; // 32-bit reads are always atomic.
|
return src; // 32-bit reads are always atomic.
|
||||||
}
|
}
|
||||||
inline u32 AtomicLoadAcquire(volatile u32& src) {
|
inline u32 AtomicLoadAcquire(volatile u32& src) {
|
||||||
u32 result = src; // 32-bit reads are always atomic.
|
u32 result = src; // 32-bit reads are always atomic.
|
||||||
_ReadBarrier(); // Compiler instruction only. x86 loads always have acquire semantics.
|
_ReadBarrier(); // Compiler instruction only. x86 loads always have acquire semantics.
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void AtomicOr(volatile u32& target, u32 value) {
|
inline void AtomicOr(volatile u32& target, u32 value) {
|
||||||
_InterlockedOr((volatile LONG*)&target, (LONG)value);
|
_InterlockedOr((volatile LONG*)&target, (LONG)value);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void AtomicStore(volatile u32& dest, u32 value) {
|
inline void AtomicStore(volatile u32& dest, u32 value) {
|
||||||
dest = value; // 32-bit writes are always atomic.
|
dest = value; // 32-bit writes are always atomic.
|
||||||
}
|
}
|
||||||
inline void AtomicStoreRelease(volatile u32& dest, u32 value) {
|
inline void AtomicStoreRelease(volatile u32& dest, u32 value) {
|
||||||
_WriteBarrier(); // Compiler instruction only. x86 stores always have release semantics.
|
_WriteBarrier(); // Compiler instruction only. x86 stores always have release semantics.
|
||||||
dest = value; // 32-bit writes are always atomic.
|
dest = value; // 32-bit writes are always atomic.
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,193 +11,193 @@
|
||||||
|
|
||||||
bool BreakPoints::IsAddressBreakPoint(u32 _iAddress)
|
bool BreakPoints::IsAddressBreakPoint(u32 _iAddress)
|
||||||
{
|
{
|
||||||
for (TBreakPoints::iterator i = m_BreakPoints.begin(); i != m_BreakPoints.end(); ++i)
|
for (TBreakPoints::iterator i = m_BreakPoints.begin(); i != m_BreakPoints.end(); ++i)
|
||||||
if (i->iAddress == _iAddress)
|
if (i->iAddress == _iAddress)
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BreakPoints::IsTempBreakPoint(u32 _iAddress)
|
bool BreakPoints::IsTempBreakPoint(u32 _iAddress)
|
||||||
{
|
{
|
||||||
for (TBreakPoints::iterator i = m_BreakPoints.begin(); i != m_BreakPoints.end(); ++i)
|
for (TBreakPoints::iterator i = m_BreakPoints.begin(); i != m_BreakPoints.end(); ++i)
|
||||||
if (i->iAddress == _iAddress && i->bTemporary)
|
if (i->iAddress == _iAddress && i->bTemporary)
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
BreakPoints::TBreakPointsStr BreakPoints::GetStrings() const
|
BreakPoints::TBreakPointsStr BreakPoints::GetStrings() const
|
||||||
{
|
{
|
||||||
TBreakPointsStr bps;
|
TBreakPointsStr bps;
|
||||||
for (TBreakPoints::const_iterator i = m_BreakPoints.begin();
|
for (TBreakPoints::const_iterator i = m_BreakPoints.begin();
|
||||||
i != m_BreakPoints.end(); ++i)
|
i != m_BreakPoints.end(); ++i)
|
||||||
{
|
{
|
||||||
if (!i->bTemporary)
|
if (!i->bTemporary)
|
||||||
{
|
{
|
||||||
std::stringstream bp;
|
std::stringstream bp;
|
||||||
bp << std::hex << i->iAddress << " " << (i->bOn ? "n" : "");
|
bp << std::hex << i->iAddress << " " << (i->bOn ? "n" : "");
|
||||||
bps.push_back(bp.str());
|
bps.push_back(bp.str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return bps;
|
return bps;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BreakPoints::AddFromStrings(const TBreakPointsStr& bps)
|
void BreakPoints::AddFromStrings(const TBreakPointsStr& bps)
|
||||||
{
|
{
|
||||||
for (TBreakPointsStr::const_iterator i = bps.begin(); i != bps.end(); ++i)
|
for (TBreakPointsStr::const_iterator i = bps.begin(); i != bps.end(); ++i)
|
||||||
{
|
{
|
||||||
TBreakPoint bp;
|
TBreakPoint bp;
|
||||||
std::stringstream bpstr;
|
std::stringstream bpstr;
|
||||||
bpstr << std::hex << *i;
|
bpstr << std::hex << *i;
|
||||||
bpstr >> bp.iAddress;
|
bpstr >> bp.iAddress;
|
||||||
bp.bOn = i->find("n") != i->npos;
|
bp.bOn = i->find("n") != i->npos;
|
||||||
bp.bTemporary = false;
|
bp.bTemporary = false;
|
||||||
Add(bp);
|
Add(bp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BreakPoints::Add(const TBreakPoint& bp)
|
void BreakPoints::Add(const TBreakPoint& bp)
|
||||||
{
|
{
|
||||||
if (!IsAddressBreakPoint(bp.iAddress))
|
if (!IsAddressBreakPoint(bp.iAddress))
|
||||||
{
|
{
|
||||||
m_BreakPoints.push_back(bp);
|
m_BreakPoints.push_back(bp);
|
||||||
//if (jit)
|
//if (jit)
|
||||||
// jit->GetBlockCache()->InvalidateICache(bp.iAddress, 4);
|
// jit->GetBlockCache()->InvalidateICache(bp.iAddress, 4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BreakPoints::Add(u32 em_address, bool temp)
|
void BreakPoints::Add(u32 em_address, bool temp)
|
||||||
{
|
{
|
||||||
if (!IsAddressBreakPoint(em_address)) // only add new addresses
|
if (!IsAddressBreakPoint(em_address)) // only add new addresses
|
||||||
{
|
{
|
||||||
TBreakPoint pt; // breakpoint settings
|
TBreakPoint pt; // breakpoint settings
|
||||||
pt.bOn = true;
|
pt.bOn = true;
|
||||||
pt.bTemporary = temp;
|
pt.bTemporary = temp;
|
||||||
pt.iAddress = em_address;
|
pt.iAddress = em_address;
|
||||||
|
|
||||||
m_BreakPoints.push_back(pt);
|
m_BreakPoints.push_back(pt);
|
||||||
|
|
||||||
//if (jit)
|
//if (jit)
|
||||||
// jit->GetBlockCache()->InvalidateICache(em_address, 4);
|
// jit->GetBlockCache()->InvalidateICache(em_address, 4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BreakPoints::Remove(u32 em_address)
|
void BreakPoints::Remove(u32 em_address)
|
||||||
{
|
{
|
||||||
for (TBreakPoints::iterator i = m_BreakPoints.begin(); i != m_BreakPoints.end(); ++i)
|
for (TBreakPoints::iterator i = m_BreakPoints.begin(); i != m_BreakPoints.end(); ++i)
|
||||||
{
|
{
|
||||||
if (i->iAddress == em_address)
|
if (i->iAddress == em_address)
|
||||||
{
|
{
|
||||||
m_BreakPoints.erase(i);
|
m_BreakPoints.erase(i);
|
||||||
//if (jit)
|
//if (jit)
|
||||||
// jit->GetBlockCache()->InvalidateICache(em_address, 4);
|
// jit->GetBlockCache()->InvalidateICache(em_address, 4);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BreakPoints::Clear()
|
void BreakPoints::Clear()
|
||||||
{
|
{
|
||||||
//if (jit)
|
//if (jit)
|
||||||
//{
|
//{
|
||||||
// std::for_each(m_BreakPoints.begin(), m_BreakPoints.end(),
|
// std::for_each(m_BreakPoints.begin(), m_BreakPoints.end(),
|
||||||
// [](const TBreakPoint& bp)
|
// [](const TBreakPoint& bp)
|
||||||
// {
|
// {
|
||||||
// jit->GetBlockCache()->InvalidateICache(bp.iAddress, 4);
|
// jit->GetBlockCache()->InvalidateICache(bp.iAddress, 4);
|
||||||
// }
|
// }
|
||||||
// );
|
// );
|
||||||
//}
|
//}
|
||||||
|
|
||||||
m_BreakPoints.clear();
|
m_BreakPoints.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
MemChecks::TMemChecksStr MemChecks::GetStrings() const
|
MemChecks::TMemChecksStr MemChecks::GetStrings() const
|
||||||
{
|
{
|
||||||
TMemChecksStr mcs;
|
TMemChecksStr mcs;
|
||||||
for (TMemChecks::const_iterator i = m_MemChecks.begin();
|
for (TMemChecks::const_iterator i = m_MemChecks.begin();
|
||||||
i != m_MemChecks.end(); ++i)
|
i != m_MemChecks.end(); ++i)
|
||||||
{
|
{
|
||||||
std::stringstream mc;
|
std::stringstream mc;
|
||||||
mc << std::hex << i->StartAddress;
|
mc << std::hex << i->StartAddress;
|
||||||
mc << " " << (i->bRange ? i->EndAddress : i->StartAddress) << " " <<
|
mc << " " << (i->bRange ? i->EndAddress : i->StartAddress) << " " <<
|
||||||
(i->bRange ? "n" : "") << (i->OnRead ? "r" : "") <<
|
(i->bRange ? "n" : "") << (i->OnRead ? "r" : "") <<
|
||||||
(i->OnWrite ? "w" : "") << (i->Log ? "l" : "") << (i->Break ? "p" : "");
|
(i->OnWrite ? "w" : "") << (i->Log ? "l" : "") << (i->Break ? "p" : "");
|
||||||
mcs.push_back(mc.str());
|
mcs.push_back(mc.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
return mcs;
|
return mcs;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MemChecks::AddFromStrings(const TMemChecksStr& mcs)
|
void MemChecks::AddFromStrings(const TMemChecksStr& mcs)
|
||||||
{
|
{
|
||||||
for (TMemChecksStr::const_iterator i = mcs.begin(); i != mcs.end(); ++i)
|
for (TMemChecksStr::const_iterator i = mcs.begin(); i != mcs.end(); ++i)
|
||||||
{
|
{
|
||||||
TMemCheck mc;
|
TMemCheck mc;
|
||||||
std::stringstream mcstr;
|
std::stringstream mcstr;
|
||||||
mcstr << std::hex << *i;
|
mcstr << std::hex << *i;
|
||||||
mcstr >> mc.StartAddress;
|
mcstr >> mc.StartAddress;
|
||||||
mc.bRange = i->find("n") != i->npos;
|
mc.bRange = i->find("n") != i->npos;
|
||||||
mc.OnRead = i->find("r") != i->npos;
|
mc.OnRead = i->find("r") != i->npos;
|
||||||
mc.OnWrite = i->find("w") != i->npos;
|
mc.OnWrite = i->find("w") != i->npos;
|
||||||
mc.Log = i->find("l") != i->npos;
|
mc.Log = i->find("l") != i->npos;
|
||||||
mc.Break = i->find("p") != i->npos;
|
mc.Break = i->find("p") != i->npos;
|
||||||
if (mc.bRange)
|
if (mc.bRange)
|
||||||
mcstr >> mc.EndAddress;
|
mcstr >> mc.EndAddress;
|
||||||
else
|
else
|
||||||
mc.EndAddress = mc.StartAddress;
|
mc.EndAddress = mc.StartAddress;
|
||||||
Add(mc);
|
Add(mc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MemChecks::Add(const TMemCheck& _rMemoryCheck)
|
void MemChecks::Add(const TMemCheck& _rMemoryCheck)
|
||||||
{
|
{
|
||||||
if (GetMemCheck(_rMemoryCheck.StartAddress) == 0)
|
if (GetMemCheck(_rMemoryCheck.StartAddress) == 0)
|
||||||
m_MemChecks.push_back(_rMemoryCheck);
|
m_MemChecks.push_back(_rMemoryCheck);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MemChecks::Remove(u32 _Address)
|
void MemChecks::Remove(u32 _Address)
|
||||||
{
|
{
|
||||||
for (TMemChecks::iterator i = m_MemChecks.begin(); i != m_MemChecks.end(); ++i)
|
for (TMemChecks::iterator i = m_MemChecks.begin(); i != m_MemChecks.end(); ++i)
|
||||||
{
|
{
|
||||||
if (i->StartAddress == _Address)
|
if (i->StartAddress == _Address)
|
||||||
{
|
{
|
||||||
m_MemChecks.erase(i);
|
m_MemChecks.erase(i);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TMemCheck *MemChecks::GetMemCheck(u32 address)
|
TMemCheck *MemChecks::GetMemCheck(u32 address)
|
||||||
{
|
{
|
||||||
for (TMemChecks::iterator i = m_MemChecks.begin(); i != m_MemChecks.end(); ++i)
|
for (TMemChecks::iterator i = m_MemChecks.begin(); i != m_MemChecks.end(); ++i)
|
||||||
{
|
{
|
||||||
if (i->bRange)
|
if (i->bRange)
|
||||||
{
|
{
|
||||||
if (address >= i->StartAddress && address <= i->EndAddress)
|
if (address >= i->StartAddress && address <= i->EndAddress)
|
||||||
return &(*i);
|
return &(*i);
|
||||||
}
|
}
|
||||||
else if (i->StartAddress == address)
|
else if (i->StartAddress == address)
|
||||||
return &(*i);
|
return &(*i);
|
||||||
}
|
}
|
||||||
|
|
||||||
// none found
|
// none found
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TMemCheck::Action(DebugInterface *debug_interface, u32 iValue, u32 addr,
|
void TMemCheck::Action(DebugInterface *debug_interface, u32 iValue, u32 addr,
|
||||||
bool write, int size, u32 pc)
|
bool write, int size, u32 pc)
|
||||||
{
|
{
|
||||||
if ((write && OnWrite) || (!write && OnRead))
|
if ((write && OnWrite) || (!write && OnRead))
|
||||||
{
|
{
|
||||||
if (Log)
|
if (Log)
|
||||||
{
|
{
|
||||||
INFO_LOG(MEMMAP, "CHK %08x (%s) %s%i %0*x at %08x (%s)",
|
INFO_LOG(MEMMAP, "CHK %08x (%s) %s%i %0*x at %08x (%s)",
|
||||||
pc, debug_interface->getDescription(pc).c_str(),
|
pc, debug_interface->getDescription(pc).c_str(),
|
||||||
write ? "Write" : "Read", size*8, size*2, iValue, addr,
|
write ? "Write" : "Read", size*8, size*2, iValue, addr,
|
||||||
debug_interface->getDescription(addr).c_str()
|
debug_interface->getDescription(addr).c_str()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (Break)
|
if (Break)
|
||||||
debug_interface->breakNow();
|
debug_interface->breakNow();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,64 +14,64 @@ class DebugInterface;
|
||||||
|
|
||||||
struct TBreakPoint
|
struct TBreakPoint
|
||||||
{
|
{
|
||||||
u32 iAddress;
|
u32 iAddress;
|
||||||
bool bOn;
|
bool bOn;
|
||||||
bool bTemporary;
|
bool bTemporary;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TMemCheck
|
struct TMemCheck
|
||||||
{
|
{
|
||||||
TMemCheck() {
|
TMemCheck() {
|
||||||
numHits = 0;
|
numHits = 0;
|
||||||
StartAddress = EndAddress = 0;
|
StartAddress = EndAddress = 0;
|
||||||
bRange = OnRead = OnWrite = Log = Break = false;
|
bRange = OnRead = OnWrite = Log = Break = false;
|
||||||
}
|
}
|
||||||
u32 StartAddress;
|
u32 StartAddress;
|
||||||
u32 EndAddress;
|
u32 EndAddress;
|
||||||
|
|
||||||
bool bRange;
|
bool bRange;
|
||||||
|
|
||||||
bool OnRead;
|
bool OnRead;
|
||||||
bool OnWrite;
|
bool OnWrite;
|
||||||
|
|
||||||
bool Log;
|
bool Log;
|
||||||
bool Break;
|
bool Break;
|
||||||
|
|
||||||
u32 numHits;
|
u32 numHits;
|
||||||
|
|
||||||
void Action(DebugInterface *dbg_interface, u32 _iValue, u32 addr,
|
void Action(DebugInterface *dbg_interface, u32 _iValue, u32 addr,
|
||||||
bool write, int size, u32 pc);
|
bool write, int size, u32 pc);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Code breakpoints.
|
// Code breakpoints.
|
||||||
class BreakPoints
|
class BreakPoints
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef std::vector<TBreakPoint> TBreakPoints;
|
typedef std::vector<TBreakPoint> TBreakPoints;
|
||||||
typedef std::vector<std::string> TBreakPointsStr;
|
typedef std::vector<std::string> TBreakPointsStr;
|
||||||
|
|
||||||
const TBreakPoints& GetBreakPoints() { return m_BreakPoints; }
|
const TBreakPoints& GetBreakPoints() { return m_BreakPoints; }
|
||||||
|
|
||||||
TBreakPointsStr GetStrings() const;
|
TBreakPointsStr GetStrings() const;
|
||||||
void AddFromStrings(const TBreakPointsStr& bps);
|
void AddFromStrings(const TBreakPointsStr& bps);
|
||||||
|
|
||||||
// is address breakpoint
|
// is address breakpoint
|
||||||
bool IsAddressBreakPoint(u32 _iAddress);
|
bool IsAddressBreakPoint(u32 _iAddress);
|
||||||
bool IsTempBreakPoint(u32 _iAddress);
|
bool IsTempBreakPoint(u32 _iAddress);
|
||||||
|
|
||||||
// Add BreakPoint
|
// Add BreakPoint
|
||||||
void Add(u32 em_address, bool temp=false);
|
void Add(u32 em_address, bool temp=false);
|
||||||
void Add(const TBreakPoint& bp);
|
void Add(const TBreakPoint& bp);
|
||||||
|
|
||||||
// Remove Breakpoint
|
// Remove Breakpoint
|
||||||
void Remove(u32 _iAddress);
|
void Remove(u32 _iAddress);
|
||||||
void Clear();
|
void Clear();
|
||||||
|
|
||||||
void DeleteByAddress(u32 _Address);
|
void DeleteByAddress(u32 _Address);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TBreakPoints m_BreakPoints;
|
TBreakPoints m_BreakPoints;
|
||||||
u32 m_iBreakOnCount;
|
u32 m_iBreakOnCount;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -79,23 +79,23 @@ private:
|
||||||
class MemChecks
|
class MemChecks
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef std::vector<TMemCheck> TMemChecks;
|
typedef std::vector<TMemCheck> TMemChecks;
|
||||||
typedef std::vector<std::string> TMemChecksStr;
|
typedef std::vector<std::string> TMemChecksStr;
|
||||||
|
|
||||||
TMemChecks m_MemChecks;
|
TMemChecks m_MemChecks;
|
||||||
|
|
||||||
const TMemChecks& GetMemChecks() { return m_MemChecks; }
|
const TMemChecks& GetMemChecks() { return m_MemChecks; }
|
||||||
|
|
||||||
TMemChecksStr GetStrings() const;
|
TMemChecksStr GetStrings() const;
|
||||||
void AddFromStrings(const TMemChecksStr& mcs);
|
void AddFromStrings(const TMemChecksStr& mcs);
|
||||||
|
|
||||||
void Add(const TMemCheck& _rMemoryCheck);
|
void Add(const TMemCheck& _rMemoryCheck);
|
||||||
|
|
||||||
// memory breakpoint
|
// memory breakpoint
|
||||||
TMemCheck *GetMemCheck(u32 address);
|
TMemCheck *GetMemCheck(u32 address);
|
||||||
void Remove(u32 _Address);
|
void Remove(u32 _Address);
|
||||||
|
|
||||||
void Clear() { m_MemChecks.clear(); };
|
void Clear() { m_MemChecks.clear(); };
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -34,12 +34,12 @@ extern const char *netplay_dolphin_ver;
|
||||||
class NonCopyable
|
class NonCopyable
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
NonCopyable() {}
|
NonCopyable() {}
|
||||||
NonCopyable(const NonCopyable&&) {}
|
NonCopyable(const NonCopyable&&) {}
|
||||||
void operator=(const NonCopyable&&) {}
|
void operator=(const NonCopyable&&) {}
|
||||||
private:
|
private:
|
||||||
NonCopyable(NonCopyable&);
|
NonCopyable(NonCopyable&);
|
||||||
NonCopyable& operator=(NonCopyable& other);
|
NonCopyable& operator=(NonCopyable& other);
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -61,40 +61,40 @@ private:
|
||||||
#elif defined _WIN32
|
#elif defined _WIN32
|
||||||
|
|
||||||
// Check MSC ver
|
// Check MSC ver
|
||||||
#if !defined _MSC_VER || _MSC_VER <= 1000
|
#if !defined _MSC_VER || _MSC_VER <= 1000
|
||||||
#error needs at least version 1000 of MSC
|
#error needs at least version 1000 of MSC
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define NOMINMAX
|
#define NOMINMAX
|
||||||
|
|
||||||
// Memory leak checks
|
// Memory leak checks
|
||||||
#define CHECK_HEAP_INTEGRITY()
|
#define CHECK_HEAP_INTEGRITY()
|
||||||
|
|
||||||
// Alignment
|
// Alignment
|
||||||
#define MEMORY_ALIGNED16(x) __declspec(align(16)) x
|
#define MEMORY_ALIGNED16(x) __declspec(align(16)) x
|
||||||
#define MEMORY_ALIGNED32(x) __declspec(align(32)) x
|
#define MEMORY_ALIGNED32(x) __declspec(align(32)) x
|
||||||
#define MEMORY_ALIGNED64(x) __declspec(align(64)) x
|
#define MEMORY_ALIGNED64(x) __declspec(align(64)) x
|
||||||
#define MEMORY_ALIGNED128(x) __declspec(align(128)) x
|
#define MEMORY_ALIGNED128(x) __declspec(align(128)) x
|
||||||
#define MEMORY_ALIGNED16_DECL(x) __declspec(align(16)) x
|
#define MEMORY_ALIGNED16_DECL(x) __declspec(align(16)) x
|
||||||
#define MEMORY_ALIGNED64_DECL(x) __declspec(align(64)) x
|
#define MEMORY_ALIGNED64_DECL(x) __declspec(align(64)) x
|
||||||
|
|
||||||
// Since they are always around on windows
|
// Since they are always around on windows
|
||||||
#define HAVE_WX 1
|
#define HAVE_WX 1
|
||||||
#define HAVE_OPENAL 1
|
#define HAVE_OPENAL 1
|
||||||
|
|
||||||
#define HAVE_PORTAUDIO 1
|
#define HAVE_PORTAUDIO 1
|
||||||
|
|
||||||
// Debug definitions
|
// Debug definitions
|
||||||
#if defined(_DEBUG)
|
#if defined(_DEBUG)
|
||||||
#include <crtdbg.h>
|
#include <crtdbg.h>
|
||||||
#undef CHECK_HEAP_INTEGRITY
|
#undef CHECK_HEAP_INTEGRITY
|
||||||
#define CHECK_HEAP_INTEGRITY() {if (!_CrtCheckMemory()) PanicAlert("memory corruption detected. see log.");}
|
#define CHECK_HEAP_INTEGRITY() {if (!_CrtCheckMemory()) PanicAlert("memory corruption detected. see log.");}
|
||||||
// If you want to see how much a pain in the ass singletons are, for example:
|
// If you want to see how much a pain in the ass singletons are, for example:
|
||||||
// {614} normal block at 0x030C5310, 188 bytes long.
|
// {614} normal block at 0x030C5310, 188 bytes long.
|
||||||
// Data: <Master Log > 4D 61 73 74 65 72 20 4C 6F 67 00 00 00 00 00 00
|
// Data: <Master Log > 4D 61 73 74 65 72 20 4C 6F 67 00 00 00 00 00 00
|
||||||
struct CrtDebugBreak { CrtDebugBreak(int spot) { _CrtSetBreakAlloc(spot); } };
|
struct CrtDebugBreak { CrtDebugBreak(int spot) { _CrtSetBreakAlloc(spot); } };
|
||||||
//CrtDebugBreak breakAt(614);
|
//CrtDebugBreak breakAt(614);
|
||||||
#endif // end DEBUG/FAST
|
#endif // end DEBUG/FAST
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -149,18 +149,18 @@ private:
|
||||||
// Host communication.
|
// Host communication.
|
||||||
enum HOST_COMM
|
enum HOST_COMM
|
||||||
{
|
{
|
||||||
// Begin at 10 in case there is already messages with wParam = 0, 1, 2 and so on
|
// Begin at 10 in case there is already messages with wParam = 0, 1, 2 and so on
|
||||||
WM_USER_STOP = 10,
|
WM_USER_STOP = 10,
|
||||||
WM_USER_CREATE,
|
WM_USER_CREATE,
|
||||||
WM_USER_SETCURSOR,
|
WM_USER_SETCURSOR,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Used for notification on emulation state
|
// Used for notification on emulation state
|
||||||
enum EMUSTATE_CHANGE
|
enum EMUSTATE_CHANGE
|
||||||
{
|
{
|
||||||
EMUSTATE_CHANGE_PLAY = 1,
|
EMUSTATE_CHANGE_PLAY = 1,
|
||||||
EMUSTATE_CHANGE_PAUSE,
|
EMUSTATE_CHANGE_PAUSE,
|
||||||
EMUSTATE_CHANGE_STOP
|
EMUSTATE_CHANGE_STOP
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _COMMON_H_
|
#endif // _COMMON_H_
|
||||||
|
|
|
@ -20,7 +20,7 @@ template<> struct CompileTimeAssert<true> {};
|
||||||
#define b8(x) ( b4(x) | ( b4(x) >> 4) )
|
#define b8(x) ( b4(x) | ( b4(x) >> 4) )
|
||||||
#define b16(x) ( b8(x) | ( b8(x) >> 8) )
|
#define b16(x) ( b8(x) | ( b8(x) >> 8) )
|
||||||
#define b32(x) (b16(x) | (b16(x) >>16) )
|
#define b32(x) (b16(x) | (b16(x) >>16) )
|
||||||
#define ROUND_UP_POW2(x) (b32(x - 1) + 1)
|
#define ROUND_UP_POW2(x) (b32(x - 1) + 1)
|
||||||
|
|
||||||
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
|
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
|
||||||
|
|
||||||
|
@ -29,11 +29,11 @@ template<> struct CompileTimeAssert<true> {};
|
||||||
static __inline __m128i __attribute__((__always_inline__))
|
static __inline __m128i __attribute__((__always_inline__))
|
||||||
_mm_shuffle_epi8(__m128i a, __m128i mask)
|
_mm_shuffle_epi8(__m128i a, __m128i mask)
|
||||||
{
|
{
|
||||||
__m128i result;
|
__m128i result;
|
||||||
__asm__("pshufb %1, %0"
|
__asm__("pshufb %1, %0"
|
||||||
: "=x" (result)
|
: "=x" (result)
|
||||||
: "xm" (mask), "0" (a));
|
: "xm" (mask), "0" (a));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -47,103 +47,103 @@ _mm_shuffle_epi8(__m128i a, __m128i mask)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// go to debugger mode
|
// go to debugger mode
|
||||||
#ifdef GEKKO
|
#ifdef GEKKO
|
||||||
#define Crash()
|
#define Crash()
|
||||||
#elif defined _M_GENERIC
|
#elif defined _M_GENERIC
|
||||||
#define Crash() { exit(1); }
|
#define Crash() { exit(1); }
|
||||||
#else
|
#else
|
||||||
#define Crash() {asm ("int $3");}
|
#define Crash() {asm ("int $3");}
|
||||||
#endif
|
#endif
|
||||||
#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
|
#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
|
||||||
// GCC 4.8 defines all the rotate functions now
|
// GCC 4.8 defines all the rotate functions now
|
||||||
// Small issue with GCC's lrotl/lrotr intrinsics is they are still 32bit while we require 64bit
|
// Small issue with GCC's lrotl/lrotr intrinsics is they are still 32bit while we require 64bit
|
||||||
#ifndef _rotl
|
#ifndef _rotl
|
||||||
inline u32 _rotl(u32 x, int shift) {
|
inline u32 _rotl(u32 x, int shift) {
|
||||||
shift &= 31;
|
shift &= 31;
|
||||||
if (!shift) return x;
|
if (!shift) return x;
|
||||||
return (x << shift) | (x >> (32 - shift));
|
return (x << shift) | (x >> (32 - shift));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline u32 _rotr(u32 x, int shift) {
|
inline u32 _rotr(u32 x, int shift) {
|
||||||
shift &= 31;
|
shift &= 31;
|
||||||
if (!shift) return x;
|
if (!shift) return x;
|
||||||
return (x >> shift) | (x << (32 - shift));
|
return (x >> shift) | (x << (32 - shift));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
inline u64 _rotl64(u64 x, unsigned int shift){
|
inline u64 _rotl64(u64 x, unsigned int shift){
|
||||||
unsigned int n = shift % 64;
|
unsigned int n = shift % 64;
|
||||||
return (x << n) | (x >> (64 - n));
|
return (x << n) | (x >> (64 - n));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline u64 _rotr64(u64 x, unsigned int shift){
|
inline u64 _rotr64(u64 x, unsigned int shift){
|
||||||
unsigned int n = shift % 64;
|
unsigned int n = shift % 64;
|
||||||
return (x >> n) | (x << (64 - n));
|
return (x >> n) | (x << (64 - n));
|
||||||
}
|
}
|
||||||
|
|
||||||
#else // WIN32
|
#else // WIN32
|
||||||
// Function Cross-Compatibility
|
// Function Cross-Compatibility
|
||||||
#define strcasecmp _stricmp
|
#define strcasecmp _stricmp
|
||||||
#define strncasecmp _strnicmp
|
#define strncasecmp _strnicmp
|
||||||
#define unlink _unlink
|
#define unlink _unlink
|
||||||
#define snprintf _snprintf
|
#define snprintf _snprintf
|
||||||
#define vscprintf _vscprintf
|
#define vscprintf _vscprintf
|
||||||
|
|
||||||
// Locale Cross-Compatibility
|
// Locale Cross-Compatibility
|
||||||
#define locale_t _locale_t
|
#define locale_t _locale_t
|
||||||
#define freelocale _free_locale
|
#define freelocale _free_locale
|
||||||
#define newlocale(mask, locale, base) _create_locale(mask, locale)
|
#define newlocale(mask, locale, base) _create_locale(mask, locale)
|
||||||
|
|
||||||
#define LC_GLOBAL_LOCALE ((locale_t)-1)
|
#define LC_GLOBAL_LOCALE ((locale_t)-1)
|
||||||
#define LC_ALL_MASK LC_ALL
|
#define LC_ALL_MASK LC_ALL
|
||||||
#define LC_COLLATE_MASK LC_COLLATE
|
#define LC_COLLATE_MASK LC_COLLATE
|
||||||
#define LC_CTYPE_MASK LC_CTYPE
|
#define LC_CTYPE_MASK LC_CTYPE
|
||||||
#define LC_MONETARY_MASK LC_MONETARY
|
#define LC_MONETARY_MASK LC_MONETARY
|
||||||
#define LC_NUMERIC_MASK LC_NUMERIC
|
#define LC_NUMERIC_MASK LC_NUMERIC
|
||||||
#define LC_TIME_MASK LC_TIME
|
#define LC_TIME_MASK LC_TIME
|
||||||
|
|
||||||
inline locale_t uselocale(locale_t new_locale)
|
inline locale_t uselocale(locale_t new_locale)
|
||||||
{
|
{
|
||||||
// Retrieve the current per thread locale setting
|
// Retrieve the current per thread locale setting
|
||||||
bool bIsPerThread = (_configthreadlocale(0) == _ENABLE_PER_THREAD_LOCALE);
|
bool bIsPerThread = (_configthreadlocale(0) == _ENABLE_PER_THREAD_LOCALE);
|
||||||
|
|
||||||
// Retrieve the current thread-specific locale
|
// Retrieve the current thread-specific locale
|
||||||
locale_t old_locale = bIsPerThread ? _get_current_locale() : LC_GLOBAL_LOCALE;
|
locale_t old_locale = bIsPerThread ? _get_current_locale() : LC_GLOBAL_LOCALE;
|
||||||
|
|
||||||
if(new_locale == LC_GLOBAL_LOCALE)
|
if(new_locale == LC_GLOBAL_LOCALE)
|
||||||
{
|
{
|
||||||
// Restore the global locale
|
// Restore the global locale
|
||||||
_configthreadlocale(_DISABLE_PER_THREAD_LOCALE);
|
_configthreadlocale(_DISABLE_PER_THREAD_LOCALE);
|
||||||
}
|
}
|
||||||
else if(new_locale != NULL)
|
else if(new_locale != NULL)
|
||||||
{
|
{
|
||||||
// Configure the thread to set the locale only for this thread
|
// Configure the thread to set the locale only for this thread
|
||||||
_configthreadlocale(_ENABLE_PER_THREAD_LOCALE);
|
_configthreadlocale(_ENABLE_PER_THREAD_LOCALE);
|
||||||
|
|
||||||
// Set all locale categories
|
// Set all locale categories
|
||||||
for(int i = LC_MIN; i <= LC_MAX; i++)
|
for(int i = LC_MIN; i <= LC_MAX; i++)
|
||||||
setlocale(i, new_locale->locinfo->lc_category[i].locale);
|
setlocale(i, new_locale->locinfo->lc_category[i].locale);
|
||||||
}
|
}
|
||||||
|
|
||||||
return old_locale;
|
return old_locale;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 64 bit offsets for windows
|
// 64 bit offsets for windows
|
||||||
#define fseeko _fseeki64
|
#define fseeko _fseeki64
|
||||||
#define ftello _ftelli64
|
#define ftello _ftelli64
|
||||||
#define atoll _atoi64
|
#define atoll _atoi64
|
||||||
#define stat64 _stat64
|
#define stat64 _stat64
|
||||||
#define fstat64 _fstat64
|
#define fstat64 _fstat64
|
||||||
#define fileno _fileno
|
#define fileno _fileno
|
||||||
|
|
||||||
#if _M_IX86
|
#if _M_IX86
|
||||||
#define Crash() {__asm int 3}
|
#define Crash() {__asm int 3}
|
||||||
#else
|
#else
|
||||||
extern "C" {
|
extern "C" {
|
||||||
__declspec(dllimport) void __stdcall DebugBreak(void);
|
__declspec(dllimport) void __stdcall DebugBreak(void);
|
||||||
}
|
}
|
||||||
#define Crash() {DebugBreak();}
|
#define Crash() {DebugBreak();}
|
||||||
#endif // M_IX86
|
#endif // M_IX86
|
||||||
#endif // WIN32 ndef
|
#endif // WIN32 ndef
|
||||||
|
|
||||||
// Dolphin's min and max functions
|
// Dolphin's min and max functions
|
||||||
|
@ -186,11 +186,11 @@ inline u32 swap32(u32 _data) {return bswap_32(_data);}
|
||||||
inline u64 swap64(u64 _data) {return bswap_64(_data);}
|
inline u64 swap64(u64 _data) {return bswap_64(_data);}
|
||||||
#elif __APPLE__
|
#elif __APPLE__
|
||||||
inline __attribute__((always_inline)) u16 swap16(u16 _data)
|
inline __attribute__((always_inline)) u16 swap16(u16 _data)
|
||||||
{return (_data >> 8) | (_data << 8);}
|
{return (_data >> 8) | (_data << 8);}
|
||||||
inline __attribute__((always_inline)) u32 swap32(u32 _data)
|
inline __attribute__((always_inline)) u32 swap32(u32 _data)
|
||||||
{return __builtin_bswap32(_data);}
|
{return __builtin_bswap32(_data);}
|
||||||
inline __attribute__((always_inline)) u64 swap64(u64 _data)
|
inline __attribute__((always_inline)) u64 swap64(u64 _data)
|
||||||
{return __builtin_bswap64(_data);}
|
{return __builtin_bswap64(_data);}
|
||||||
#elif __FreeBSD__
|
#elif __FreeBSD__
|
||||||
inline u16 swap16(u16 _data) {return bswap16(_data);}
|
inline u16 swap16(u16 _data) {return bswap16(_data);}
|
||||||
inline u32 swap32(u32 _data) {return bswap32(_data);}
|
inline u32 swap32(u32 _data) {return bswap32(_data);}
|
||||||
|
@ -216,28 +216,28 @@ inline void swap<1>(u8* data)
|
||||||
template <>
|
template <>
|
||||||
inline void swap<2>(u8* data)
|
inline void swap<2>(u8* data)
|
||||||
{
|
{
|
||||||
*reinterpret_cast<u16*>(data) = swap16(data);
|
*reinterpret_cast<u16*>(data) = swap16(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
inline void swap<4>(u8* data)
|
inline void swap<4>(u8* data)
|
||||||
{
|
{
|
||||||
*reinterpret_cast<u32*>(data) = swap32(data);
|
*reinterpret_cast<u32*>(data) = swap32(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
inline void swap<8>(u8* data)
|
inline void swap<8>(u8* data)
|
||||||
{
|
{
|
||||||
*reinterpret_cast<u64*>(data) = swap64(data);
|
*reinterpret_cast<u64*>(data) = swap64(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline T FromBigEndian(T data)
|
inline T FromBigEndian(T data)
|
||||||
{
|
{
|
||||||
//static_assert(std::is_arithmetic<T>::value, "function only makes sense with arithmetic types");
|
//static_assert(std::is_arithmetic<T>::value, "function only makes sense with arithmetic types");
|
||||||
|
|
||||||
swap<sizeof(data)>(reinterpret_cast<u8*>(&data));
|
swap<sizeof(data)>(reinterpret_cast<u8*>(&data));
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // Namespace Common
|
} // Namespace Common
|
||||||
|
|
|
@ -13,34 +13,34 @@
|
||||||
#define DIR_SEP_CHR '/'
|
#define DIR_SEP_CHR '/'
|
||||||
|
|
||||||
#ifndef MAX_PATH
|
#ifndef MAX_PATH
|
||||||
#define MAX_PATH 260
|
#define MAX_PATH 260
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// The user data dir
|
// The user data dir
|
||||||
#define ROOT_DIR "."
|
#define ROOT_DIR "."
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#define USERDATA_DIR "user"
|
#define USERDATA_DIR "user"
|
||||||
#define EMU_DATA_DIR "emu"
|
#define EMU_DATA_DIR "emu"
|
||||||
#else
|
#else
|
||||||
#define USERDATA_DIR "user"
|
#define USERDATA_DIR "user"
|
||||||
#ifdef USER_DIR
|
#ifdef USER_DIR
|
||||||
#define EMU_DATA_DIR USER_DIR
|
#define EMU_DATA_DIR USER_DIR
|
||||||
#else
|
#else
|
||||||
#define EMU_DATA_DIR ".emu"
|
#define EMU_DATA_DIR ".emu"
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Shared data dirs (Sys and shared User for linux)
|
// Shared data dirs (Sys and shared User for linux)
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#define SYSDATA_DIR "sys"
|
#define SYSDATA_DIR "sys"
|
||||||
#else
|
#else
|
||||||
#ifdef DATA_DIR
|
#ifdef DATA_DIR
|
||||||
#define SYSDATA_DIR DATA_DIR "sys"
|
#define SYSDATA_DIR DATA_DIR "sys"
|
||||||
#define SHARED_USER_DIR DATA_DIR USERDATA_DIR DIR_SEP
|
#define SHARED_USER_DIR DATA_DIR USERDATA_DIR DIR_SEP
|
||||||
#else
|
#else
|
||||||
#define SYSDATA_DIR "sys"
|
#define SYSDATA_DIR "sys"
|
||||||
#define SHARED_USER_DIR ROOT_DIR DIR_SEP USERDATA_DIR DIR_SEP
|
#define SHARED_USER_DIR ROOT_DIR DIR_SEP USERDATA_DIR DIR_SEP
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Dirs in both User and Sys
|
// Dirs in both User and Sys
|
||||||
|
@ -49,31 +49,31 @@
|
||||||
#define JAP_DIR "JAP"
|
#define JAP_DIR "JAP"
|
||||||
|
|
||||||
// Subdirs in the User dir returned by GetUserPath(D_USER_IDX)
|
// Subdirs in the User dir returned by GetUserPath(D_USER_IDX)
|
||||||
#define CONFIG_DIR "config"
|
#define CONFIG_DIR "config"
|
||||||
#define GAMECONFIG_DIR "game_config"
|
#define GAMECONFIG_DIR "game_config"
|
||||||
#define MAPS_DIR "maps"
|
#define MAPS_DIR "maps"
|
||||||
#define CACHE_DIR "cache"
|
#define CACHE_DIR "cache"
|
||||||
#define SHADERCACHE_DIR "shader_cache"
|
#define SHADERCACHE_DIR "shader_cache"
|
||||||
#define STATESAVES_DIR "state_saves"
|
#define STATESAVES_DIR "state_saves"
|
||||||
#define SCREENSHOTS_DIR "screenShots"
|
#define SCREENSHOTS_DIR "screenShots"
|
||||||
#define DUMP_DIR "dump"
|
#define DUMP_DIR "dump"
|
||||||
#define DUMP_TEXTURES_DIR "textures"
|
#define DUMP_TEXTURES_DIR "textures"
|
||||||
#define DUMP_FRAMES_DIR "frames"
|
#define DUMP_FRAMES_DIR "frames"
|
||||||
#define DUMP_AUDIO_DIR "audio"
|
#define DUMP_AUDIO_DIR "audio"
|
||||||
#define LOGS_DIR "logs"
|
#define LOGS_DIR "logs"
|
||||||
#define SHADERS_DIR "shaders"
|
#define SHADERS_DIR "shaders"
|
||||||
#define SYSCONF_DIR "sysconf"
|
#define SYSCONF_DIR "sysconf"
|
||||||
|
|
||||||
// Filenames
|
// Filenames
|
||||||
// Files in the directory returned by GetUserPath(D_CONFIG_IDX)
|
// Files in the directory returned by GetUserPath(D_CONFIG_IDX)
|
||||||
#define EMU_CONFIG "emu.ini"
|
#define EMU_CONFIG "emu.ini"
|
||||||
#define DEBUGGER_CONFIG "debugger.ini"
|
#define DEBUGGER_CONFIG "debugger.ini"
|
||||||
#define LOGGER_CONFIG "logger.ini"
|
#define LOGGER_CONFIG "logger.ini"
|
||||||
|
|
||||||
// Files in the directory returned by GetUserPath(D_LOGS_IDX)
|
// Files in the directory returned by GetUserPath(D_LOGS_IDX)
|
||||||
#define MAIN_LOG "emu.log"
|
#define MAIN_LOG "emu.log"
|
||||||
|
|
||||||
// Files in the directory returned by GetUserPath(D_SYSCONF_IDX)
|
// Files in the directory returned by GetUserPath(D_SYSCONF_IDX)
|
||||||
#define SYSCONF "SYSCONF"
|
#define SYSCONF "SYSCONF"
|
||||||
|
|
||||||
#endif // _COMMON_PATHS_H_
|
#endif // _COMMON_PATHS_H_
|
||||||
|
|
|
@ -20,16 +20,16 @@
|
||||||
ConsoleListener::ConsoleListener()
|
ConsoleListener::ConsoleListener()
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
hConsole = NULL;
|
hConsole = NULL;
|
||||||
bUseColor = true;
|
bUseColor = true;
|
||||||
#else
|
#else
|
||||||
bUseColor = isatty(fileno(stdout));
|
bUseColor = isatty(fileno(stdout));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
ConsoleListener::~ConsoleListener()
|
ConsoleListener::~ConsoleListener()
|
||||||
{
|
{
|
||||||
Close();
|
Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 100, 100, "Dolphin Log Console"
|
// 100, 100, "Dolphin Log Console"
|
||||||
|
@ -38,31 +38,31 @@ ConsoleListener::~ConsoleListener()
|
||||||
void ConsoleListener::Open(bool Hidden, int Width, int Height, const char *Title)
|
void ConsoleListener::Open(bool Hidden, int Width, int Height, const char *Title)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
if (!GetConsoleWindow())
|
if (!GetConsoleWindow())
|
||||||
{
|
{
|
||||||
// Open the console window and create the window handle for GetStdHandle()
|
// Open the console window and create the window handle for GetStdHandle()
|
||||||
AllocConsole();
|
AllocConsole();
|
||||||
// Hide
|
// Hide
|
||||||
if (Hidden) ShowWindow(GetConsoleWindow(), SW_HIDE);
|
if (Hidden) ShowWindow(GetConsoleWindow(), SW_HIDE);
|
||||||
// Save the window handle that AllocConsole() created
|
// Save the window handle that AllocConsole() created
|
||||||
hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
|
hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
// Set the console window title
|
// Set the console window title
|
||||||
SetConsoleTitle(UTF8ToTStr(Title).c_str());
|
SetConsoleTitle(UTF8ToTStr(Title).c_str());
|
||||||
// Set letter space
|
// Set letter space
|
||||||
LetterSpace(80, 4000);
|
LetterSpace(80, 4000);
|
||||||
//MoveWindow(GetConsoleWindow(), 200,200, 800,800, true);
|
//MoveWindow(GetConsoleWindow(), 200,200, 800,800, true);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
|
hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConsoleListener::UpdateHandle()
|
void ConsoleListener::UpdateHandle()
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
|
hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,267 +70,267 @@ void ConsoleListener::UpdateHandle()
|
||||||
void ConsoleListener::Close()
|
void ConsoleListener::Close()
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
if (hConsole == NULL)
|
if (hConsole == NULL)
|
||||||
return;
|
return;
|
||||||
FreeConsole();
|
FreeConsole();
|
||||||
hConsole = NULL;
|
hConsole = NULL;
|
||||||
#else
|
#else
|
||||||
fflush(NULL);
|
fflush(NULL);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ConsoleListener::IsOpen()
|
bool ConsoleListener::IsOpen()
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
return (hConsole != NULL);
|
return (hConsole != NULL);
|
||||||
#else
|
#else
|
||||||
return true;
|
return true;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
LetterSpace: SetConsoleScreenBufferSize and SetConsoleWindowInfo are
|
LetterSpace: SetConsoleScreenBufferSize and SetConsoleWindowInfo are
|
||||||
dependent on each other, that's the reason for the additional checks.
|
dependent on each other, that's the reason for the additional checks.
|
||||||
*/
|
*/
|
||||||
void ConsoleListener::BufferWidthHeight(int BufferWidth, int BufferHeight, int ScreenWidth, int ScreenHeight, bool BufferFirst)
|
void ConsoleListener::BufferWidthHeight(int BufferWidth, int BufferHeight, int ScreenWidth, int ScreenHeight, bool BufferFirst)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
BOOL SB, SW;
|
BOOL SB, SW;
|
||||||
if (BufferFirst)
|
if (BufferFirst)
|
||||||
{
|
{
|
||||||
// Change screen buffer size
|
// Change screen buffer size
|
||||||
COORD Co = {BufferWidth, BufferHeight};
|
COORD Co = {BufferWidth, BufferHeight};
|
||||||
SB = SetConsoleScreenBufferSize(hConsole, Co);
|
SB = SetConsoleScreenBufferSize(hConsole, Co);
|
||||||
// Change the screen buffer window size
|
// Change the screen buffer window size
|
||||||
SMALL_RECT coo = {0,0,ScreenWidth, ScreenHeight}; // top, left, right, bottom
|
SMALL_RECT coo = {0,0,ScreenWidth, ScreenHeight}; // top, left, right, bottom
|
||||||
SW = SetConsoleWindowInfo(hConsole, TRUE, &coo);
|
SW = SetConsoleWindowInfo(hConsole, TRUE, &coo);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Change the screen buffer window size
|
// Change the screen buffer window size
|
||||||
SMALL_RECT coo = {0,0, ScreenWidth, ScreenHeight}; // top, left, right, bottom
|
SMALL_RECT coo = {0,0, ScreenWidth, ScreenHeight}; // top, left, right, bottom
|
||||||
SW = SetConsoleWindowInfo(hConsole, TRUE, &coo);
|
SW = SetConsoleWindowInfo(hConsole, TRUE, &coo);
|
||||||
// Change screen buffer size
|
// Change screen buffer size
|
||||||
COORD Co = {BufferWidth, BufferHeight};
|
COORD Co = {BufferWidth, BufferHeight};
|
||||||
SB = SetConsoleScreenBufferSize(hConsole, Co);
|
SB = SetConsoleScreenBufferSize(hConsole, Co);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
void ConsoleListener::LetterSpace(int Width, int Height)
|
void ConsoleListener::LetterSpace(int Width, int Height)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
// Get console info
|
// Get console info
|
||||||
CONSOLE_SCREEN_BUFFER_INFO ConInfo;
|
CONSOLE_SCREEN_BUFFER_INFO ConInfo;
|
||||||
GetConsoleScreenBufferInfo(hConsole, &ConInfo);
|
GetConsoleScreenBufferInfo(hConsole, &ConInfo);
|
||||||
|
|
||||||
//
|
//
|
||||||
int OldBufferWidth = ConInfo.dwSize.X;
|
int OldBufferWidth = ConInfo.dwSize.X;
|
||||||
int OldBufferHeight = ConInfo.dwSize.Y;
|
int OldBufferHeight = ConInfo.dwSize.Y;
|
||||||
int OldScreenWidth = (ConInfo.srWindow.Right - ConInfo.srWindow.Left);
|
int OldScreenWidth = (ConInfo.srWindow.Right - ConInfo.srWindow.Left);
|
||||||
int OldScreenHeight = (ConInfo.srWindow.Bottom - ConInfo.srWindow.Top);
|
int OldScreenHeight = (ConInfo.srWindow.Bottom - ConInfo.srWindow.Top);
|
||||||
//
|
//
|
||||||
int NewBufferWidth = Width;
|
int NewBufferWidth = Width;
|
||||||
int NewBufferHeight = Height;
|
int NewBufferHeight = Height;
|
||||||
int NewScreenWidth = NewBufferWidth - 1;
|
int NewScreenWidth = NewBufferWidth - 1;
|
||||||
int NewScreenHeight = OldScreenHeight;
|
int NewScreenHeight = OldScreenHeight;
|
||||||
|
|
||||||
// Width
|
// Width
|
||||||
BufferWidthHeight(NewBufferWidth, OldBufferHeight, NewScreenWidth, OldScreenHeight, (NewBufferWidth > OldScreenWidth-1));
|
BufferWidthHeight(NewBufferWidth, OldBufferHeight, NewScreenWidth, OldScreenHeight, (NewBufferWidth > OldScreenWidth-1));
|
||||||
// Height
|
// Height
|
||||||
BufferWidthHeight(NewBufferWidth, NewBufferHeight, NewScreenWidth, NewScreenHeight, (NewBufferHeight > OldScreenHeight-1));
|
BufferWidthHeight(NewBufferWidth, NewBufferHeight, NewScreenWidth, NewScreenHeight, (NewBufferHeight > OldScreenHeight-1));
|
||||||
|
|
||||||
// Resize the window too
|
// Resize the window too
|
||||||
//MoveWindow(GetConsoleWindow(), 200,200, (Width*8 + 50),(NewScreenHeight*12 + 200), true);
|
//MoveWindow(GetConsoleWindow(), 200,200, (Width*8 + 50),(NewScreenHeight*12 + 200), true);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
COORD ConsoleListener::GetCoordinates(int BytesRead, int BufferWidth)
|
COORD ConsoleListener::GetCoordinates(int BytesRead, int BufferWidth)
|
||||||
{
|
{
|
||||||
COORD Ret = {0, 0};
|
COORD Ret = {0, 0};
|
||||||
// Full rows
|
// Full rows
|
||||||
int Step = (int)floor((float)BytesRead / (float)BufferWidth);
|
int Step = (int)floor((float)BytesRead / (float)BufferWidth);
|
||||||
Ret.Y += Step;
|
Ret.Y += Step;
|
||||||
// Partial row
|
// Partial row
|
||||||
Ret.X = BytesRead - (BufferWidth * Step);
|
Ret.X = BytesRead - (BufferWidth * Step);
|
||||||
return Ret;
|
return Ret;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
void ConsoleListener::PixelSpace(int Left, int Top, int Width, int Height, bool Resize)
|
void ConsoleListener::PixelSpace(int Left, int Top, int Width, int Height, bool Resize)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
// Check size
|
// Check size
|
||||||
if (Width < 8 || Height < 12) return;
|
if (Width < 8 || Height < 12) return;
|
||||||
|
|
||||||
bool DBef = true;
|
bool DBef = true;
|
||||||
bool DAft = true;
|
bool DAft = true;
|
||||||
std::string SLog = "";
|
std::string SLog = "";
|
||||||
|
|
||||||
const HWND hWnd = GetConsoleWindow();
|
const HWND hWnd = GetConsoleWindow();
|
||||||
const HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
|
const HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
|
|
||||||
// Get console info
|
// Get console info
|
||||||
CONSOLE_SCREEN_BUFFER_INFO ConInfo;
|
CONSOLE_SCREEN_BUFFER_INFO ConInfo;
|
||||||
GetConsoleScreenBufferInfo(hConsole, &ConInfo);
|
GetConsoleScreenBufferInfo(hConsole, &ConInfo);
|
||||||
DWORD BufferSize = ConInfo.dwSize.X * ConInfo.dwSize.Y;
|
DWORD BufferSize = ConInfo.dwSize.X * ConInfo.dwSize.Y;
|
||||||
|
|
||||||
// ---------------------------------------------------------------------
|
// ---------------------------------------------------------------------
|
||||||
// Save the current text
|
// Save the current text
|
||||||
// ------------------------
|
// ------------------------
|
||||||
DWORD cCharsRead = 0;
|
DWORD cCharsRead = 0;
|
||||||
COORD coordScreen = { 0, 0 };
|
COORD coordScreen = { 0, 0 };
|
||||||
|
|
||||||
static const int MAX_BYTES = 1024 * 16;
|
static const int MAX_BYTES = 1024 * 16;
|
||||||
|
|
||||||
std::vector<std::array<TCHAR, MAX_BYTES>> Str;
|
std::vector<std::array<TCHAR, MAX_BYTES>> Str;
|
||||||
std::vector<std::array<WORD, MAX_BYTES>> Attr;
|
std::vector<std::array<WORD, MAX_BYTES>> Attr;
|
||||||
|
|
||||||
// ReadConsoleOutputAttribute seems to have a limit at this level
|
// ReadConsoleOutputAttribute seems to have a limit at this level
|
||||||
static const int ReadBufferSize = MAX_BYTES - 32;
|
static const int ReadBufferSize = MAX_BYTES - 32;
|
||||||
|
|
||||||
DWORD cAttrRead = ReadBufferSize;
|
DWORD cAttrRead = ReadBufferSize;
|
||||||
DWORD BytesRead = 0;
|
DWORD BytesRead = 0;
|
||||||
while (BytesRead < BufferSize)
|
while (BytesRead < BufferSize)
|
||||||
{
|
{
|
||||||
Str.resize(Str.size() + 1);
|
Str.resize(Str.size() + 1);
|
||||||
if (!ReadConsoleOutputCharacter(hConsole, Str.back().data(), ReadBufferSize, coordScreen, &cCharsRead))
|
if (!ReadConsoleOutputCharacter(hConsole, Str.back().data(), ReadBufferSize, coordScreen, &cCharsRead))
|
||||||
SLog += StringFromFormat("WriteConsoleOutputCharacter error");
|
SLog += StringFromFormat("WriteConsoleOutputCharacter error");
|
||||||
|
|
||||||
Attr.resize(Attr.size() + 1);
|
Attr.resize(Attr.size() + 1);
|
||||||
if (!ReadConsoleOutputAttribute(hConsole, Attr.back().data(), ReadBufferSize, coordScreen, &cAttrRead))
|
if (!ReadConsoleOutputAttribute(hConsole, Attr.back().data(), ReadBufferSize, coordScreen, &cAttrRead))
|
||||||
SLog += StringFromFormat("WriteConsoleOutputAttribute error");
|
SLog += StringFromFormat("WriteConsoleOutputAttribute error");
|
||||||
|
|
||||||
// Break on error
|
// Break on error
|
||||||
if (cAttrRead == 0) break;
|
if (cAttrRead == 0) break;
|
||||||
BytesRead += cAttrRead;
|
BytesRead += cAttrRead;
|
||||||
coordScreen = GetCoordinates(BytesRead, ConInfo.dwSize.X);
|
coordScreen = GetCoordinates(BytesRead, ConInfo.dwSize.X);
|
||||||
}
|
}
|
||||||
// Letter space
|
// Letter space
|
||||||
int LWidth = (int)(floor((float)Width / 8.0f) - 1.0f);
|
int LWidth = (int)(floor((float)Width / 8.0f) - 1.0f);
|
||||||
int LHeight = (int)(floor((float)Height / 12.0f) - 1.0f);
|
int LHeight = (int)(floor((float)Height / 12.0f) - 1.0f);
|
||||||
int LBufWidth = LWidth + 1;
|
int LBufWidth = LWidth + 1;
|
||||||
int LBufHeight = (int)floor((float)BufferSize / (float)LBufWidth);
|
int LBufHeight = (int)floor((float)BufferSize / (float)LBufWidth);
|
||||||
// Change screen buffer size
|
// Change screen buffer size
|
||||||
LetterSpace(LBufWidth, LBufHeight);
|
LetterSpace(LBufWidth, LBufHeight);
|
||||||
|
|
||||||
|
|
||||||
ClearScreen(true);
|
ClearScreen(true);
|
||||||
coordScreen.Y = 0;
|
coordScreen.Y = 0;
|
||||||
coordScreen.X = 0;
|
coordScreen.X = 0;
|
||||||
DWORD cCharsWritten = 0;
|
DWORD cCharsWritten = 0;
|
||||||
|
|
||||||
int BytesWritten = 0;
|
int BytesWritten = 0;
|
||||||
DWORD cAttrWritten = 0;
|
DWORD cAttrWritten = 0;
|
||||||
for (size_t i = 0; i < Attr.size(); i++)
|
for (size_t i = 0; i < Attr.size(); i++)
|
||||||
{
|
{
|
||||||
if (!WriteConsoleOutputCharacter(hConsole, Str[i].data(), ReadBufferSize, coordScreen, &cCharsWritten))
|
if (!WriteConsoleOutputCharacter(hConsole, Str[i].data(), ReadBufferSize, coordScreen, &cCharsWritten))
|
||||||
SLog += StringFromFormat("WriteConsoleOutputCharacter error");
|
SLog += StringFromFormat("WriteConsoleOutputCharacter error");
|
||||||
if (!WriteConsoleOutputAttribute(hConsole, Attr[i].data(), ReadBufferSize, coordScreen, &cAttrWritten))
|
if (!WriteConsoleOutputAttribute(hConsole, Attr[i].data(), ReadBufferSize, coordScreen, &cAttrWritten))
|
||||||
SLog += StringFromFormat("WriteConsoleOutputAttribute error");
|
SLog += StringFromFormat("WriteConsoleOutputAttribute error");
|
||||||
|
|
||||||
BytesWritten += cAttrWritten;
|
BytesWritten += cAttrWritten;
|
||||||
coordScreen = GetCoordinates(BytesWritten, LBufWidth);
|
coordScreen = GetCoordinates(BytesWritten, LBufWidth);
|
||||||
}
|
}
|
||||||
|
|
||||||
const int OldCursor = ConInfo.dwCursorPosition.Y * ConInfo.dwSize.X + ConInfo.dwCursorPosition.X;
|
const int OldCursor = ConInfo.dwCursorPosition.Y * ConInfo.dwSize.X + ConInfo.dwCursorPosition.X;
|
||||||
COORD Coo = GetCoordinates(OldCursor, LBufWidth);
|
COORD Coo = GetCoordinates(OldCursor, LBufWidth);
|
||||||
SetConsoleCursorPosition(hConsole, Coo);
|
SetConsoleCursorPosition(hConsole, Coo);
|
||||||
|
|
||||||
if (SLog.length() > 0) Log(LogTypes::LNOTICE, SLog.c_str());
|
if (SLog.length() > 0) Log(LogTypes::LNOTICE, SLog.c_str());
|
||||||
|
|
||||||
// Resize the window too
|
// Resize the window too
|
||||||
if (Resize) MoveWindow(GetConsoleWindow(), Left,Top, (Width + 100),Height, true);
|
if (Resize) MoveWindow(GetConsoleWindow(), Left,Top, (Width + 100),Height, true);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConsoleListener::Log(LogTypes::LOG_LEVELS Level, const char *Text)
|
void ConsoleListener::Log(LogTypes::LOG_LEVELS Level, const char *Text)
|
||||||
{
|
{
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
/*
|
/*
|
||||||
const int MAX_BYTES = 1024*10;
|
const int MAX_BYTES = 1024*10;
|
||||||
char Str[MAX_BYTES];
|
char Str[MAX_BYTES];
|
||||||
va_list ArgPtr;
|
va_list ArgPtr;
|
||||||
int Cnt;
|
int Cnt;
|
||||||
va_start(ArgPtr, Text);
|
va_start(ArgPtr, Text);
|
||||||
Cnt = vsnprintf(Str, MAX_BYTES, Text, ArgPtr);
|
Cnt = vsnprintf(Str, MAX_BYTES, Text, ArgPtr);
|
||||||
va_end(ArgPtr);
|
va_end(ArgPtr);
|
||||||
*/
|
*/
|
||||||
DWORD cCharsWritten;
|
DWORD cCharsWritten;
|
||||||
WORD Color;
|
WORD Color;
|
||||||
|
|
||||||
switch (Level)
|
switch (Level)
|
||||||
{
|
{
|
||||||
case NOTICE_LEVEL: // light green
|
case NOTICE_LEVEL: // light green
|
||||||
Color = FOREGROUND_GREEN | FOREGROUND_INTENSITY;
|
Color = FOREGROUND_GREEN | FOREGROUND_INTENSITY;
|
||||||
break;
|
break;
|
||||||
case ERROR_LEVEL: // light red
|
case ERROR_LEVEL: // light red
|
||||||
Color = FOREGROUND_RED | FOREGROUND_INTENSITY;
|
Color = FOREGROUND_RED | FOREGROUND_INTENSITY;
|
||||||
break;
|
break;
|
||||||
case WARNING_LEVEL: // light yellow
|
case WARNING_LEVEL: // light yellow
|
||||||
Color = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY;
|
Color = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY;
|
||||||
break;
|
break;
|
||||||
case INFO_LEVEL: // cyan
|
case INFO_LEVEL: // cyan
|
||||||
Color = FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY;
|
Color = FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY;
|
||||||
break;
|
break;
|
||||||
case DEBUG_LEVEL: // gray
|
case DEBUG_LEVEL: // gray
|
||||||
Color = FOREGROUND_INTENSITY;
|
Color = FOREGROUND_INTENSITY;
|
||||||
break;
|
break;
|
||||||
default: // off-white
|
default: // off-white
|
||||||
Color = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
|
Color = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (strlen(Text) > 10)
|
if (strlen(Text) > 10)
|
||||||
{
|
{
|
||||||
// First 10 chars white
|
// First 10 chars white
|
||||||
SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
|
SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
|
||||||
WriteConsole(hConsole, Text, 10, &cCharsWritten, NULL);
|
WriteConsole(hConsole, Text, 10, &cCharsWritten, NULL);
|
||||||
Text += 10;
|
Text += 10;
|
||||||
}
|
}
|
||||||
SetConsoleTextAttribute(hConsole, Color);
|
SetConsoleTextAttribute(hConsole, Color);
|
||||||
WriteConsole(hConsole, Text, (DWORD)strlen(Text), &cCharsWritten, NULL);
|
WriteConsole(hConsole, Text, (DWORD)strlen(Text), &cCharsWritten, NULL);
|
||||||
#else
|
#else
|
||||||
char ColorAttr[16] = "";
|
char ColorAttr[16] = "";
|
||||||
char ResetAttr[16] = "";
|
char ResetAttr[16] = "";
|
||||||
|
|
||||||
if (bUseColor)
|
if (bUseColor)
|
||||||
{
|
{
|
||||||
strcpy(ResetAttr, "\033[0m");
|
strcpy(ResetAttr, "\033[0m");
|
||||||
switch (Level)
|
switch (Level)
|
||||||
{
|
{
|
||||||
case NOTICE_LEVEL: // light green
|
case NOTICE_LEVEL: // light green
|
||||||
strcpy(ColorAttr, "\033[92m");
|
strcpy(ColorAttr, "\033[92m");
|
||||||
break;
|
break;
|
||||||
case ERROR_LEVEL: // light red
|
case ERROR_LEVEL: // light red
|
||||||
strcpy(ColorAttr, "\033[91m");
|
strcpy(ColorAttr, "\033[91m");
|
||||||
break;
|
break;
|
||||||
case WARNING_LEVEL: // light yellow
|
case WARNING_LEVEL: // light yellow
|
||||||
strcpy(ColorAttr, "\033[93m");
|
strcpy(ColorAttr, "\033[93m");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fprintf(stderr, "%s%s%s", ColorAttr, Text, ResetAttr);
|
fprintf(stderr, "%s%s%s", ColorAttr, Text, ResetAttr);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
// Clear console screen
|
// Clear console screen
|
||||||
void ConsoleListener::ClearScreen(bool Cursor)
|
void ConsoleListener::ClearScreen(bool Cursor)
|
||||||
{
|
{
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
COORD coordScreen = { 0, 0 };
|
COORD coordScreen = { 0, 0 };
|
||||||
DWORD cCharsWritten;
|
DWORD cCharsWritten;
|
||||||
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
||||||
DWORD dwConSize;
|
DWORD dwConSize;
|
||||||
|
|
||||||
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
|
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
|
|
||||||
GetConsoleScreenBufferInfo(hConsole, &csbi);
|
GetConsoleScreenBufferInfo(hConsole, &csbi);
|
||||||
dwConSize = csbi.dwSize.X * csbi.dwSize.Y;
|
dwConSize = csbi.dwSize.X * csbi.dwSize.Y;
|
||||||
// Write space to the entire console
|
// Write space to the entire console
|
||||||
FillConsoleOutputCharacter(hConsole, TEXT(' '), dwConSize, coordScreen, &cCharsWritten);
|
FillConsoleOutputCharacter(hConsole, TEXT(' '), dwConSize, coordScreen, &cCharsWritten);
|
||||||
GetConsoleScreenBufferInfo(hConsole, &csbi);
|
GetConsoleScreenBufferInfo(hConsole, &csbi);
|
||||||
FillConsoleOutputAttribute(hConsole, csbi.wAttributes, dwConSize, coordScreen, &cCharsWritten);
|
FillConsoleOutputAttribute(hConsole, csbi.wAttributes, dwConSize, coordScreen, &cCharsWritten);
|
||||||
// Reset cursor
|
// Reset cursor
|
||||||
if (Cursor) SetConsoleCursorPosition(hConsole, coordScreen);
|
if (Cursor) SetConsoleCursorPosition(hConsole, coordScreen);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,28 +14,28 @@
|
||||||
class ConsoleListener : public LogListener
|
class ConsoleListener : public LogListener
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ConsoleListener();
|
ConsoleListener();
|
||||||
~ConsoleListener();
|
~ConsoleListener();
|
||||||
|
|
||||||
void Open(bool Hidden = false, int Width = 100, int Height = 100, const char * Name = "Console");
|
void Open(bool Hidden = false, int Width = 100, int Height = 100, const char * Name = "Console");
|
||||||
void UpdateHandle();
|
void UpdateHandle();
|
||||||
void Close();
|
void Close();
|
||||||
bool IsOpen();
|
bool IsOpen();
|
||||||
void LetterSpace(int Width, int Height);
|
void LetterSpace(int Width, int Height);
|
||||||
void BufferWidthHeight(int BufferWidth, int BufferHeight, int ScreenWidth, int ScreenHeight, bool BufferFirst);
|
void BufferWidthHeight(int BufferWidth, int BufferHeight, int ScreenWidth, int ScreenHeight, bool BufferFirst);
|
||||||
void PixelSpace(int Left, int Top, int Width, int Height, bool);
|
void PixelSpace(int Left, int Top, int Width, int Height, bool);
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
COORD GetCoordinates(int BytesRead, int BufferWidth);
|
COORD GetCoordinates(int BytesRead, int BufferWidth);
|
||||||
#endif
|
#endif
|
||||||
void Log(LogTypes::LOG_LEVELS, const char *Text);
|
void Log(LogTypes::LOG_LEVELS, const char *Text);
|
||||||
void ClearScreen(bool Cursor = true);
|
void ClearScreen(bool Cursor = true);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
HWND GetHwnd(void);
|
HWND GetHwnd(void);
|
||||||
HANDLE hConsole;
|
HANDLE hConsole;
|
||||||
#endif
|
#endif
|
||||||
bool bUseColor;
|
bool bUseColor;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _CONSOLELISTENER_H
|
#endif // _CONSOLELISTENER_H
|
||||||
|
|
|
@ -11,69 +11,69 @@
|
||||||
|
|
||||||
enum CPUVendor
|
enum CPUVendor
|
||||||
{
|
{
|
||||||
VENDOR_INTEL = 0,
|
VENDOR_INTEL = 0,
|
||||||
VENDOR_AMD = 1,
|
VENDOR_AMD = 1,
|
||||||
VENDOR_ARM = 2,
|
VENDOR_ARM = 2,
|
||||||
VENDOR_OTHER = 3,
|
VENDOR_OTHER = 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CPUInfo
|
struct CPUInfo
|
||||||
{
|
{
|
||||||
CPUVendor vendor;
|
CPUVendor vendor;
|
||||||
|
|
||||||
char cpu_string[0x21];
|
char cpu_string[0x21];
|
||||||
char brand_string[0x41];
|
char brand_string[0x41];
|
||||||
bool OS64bit;
|
bool OS64bit;
|
||||||
bool CPU64bit;
|
bool CPU64bit;
|
||||||
bool Mode64bit;
|
bool Mode64bit;
|
||||||
|
|
||||||
bool HTT;
|
bool HTT;
|
||||||
int num_cores;
|
int num_cores;
|
||||||
int logical_cpu_count;
|
int logical_cpu_count;
|
||||||
|
|
||||||
bool bSSE;
|
bool bSSE;
|
||||||
bool bSSE2;
|
bool bSSE2;
|
||||||
bool bSSE3;
|
bool bSSE3;
|
||||||
bool bSSSE3;
|
bool bSSSE3;
|
||||||
bool bPOPCNT;
|
bool bPOPCNT;
|
||||||
bool bSSE4_1;
|
bool bSSE4_1;
|
||||||
bool bSSE4_2;
|
bool bSSE4_2;
|
||||||
bool bLZCNT;
|
bool bLZCNT;
|
||||||
bool bSSE4A;
|
bool bSSE4A;
|
||||||
bool bAVX;
|
bool bAVX;
|
||||||
bool bAES;
|
bool bAES;
|
||||||
bool bLAHFSAHF64;
|
bool bLAHFSAHF64;
|
||||||
bool bLongMode;
|
bool bLongMode;
|
||||||
|
|
||||||
// ARM specific CPUInfo
|
// ARM specific CPUInfo
|
||||||
bool bSwp;
|
bool bSwp;
|
||||||
bool bHalf;
|
bool bHalf;
|
||||||
bool bThumb;
|
bool bThumb;
|
||||||
bool bFastMult;
|
bool bFastMult;
|
||||||
bool bVFP;
|
bool bVFP;
|
||||||
bool bEDSP;
|
bool bEDSP;
|
||||||
bool bThumbEE;
|
bool bThumbEE;
|
||||||
bool bNEON;
|
bool bNEON;
|
||||||
bool bVFPv3;
|
bool bVFPv3;
|
||||||
bool bTLS;
|
bool bTLS;
|
||||||
bool bVFPv4;
|
bool bVFPv4;
|
||||||
bool bIDIVa;
|
bool bIDIVa;
|
||||||
bool bIDIVt;
|
bool bIDIVt;
|
||||||
bool bArmV7; // enable MOVT, MOVW etc
|
bool bArmV7; // enable MOVT, MOVW etc
|
||||||
|
|
||||||
// ARMv8 specific
|
// ARMv8 specific
|
||||||
bool bFP;
|
bool bFP;
|
||||||
bool bASIMD;
|
bool bASIMD;
|
||||||
|
|
||||||
// Call Detect()
|
// Call Detect()
|
||||||
explicit CPUInfo();
|
explicit CPUInfo();
|
||||||
|
|
||||||
// Turn the cpu info into a string we can show
|
// Turn the cpu info into a string we can show
|
||||||
std::string Summarize();
|
std::string Summarize();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Detects the various cpu features
|
// Detects the various cpu features
|
||||||
void Detect();
|
void Detect();
|
||||||
};
|
};
|
||||||
|
|
||||||
extern CPUInfo cpu_info;
|
extern CPUInfo cpu_info;
|
||||||
|
|
|
@ -7,33 +7,33 @@
|
||||||
class DebugInterface
|
class DebugInterface
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
virtual ~DebugInterface() {}
|
virtual ~DebugInterface() {}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual void disasm(unsigned int /*address*/, char *dest, int /*max_size*/) {strcpy(dest, "NODEBUGGER");}
|
virtual void disasm(unsigned int /*address*/, char *dest, int /*max_size*/) {strcpy(dest, "NODEBUGGER");}
|
||||||
virtual void getRawMemoryString(int /*memory*/, unsigned int /*address*/, char *dest, int /*max_size*/) {strcpy(dest, "NODEBUGGER");}
|
virtual void getRawMemoryString(int /*memory*/, unsigned int /*address*/, char *dest, int /*max_size*/) {strcpy(dest, "NODEBUGGER");}
|
||||||
virtual int getInstructionSize(int /*instruction*/) {return 1;}
|
virtual int getInstructionSize(int /*instruction*/) {return 1;}
|
||||||
virtual bool isAlive() {return true;}
|
virtual bool isAlive() {return true;}
|
||||||
virtual bool isBreakpoint(unsigned int /*address*/) {return false;}
|
virtual bool isBreakpoint(unsigned int /*address*/) {return false;}
|
||||||
virtual void setBreakpoint(unsigned int /*address*/){}
|
virtual void setBreakpoint(unsigned int /*address*/){}
|
||||||
virtual void clearBreakpoint(unsigned int /*address*/){}
|
virtual void clearBreakpoint(unsigned int /*address*/){}
|
||||||
virtual void clearAllBreakpoints() {}
|
virtual void clearAllBreakpoints() {}
|
||||||
virtual void toggleBreakpoint(unsigned int /*address*/){}
|
virtual void toggleBreakpoint(unsigned int /*address*/){}
|
||||||
virtual bool isMemCheck(unsigned int /*address*/) {return false;}
|
virtual bool isMemCheck(unsigned int /*address*/) {return false;}
|
||||||
virtual void toggleMemCheck(unsigned int /*address*/){}
|
virtual void toggleMemCheck(unsigned int /*address*/){}
|
||||||
virtual unsigned int readMemory(unsigned int /*address*/){return 0;}
|
virtual unsigned int readMemory(unsigned int /*address*/){return 0;}
|
||||||
virtual void writeExtraMemory(int /*memory*/, unsigned int /*value*/, unsigned int /*address*/) {}
|
virtual void writeExtraMemory(int /*memory*/, unsigned int /*value*/, unsigned int /*address*/) {}
|
||||||
virtual unsigned int readExtraMemory(int /*memory*/, unsigned int /*address*/){return 0;}
|
virtual unsigned int readExtraMemory(int /*memory*/, unsigned int /*address*/){return 0;}
|
||||||
virtual unsigned int readInstruction(unsigned int /*address*/){return 0;}
|
virtual unsigned int readInstruction(unsigned int /*address*/){return 0;}
|
||||||
virtual unsigned int getPC() {return 0;}
|
virtual unsigned int getPC() {return 0;}
|
||||||
virtual void setPC(unsigned int /*address*/) {}
|
virtual void setPC(unsigned int /*address*/) {}
|
||||||
virtual void step() {}
|
virtual void step() {}
|
||||||
virtual void runToBreakpoint() {}
|
virtual void runToBreakpoint() {}
|
||||||
virtual void breakNow() {}
|
virtual void breakNow() {}
|
||||||
virtual void insertBLR(unsigned int /*address*/, unsigned int /*value*/) {}
|
virtual void insertBLR(unsigned int /*address*/, unsigned int /*value*/) {}
|
||||||
virtual void showJitResults(unsigned int /*address*/) {};
|
virtual void showJitResults(unsigned int /*address*/) {};
|
||||||
virtual int getColor(unsigned int /*address*/){return 0xFFFFFFFF;}
|
virtual int getColor(unsigned int /*address*/){return 0xFFFFFFFF;}
|
||||||
virtual std::string getDescription(unsigned int /*address*/) = 0;
|
virtual std::string getDescription(unsigned int /*address*/) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -48,8 +48,8 @@ public:
|
||||||
/// Swap buffers to display the next frame
|
/// Swap buffers to display the next frame
|
||||||
virtual void SwapBuffers() = 0;
|
virtual void SwapBuffers() = 0;
|
||||||
|
|
||||||
/// Polls window events
|
/// Polls window events
|
||||||
virtual void PollEvents() = 0;
|
virtual void PollEvents() = 0;
|
||||||
|
|
||||||
/// Makes the graphics context current for the caller thread
|
/// Makes the graphics context current for the caller thread
|
||||||
virtual void MakeCurrent() = 0;
|
virtual void MakeCurrent() = 0;
|
||||||
|
|
|
@ -30,18 +30,18 @@ using namespace std;
|
||||||
void PCSTR2LPTSTR( PCSTR lpszIn, LPTSTR lpszOut )
|
void PCSTR2LPTSTR( PCSTR lpszIn, LPTSTR lpszOut )
|
||||||
{
|
{
|
||||||
#if defined(UNICODE)||defined(_UNICODE)
|
#if defined(UNICODE)||defined(_UNICODE)
|
||||||
ULONG index = 0;
|
ULONG index = 0;
|
||||||
PCSTR lpAct = lpszIn;
|
PCSTR lpAct = lpszIn;
|
||||||
|
|
||||||
for( ; ; lpAct++ )
|
for( ; ; lpAct++ )
|
||||||
{
|
{
|
||||||
lpszOut[index++] = (TCHAR)(*lpAct);
|
lpszOut[index++] = (TCHAR)(*lpAct);
|
||||||
if ( *lpAct == 0 )
|
if ( *lpAct == 0 )
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
// This is trivial :)
|
// This is trivial :)
|
||||||
strcpy( lpszOut, lpszIn );
|
strcpy( lpszOut, lpszIn );
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,184 +50,184 @@ void PCSTR2LPTSTR( PCSTR lpszIn, LPTSTR lpszOut )
|
||||||
// Note: There is no size check for lpszSymbolPath!
|
// Note: There is no size check for lpszSymbolPath!
|
||||||
static void InitSymbolPath( PSTR lpszSymbolPath, PCSTR lpszIniPath )
|
static void InitSymbolPath( PSTR lpszSymbolPath, PCSTR lpszIniPath )
|
||||||
{
|
{
|
||||||
CHAR lpszPath[BUFFERSIZE];
|
CHAR lpszPath[BUFFERSIZE];
|
||||||
|
|
||||||
// Creating the default path
|
// Creating the default path
|
||||||
// ".;%_NT_SYMBOL_PATH%;%_NT_ALTERNATE_SYMBOL_PATH%;%SYSTEMROOT%;%SYSTEMROOT%\System32;"
|
// ".;%_NT_SYMBOL_PATH%;%_NT_ALTERNATE_SYMBOL_PATH%;%SYSTEMROOT%;%SYSTEMROOT%\System32;"
|
||||||
strcpy( lpszSymbolPath, "." );
|
strcpy( lpszSymbolPath, "." );
|
||||||
|
|
||||||
// environment variable _NT_SYMBOL_PATH
|
// environment variable _NT_SYMBOL_PATH
|
||||||
if ( GetEnvironmentVariableA( "_NT_SYMBOL_PATH", lpszPath, BUFFERSIZE ) )
|
if ( GetEnvironmentVariableA( "_NT_SYMBOL_PATH", lpszPath, BUFFERSIZE ) )
|
||||||
{
|
{
|
||||||
strcat( lpszSymbolPath, ";" );
|
strcat( lpszSymbolPath, ";" );
|
||||||
strcat( lpszSymbolPath, lpszPath );
|
strcat( lpszSymbolPath, lpszPath );
|
||||||
}
|
}
|
||||||
|
|
||||||
// environment variable _NT_ALTERNATE_SYMBOL_PATH
|
// environment variable _NT_ALTERNATE_SYMBOL_PATH
|
||||||
if ( GetEnvironmentVariableA( "_NT_ALTERNATE_SYMBOL_PATH", lpszPath, BUFFERSIZE ) )
|
if ( GetEnvironmentVariableA( "_NT_ALTERNATE_SYMBOL_PATH", lpszPath, BUFFERSIZE ) )
|
||||||
{
|
{
|
||||||
strcat( lpszSymbolPath, ";" );
|
strcat( lpszSymbolPath, ";" );
|
||||||
strcat( lpszSymbolPath, lpszPath );
|
strcat( lpszSymbolPath, lpszPath );
|
||||||
}
|
}
|
||||||
|
|
||||||
// environment variable SYSTEMROOT
|
// environment variable SYSTEMROOT
|
||||||
if ( GetEnvironmentVariableA( "SYSTEMROOT", lpszPath, BUFFERSIZE ) )
|
if ( GetEnvironmentVariableA( "SYSTEMROOT", lpszPath, BUFFERSIZE ) )
|
||||||
{
|
{
|
||||||
strcat( lpszSymbolPath, ";" );
|
strcat( lpszSymbolPath, ";" );
|
||||||
strcat( lpszSymbolPath, lpszPath );
|
strcat( lpszSymbolPath, lpszPath );
|
||||||
strcat( lpszSymbolPath, ";" );
|
strcat( lpszSymbolPath, ";" );
|
||||||
|
|
||||||
// SYSTEMROOT\System32
|
// SYSTEMROOT\System32
|
||||||
strcat( lpszSymbolPath, lpszPath );
|
strcat( lpszSymbolPath, lpszPath );
|
||||||
strcat( lpszSymbolPath, "\\System32" );
|
strcat( lpszSymbolPath, "\\System32" );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add user defined path
|
// Add user defined path
|
||||||
if ( lpszIniPath != NULL )
|
if ( lpszIniPath != NULL )
|
||||||
if ( lpszIniPath[0] != '\0' )
|
if ( lpszIniPath[0] != '\0' )
|
||||||
{
|
{
|
||||||
strcat( lpszSymbolPath, ";" );
|
strcat( lpszSymbolPath, ";" );
|
||||||
strcat( lpszSymbolPath, lpszIniPath );
|
strcat( lpszSymbolPath, lpszIniPath );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Uninitialize the loaded symbol files
|
// Uninitialize the loaded symbol files
|
||||||
BOOL UninitSymInfo() {
|
BOOL UninitSymInfo() {
|
||||||
return SymCleanup( GetCurrentProcess() );
|
return SymCleanup( GetCurrentProcess() );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initializes the symbol files
|
// Initializes the symbol files
|
||||||
BOOL InitSymInfo( PCSTR lpszInitialSymbolPath )
|
BOOL InitSymInfo( PCSTR lpszInitialSymbolPath )
|
||||||
{
|
{
|
||||||
CHAR lpszSymbolPath[BUFFERSIZE];
|
CHAR lpszSymbolPath[BUFFERSIZE];
|
||||||
DWORD symOptions = SymGetOptions();
|
DWORD symOptions = SymGetOptions();
|
||||||
|
|
||||||
symOptions |= SYMOPT_LOAD_LINES;
|
symOptions |= SYMOPT_LOAD_LINES;
|
||||||
symOptions &= ~SYMOPT_UNDNAME;
|
symOptions &= ~SYMOPT_UNDNAME;
|
||||||
SymSetOptions( symOptions );
|
SymSetOptions( symOptions );
|
||||||
InitSymbolPath( lpszSymbolPath, lpszInitialSymbolPath );
|
InitSymbolPath( lpszSymbolPath, lpszInitialSymbolPath );
|
||||||
|
|
||||||
return SymInitialize( GetCurrentProcess(), lpszSymbolPath, TRUE);
|
return SymInitialize( GetCurrentProcess(), lpszSymbolPath, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the module name from a given address
|
// Get the module name from a given address
|
||||||
static BOOL GetModuleNameFromAddress( UINT address, LPTSTR lpszModule )
|
static BOOL GetModuleNameFromAddress( UINT address, LPTSTR lpszModule )
|
||||||
{
|
{
|
||||||
BOOL ret = FALSE;
|
BOOL ret = FALSE;
|
||||||
IMAGEHLP_MODULE moduleInfo;
|
IMAGEHLP_MODULE moduleInfo;
|
||||||
|
|
||||||
::ZeroMemory( &moduleInfo, sizeof(moduleInfo) );
|
::ZeroMemory( &moduleInfo, sizeof(moduleInfo) );
|
||||||
moduleInfo.SizeOfStruct = sizeof(moduleInfo);
|
moduleInfo.SizeOfStruct = sizeof(moduleInfo);
|
||||||
|
|
||||||
if ( SymGetModuleInfo( GetCurrentProcess(), (DWORD)address, &moduleInfo ) )
|
if ( SymGetModuleInfo( GetCurrentProcess(), (DWORD)address, &moduleInfo ) )
|
||||||
{
|
{
|
||||||
// Got it!
|
// Got it!
|
||||||
PCSTR2LPTSTR( moduleInfo.ModuleName, lpszModule );
|
PCSTR2LPTSTR( moduleInfo.ModuleName, lpszModule );
|
||||||
ret = TRUE;
|
ret = TRUE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
// Not found :(
|
// Not found :(
|
||||||
_tcscpy( lpszModule, _T("?") );
|
_tcscpy( lpszModule, _T("?") );
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get function prototype and parameter info from ip address and stack address
|
// Get function prototype and parameter info from ip address and stack address
|
||||||
static BOOL GetFunctionInfoFromAddresses( ULONG fnAddress, ULONG stackAddress, LPTSTR lpszSymbol )
|
static BOOL GetFunctionInfoFromAddresses( ULONG fnAddress, ULONG stackAddress, LPTSTR lpszSymbol )
|
||||||
{
|
{
|
||||||
BOOL ret = FALSE;
|
BOOL ret = FALSE;
|
||||||
DWORD dwSymSize = 10000;
|
DWORD dwSymSize = 10000;
|
||||||
TCHAR lpszUnDSymbol[BUFFERSIZE]=_T("?");
|
TCHAR lpszUnDSymbol[BUFFERSIZE]=_T("?");
|
||||||
CHAR lpszNonUnicodeUnDSymbol[BUFFERSIZE]="?";
|
CHAR lpszNonUnicodeUnDSymbol[BUFFERSIZE]="?";
|
||||||
LPTSTR lpszParamSep = NULL;
|
LPTSTR lpszParamSep = NULL;
|
||||||
LPTSTR lpszParsed = lpszUnDSymbol;
|
LPTSTR lpszParsed = lpszUnDSymbol;
|
||||||
PIMAGEHLP_SYMBOL pSym = (PIMAGEHLP_SYMBOL)GlobalAlloc( GMEM_FIXED, dwSymSize );
|
PIMAGEHLP_SYMBOL pSym = (PIMAGEHLP_SYMBOL)GlobalAlloc( GMEM_FIXED, dwSymSize );
|
||||||
|
|
||||||
::ZeroMemory( pSym, dwSymSize );
|
::ZeroMemory( pSym, dwSymSize );
|
||||||
pSym->SizeOfStruct = dwSymSize;
|
pSym->SizeOfStruct = dwSymSize;
|
||||||
pSym->MaxNameLength = dwSymSize - sizeof(IMAGEHLP_SYMBOL);
|
pSym->MaxNameLength = dwSymSize - sizeof(IMAGEHLP_SYMBOL);
|
||||||
|
|
||||||
// Set the default to unknown
|
// Set the default to unknown
|
||||||
_tcscpy( lpszSymbol, _T("?") );
|
_tcscpy( lpszSymbol, _T("?") );
|
||||||
|
|
||||||
// Get symbol info for IP
|
// Get symbol info for IP
|
||||||
#ifndef _M_X64
|
#ifndef _M_X64
|
||||||
DWORD dwDisp = 0;
|
DWORD dwDisp = 0;
|
||||||
if ( SymGetSymFromAddr( GetCurrentProcess(), (ULONG)fnAddress, &dwDisp, pSym ) )
|
if ( SymGetSymFromAddr( GetCurrentProcess(), (ULONG)fnAddress, &dwDisp, pSym ) )
|
||||||
#else
|
#else
|
||||||
//makes it compile but hell im not sure if this works...
|
//makes it compile but hell im not sure if this works...
|
||||||
DWORD64 dwDisp = 0;
|
DWORD64 dwDisp = 0;
|
||||||
if ( SymGetSymFromAddr( GetCurrentProcess(), (ULONG)fnAddress, (PDWORD64)&dwDisp, pSym ) )
|
if ( SymGetSymFromAddr( GetCurrentProcess(), (ULONG)fnAddress, (PDWORD64)&dwDisp, pSym ) )
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
// Make the symbol readable for humans
|
// Make the symbol readable for humans
|
||||||
UnDecorateSymbolName( pSym->Name, lpszNonUnicodeUnDSymbol, BUFFERSIZE,
|
UnDecorateSymbolName( pSym->Name, lpszNonUnicodeUnDSymbol, BUFFERSIZE,
|
||||||
UNDNAME_COMPLETE |
|
UNDNAME_COMPLETE |
|
||||||
UNDNAME_NO_THISTYPE |
|
UNDNAME_NO_THISTYPE |
|
||||||
UNDNAME_NO_SPECIAL_SYMS |
|
UNDNAME_NO_SPECIAL_SYMS |
|
||||||
UNDNAME_NO_MEMBER_TYPE |
|
UNDNAME_NO_MEMBER_TYPE |
|
||||||
UNDNAME_NO_MS_KEYWORDS |
|
UNDNAME_NO_MS_KEYWORDS |
|
||||||
UNDNAME_NO_ACCESS_SPECIFIERS );
|
UNDNAME_NO_ACCESS_SPECIFIERS );
|
||||||
|
|
||||||
// Symbol information is ANSI string
|
// Symbol information is ANSI string
|
||||||
PCSTR2LPTSTR( lpszNonUnicodeUnDSymbol, lpszUnDSymbol );
|
PCSTR2LPTSTR( lpszNonUnicodeUnDSymbol, lpszUnDSymbol );
|
||||||
|
|
||||||
// I am just smarter than the symbol file :)
|
// I am just smarter than the symbol file :)
|
||||||
if ( _tcscmp(lpszUnDSymbol, _T("_WinMain@16")) == 0 )
|
if ( _tcscmp(lpszUnDSymbol, _T("_WinMain@16")) == 0 )
|
||||||
_tcscpy(lpszUnDSymbol, _T("WinMain(HINSTANCE,HINSTANCE,LPCTSTR,int)"));
|
_tcscpy(lpszUnDSymbol, _T("WinMain(HINSTANCE,HINSTANCE,LPCTSTR,int)"));
|
||||||
else
|
else
|
||||||
if ( _tcscmp(lpszUnDSymbol, _T("_main")) == 0 )
|
if ( _tcscmp(lpszUnDSymbol, _T("_main")) == 0 )
|
||||||
_tcscpy(lpszUnDSymbol, _T("main(int,TCHAR * *)"));
|
_tcscpy(lpszUnDSymbol, _T("main(int,TCHAR * *)"));
|
||||||
else
|
else
|
||||||
if ( _tcscmp(lpszUnDSymbol, _T("_mainCRTStartup")) == 0 )
|
if ( _tcscmp(lpszUnDSymbol, _T("_mainCRTStartup")) == 0 )
|
||||||
_tcscpy(lpszUnDSymbol, _T("mainCRTStartup()"));
|
_tcscpy(lpszUnDSymbol, _T("mainCRTStartup()"));
|
||||||
else
|
else
|
||||||
if ( _tcscmp(lpszUnDSymbol, _T("_wmain")) == 0 )
|
if ( _tcscmp(lpszUnDSymbol, _T("_wmain")) == 0 )
|
||||||
_tcscpy(lpszUnDSymbol, _T("wmain(int,TCHAR * *,TCHAR * *)"));
|
_tcscpy(lpszUnDSymbol, _T("wmain(int,TCHAR * *,TCHAR * *)"));
|
||||||
else
|
else
|
||||||
if ( _tcscmp(lpszUnDSymbol, _T("_wmainCRTStartup")) == 0 )
|
if ( _tcscmp(lpszUnDSymbol, _T("_wmainCRTStartup")) == 0 )
|
||||||
_tcscpy(lpszUnDSymbol, _T("wmainCRTStartup()"));
|
_tcscpy(lpszUnDSymbol, _T("wmainCRTStartup()"));
|
||||||
|
|
||||||
lpszSymbol[0] = _T('\0');
|
lpszSymbol[0] = _T('\0');
|
||||||
|
|
||||||
// Let's go through the stack, and modify the function prototype, and insert the actual
|
// Let's go through the stack, and modify the function prototype, and insert the actual
|
||||||
// parameter values from the stack
|
// parameter values from the stack
|
||||||
if ( _tcsstr( lpszUnDSymbol, _T("(void)") ) == NULL && _tcsstr( lpszUnDSymbol, _T("()") ) == NULL)
|
if ( _tcsstr( lpszUnDSymbol, _T("(void)") ) == NULL && _tcsstr( lpszUnDSymbol, _T("()") ) == NULL)
|
||||||
{
|
{
|
||||||
ULONG index = 0;
|
ULONG index = 0;
|
||||||
for( ; ; index++ )
|
for( ; ; index++ )
|
||||||
{
|
{
|
||||||
lpszParamSep = _tcschr( lpszParsed, _T(',') );
|
lpszParamSep = _tcschr( lpszParsed, _T(',') );
|
||||||
if ( lpszParamSep == NULL )
|
if ( lpszParamSep == NULL )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
*lpszParamSep = _T('\0');
|
*lpszParamSep = _T('\0');
|
||||||
|
|
||||||
_tcscat( lpszSymbol, lpszParsed );
|
_tcscat( lpszSymbol, lpszParsed );
|
||||||
_stprintf( lpszSymbol + _tcslen(lpszSymbol), _T("=0x%08X,"), *((ULONG*)(stackAddress) + 2 + index) );
|
_stprintf( lpszSymbol + _tcslen(lpszSymbol), _T("=0x%08X,"), *((ULONG*)(stackAddress) + 2 + index) );
|
||||||
|
|
||||||
lpszParsed = lpszParamSep + 1;
|
lpszParsed = lpszParamSep + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
lpszParamSep = _tcschr( lpszParsed, _T(')') );
|
lpszParamSep = _tcschr( lpszParsed, _T(')') );
|
||||||
if ( lpszParamSep != NULL )
|
if ( lpszParamSep != NULL )
|
||||||
{
|
{
|
||||||
*lpszParamSep = _T('\0');
|
*lpszParamSep = _T('\0');
|
||||||
|
|
||||||
_tcscat( lpszSymbol, lpszParsed );
|
_tcscat( lpszSymbol, lpszParsed );
|
||||||
_stprintf( lpszSymbol + _tcslen(lpszSymbol), _T("=0x%08X)"), *((ULONG*)(stackAddress) + 2 + index) );
|
_stprintf( lpszSymbol + _tcslen(lpszSymbol), _T("=0x%08X)"), *((ULONG*)(stackAddress) + 2 + index) );
|
||||||
|
|
||||||
lpszParsed = lpszParamSep + 1;
|
lpszParsed = lpszParamSep + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_tcscat( lpszSymbol, lpszParsed );
|
_tcscat( lpszSymbol, lpszParsed );
|
||||||
|
|
||||||
ret = TRUE;
|
ret = TRUE;
|
||||||
}
|
}
|
||||||
GlobalFree( pSym );
|
GlobalFree( pSym );
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get source file name and line number from IP address
|
// Get source file name and line number from IP address
|
||||||
|
@ -236,198 +236,198 @@ static BOOL GetFunctionInfoFromAddresses( ULONG fnAddress, ULONG stackAddress, L
|
||||||
// "address"
|
// "address"
|
||||||
static BOOL GetSourceInfoFromAddress( UINT address, LPTSTR lpszSourceInfo )
|
static BOOL GetSourceInfoFromAddress( UINT address, LPTSTR lpszSourceInfo )
|
||||||
{
|
{
|
||||||
BOOL ret = FALSE;
|
BOOL ret = FALSE;
|
||||||
IMAGEHLP_LINE lineInfo;
|
IMAGEHLP_LINE lineInfo;
|
||||||
DWORD dwDisp;
|
DWORD dwDisp;
|
||||||
TCHAR lpszFileName[BUFFERSIZE] = _T("");
|
TCHAR lpszFileName[BUFFERSIZE] = _T("");
|
||||||
TCHAR lpModuleInfo[BUFFERSIZE] = _T("");
|
TCHAR lpModuleInfo[BUFFERSIZE] = _T("");
|
||||||
|
|
||||||
_tcscpy( lpszSourceInfo, _T("?(?)") );
|
_tcscpy( lpszSourceInfo, _T("?(?)") );
|
||||||
|
|
||||||
::ZeroMemory( &lineInfo, sizeof( lineInfo ) );
|
::ZeroMemory( &lineInfo, sizeof( lineInfo ) );
|
||||||
lineInfo.SizeOfStruct = sizeof( lineInfo );
|
lineInfo.SizeOfStruct = sizeof( lineInfo );
|
||||||
|
|
||||||
if ( SymGetLineFromAddr( GetCurrentProcess(), address, &dwDisp, &lineInfo ) )
|
if ( SymGetLineFromAddr( GetCurrentProcess(), address, &dwDisp, &lineInfo ) )
|
||||||
{
|
{
|
||||||
// Got it. Let's use "sourcefile(linenumber)" format
|
// Got it. Let's use "sourcefile(linenumber)" format
|
||||||
PCSTR2LPTSTR( lineInfo.FileName, lpszFileName );
|
PCSTR2LPTSTR( lineInfo.FileName, lpszFileName );
|
||||||
TCHAR fname[_MAX_FNAME];
|
TCHAR fname[_MAX_FNAME];
|
||||||
TCHAR ext[_MAX_EXT];
|
TCHAR ext[_MAX_EXT];
|
||||||
_tsplitpath(lpszFileName, NULL, NULL, fname, ext);
|
_tsplitpath(lpszFileName, NULL, NULL, fname, ext);
|
||||||
_stprintf( lpszSourceInfo, _T("%s%s(%d)"), fname, ext, lineInfo.LineNumber );
|
_stprintf( lpszSourceInfo, _T("%s%s(%d)"), fname, ext, lineInfo.LineNumber );
|
||||||
ret = TRUE;
|
ret = TRUE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// There is no source file information. :(
|
// There is no source file information. :(
|
||||||
// Let's use the "modulename!address" format
|
// Let's use the "modulename!address" format
|
||||||
GetModuleNameFromAddress( address, lpModuleInfo );
|
GetModuleNameFromAddress( address, lpModuleInfo );
|
||||||
|
|
||||||
if ( lpModuleInfo[0] == _T('?') || lpModuleInfo[0] == _T('\0'))
|
if ( lpModuleInfo[0] == _T('?') || lpModuleInfo[0] == _T('\0'))
|
||||||
// There is no modulename information. :((
|
// There is no modulename information. :((
|
||||||
// Let's use the "address" format
|
// Let's use the "address" format
|
||||||
_stprintf( lpszSourceInfo, _T("0x%08X"), address );
|
_stprintf( lpszSourceInfo, _T("0x%08X"), address );
|
||||||
else
|
else
|
||||||
_stprintf( lpszSourceInfo, _T("%s!0x%08X"), lpModuleInfo, address );
|
_stprintf( lpszSourceInfo, _T("%s!0x%08X"), lpModuleInfo, address );
|
||||||
|
|
||||||
ret = FALSE;
|
ret = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrintFunctionAndSourceInfo(FILE* file, const STACKFRAME& callstack)
|
void PrintFunctionAndSourceInfo(FILE* file, const STACKFRAME& callstack)
|
||||||
{
|
{
|
||||||
TCHAR symInfo[BUFFERSIZE] = _T("?");
|
TCHAR symInfo[BUFFERSIZE] = _T("?");
|
||||||
TCHAR srcInfo[BUFFERSIZE] = _T("?");
|
TCHAR srcInfo[BUFFERSIZE] = _T("?");
|
||||||
|
|
||||||
GetFunctionInfoFromAddresses((ULONG)callstack.AddrPC.Offset, (ULONG)callstack.AddrFrame.Offset, symInfo);
|
GetFunctionInfoFromAddresses((ULONG)callstack.AddrPC.Offset, (ULONG)callstack.AddrFrame.Offset, symInfo);
|
||||||
GetSourceInfoFromAddress((ULONG)callstack.AddrPC.Offset, srcInfo);
|
GetSourceInfoFromAddress((ULONG)callstack.AddrPC.Offset, srcInfo);
|
||||||
etfprint(file, " " + TStrToUTF8(srcInfo) + " : " + TStrToUTF8(symInfo) + "\n");
|
etfprint(file, " " + TStrToUTF8(srcInfo) + " : " + TStrToUTF8(symInfo) + "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void StackTrace( HANDLE hThread, const char* lpszMessage, FILE *file )
|
void StackTrace( HANDLE hThread, const char* lpszMessage, FILE *file )
|
||||||
{
|
{
|
||||||
STACKFRAME callStack;
|
STACKFRAME callStack;
|
||||||
BOOL bResult;
|
BOOL bResult;
|
||||||
CONTEXT context;
|
CONTEXT context;
|
||||||
HANDLE hProcess = GetCurrentProcess();
|
HANDLE hProcess = GetCurrentProcess();
|
||||||
|
|
||||||
// If it's not this thread, let's suspend it, and resume it at the end
|
// If it's not this thread, let's suspend it, and resume it at the end
|
||||||
if ( hThread != GetCurrentThread() )
|
if ( hThread != GetCurrentThread() )
|
||||||
if ( SuspendThread( hThread ) == -1 )
|
if ( SuspendThread( hThread ) == -1 )
|
||||||
{
|
{
|
||||||
// whaaat ?!
|
// whaaat ?!
|
||||||
etfprint(file, "Call stack info failed\n");
|
etfprint(file, "Call stack info failed\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
::ZeroMemory( &context, sizeof(context) );
|
::ZeroMemory( &context, sizeof(context) );
|
||||||
context.ContextFlags = CONTEXT_FULL;
|
context.ContextFlags = CONTEXT_FULL;
|
||||||
|
|
||||||
if ( !GetThreadContext( hThread, &context ) )
|
if ( !GetThreadContext( hThread, &context ) )
|
||||||
{
|
{
|
||||||
etfprint(file, "Call stack info failed\n");
|
etfprint(file, "Call stack info failed\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
::ZeroMemory( &callStack, sizeof(callStack) );
|
::ZeroMemory( &callStack, sizeof(callStack) );
|
||||||
#ifndef _M_X64
|
#ifndef _M_X64
|
||||||
callStack.AddrPC.Offset = context.Eip;
|
callStack.AddrPC.Offset = context.Eip;
|
||||||
callStack.AddrStack.Offset = context.Esp;
|
callStack.AddrStack.Offset = context.Esp;
|
||||||
callStack.AddrFrame.Offset = context.Ebp;
|
callStack.AddrFrame.Offset = context.Ebp;
|
||||||
#else
|
#else
|
||||||
callStack.AddrPC.Offset = context.Rip;
|
callStack.AddrPC.Offset = context.Rip;
|
||||||
callStack.AddrStack.Offset = context.Rsp;
|
callStack.AddrStack.Offset = context.Rsp;
|
||||||
callStack.AddrFrame.Offset = context.Rbp;
|
callStack.AddrFrame.Offset = context.Rbp;
|
||||||
#endif
|
#endif
|
||||||
callStack.AddrPC.Mode = AddrModeFlat;
|
callStack.AddrPC.Mode = AddrModeFlat;
|
||||||
callStack.AddrStack.Mode = AddrModeFlat;
|
callStack.AddrStack.Mode = AddrModeFlat;
|
||||||
callStack.AddrFrame.Mode = AddrModeFlat;
|
callStack.AddrFrame.Mode = AddrModeFlat;
|
||||||
|
|
||||||
etfprint(file, "Call stack info: \n");
|
etfprint(file, "Call stack info: \n");
|
||||||
etfprint(file, lpszMessage);
|
etfprint(file, lpszMessage);
|
||||||
|
|
||||||
PrintFunctionAndSourceInfo(file, callStack);
|
PrintFunctionAndSourceInfo(file, callStack);
|
||||||
|
|
||||||
for( ULONG index = 0; ; index++ )
|
for( ULONG index = 0; ; index++ )
|
||||||
{
|
{
|
||||||
bResult = StackWalk(
|
bResult = StackWalk(
|
||||||
IMAGE_FILE_MACHINE_I386,
|
IMAGE_FILE_MACHINE_I386,
|
||||||
hProcess,
|
hProcess,
|
||||||
hThread,
|
hThread,
|
||||||
&callStack,
|
&callStack,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
SymFunctionTableAccess,
|
SymFunctionTableAccess,
|
||||||
SymGetModuleBase,
|
SymGetModuleBase,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
if ( index == 0 )
|
if ( index == 0 )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if( !bResult || callStack.AddrFrame.Offset == 0 )
|
if( !bResult || callStack.AddrFrame.Offset == 0 )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
PrintFunctionAndSourceInfo(file, callStack);
|
PrintFunctionAndSourceInfo(file, callStack);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( hThread != GetCurrentThread() )
|
if ( hThread != GetCurrentThread() )
|
||||||
ResumeThread( hThread );
|
ResumeThread( hThread );
|
||||||
}
|
}
|
||||||
|
|
||||||
void StackTrace(HANDLE hThread, const char* lpszMessage, FILE *file, DWORD eip, DWORD esp, DWORD ebp )
|
void StackTrace(HANDLE hThread, const char* lpszMessage, FILE *file, DWORD eip, DWORD esp, DWORD ebp )
|
||||||
{
|
{
|
||||||
STACKFRAME callStack;
|
STACKFRAME callStack;
|
||||||
BOOL bResult;
|
BOOL bResult;
|
||||||
TCHAR symInfo[BUFFERSIZE] = _T("?");
|
TCHAR symInfo[BUFFERSIZE] = _T("?");
|
||||||
TCHAR srcInfo[BUFFERSIZE] = _T("?");
|
TCHAR srcInfo[BUFFERSIZE] = _T("?");
|
||||||
HANDLE hProcess = GetCurrentProcess();
|
HANDLE hProcess = GetCurrentProcess();
|
||||||
|
|
||||||
// If it's not this thread, let's suspend it, and resume it at the end
|
// If it's not this thread, let's suspend it, and resume it at the end
|
||||||
if ( hThread != GetCurrentThread() )
|
if ( hThread != GetCurrentThread() )
|
||||||
if ( SuspendThread( hThread ) == -1 )
|
if ( SuspendThread( hThread ) == -1 )
|
||||||
{
|
{
|
||||||
// whaaat ?!
|
// whaaat ?!
|
||||||
etfprint(file, "Call stack info failed\n");
|
etfprint(file, "Call stack info failed\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
::ZeroMemory( &callStack, sizeof(callStack) );
|
::ZeroMemory( &callStack, sizeof(callStack) );
|
||||||
callStack.AddrPC.Offset = eip;
|
callStack.AddrPC.Offset = eip;
|
||||||
callStack.AddrStack.Offset = esp;
|
callStack.AddrStack.Offset = esp;
|
||||||
callStack.AddrFrame.Offset = ebp;
|
callStack.AddrFrame.Offset = ebp;
|
||||||
callStack.AddrPC.Mode = AddrModeFlat;
|
callStack.AddrPC.Mode = AddrModeFlat;
|
||||||
callStack.AddrStack.Mode = AddrModeFlat;
|
callStack.AddrStack.Mode = AddrModeFlat;
|
||||||
callStack.AddrFrame.Mode = AddrModeFlat;
|
callStack.AddrFrame.Mode = AddrModeFlat;
|
||||||
|
|
||||||
etfprint(file, "Call stack info: \n");
|
etfprint(file, "Call stack info: \n");
|
||||||
etfprint(file, lpszMessage);
|
etfprint(file, lpszMessage);
|
||||||
|
|
||||||
PrintFunctionAndSourceInfo(file, callStack);
|
PrintFunctionAndSourceInfo(file, callStack);
|
||||||
|
|
||||||
for( ULONG index = 0; ; index++ )
|
for( ULONG index = 0; ; index++ )
|
||||||
{
|
{
|
||||||
bResult = StackWalk(
|
bResult = StackWalk(
|
||||||
IMAGE_FILE_MACHINE_I386,
|
IMAGE_FILE_MACHINE_I386,
|
||||||
hProcess,
|
hProcess,
|
||||||
hThread,
|
hThread,
|
||||||
&callStack,
|
&callStack,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
SymFunctionTableAccess,
|
SymFunctionTableAccess,
|
||||||
SymGetModuleBase,
|
SymGetModuleBase,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
if ( index == 0 )
|
if ( index == 0 )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if( !bResult || callStack.AddrFrame.Offset == 0 )
|
if( !bResult || callStack.AddrFrame.Offset == 0 )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
PrintFunctionAndSourceInfo(file, callStack);
|
PrintFunctionAndSourceInfo(file, callStack);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( hThread != GetCurrentThread() )
|
if ( hThread != GetCurrentThread() )
|
||||||
ResumeThread( hThread );
|
ResumeThread( hThread );
|
||||||
}
|
}
|
||||||
|
|
||||||
char g_uefbuf[2048];
|
char g_uefbuf[2048];
|
||||||
|
|
||||||
void etfprintf(FILE *file, const char *format, ...)
|
void etfprintf(FILE *file, const char *format, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
va_start(ap, format);
|
va_start(ap, format);
|
||||||
int len = vsprintf(g_uefbuf, format, ap);
|
int len = vsprintf(g_uefbuf, format, ap);
|
||||||
fwrite(g_uefbuf, 1, len, file);
|
fwrite(g_uefbuf, 1, len, file);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
void etfprint(FILE *file, const std::string &text)
|
void etfprint(FILE *file, const std::string &text)
|
||||||
{
|
{
|
||||||
size_t len = text.length();
|
size_t len = text.length();
|
||||||
fwrite(text.data(), 1, len, file);
|
fwrite(text.data(), 1, len, file);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //WIN32
|
#endif //WIN32
|
||||||
|
|
|
@ -24,9 +24,9 @@
|
||||||
|
|
||||||
#pragma comment( lib, "imagehlp.lib" )
|
#pragma comment( lib, "imagehlp.lib" )
|
||||||
|
|
||||||
#define EXTENDEDTRACEINITIALIZE( IniSymbolPath ) InitSymInfo( IniSymbolPath )
|
#define EXTENDEDTRACEINITIALIZE( IniSymbolPath ) InitSymInfo( IniSymbolPath )
|
||||||
#define EXTENDEDTRACEUNINITIALIZE() UninitSymInfo()
|
#define EXTENDEDTRACEUNINITIALIZE() UninitSymInfo()
|
||||||
#define STACKTRACE(file) StackTrace( GetCurrentThread(), "", file)
|
#define STACKTRACE(file) StackTrace( GetCurrentThread(), "", file)
|
||||||
#define STACKTRACE2(file, eip, esp, ebp) StackTrace(GetCurrentThread(), "", file, eip, esp, ebp)
|
#define STACKTRACE2(file, eip, esp, ebp) StackTrace(GetCurrentThread(), "", file, eip, esp, ebp)
|
||||||
// class File;
|
// class File;
|
||||||
|
|
||||||
|
@ -41,13 +41,13 @@ void etfprint(FILE *file, const std::string &text);
|
||||||
#define UEFBUFSIZE 2048
|
#define UEFBUFSIZE 2048
|
||||||
extern char g_uefbuf[UEFBUFSIZE];
|
extern char g_uefbuf[UEFBUFSIZE];
|
||||||
|
|
||||||
#else // not WIN32
|
#else // not WIN32
|
||||||
|
|
||||||
#define EXTENDEDTRACEINITIALIZE( IniSymbolPath ) ((void)0)
|
#define EXTENDEDTRACEINITIALIZE( IniSymbolPath ) ((void)0)
|
||||||
#define EXTENDEDTRACEUNINITIALIZE() ((void)0)
|
#define EXTENDEDTRACEUNINITIALIZE() ((void)0)
|
||||||
#define STACKTRACE(file) ((void)0)
|
#define STACKTRACE(file) ((void)0)
|
||||||
#define STACKTRACE2(file, eip, esp, ebp) ((void)0)
|
#define STACKTRACE2(file, eip, esp, ebp) ((void)0)
|
||||||
|
|
||||||
#endif // WIN32
|
#endif // WIN32
|
||||||
|
|
||||||
#endif // _EXTENDEDTRACE_H_INCLUDED_
|
#endif // _EXTENDEDTRACE_H_INCLUDED_
|
||||||
|
|
|
@ -14,100 +14,100 @@ template <typename T>
|
||||||
class FifoQueue
|
class FifoQueue
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
FifoQueue() : m_size(0)
|
FifoQueue() : m_size(0)
|
||||||
{
|
{
|
||||||
m_write_ptr = m_read_ptr = new ElementPtr();
|
m_write_ptr = m_read_ptr = new ElementPtr();
|
||||||
}
|
}
|
||||||
|
|
||||||
~FifoQueue()
|
~FifoQueue()
|
||||||
{
|
{
|
||||||
// this will empty out the whole queue
|
// this will empty out the whole queue
|
||||||
delete m_read_ptr;
|
delete m_read_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 Size() const
|
u32 Size() const
|
||||||
{
|
{
|
||||||
return m_size;
|
return m_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Empty() const
|
bool Empty() const
|
||||||
{
|
{
|
||||||
//return (m_read_ptr == m_write_ptr);
|
//return (m_read_ptr == m_write_ptr);
|
||||||
return (0 == m_size);
|
return (0 == m_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
T& Front() const
|
T& Front() const
|
||||||
{
|
{
|
||||||
return *m_read_ptr->current;
|
return *m_read_ptr->current;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Arg>
|
template <typename Arg>
|
||||||
void Push(Arg&& t)
|
void Push(Arg&& t)
|
||||||
{
|
{
|
||||||
// create the element, add it to the queue
|
// create the element, add it to the queue
|
||||||
m_write_ptr->current = new T(std::forward<Arg>(t));
|
m_write_ptr->current = new T(std::forward<Arg>(t));
|
||||||
// set the next pointer to a new element ptr
|
// set the next pointer to a new element ptr
|
||||||
// then advance the write pointer
|
// then advance the write pointer
|
||||||
m_write_ptr = m_write_ptr->next = new ElementPtr();
|
m_write_ptr = m_write_ptr->next = new ElementPtr();
|
||||||
Common::AtomicIncrement(m_size);
|
Common::AtomicIncrement(m_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Pop()
|
void Pop()
|
||||||
{
|
{
|
||||||
Common::AtomicDecrement(m_size);
|
Common::AtomicDecrement(m_size);
|
||||||
ElementPtr *const tmpptr = m_read_ptr;
|
ElementPtr *const tmpptr = m_read_ptr;
|
||||||
// advance the read pointer
|
// advance the read pointer
|
||||||
m_read_ptr = m_read_ptr->next;
|
m_read_ptr = m_read_ptr->next;
|
||||||
// set the next element to NULL to stop the recursive deletion
|
// set the next element to NULL to stop the recursive deletion
|
||||||
tmpptr->next = NULL;
|
tmpptr->next = NULL;
|
||||||
delete tmpptr; // this also deletes the element
|
delete tmpptr; // this also deletes the element
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Pop(T& t)
|
bool Pop(T& t)
|
||||||
{
|
{
|
||||||
if (Empty())
|
if (Empty())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
t = std::move(Front());
|
t = std::move(Front());
|
||||||
Pop();
|
Pop();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// not thread-safe
|
// not thread-safe
|
||||||
void Clear()
|
void Clear()
|
||||||
{
|
{
|
||||||
m_size = 0;
|
m_size = 0;
|
||||||
delete m_read_ptr;
|
delete m_read_ptr;
|
||||||
m_write_ptr = m_read_ptr = new ElementPtr();
|
m_write_ptr = m_read_ptr = new ElementPtr();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// stores a pointer to element
|
// stores a pointer to element
|
||||||
// and a pointer to the next ElementPtr
|
// and a pointer to the next ElementPtr
|
||||||
class ElementPtr
|
class ElementPtr
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ElementPtr() : current(NULL), next(NULL) {}
|
ElementPtr() : current(NULL), next(NULL) {}
|
||||||
|
|
||||||
~ElementPtr()
|
~ElementPtr()
|
||||||
{
|
{
|
||||||
if (current)
|
if (current)
|
||||||
{
|
{
|
||||||
delete current;
|
delete current;
|
||||||
// recusion ftw
|
// recusion ftw
|
||||||
if (next)
|
if (next)
|
||||||
delete next;
|
delete next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
T *volatile current;
|
T *volatile current;
|
||||||
ElementPtr *volatile next;
|
ElementPtr *volatile next;
|
||||||
};
|
};
|
||||||
|
|
||||||
ElementPtr *volatile m_write_ptr;
|
ElementPtr *volatile m_write_ptr;
|
||||||
ElementPtr *volatile m_read_ptr;
|
ElementPtr *volatile m_read_ptr;
|
||||||
volatile u32 m_size;
|
volatile u32 m_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,85 +22,85 @@
|
||||||
|
|
||||||
CFileSearch::CFileSearch(const CFileSearch::XStringVector& _rSearchStrings, const CFileSearch::XStringVector& _rDirectories)
|
CFileSearch::CFileSearch(const CFileSearch::XStringVector& _rSearchStrings, const CFileSearch::XStringVector& _rDirectories)
|
||||||
{
|
{
|
||||||
// Reverse the loop order for speed?
|
// Reverse the loop order for speed?
|
||||||
for (size_t j = 0; j < _rSearchStrings.size(); j++)
|
for (size_t j = 0; j < _rSearchStrings.size(); j++)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < _rDirectories.size(); i++)
|
for (size_t i = 0; i < _rDirectories.size(); i++)
|
||||||
{
|
{
|
||||||
FindFiles(_rSearchStrings[j], _rDirectories[i]);
|
FindFiles(_rSearchStrings[j], _rDirectories[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void CFileSearch::FindFiles(const std::string& _searchString, const std::string& _strPath)
|
void CFileSearch::FindFiles(const std::string& _searchString, const std::string& _strPath)
|
||||||
{
|
{
|
||||||
std::string GCMSearchPath;
|
std::string GCMSearchPath;
|
||||||
BuildCompleteFilename(GCMSearchPath, _strPath, _searchString);
|
BuildCompleteFilename(GCMSearchPath, _strPath, _searchString);
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
WIN32_FIND_DATA findData;
|
WIN32_FIND_DATA findData;
|
||||||
HANDLE FindFirst = FindFirstFile(UTF8ToTStr(GCMSearchPath).c_str(), &findData);
|
HANDLE FindFirst = FindFirstFile(UTF8ToTStr(GCMSearchPath).c_str(), &findData);
|
||||||
|
|
||||||
if (FindFirst != INVALID_HANDLE_VALUE)
|
if (FindFirst != INVALID_HANDLE_VALUE)
|
||||||
{
|
{
|
||||||
bool bkeepLooping = true;
|
bool bkeepLooping = true;
|
||||||
|
|
||||||
while (bkeepLooping)
|
while (bkeepLooping)
|
||||||
{
|
{
|
||||||
if (findData.cFileName[0] != '.')
|
if (findData.cFileName[0] != '.')
|
||||||
{
|
{
|
||||||
std::string strFilename;
|
std::string strFilename;
|
||||||
BuildCompleteFilename(strFilename, _strPath, TStrToUTF8(findData.cFileName));
|
BuildCompleteFilename(strFilename, _strPath, TStrToUTF8(findData.cFileName));
|
||||||
m_FileNames.push_back(strFilename);
|
m_FileNames.push_back(strFilename);
|
||||||
}
|
}
|
||||||
|
|
||||||
bkeepLooping = FindNextFile(FindFirst, &findData) ? true : false;
|
bkeepLooping = FindNextFile(FindFirst, &findData) ? true : false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FindClose(FindFirst);
|
FindClose(FindFirst);
|
||||||
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
// TODO: super lame/broken
|
// TODO: super lame/broken
|
||||||
|
|
||||||
auto end_match(_searchString);
|
auto end_match(_searchString);
|
||||||
|
|
||||||
// assuming we have a "*.blah"-like pattern
|
// assuming we have a "*.blah"-like pattern
|
||||||
if (!end_match.empty() && end_match[0] == '*')
|
if (!end_match.empty() && end_match[0] == '*')
|
||||||
end_match.erase(0, 1);
|
end_match.erase(0, 1);
|
||||||
|
|
||||||
// ugly
|
// ugly
|
||||||
if (end_match == ".*")
|
if (end_match == ".*")
|
||||||
end_match.clear();
|
end_match.clear();
|
||||||
|
|
||||||
DIR* dir = opendir(_strPath.c_str());
|
DIR* dir = opendir(_strPath.c_str());
|
||||||
|
|
||||||
if (!dir)
|
if (!dir)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
while (auto const dp = readdir(dir))
|
while (auto const dp = readdir(dir))
|
||||||
{
|
{
|
||||||
std::string found(dp->d_name);
|
std::string found(dp->d_name);
|
||||||
|
|
||||||
if ((found != ".") && (found != "..")
|
if ((found != ".") && (found != "..")
|
||||||
&& (found.size() >= end_match.size())
|
&& (found.size() >= end_match.size())
|
||||||
&& std::equal(end_match.rbegin(), end_match.rend(), found.rbegin()))
|
&& std::equal(end_match.rbegin(), end_match.rend(), found.rbegin()))
|
||||||
{
|
{
|
||||||
std::string full_name;
|
std::string full_name;
|
||||||
if (_strPath.c_str()[_strPath.size()-1] == DIR_SEP_CHR)
|
if (_strPath.c_str()[_strPath.size()-1] == DIR_SEP_CHR)
|
||||||
full_name = _strPath + found;
|
full_name = _strPath + found;
|
||||||
else
|
else
|
||||||
full_name = _strPath + DIR_SEP + found;
|
full_name = _strPath + DIR_SEP + found;
|
||||||
|
|
||||||
m_FileNames.push_back(full_name);
|
m_FileNames.push_back(full_name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
closedir(dir);
|
closedir(dir);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
const CFileSearch::XStringVector& CFileSearch::GetFileNames() const
|
const CFileSearch::XStringVector& CFileSearch::GetFileNames() const
|
||||||
{
|
{
|
||||||
return m_FileNames;
|
return m_FileNames;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,16 +12,16 @@
|
||||||
class CFileSearch
|
class CFileSearch
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef std::vector<std::string>XStringVector;
|
typedef std::vector<std::string>XStringVector;
|
||||||
|
|
||||||
CFileSearch(const XStringVector& _rSearchStrings, const XStringVector& _rDirectories);
|
CFileSearch(const XStringVector& _rSearchStrings, const XStringVector& _rDirectories);
|
||||||
const XStringVector& GetFileNames() const;
|
const XStringVector& GetFileNames() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void FindFiles(const std::string& _searchString, const std::string& _strPath);
|
void FindFiles(const std::string& _searchString, const std::string& _strPath);
|
||||||
|
|
||||||
XStringVector m_FileNames;
|
XStringVector m_FileNames;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _FILESEARCH_H_
|
#endif // _FILESEARCH_H_
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -16,59 +16,59 @@
|
||||||
template <class T, int N>
|
template <class T, int N>
|
||||||
class fixed_size_queue.h
|
class fixed_size_queue.h
|
||||||
{
|
{
|
||||||
T *storage;
|
T *storage;
|
||||||
int head;
|
int head;
|
||||||
int tail;
|
int tail;
|
||||||
int count; // sacrifice 4 bytes for a simpler implementation. may optimize away in the future.
|
int count; // sacrifice 4 bytes for a simpler implementation. may optimize away in the future.
|
||||||
|
|
||||||
// Make copy constructor private for now.
|
// Make copy constructor private for now.
|
||||||
fixed_size_queue.h(fixed_size_queue.h &other) { }
|
fixed_size_queue.h(fixed_size_queue.h &other) { }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
fixed_size_queue.h()
|
fixed_size_queue.h()
|
||||||
{
|
{
|
||||||
storage = new T[N];
|
storage = new T[N];
|
||||||
clear();
|
clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
~fixed_size_queue.h()
|
~fixed_size_queue.h()
|
||||||
{
|
{
|
||||||
delete [] storage;
|
delete [] storage;
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear() {
|
void clear() {
|
||||||
head = 0;
|
head = 0;
|
||||||
tail = 0;
|
tail = 0;
|
||||||
count = 0;
|
count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void push(T t) {
|
void push(T t) {
|
||||||
storage[tail] = t;
|
storage[tail] = t;
|
||||||
tail++;
|
tail++;
|
||||||
if (tail == N)
|
if (tail == N)
|
||||||
tail = 0;
|
tail = 0;
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pop() {
|
void pop() {
|
||||||
head++;
|
head++;
|
||||||
if (head == N)
|
if (head == N)
|
||||||
head = 0;
|
head = 0;
|
||||||
count--;
|
count--;
|
||||||
}
|
}
|
||||||
|
|
||||||
T pop_front() {
|
T pop_front() {
|
||||||
const T &temp = storage[head];
|
const T &temp = storage[head];
|
||||||
pop();
|
pop();
|
||||||
return temp;
|
return temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
T &front() { return storage[head]; }
|
T &front() { return storage[head]; }
|
||||||
const T &front() const { return storage[head]; }
|
const T &front() const { return storage[head]; }
|
||||||
|
|
||||||
size_t size() const {
|
size_t size() const {
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _FIXED_SIZE_QUEUE_H_
|
#endif // _FIXED_SIZE_QUEUE_H_
|
||||||
|
|
|
@ -16,29 +16,29 @@ static u64 (*ptrHashFunction)(const u8 *src, int len, u32 samples) = &GetMurmurH
|
||||||
// Implementation from Wikipedia.
|
// Implementation from Wikipedia.
|
||||||
u32 HashFletcher(const u8* data_u8, size_t length)
|
u32 HashFletcher(const u8* data_u8, size_t length)
|
||||||
{
|
{
|
||||||
const u16* data = (const u16*)data_u8; /* Pointer to the data to be summed */
|
const u16* data = (const u16*)data_u8; /* Pointer to the data to be summed */
|
||||||
size_t len = (length + 1) / 2; /* Length in 16-bit words */
|
size_t len = (length + 1) / 2; /* Length in 16-bit words */
|
||||||
u32 sum1 = 0xffff, sum2 = 0xffff;
|
u32 sum1 = 0xffff, sum2 = 0xffff;
|
||||||
|
|
||||||
while (len)
|
while (len)
|
||||||
{
|
{
|
||||||
size_t tlen = len > 360 ? 360 : len;
|
size_t tlen = len > 360 ? 360 : len;
|
||||||
len -= tlen;
|
len -= tlen;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
sum1 += *data++;
|
sum1 += *data++;
|
||||||
sum2 += sum1;
|
sum2 += sum1;
|
||||||
}
|
}
|
||||||
while (--tlen);
|
while (--tlen);
|
||||||
|
|
||||||
sum1 = (sum1 & 0xffff) + (sum1 >> 16);
|
sum1 = (sum1 & 0xffff) + (sum1 >> 16);
|
||||||
sum2 = (sum2 & 0xffff) + (sum2 >> 16);
|
sum2 = (sum2 & 0xffff) + (sum2 >> 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Second reduction step to reduce sums to 16 bits
|
// Second reduction step to reduce sums to 16 bits
|
||||||
sum1 = (sum1 & 0xffff) + (sum1 >> 16);
|
sum1 = (sum1 & 0xffff) + (sum1 >> 16);
|
||||||
sum2 = (sum2 & 0xffff) + (sum2 >> 16);
|
sum2 = (sum2 & 0xffff) + (sum2 >> 16);
|
||||||
return(sum2 << 16 | sum1);
|
return(sum2 << 16 | sum1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -48,54 +48,54 @@ u32 HashFletcher(const u8* data_u8, size_t length)
|
||||||
// data: Pointer to the data to be summed; len is in bytes
|
// data: Pointer to the data to be summed; len is in bytes
|
||||||
u32 HashAdler32(const u8* data, size_t len)
|
u32 HashAdler32(const u8* data, size_t len)
|
||||||
{
|
{
|
||||||
u32 a = 1, b = 0;
|
u32 a = 1, b = 0;
|
||||||
|
|
||||||
while (len)
|
while (len)
|
||||||
{
|
{
|
||||||
size_t tlen = len > 5550 ? 5550 : len;
|
size_t tlen = len > 5550 ? 5550 : len;
|
||||||
len -= tlen;
|
len -= tlen;
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
a += *data++;
|
a += *data++;
|
||||||
b += a;
|
b += a;
|
||||||
}
|
}
|
||||||
while (--tlen);
|
while (--tlen);
|
||||||
|
|
||||||
a = (a & 0xffff) + (a >> 16) * (65536 - MOD_ADLER);
|
a = (a & 0xffff) + (a >> 16) * (65536 - MOD_ADLER);
|
||||||
b = (b & 0xffff) + (b >> 16) * (65536 - MOD_ADLER);
|
b = (b & 0xffff) + (b >> 16) * (65536 - MOD_ADLER);
|
||||||
}
|
}
|
||||||
|
|
||||||
// It can be shown that a <= 0x1013a here, so a single subtract will do.
|
// It can be shown that a <= 0x1013a here, so a single subtract will do.
|
||||||
if (a >= MOD_ADLER)
|
if (a >= MOD_ADLER)
|
||||||
{
|
{
|
||||||
a -= MOD_ADLER;
|
a -= MOD_ADLER;
|
||||||
}
|
}
|
||||||
|
|
||||||
// It can be shown that b can reach 0xfff87 here.
|
// It can be shown that b can reach 0xfff87 here.
|
||||||
b = (b & 0xffff) + (b >> 16) * (65536 - MOD_ADLER);
|
b = (b & 0xffff) + (b >> 16) * (65536 - MOD_ADLER);
|
||||||
|
|
||||||
if (b >= MOD_ADLER)
|
if (b >= MOD_ADLER)
|
||||||
{
|
{
|
||||||
b -= MOD_ADLER;
|
b -= MOD_ADLER;
|
||||||
}
|
}
|
||||||
|
|
||||||
return((b << 16) | a);
|
return((b << 16) | a);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stupid hash - but can't go back now :)
|
// Stupid hash - but can't go back now :)
|
||||||
// Don't use for new things. At least it's reasonably fast.
|
// Don't use for new things. At least it's reasonably fast.
|
||||||
u32 HashEctor(const u8* ptr, int length)
|
u32 HashEctor(const u8* ptr, int length)
|
||||||
{
|
{
|
||||||
u32 crc = 0;
|
u32 crc = 0;
|
||||||
|
|
||||||
for (int i = 0; i < length; i++)
|
for (int i = 0; i < length; i++)
|
||||||
{
|
{
|
||||||
crc ^= ptr[i];
|
crc ^= ptr[i];
|
||||||
crc = (crc << 3) | (crc >> 29);
|
crc = (crc << 3) | (crc >> 29);
|
||||||
}
|
}
|
||||||
|
|
||||||
return(crc);
|
return(crc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -107,7 +107,7 @@ u32 HashEctor(const u8* ptr, int length)
|
||||||
|
|
||||||
inline u64 getblock(const u64 * p, int i)
|
inline u64 getblock(const u64 * p, int i)
|
||||||
{
|
{
|
||||||
return p[i];
|
return p[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------
|
//----------
|
||||||
|
@ -115,25 +115,25 @@ inline u64 getblock(const u64 * p, int i)
|
||||||
|
|
||||||
inline void bmix64(u64 & h1, u64 & h2, u64 & k1, u64 & k2, u64 & c1, u64 & c2)
|
inline void bmix64(u64 & h1, u64 & h2, u64 & k1, u64 & k2, u64 & c1, u64 & c2)
|
||||||
{
|
{
|
||||||
k1 *= c1;
|
k1 *= c1;
|
||||||
k1 = _rotl64(k1,23);
|
k1 = _rotl64(k1,23);
|
||||||
k1 *= c2;
|
k1 *= c2;
|
||||||
h1 ^= k1;
|
h1 ^= k1;
|
||||||
h1 += h2;
|
h1 += h2;
|
||||||
|
|
||||||
h2 = _rotl64(h2,41);
|
h2 = _rotl64(h2,41);
|
||||||
|
|
||||||
k2 *= c2;
|
k2 *= c2;
|
||||||
k2 = _rotl64(k2,23);
|
k2 = _rotl64(k2,23);
|
||||||
k2 *= c1;
|
k2 *= c1;
|
||||||
h2 ^= k2;
|
h2 ^= k2;
|
||||||
h2 += h1;
|
h2 += h1;
|
||||||
|
|
||||||
h1 = h1*3+0x52dce729;
|
h1 = h1*3+0x52dce729;
|
||||||
h2 = h2*3+0x38495ab5;
|
h2 = h2*3+0x38495ab5;
|
||||||
|
|
||||||
c1 = c1*5+0x7b7d159c;
|
c1 = c1*5+0x7b7d159c;
|
||||||
c2 = c2*5+0x6bce6396;
|
c2 = c2*5+0x6bce6396;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------
|
//----------
|
||||||
|
@ -141,87 +141,87 @@ inline void bmix64(u64 & h1, u64 & h2, u64 & k1, u64 & k2, u64 & c1, u64 & c2)
|
||||||
|
|
||||||
inline u64 fmix64(u64 k)
|
inline u64 fmix64(u64 k)
|
||||||
{
|
{
|
||||||
k ^= k >> 33;
|
k ^= k >> 33;
|
||||||
k *= 0xff51afd7ed558ccd;
|
k *= 0xff51afd7ed558ccd;
|
||||||
k ^= k >> 33;
|
k ^= k >> 33;
|
||||||
k *= 0xc4ceb9fe1a85ec53;
|
k *= 0xc4ceb9fe1a85ec53;
|
||||||
k ^= k >> 33;
|
k ^= k >> 33;
|
||||||
|
|
||||||
return k;
|
return k;
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 GetMurmurHash3(const u8 *src, int len, u32 samples)
|
u64 GetMurmurHash3(const u8 *src, int len, u32 samples)
|
||||||
{
|
{
|
||||||
const u8 * data = (const u8*)src;
|
const u8 * data = (const u8*)src;
|
||||||
const int nblocks = len / 16;
|
const int nblocks = len / 16;
|
||||||
u32 Step = (len / 8);
|
u32 Step = (len / 8);
|
||||||
if(samples == 0) samples = max(Step, 1u);
|
if(samples == 0) samples = max(Step, 1u);
|
||||||
Step = Step / samples;
|
Step = Step / samples;
|
||||||
if(Step < 1) Step = 1;
|
if(Step < 1) Step = 1;
|
||||||
|
|
||||||
u64 h1 = 0x9368e53c2f6af274;
|
u64 h1 = 0x9368e53c2f6af274;
|
||||||
u64 h2 = 0x586dcd208f7cd3fd;
|
u64 h2 = 0x586dcd208f7cd3fd;
|
||||||
|
|
||||||
u64 c1 = 0x87c37b91114253d5;
|
u64 c1 = 0x87c37b91114253d5;
|
||||||
u64 c2 = 0x4cf5ad432745937f;
|
u64 c2 = 0x4cf5ad432745937f;
|
||||||
|
|
||||||
|
|
||||||
//----------
|
//----------
|
||||||
// body
|
// body
|
||||||
|
|
||||||
const u64 * blocks = (const u64 *)(data);
|
const u64 * blocks = (const u64 *)(data);
|
||||||
|
|
||||||
for(int i = 0; i < nblocks; i+=Step)
|
for(int i = 0; i < nblocks; i+=Step)
|
||||||
{
|
{
|
||||||
u64 k1 = getblock(blocks,i*2+0);
|
u64 k1 = getblock(blocks,i*2+0);
|
||||||
u64 k2 = getblock(blocks,i*2+1);
|
u64 k2 = getblock(blocks,i*2+1);
|
||||||
|
|
||||||
bmix64(h1,h2,k1,k2,c1,c2);
|
bmix64(h1,h2,k1,k2,c1,c2);
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------
|
//----------
|
||||||
// tail
|
// tail
|
||||||
|
|
||||||
const u8 * tail = (const u8*)(data + nblocks*16);
|
const u8 * tail = (const u8*)(data + nblocks*16);
|
||||||
|
|
||||||
u64 k1 = 0;
|
u64 k1 = 0;
|
||||||
u64 k2 = 0;
|
u64 k2 = 0;
|
||||||
|
|
||||||
switch(len & 15)
|
switch(len & 15)
|
||||||
{
|
{
|
||||||
case 15: k2 ^= u64(tail[14]) << 48;
|
case 15: k2 ^= u64(tail[14]) << 48;
|
||||||
case 14: k2 ^= u64(tail[13]) << 40;
|
case 14: k2 ^= u64(tail[13]) << 40;
|
||||||
case 13: k2 ^= u64(tail[12]) << 32;
|
case 13: k2 ^= u64(tail[12]) << 32;
|
||||||
case 12: k2 ^= u64(tail[11]) << 24;
|
case 12: k2 ^= u64(tail[11]) << 24;
|
||||||
case 11: k2 ^= u64(tail[10]) << 16;
|
case 11: k2 ^= u64(tail[10]) << 16;
|
||||||
case 10: k2 ^= u64(tail[ 9]) << 8;
|
case 10: k2 ^= u64(tail[ 9]) << 8;
|
||||||
case 9: k2 ^= u64(tail[ 8]) << 0;
|
case 9: k2 ^= u64(tail[ 8]) << 0;
|
||||||
|
|
||||||
case 8: k1 ^= u64(tail[ 7]) << 56;
|
case 8: k1 ^= u64(tail[ 7]) << 56;
|
||||||
case 7: k1 ^= u64(tail[ 6]) << 48;
|
case 7: k1 ^= u64(tail[ 6]) << 48;
|
||||||
case 6: k1 ^= u64(tail[ 5]) << 40;
|
case 6: k1 ^= u64(tail[ 5]) << 40;
|
||||||
case 5: k1 ^= u64(tail[ 4]) << 32;
|
case 5: k1 ^= u64(tail[ 4]) << 32;
|
||||||
case 4: k1 ^= u64(tail[ 3]) << 24;
|
case 4: k1 ^= u64(tail[ 3]) << 24;
|
||||||
case 3: k1 ^= u64(tail[ 2]) << 16;
|
case 3: k1 ^= u64(tail[ 2]) << 16;
|
||||||
case 2: k1 ^= u64(tail[ 1]) << 8;
|
case 2: k1 ^= u64(tail[ 1]) << 8;
|
||||||
case 1: k1 ^= u64(tail[ 0]) << 0;
|
case 1: k1 ^= u64(tail[ 0]) << 0;
|
||||||
bmix64(h1,h2,k1,k2,c1,c2);
|
bmix64(h1,h2,k1,k2,c1,c2);
|
||||||
};
|
};
|
||||||
|
|
||||||
//----------
|
//----------
|
||||||
// finalization
|
// finalization
|
||||||
|
|
||||||
h2 ^= len;
|
h2 ^= len;
|
||||||
|
|
||||||
h1 += h2;
|
h1 += h2;
|
||||||
h2 += h1;
|
h2 += h1;
|
||||||
|
|
||||||
h1 = fmix64(h1);
|
h1 = fmix64(h1);
|
||||||
h2 = fmix64(h2);
|
h2 = fmix64(h2);
|
||||||
|
|
||||||
h1 += h2;
|
h1 += h2;
|
||||||
|
|
||||||
return h1;
|
return h1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -229,23 +229,23 @@ u64 GetMurmurHash3(const u8 *src, int len, u32 samples)
|
||||||
u64 GetCRC32(const u8 *src, int len, u32 samples)
|
u64 GetCRC32(const u8 *src, int len, u32 samples)
|
||||||
{
|
{
|
||||||
#if _M_SSE >= 0x402
|
#if _M_SSE >= 0x402
|
||||||
u64 h = len;
|
u64 h = len;
|
||||||
u32 Step = (len / 8);
|
u32 Step = (len / 8);
|
||||||
const u64 *data = (const u64 *)src;
|
const u64 *data = (const u64 *)src;
|
||||||
const u64 *end = data + Step;
|
const u64 *end = data + Step;
|
||||||
if(samples == 0) samples = max(Step, 1u);
|
if(samples == 0) samples = max(Step, 1u);
|
||||||
Step = Step / samples;
|
Step = Step / samples;
|
||||||
if(Step < 1) Step = 1;
|
if(Step < 1) Step = 1;
|
||||||
while(data < end)
|
while(data < end)
|
||||||
{
|
{
|
||||||
h = _mm_crc32_u64(h, data[0]);
|
h = _mm_crc32_u64(h, data[0]);
|
||||||
data += Step;
|
data += Step;
|
||||||
}
|
}
|
||||||
|
|
||||||
const u8 *data2 = (const u8*)end;
|
const u8 *data2 = (const u8*)end;
|
||||||
return _mm_crc32_u64(h, u64(data2[0]));
|
return _mm_crc32_u64(h, u64(data2[0]));
|
||||||
#else
|
#else
|
||||||
return 0;
|
return 0;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -259,68 +259,68 @@ u64 GetCRC32(const u8 *src, int len, u32 samples)
|
||||||
*/
|
*/
|
||||||
u64 GetHashHiresTexture(const u8 *src, int len, u32 samples)
|
u64 GetHashHiresTexture(const u8 *src, int len, u32 samples)
|
||||||
{
|
{
|
||||||
const u64 m = 0xc6a4a7935bd1e995;
|
const u64 m = 0xc6a4a7935bd1e995;
|
||||||
u64 h = len * m;
|
u64 h = len * m;
|
||||||
const int r = 47;
|
const int r = 47;
|
||||||
u32 Step = (len / 8);
|
u32 Step = (len / 8);
|
||||||
const u64 *data = (const u64 *)src;
|
const u64 *data = (const u64 *)src;
|
||||||
const u64 *end = data + Step;
|
const u64 *end = data + Step;
|
||||||
if(samples == 0) samples = max(Step, 1u);
|
if(samples == 0) samples = max(Step, 1u);
|
||||||
Step = Step / samples;
|
Step = Step / samples;
|
||||||
if(Step < 1) Step = 1;
|
if(Step < 1) Step = 1;
|
||||||
while(data < end)
|
while(data < end)
|
||||||
{
|
{
|
||||||
u64 k = data[0];
|
u64 k = data[0];
|
||||||
data+=Step;
|
data+=Step;
|
||||||
k *= m;
|
k *= m;
|
||||||
k ^= k >> r;
|
k ^= k >> r;
|
||||||
k *= m;
|
k *= m;
|
||||||
h ^= k;
|
h ^= k;
|
||||||
h *= m;
|
h *= m;
|
||||||
}
|
}
|
||||||
|
|
||||||
const u8 * data2 = (const u8*)end;
|
const u8 * data2 = (const u8*)end;
|
||||||
|
|
||||||
switch(len & 7)
|
switch(len & 7)
|
||||||
{
|
{
|
||||||
case 7: h ^= u64(data2[6]) << 48;
|
case 7: h ^= u64(data2[6]) << 48;
|
||||||
case 6: h ^= u64(data2[5]) << 40;
|
case 6: h ^= u64(data2[5]) << 40;
|
||||||
case 5: h ^= u64(data2[4]) << 32;
|
case 5: h ^= u64(data2[4]) << 32;
|
||||||
case 4: h ^= u64(data2[3]) << 24;
|
case 4: h ^= u64(data2[3]) << 24;
|
||||||
case 3: h ^= u64(data2[2]) << 16;
|
case 3: h ^= u64(data2[2]) << 16;
|
||||||
case 2: h ^= u64(data2[1]) << 8;
|
case 2: h ^= u64(data2[1]) << 8;
|
||||||
case 1: h ^= u64(data2[0]);
|
case 1: h ^= u64(data2[0]);
|
||||||
h *= m;
|
h *= m;
|
||||||
};
|
};
|
||||||
|
|
||||||
h ^= h >> r;
|
h ^= h >> r;
|
||||||
h *= m;
|
h *= m;
|
||||||
h ^= h >> r;
|
h ^= h >> r;
|
||||||
|
|
||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
// CRC32 hash using the SSE4.2 instruction
|
// CRC32 hash using the SSE4.2 instruction
|
||||||
u64 GetCRC32(const u8 *src, int len, u32 samples)
|
u64 GetCRC32(const u8 *src, int len, u32 samples)
|
||||||
{
|
{
|
||||||
#if _M_SSE >= 0x402
|
#if _M_SSE >= 0x402
|
||||||
u32 h = len;
|
u32 h = len;
|
||||||
u32 Step = (len/4);
|
u32 Step = (len/4);
|
||||||
const u32 *data = (const u32 *)src;
|
const u32 *data = (const u32 *)src;
|
||||||
const u32 *end = data + Step;
|
const u32 *end = data + Step;
|
||||||
if(samples == 0) samples = max(Step, 1u);
|
if(samples == 0) samples = max(Step, 1u);
|
||||||
Step = Step / samples;
|
Step = Step / samples;
|
||||||
if(Step < 1) Step = 1;
|
if(Step < 1) Step = 1;
|
||||||
while(data < end)
|
while(data < end)
|
||||||
{
|
{
|
||||||
h = _mm_crc32_u32(h, data[0]);
|
h = _mm_crc32_u32(h, data[0]);
|
||||||
data += Step;
|
data += Step;
|
||||||
}
|
}
|
||||||
|
|
||||||
const u8 *data2 = (const u8*)end;
|
const u8 *data2 = (const u8*)end;
|
||||||
return (u64)_mm_crc32_u32(h, u32(data2[0]));
|
return (u64)_mm_crc32_u32(h, u32(data2[0]));
|
||||||
#else
|
#else
|
||||||
return 0;
|
return 0;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -330,7 +330,7 @@ u64 GetCRC32(const u8 *src, int len, u32 samples)
|
||||||
|
|
||||||
inline u32 getblock(const u32 * p, int i)
|
inline u32 getblock(const u32 * p, int i)
|
||||||
{
|
{
|
||||||
return p[i];
|
return p[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------
|
//----------
|
||||||
|
@ -340,107 +340,107 @@ inline u32 getblock(const u32 * p, int i)
|
||||||
|
|
||||||
inline u32 fmix32(u32 h)
|
inline u32 fmix32(u32 h)
|
||||||
{
|
{
|
||||||
h ^= h >> 16;
|
h ^= h >> 16;
|
||||||
h *= 0x85ebca6b;
|
h *= 0x85ebca6b;
|
||||||
h ^= h >> 13;
|
h ^= h >> 13;
|
||||||
h *= 0xc2b2ae35;
|
h *= 0xc2b2ae35;
|
||||||
h ^= h >> 16;
|
h ^= h >> 16;
|
||||||
|
|
||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void bmix32(u32 & h1, u32 & h2, u32 & k1, u32 & k2, u32 & c1, u32 & c2)
|
inline void bmix32(u32 & h1, u32 & h2, u32 & k1, u32 & k2, u32 & c1, u32 & c2)
|
||||||
{
|
{
|
||||||
k1 *= c1;
|
k1 *= c1;
|
||||||
k1 = _rotl(k1,11);
|
k1 = _rotl(k1,11);
|
||||||
k1 *= c2;
|
k1 *= c2;
|
||||||
h1 ^= k1;
|
h1 ^= k1;
|
||||||
h1 += h2;
|
h1 += h2;
|
||||||
|
|
||||||
h2 = _rotl(h2,17);
|
h2 = _rotl(h2,17);
|
||||||
|
|
||||||
k2 *= c2;
|
k2 *= c2;
|
||||||
k2 = _rotl(k2,11);
|
k2 = _rotl(k2,11);
|
||||||
k2 *= c1;
|
k2 *= c1;
|
||||||
h2 ^= k2;
|
h2 ^= k2;
|
||||||
h2 += h1;
|
h2 += h1;
|
||||||
|
|
||||||
h1 = h1*3+0x52dce729;
|
h1 = h1*3+0x52dce729;
|
||||||
h2 = h2*3+0x38495ab5;
|
h2 = h2*3+0x38495ab5;
|
||||||
|
|
||||||
c1 = c1*5+0x7b7d159c;
|
c1 = c1*5+0x7b7d159c;
|
||||||
c2 = c2*5+0x6bce6396;
|
c2 = c2*5+0x6bce6396;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------
|
//----------
|
||||||
|
|
||||||
u64 GetMurmurHash3(const u8* src, int len, u32 samples)
|
u64 GetMurmurHash3(const u8* src, int len, u32 samples)
|
||||||
{
|
{
|
||||||
const u8 * data = (const u8*)src;
|
const u8 * data = (const u8*)src;
|
||||||
u32 out[2];
|
u32 out[2];
|
||||||
const int nblocks = len / 8;
|
const int nblocks = len / 8;
|
||||||
u32 Step = (len / 4);
|
u32 Step = (len / 4);
|
||||||
if(samples == 0) samples = max(Step, 1u);
|
if(samples == 0) samples = max(Step, 1u);
|
||||||
Step = Step / samples;
|
Step = Step / samples;
|
||||||
if(Step < 1) Step = 1;
|
if(Step < 1) Step = 1;
|
||||||
|
|
||||||
u32 h1 = 0x8de1c3ac;
|
u32 h1 = 0x8de1c3ac;
|
||||||
u32 h2 = 0xbab98226;
|
u32 h2 = 0xbab98226;
|
||||||
|
|
||||||
u32 c1 = 0x95543787;
|
u32 c1 = 0x95543787;
|
||||||
u32 c2 = 0x2ad7eb25;
|
u32 c2 = 0x2ad7eb25;
|
||||||
|
|
||||||
//----------
|
//----------
|
||||||
// body
|
// body
|
||||||
|
|
||||||
const u32 * blocks = (const u32 *)(data + nblocks*8);
|
const u32 * blocks = (const u32 *)(data + nblocks*8);
|
||||||
|
|
||||||
for(int i = -nblocks; i < 0; i+=Step)
|
for(int i = -nblocks; i < 0; i+=Step)
|
||||||
{
|
{
|
||||||
u32 k1 = getblock(blocks,i*2+0);
|
u32 k1 = getblock(blocks,i*2+0);
|
||||||
u32 k2 = getblock(blocks,i*2+1);
|
u32 k2 = getblock(blocks,i*2+1);
|
||||||
|
|
||||||
bmix32(h1,h2,k1,k2,c1,c2);
|
bmix32(h1,h2,k1,k2,c1,c2);
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------
|
//----------
|
||||||
// tail
|
// tail
|
||||||
|
|
||||||
const u8 * tail = (const u8*)(data + nblocks*8);
|
const u8 * tail = (const u8*)(data + nblocks*8);
|
||||||
|
|
||||||
u32 k1 = 0;
|
u32 k1 = 0;
|
||||||
u32 k2 = 0;
|
u32 k2 = 0;
|
||||||
|
|
||||||
switch(len & 7)
|
switch(len & 7)
|
||||||
{
|
{
|
||||||
case 7: k2 ^= tail[6] << 16;
|
case 7: k2 ^= tail[6] << 16;
|
||||||
case 6: k2 ^= tail[5] << 8;
|
case 6: k2 ^= tail[5] << 8;
|
||||||
case 5: k2 ^= tail[4] << 0;
|
case 5: k2 ^= tail[4] << 0;
|
||||||
case 4: k1 ^= tail[3] << 24;
|
case 4: k1 ^= tail[3] << 24;
|
||||||
case 3: k1 ^= tail[2] << 16;
|
case 3: k1 ^= tail[2] << 16;
|
||||||
case 2: k1 ^= tail[1] << 8;
|
case 2: k1 ^= tail[1] << 8;
|
||||||
case 1: k1 ^= tail[0] << 0;
|
case 1: k1 ^= tail[0] << 0;
|
||||||
bmix32(h1,h2,k1,k2,c1,c2);
|
bmix32(h1,h2,k1,k2,c1,c2);
|
||||||
};
|
};
|
||||||
|
|
||||||
//----------
|
//----------
|
||||||
// finalization
|
// finalization
|
||||||
|
|
||||||
h2 ^= len;
|
h2 ^= len;
|
||||||
|
|
||||||
h1 += h2;
|
h1 += h2;
|
||||||
h2 += h1;
|
h2 += h1;
|
||||||
|
|
||||||
h1 = fmix32(h1);
|
h1 = fmix32(h1);
|
||||||
h2 = fmix32(h2);
|
h2 = fmix32(h2);
|
||||||
|
|
||||||
h1 += h2;
|
h1 += h2;
|
||||||
h2 += h1;
|
h2 += h1;
|
||||||
|
|
||||||
out[0] = h1;
|
out[0] = h1;
|
||||||
out[1] = h2;
|
out[1] = h2;
|
||||||
|
|
||||||
return *((u64 *)&out);
|
return *((u64 *)&out);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -450,70 +450,70 @@ u64 GetMurmurHash3(const u8* src, int len, u32 samples)
|
||||||
*/
|
*/
|
||||||
u64 GetHashHiresTexture(const u8 *src, int len, u32 samples)
|
u64 GetHashHiresTexture(const u8 *src, int len, u32 samples)
|
||||||
{
|
{
|
||||||
const u64 m = 0xc6a4a7935bd1e995ULL;
|
const u64 m = 0xc6a4a7935bd1e995ULL;
|
||||||
u64 h = len * m;
|
u64 h = len * m;
|
||||||
const int r = 47;
|
const int r = 47;
|
||||||
u32 Step = (len / 8);
|
u32 Step = (len / 8);
|
||||||
const u64 *data = (const u64 *)src;
|
const u64 *data = (const u64 *)src;
|
||||||
const u64 *end = data + Step;
|
const u64 *end = data + Step;
|
||||||
if(samples == 0) samples = max(Step, 1u);
|
if(samples == 0) samples = max(Step, 1u);
|
||||||
Step = Step / samples;
|
Step = Step / samples;
|
||||||
if(Step < 1) Step = 1;
|
if(Step < 1) Step = 1;
|
||||||
while(data < end)
|
while(data < end)
|
||||||
{
|
{
|
||||||
u64 k = data[0];
|
u64 k = data[0];
|
||||||
data+=Step;
|
data+=Step;
|
||||||
k *= m;
|
k *= m;
|
||||||
k ^= k >> r;
|
k ^= k >> r;
|
||||||
k *= m;
|
k *= m;
|
||||||
h ^= k;
|
h ^= k;
|
||||||
h *= m;
|
h *= m;
|
||||||
}
|
}
|
||||||
|
|
||||||
const u8 * data2 = (const u8*)end;
|
const u8 * data2 = (const u8*)end;
|
||||||
|
|
||||||
switch(len & 7)
|
switch(len & 7)
|
||||||
{
|
{
|
||||||
case 7: h ^= u64(data2[6]) << 48;
|
case 7: h ^= u64(data2[6]) << 48;
|
||||||
case 6: h ^= u64(data2[5]) << 40;
|
case 6: h ^= u64(data2[5]) << 40;
|
||||||
case 5: h ^= u64(data2[4]) << 32;
|
case 5: h ^= u64(data2[4]) << 32;
|
||||||
case 4: h ^= u64(data2[3]) << 24;
|
case 4: h ^= u64(data2[3]) << 24;
|
||||||
case 3: h ^= u64(data2[2]) << 16;
|
case 3: h ^= u64(data2[2]) << 16;
|
||||||
case 2: h ^= u64(data2[1]) << 8;
|
case 2: h ^= u64(data2[1]) << 8;
|
||||||
case 1: h ^= u64(data2[0]);
|
case 1: h ^= u64(data2[0]);
|
||||||
h *= m;
|
h *= m;
|
||||||
};
|
};
|
||||||
|
|
||||||
h ^= h >> r;
|
h ^= h >> r;
|
||||||
h *= m;
|
h *= m;
|
||||||
h ^= h >> r;
|
h ^= h >> r;
|
||||||
|
|
||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
u64 GetHash64(const u8 *src, int len, u32 samples)
|
u64 GetHash64(const u8 *src, int len, u32 samples)
|
||||||
{
|
{
|
||||||
return ptrHashFunction(src, len, samples);
|
return ptrHashFunction(src, len, samples);
|
||||||
}
|
}
|
||||||
|
|
||||||
// sets the hash function used for the texture cache
|
// sets the hash function used for the texture cache
|
||||||
void SetHash64Function(bool useHiresTextures)
|
void SetHash64Function(bool useHiresTextures)
|
||||||
{
|
{
|
||||||
if (useHiresTextures)
|
if (useHiresTextures)
|
||||||
{
|
{
|
||||||
ptrHashFunction = &GetHashHiresTexture;
|
ptrHashFunction = &GetHashHiresTexture;
|
||||||
}
|
}
|
||||||
#if _M_SSE >= 0x402
|
#if _M_SSE >= 0x402
|
||||||
else if (cpu_info.bSSE4_2 && !useHiresTextures) // sse crc32 version
|
else if (cpu_info.bSSE4_2 && !useHiresTextures) // sse crc32 version
|
||||||
{
|
{
|
||||||
ptrHashFunction = &GetCRC32;
|
ptrHashFunction = &GetCRC32;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ptrHashFunction = &GetMurmurHash3;
|
ptrHashFunction = &GetMurmurHash3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ template <typename K, typename V>
|
||||||
class LinearDiskCacheReader
|
class LinearDiskCacheReader
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void Read(const K &key, const V *value, u32 value_size) = 0;
|
virtual void Read(const K &key, const V *value, u32 value_size) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Dead simple unsorted key-value store with append functionality.
|
// Dead simple unsorted key-value store with append functionality.
|
||||||
|
@ -49,143 +49,143 @@ template <typename K, typename V>
|
||||||
class LinearDiskCache
|
class LinearDiskCache
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// return number of read entries
|
// return number of read entries
|
||||||
u32 OpenAndRead(const char *filename, LinearDiskCacheReader<K, V> &reader)
|
u32 OpenAndRead(const char *filename, LinearDiskCacheReader<K, V> &reader)
|
||||||
{
|
{
|
||||||
using std::ios_base;
|
using std::ios_base;
|
||||||
|
|
||||||
// close any currently opened file
|
// close any currently opened file
|
||||||
Close();
|
Close();
|
||||||
m_num_entries = 0;
|
m_num_entries = 0;
|
||||||
|
|
||||||
// try opening for reading/writing
|
// try opening for reading/writing
|
||||||
OpenFStream(m_file, filename, ios_base::in | ios_base::out | ios_base::binary);
|
OpenFStream(m_file, filename, ios_base::in | ios_base::out | ios_base::binary);
|
||||||
|
|
||||||
m_file.seekg(0, std::ios::end);
|
m_file.seekg(0, std::ios::end);
|
||||||
std::fstream::pos_type end_pos = m_file.tellg();
|
std::fstream::pos_type end_pos = m_file.tellg();
|
||||||
m_file.seekg(0, std::ios::beg);
|
m_file.seekg(0, std::ios::beg);
|
||||||
std::fstream::pos_type start_pos = m_file.tellg();
|
std::fstream::pos_type start_pos = m_file.tellg();
|
||||||
std::streamoff file_size = end_pos - start_pos;
|
std::streamoff file_size = end_pos - start_pos;
|
||||||
|
|
||||||
if (m_file.is_open() && ValidateHeader())
|
if (m_file.is_open() && ValidateHeader())
|
||||||
{
|
{
|
||||||
// good header, read some key/value pairs
|
// good header, read some key/value pairs
|
||||||
K key;
|
K key;
|
||||||
|
|
||||||
V *value = NULL;
|
V *value = NULL;
|
||||||
u32 value_size;
|
u32 value_size;
|
||||||
u32 entry_number;
|
u32 entry_number;
|
||||||
|
|
||||||
std::fstream::pos_type last_pos = m_file.tellg();
|
std::fstream::pos_type last_pos = m_file.tellg();
|
||||||
|
|
||||||
while (Read(&value_size))
|
while (Read(&value_size))
|
||||||
{
|
{
|
||||||
std::streamoff next_extent = (last_pos - start_pos) + sizeof(value_size) + value_size;
|
std::streamoff next_extent = (last_pos - start_pos) + sizeof(value_size) + value_size;
|
||||||
if (next_extent > file_size)
|
if (next_extent > file_size)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
delete[] value;
|
delete[] value;
|
||||||
value = new V[value_size];
|
value = new V[value_size];
|
||||||
|
|
||||||
// read key/value and pass to reader
|
// read key/value and pass to reader
|
||||||
if (Read(&key) &&
|
if (Read(&key) &&
|
||||||
Read(value, value_size) &&
|
Read(value, value_size) &&
|
||||||
Read(&entry_number) &&
|
Read(&entry_number) &&
|
||||||
entry_number == m_num_entries+1)
|
entry_number == m_num_entries+1)
|
||||||
{
|
{
|
||||||
reader.Read(key, value, value_size);
|
reader.Read(key, value, value_size);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_num_entries++;
|
m_num_entries++;
|
||||||
last_pos = m_file.tellg();
|
last_pos = m_file.tellg();
|
||||||
}
|
}
|
||||||
m_file.seekp(last_pos);
|
m_file.seekp(last_pos);
|
||||||
m_file.clear();
|
m_file.clear();
|
||||||
|
|
||||||
delete[] value;
|
delete[] value;
|
||||||
return m_num_entries;
|
return m_num_entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
// failed to open file for reading or bad header
|
// failed to open file for reading or bad header
|
||||||
// close and recreate file
|
// close and recreate file
|
||||||
Close();
|
Close();
|
||||||
m_file.open(filename, ios_base::out | ios_base::trunc | ios_base::binary);
|
m_file.open(filename, ios_base::out | ios_base::trunc | ios_base::binary);
|
||||||
WriteHeader();
|
WriteHeader();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sync()
|
void Sync()
|
||||||
{
|
{
|
||||||
m_file.flush();
|
m_file.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Close()
|
void Close()
|
||||||
{
|
{
|
||||||
if (m_file.is_open())
|
if (m_file.is_open())
|
||||||
m_file.close();
|
m_file.close();
|
||||||
// clear any error flags
|
// clear any error flags
|
||||||
m_file.clear();
|
m_file.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Appends a key-value pair to the store.
|
// Appends a key-value pair to the store.
|
||||||
void Append(const K &key, const V *value, u32 value_size)
|
void Append(const K &key, const V *value, u32 value_size)
|
||||||
{
|
{
|
||||||
// TODO: Should do a check that we don't already have "key"? (I think each caller does that already.)
|
// TODO: Should do a check that we don't already have "key"? (I think each caller does that already.)
|
||||||
Write(&value_size);
|
Write(&value_size);
|
||||||
Write(&key);
|
Write(&key);
|
||||||
Write(value, value_size);
|
Write(value, value_size);
|
||||||
m_num_entries++;
|
m_num_entries++;
|
||||||
Write(&m_num_entries);
|
Write(&m_num_entries);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void WriteHeader()
|
void WriteHeader()
|
||||||
{
|
{
|
||||||
Write(&m_header);
|
Write(&m_header);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ValidateHeader()
|
bool ValidateHeader()
|
||||||
{
|
{
|
||||||
char file_header[sizeof(Header)];
|
char file_header[sizeof(Header)];
|
||||||
|
|
||||||
return (Read(file_header, sizeof(Header))
|
return (Read(file_header, sizeof(Header))
|
||||||
&& !memcmp((const char*)&m_header, file_header, sizeof(Header)));
|
&& !memcmp((const char*)&m_header, file_header, sizeof(Header)));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename D>
|
template <typename D>
|
||||||
bool Write(const D *data, u32 count = 1)
|
bool Write(const D *data, u32 count = 1)
|
||||||
{
|
{
|
||||||
return m_file.write((const char*)data, count * sizeof(D)).good();
|
return m_file.write((const char*)data, count * sizeof(D)).good();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename D>
|
template <typename D>
|
||||||
bool Read(const D *data, u32 count = 1)
|
bool Read(const D *data, u32 count = 1)
|
||||||
{
|
{
|
||||||
return m_file.read((char*)data, count * sizeof(D)).good();
|
return m_file.read((char*)data, count * sizeof(D)).good();
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Header
|
struct Header
|
||||||
{
|
{
|
||||||
Header()
|
Header()
|
||||||
: id(*(u32*)"DCAC")
|
: id(*(u32*)"DCAC")
|
||||||
, key_t_size(sizeof(K))
|
, key_t_size(sizeof(K))
|
||||||
, value_t_size(sizeof(V))
|
, value_t_size(sizeof(V))
|
||||||
{
|
{
|
||||||
memcpy(ver, scm_rev_git_str, 40);
|
memcpy(ver, scm_rev_git_str, 40);
|
||||||
}
|
}
|
||||||
|
|
||||||
const u32 id;
|
const u32 id;
|
||||||
const u16 key_t_size, value_t_size;
|
const u16 key_t_size, value_t_size;
|
||||||
char ver[40];
|
char ver[40];
|
||||||
|
|
||||||
} m_header;
|
} m_header;
|
||||||
|
|
||||||
std::fstream m_file;
|
std::fstream m_file;
|
||||||
u32 m_num_entries;
|
u32 m_num_entries;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _LINEAR_DISKCACHE
|
#endif // _LINEAR_DISKCACHE
|
||||||
|
|
|
@ -5,74 +5,74 @@
|
||||||
#ifndef _LOG_H_
|
#ifndef _LOG_H_
|
||||||
#define _LOG_H_
|
#define _LOG_H_
|
||||||
|
|
||||||
#define NOTICE_LEVEL 1 // VERY important information that is NOT errors. Like startup and OSReports.
|
#define NOTICE_LEVEL 1 // VERY important information that is NOT errors. Like startup and OSReports.
|
||||||
#define ERROR_LEVEL 2 // Critical errors
|
#define ERROR_LEVEL 2 // Critical errors
|
||||||
#define WARNING_LEVEL 3 // Something is suspicious.
|
#define WARNING_LEVEL 3 // Something is suspicious.
|
||||||
#define INFO_LEVEL 4 // General information.
|
#define INFO_LEVEL 4 // General information.
|
||||||
#define DEBUG_LEVEL 5 // Detailed debugging - might make things slow.
|
#define DEBUG_LEVEL 5 // Detailed debugging - might make things slow.
|
||||||
|
|
||||||
namespace LogTypes
|
namespace LogTypes
|
||||||
{
|
{
|
||||||
|
|
||||||
enum LOG_TYPE {
|
enum LOG_TYPE {
|
||||||
ACTIONREPLAY,
|
ACTIONREPLAY,
|
||||||
AUDIO,
|
AUDIO,
|
||||||
AUDIO_INTERFACE,
|
AUDIO_INTERFACE,
|
||||||
BOOT,
|
BOOT,
|
||||||
COMMANDPROCESSOR,
|
COMMANDPROCESSOR,
|
||||||
COMMON,
|
COMMON,
|
||||||
CONSOLE,
|
CONSOLE,
|
||||||
DISCIO,
|
DISCIO,
|
||||||
FILEMON,
|
FILEMON,
|
||||||
DSPHLE,
|
DSPHLE,
|
||||||
DSPLLE,
|
DSPLLE,
|
||||||
DSP_MAIL,
|
DSP_MAIL,
|
||||||
DSPINTERFACE,
|
DSPINTERFACE,
|
||||||
DVDINTERFACE,
|
DVDINTERFACE,
|
||||||
DYNA_REC,
|
DYNA_REC,
|
||||||
EXPANSIONINTERFACE,
|
EXPANSIONINTERFACE,
|
||||||
GDB_STUB,
|
GDB_STUB,
|
||||||
ARM11,
|
ARM11,
|
||||||
GPFIFO,
|
GPFIFO,
|
||||||
OSHLE,
|
OSHLE,
|
||||||
MASTER_LOG,
|
MASTER_LOG,
|
||||||
MEMMAP,
|
MEMMAP,
|
||||||
MEMCARD_MANAGER,
|
MEMCARD_MANAGER,
|
||||||
OSREPORT,
|
OSREPORT,
|
||||||
PAD,
|
PAD,
|
||||||
PROCESSORINTERFACE,
|
PROCESSORINTERFACE,
|
||||||
PIXELENGINE,
|
PIXELENGINE,
|
||||||
SERIALINTERFACE,
|
SERIALINTERFACE,
|
||||||
SP1,
|
SP1,
|
||||||
STREAMINGINTERFACE,
|
STREAMINGINTERFACE,
|
||||||
VIDEO,
|
VIDEO,
|
||||||
VIDEOINTERFACE,
|
VIDEOINTERFACE,
|
||||||
LOADER,
|
LOADER,
|
||||||
FILESYS,
|
FILESYS,
|
||||||
WII_IPC_DVD,
|
WII_IPC_DVD,
|
||||||
WII_IPC_ES,
|
WII_IPC_ES,
|
||||||
WII_IPC_FILEIO,
|
WII_IPC_FILEIO,
|
||||||
WII_IPC_HID,
|
WII_IPC_HID,
|
||||||
WII_IPC_HLE,
|
WII_IPC_HLE,
|
||||||
WII_IPC_NET,
|
WII_IPC_NET,
|
||||||
WII_IPC_WC24,
|
WII_IPC_WC24,
|
||||||
WII_IPC_SSL,
|
WII_IPC_SSL,
|
||||||
WII_IPC_SD,
|
WII_IPC_SD,
|
||||||
WII_IPC_STM,
|
WII_IPC_STM,
|
||||||
WII_IPC_WIIMOTE,
|
WII_IPC_WIIMOTE,
|
||||||
TIME,
|
TIME,
|
||||||
NETPLAY,
|
NETPLAY,
|
||||||
|
|
||||||
NUMBER_OF_LOGS // Must be last
|
NUMBER_OF_LOGS // Must be last
|
||||||
};
|
};
|
||||||
|
|
||||||
// FIXME: should this be removed?
|
// FIXME: should this be removed?
|
||||||
enum LOG_LEVELS {
|
enum LOG_LEVELS {
|
||||||
LNOTICE = NOTICE_LEVEL,
|
LNOTICE = NOTICE_LEVEL,
|
||||||
LERROR = ERROR_LEVEL,
|
LERROR = ERROR_LEVEL,
|
||||||
LWARNING = WARNING_LEVEL,
|
LWARNING = WARNING_LEVEL,
|
||||||
LINFO = INFO_LEVEL,
|
LINFO = INFO_LEVEL,
|
||||||
LDEBUG = DEBUG_LEVEL,
|
LDEBUG = DEBUG_LEVEL,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define LOGTYPES_LEVELS LogTypes::LOG_LEVELS
|
#define LOGTYPES_LEVELS LogTypes::LOG_LEVELS
|
||||||
|
@ -81,11 +81,11 @@ enum LOG_LEVELS {
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
void GenericLog(LOGTYPES_LEVELS level, LOGTYPES_TYPE type,
|
void GenericLog(LOGTYPES_LEVELS level, LOGTYPES_TYPE type,
|
||||||
const char *file, int line, const char *fmt, ...)
|
const char *file, int line, const char *fmt, ...)
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
__attribute__((format(printf, 5, 6)))
|
__attribute__((format(printf, 5, 6)))
|
||||||
#endif
|
#endif
|
||||||
;
|
;
|
||||||
|
|
||||||
#if defined LOGGING || defined _DEBUG || defined DEBUGFAST
|
#if defined LOGGING || defined _DEBUG || defined DEBUGFAST
|
||||||
#define MAX_LOGLEVEL DEBUG_LEVEL
|
#define MAX_LOGLEVEL DEBUG_LEVEL
|
||||||
|
@ -100,9 +100,9 @@ void GenericLog(LOGTYPES_LEVELS level, LOGTYPES_TYPE type,
|
||||||
#else
|
#else
|
||||||
// Let the compiler optimize this out
|
// Let the compiler optimize this out
|
||||||
#define GENERIC_LOG(t, v, ...) { \
|
#define GENERIC_LOG(t, v, ...) { \
|
||||||
if (v <= MAX_LOGLEVEL) \
|
if (v <= MAX_LOGLEVEL) \
|
||||||
GenericLog(v, t, __FILE__, __LINE__, __VA_ARGS__); \
|
GenericLog(v, t, __FILE__, __LINE__, __VA_ARGS__); \
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define ERROR_LOG(t,...) do { GENERIC_LOG(LogTypes::t, LogTypes::LERROR, __VA_ARGS__) } while (0)
|
#define ERROR_LOG(t,...) do { GENERIC_LOG(LogTypes::t, LogTypes::LERROR, __VA_ARGS__) } while (0)
|
||||||
|
@ -113,16 +113,16 @@ void GenericLog(LOGTYPES_LEVELS level, LOGTYPES_TYPE type,
|
||||||
|
|
||||||
#if MAX_LOGLEVEL >= DEBUG_LEVEL
|
#if MAX_LOGLEVEL >= DEBUG_LEVEL
|
||||||
#define _dbg_assert_(_t_, _a_) \
|
#define _dbg_assert_(_t_, _a_) \
|
||||||
if (!(_a_)) {\
|
if (!(_a_)) {\
|
||||||
ERROR_LOG(_t_, "Error...\n\n Line: %d\n File: %s\n Time: %s\n\nIgnore and continue?", \
|
ERROR_LOG(_t_, "Error...\n\n Line: %d\n File: %s\n Time: %s\n\nIgnore and continue?", \
|
||||||
__LINE__, __FILE__, __TIME__); \
|
__LINE__, __FILE__, __TIME__); \
|
||||||
if (!PanicYesNo("*** Assertion (see log)***\n")) {Crash();} \
|
if (!PanicYesNo("*** Assertion (see log)***\n")) {Crash();} \
|
||||||
}
|
}
|
||||||
#define _dbg_assert_msg_(_t_, _a_, ...)\
|
#define _dbg_assert_msg_(_t_, _a_, ...)\
|
||||||
if (!(_a_)) {\
|
if (!(_a_)) {\
|
||||||
ERROR_LOG(_t_, __VA_ARGS__); \
|
ERROR_LOG(_t_, __VA_ARGS__); \
|
||||||
if (!PanicYesNo(__VA_ARGS__)) {Crash();} \
|
if (!PanicYesNo(__VA_ARGS__)) {Crash();} \
|
||||||
}
|
}
|
||||||
#define _dbg_update_() Host_UpdateLogDisplay();
|
#define _dbg_update_() Host_UpdateLogDisplay();
|
||||||
|
|
||||||
#else // not debug
|
#else // not debug
|
||||||
|
@ -138,15 +138,15 @@ void GenericLog(LOGTYPES_LEVELS level, LOGTYPES_TYPE type,
|
||||||
|
|
||||||
#ifndef GEKKO
|
#ifndef GEKKO
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#define _assert_msg_(_t_, _a_, _fmt_, ...) \
|
#define _assert_msg_(_t_, _a_, _fmt_, ...) \
|
||||||
if (!(_a_)) {\
|
if (!(_a_)) {\
|
||||||
if (!PanicYesNo(_fmt_, __VA_ARGS__)) {Crash();} \
|
if (!PanicYesNo(_fmt_, __VA_ARGS__)) {Crash();} \
|
||||||
}
|
}
|
||||||
#else // not win32
|
#else // not win32
|
||||||
#define _assert_msg_(_t_, _a_, _fmt_, ...) \
|
#define _assert_msg_(_t_, _a_, _fmt_, ...) \
|
||||||
if (!(_a_)) {\
|
if (!(_a_)) {\
|
||||||
if (!PanicYesNo(_fmt_, ##__VA_ARGS__)) {Crash();} \
|
if (!PanicYesNo(_fmt_, ##__VA_ARGS__)) {Crash();} \
|
||||||
}
|
}
|
||||||
#endif // WIN32
|
#endif // WIN32
|
||||||
#else // GEKKO
|
#else // GEKKO
|
||||||
#define _assert_msg_(_t_, _a_, _fmt_, ...)
|
#define _assert_msg_(_t_, _a_, _fmt_, ...)
|
||||||
|
|
|
@ -14,187 +14,187 @@
|
||||||
#include "file_util.h"
|
#include "file_util.h"
|
||||||
|
|
||||||
void GenericLog(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type,
|
void GenericLog(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type,
|
||||||
const char *file, int line, const char* fmt, ...)
|
const char *file, int line, const char* fmt, ...)
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, fmt);
|
va_start(args, fmt);
|
||||||
if (LogManager::GetInstance())
|
if (LogManager::GetInstance())
|
||||||
LogManager::GetInstance()->Log(level, type,
|
LogManager::GetInstance()->Log(level, type,
|
||||||
file, line, fmt, args);
|
file, line, fmt, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
LogManager *LogManager::m_logManager = NULL;
|
LogManager *LogManager::m_logManager = NULL;
|
||||||
|
|
||||||
LogManager::LogManager()
|
LogManager::LogManager()
|
||||||
{
|
{
|
||||||
// create log files
|
// create log files
|
||||||
m_Log[LogTypes::MASTER_LOG] = new LogContainer("*", "Master Log");
|
m_Log[LogTypes::MASTER_LOG] = new LogContainer("*", "Master Log");
|
||||||
m_Log[LogTypes::BOOT] = new LogContainer("BOOT", "Boot");
|
m_Log[LogTypes::BOOT] = new LogContainer("BOOT", "Boot");
|
||||||
m_Log[LogTypes::COMMON] = new LogContainer("COMMON", "Common");
|
m_Log[LogTypes::COMMON] = new LogContainer("COMMON", "Common");
|
||||||
m_Log[LogTypes::DISCIO] = new LogContainer("DIO", "Disc IO");
|
m_Log[LogTypes::DISCIO] = new LogContainer("DIO", "Disc IO");
|
||||||
m_Log[LogTypes::FILEMON] = new LogContainer("FileMon", "File Monitor");
|
m_Log[LogTypes::FILEMON] = new LogContainer("FileMon", "File Monitor");
|
||||||
m_Log[LogTypes::PAD] = new LogContainer("PAD", "Pad");
|
m_Log[LogTypes::PAD] = new LogContainer("PAD", "Pad");
|
||||||
m_Log[LogTypes::PIXELENGINE] = new LogContainer("PE", "PixelEngine");
|
m_Log[LogTypes::PIXELENGINE] = new LogContainer("PE", "PixelEngine");
|
||||||
m_Log[LogTypes::COMMANDPROCESSOR] = new LogContainer("CP", "CommandProc");
|
m_Log[LogTypes::COMMANDPROCESSOR] = new LogContainer("CP", "CommandProc");
|
||||||
m_Log[LogTypes::VIDEOINTERFACE] = new LogContainer("VI", "VideoInt");
|
m_Log[LogTypes::VIDEOINTERFACE] = new LogContainer("VI", "VideoInt");
|
||||||
m_Log[LogTypes::SERIALINTERFACE] = new LogContainer("SI", "SerialInt");
|
m_Log[LogTypes::SERIALINTERFACE] = new LogContainer("SI", "SerialInt");
|
||||||
m_Log[LogTypes::PROCESSORINTERFACE] = new LogContainer("PI", "ProcessorInt");
|
m_Log[LogTypes::PROCESSORINTERFACE] = new LogContainer("PI", "ProcessorInt");
|
||||||
m_Log[LogTypes::MEMMAP] = new LogContainer("MI", "MI & memmap");
|
m_Log[LogTypes::MEMMAP] = new LogContainer("MI", "MI & memmap");
|
||||||
m_Log[LogTypes::SP1] = new LogContainer("SP1", "Serial Port 1");
|
m_Log[LogTypes::SP1] = new LogContainer("SP1", "Serial Port 1");
|
||||||
m_Log[LogTypes::STREAMINGINTERFACE] = new LogContainer("Stream", "StreamingInt");
|
m_Log[LogTypes::STREAMINGINTERFACE] = new LogContainer("Stream", "StreamingInt");
|
||||||
m_Log[LogTypes::DSPINTERFACE] = new LogContainer("DSP", "DSPInterface");
|
m_Log[LogTypes::DSPINTERFACE] = new LogContainer("DSP", "DSPInterface");
|
||||||
m_Log[LogTypes::DVDINTERFACE] = new LogContainer("DVD", "DVDInterface");
|
m_Log[LogTypes::DVDINTERFACE] = new LogContainer("DVD", "DVDInterface");
|
||||||
m_Log[LogTypes::GPFIFO] = new LogContainer("GP", "GPFifo");
|
m_Log[LogTypes::GPFIFO] = new LogContainer("GP", "GPFifo");
|
||||||
m_Log[LogTypes::EXPANSIONINTERFACE] = new LogContainer("EXI", "ExpansionInt");
|
m_Log[LogTypes::EXPANSIONINTERFACE] = new LogContainer("EXI", "ExpansionInt");
|
||||||
m_Log[LogTypes::GDB_STUB] = new LogContainer("GDB_STUB", "GDB Stub");
|
m_Log[LogTypes::GDB_STUB] = new LogContainer("GDB_STUB", "GDB Stub");
|
||||||
m_Log[LogTypes::AUDIO_INTERFACE] = new LogContainer("AI", "AudioInt");
|
m_Log[LogTypes::AUDIO_INTERFACE] = new LogContainer("AI", "AudioInt");
|
||||||
m_Log[LogTypes::ARM11] = new LogContainer("ARM11", "ARM11");
|
m_Log[LogTypes::ARM11] = new LogContainer("ARM11", "ARM11");
|
||||||
m_Log[LogTypes::OSHLE] = new LogContainer("HLE", "HLE");
|
m_Log[LogTypes::OSHLE] = new LogContainer("HLE", "HLE");
|
||||||
m_Log[LogTypes::DSPHLE] = new LogContainer("DSPHLE", "DSP HLE");
|
m_Log[LogTypes::DSPHLE] = new LogContainer("DSPHLE", "DSP HLE");
|
||||||
m_Log[LogTypes::DSPLLE] = new LogContainer("DSPLLE", "DSP LLE");
|
m_Log[LogTypes::DSPLLE] = new LogContainer("DSPLLE", "DSP LLE");
|
||||||
m_Log[LogTypes::DSP_MAIL] = new LogContainer("DSPMails", "DSP Mails");
|
m_Log[LogTypes::DSP_MAIL] = new LogContainer("DSPMails", "DSP Mails");
|
||||||
m_Log[LogTypes::VIDEO] = new LogContainer("Video", "Video Backend");
|
m_Log[LogTypes::VIDEO] = new LogContainer("Video", "Video Backend");
|
||||||
m_Log[LogTypes::AUDIO] = new LogContainer("Audio", "Audio Emulator");
|
m_Log[LogTypes::AUDIO] = new LogContainer("Audio", "Audio Emulator");
|
||||||
m_Log[LogTypes::DYNA_REC] = new LogContainer("JIT", "Dynamic Recompiler");
|
m_Log[LogTypes::DYNA_REC] = new LogContainer("JIT", "Dynamic Recompiler");
|
||||||
m_Log[LogTypes::CONSOLE] = new LogContainer("CONSOLE", "Dolphin Console");
|
m_Log[LogTypes::CONSOLE] = new LogContainer("CONSOLE", "Dolphin Console");
|
||||||
m_Log[LogTypes::OSREPORT] = new LogContainer("OSREPORT", "OSReport");
|
m_Log[LogTypes::OSREPORT] = new LogContainer("OSREPORT", "OSReport");
|
||||||
m_Log[LogTypes::TIME] = new LogContainer("Time", "Core Timing");
|
m_Log[LogTypes::TIME] = new LogContainer("Time", "Core Timing");
|
||||||
m_Log[LogTypes::LOADER] = new LogContainer("Loader", "Loader");
|
m_Log[LogTypes::LOADER] = new LogContainer("Loader", "Loader");
|
||||||
m_Log[LogTypes::FILESYS] = new LogContainer("FileSys", "File System");
|
m_Log[LogTypes::FILESYS] = new LogContainer("FileSys", "File System");
|
||||||
m_Log[LogTypes::WII_IPC_HID] = new LogContainer("WII_IPC_HID", "WII IPC HID");
|
m_Log[LogTypes::WII_IPC_HID] = new LogContainer("WII_IPC_HID", "WII IPC HID");
|
||||||
m_Log[LogTypes::WII_IPC_HLE] = new LogContainer("WII_IPC_HLE", "WII IPC HLE");
|
m_Log[LogTypes::WII_IPC_HLE] = new LogContainer("WII_IPC_HLE", "WII IPC HLE");
|
||||||
m_Log[LogTypes::WII_IPC_DVD] = new LogContainer("WII_IPC_DVD", "WII IPC DVD");
|
m_Log[LogTypes::WII_IPC_DVD] = new LogContainer("WII_IPC_DVD", "WII IPC DVD");
|
||||||
m_Log[LogTypes::WII_IPC_ES] = new LogContainer("WII_IPC_ES", "WII IPC ES");
|
m_Log[LogTypes::WII_IPC_ES] = new LogContainer("WII_IPC_ES", "WII IPC ES");
|
||||||
m_Log[LogTypes::WII_IPC_FILEIO] = new LogContainer("WII_IPC_FILEIO","WII IPC FILEIO");
|
m_Log[LogTypes::WII_IPC_FILEIO] = new LogContainer("WII_IPC_FILEIO","WII IPC FILEIO");
|
||||||
m_Log[LogTypes::WII_IPC_SD] = new LogContainer("WII_IPC_SD", "WII IPC SD");
|
m_Log[LogTypes::WII_IPC_SD] = new LogContainer("WII_IPC_SD", "WII IPC SD");
|
||||||
m_Log[LogTypes::WII_IPC_STM] = new LogContainer("WII_IPC_STM", "WII IPC STM");
|
m_Log[LogTypes::WII_IPC_STM] = new LogContainer("WII_IPC_STM", "WII IPC STM");
|
||||||
m_Log[LogTypes::WII_IPC_NET] = new LogContainer("WII_IPC_NET", "WII IPC NET");
|
m_Log[LogTypes::WII_IPC_NET] = new LogContainer("WII_IPC_NET", "WII IPC NET");
|
||||||
m_Log[LogTypes::WII_IPC_WC24] = new LogContainer("WII_IPC_WC24", "WII IPC WC24");
|
m_Log[LogTypes::WII_IPC_WC24] = new LogContainer("WII_IPC_WC24", "WII IPC WC24");
|
||||||
m_Log[LogTypes::WII_IPC_SSL] = new LogContainer("WII_IPC_SSL", "WII IPC SSL");
|
m_Log[LogTypes::WII_IPC_SSL] = new LogContainer("WII_IPC_SSL", "WII IPC SSL");
|
||||||
m_Log[LogTypes::WII_IPC_WIIMOTE] = new LogContainer("WII_IPC_WIIMOTE","WII IPC WIIMOTE");
|
m_Log[LogTypes::WII_IPC_WIIMOTE] = new LogContainer("WII_IPC_WIIMOTE","WII IPC WIIMOTE");
|
||||||
m_Log[LogTypes::ACTIONREPLAY] = new LogContainer("ActionReplay", "ActionReplay");
|
m_Log[LogTypes::ACTIONREPLAY] = new LogContainer("ActionReplay", "ActionReplay");
|
||||||
m_Log[LogTypes::MEMCARD_MANAGER] = new LogContainer("MemCard Manager", "MemCard Manager");
|
m_Log[LogTypes::MEMCARD_MANAGER] = new LogContainer("MemCard Manager", "MemCard Manager");
|
||||||
m_Log[LogTypes::NETPLAY] = new LogContainer("NETPLAY", "Netplay");
|
m_Log[LogTypes::NETPLAY] = new LogContainer("NETPLAY", "Netplay");
|
||||||
|
|
||||||
m_fileLog = new FileLogListener(File::GetUserPath(F_MAINLOG_IDX).c_str());
|
m_fileLog = new FileLogListener(File::GetUserPath(F_MAINLOG_IDX).c_str());
|
||||||
m_consoleLog = new ConsoleListener();
|
m_consoleLog = new ConsoleListener();
|
||||||
m_debuggerLog = new DebuggerLogListener();
|
m_debuggerLog = new DebuggerLogListener();
|
||||||
|
|
||||||
for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; ++i)
|
for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; ++i)
|
||||||
{
|
{
|
||||||
m_Log[i]->SetEnable(true);
|
m_Log[i]->SetEnable(true);
|
||||||
m_Log[i]->AddListener(m_fileLog);
|
m_Log[i]->AddListener(m_fileLog);
|
||||||
m_Log[i]->AddListener(m_consoleLog);
|
m_Log[i]->AddListener(m_consoleLog);
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
if (IsDebuggerPresent())
|
if (IsDebuggerPresent())
|
||||||
m_Log[i]->AddListener(m_debuggerLog);
|
m_Log[i]->AddListener(m_debuggerLog);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LogManager::~LogManager()
|
LogManager::~LogManager()
|
||||||
{
|
{
|
||||||
for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; ++i)
|
for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; ++i)
|
||||||
{
|
{
|
||||||
m_logManager->RemoveListener((LogTypes::LOG_TYPE)i, m_fileLog);
|
m_logManager->RemoveListener((LogTypes::LOG_TYPE)i, m_fileLog);
|
||||||
m_logManager->RemoveListener((LogTypes::LOG_TYPE)i, m_consoleLog);
|
m_logManager->RemoveListener((LogTypes::LOG_TYPE)i, m_consoleLog);
|
||||||
m_logManager->RemoveListener((LogTypes::LOG_TYPE)i, m_debuggerLog);
|
m_logManager->RemoveListener((LogTypes::LOG_TYPE)i, m_debuggerLog);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; ++i)
|
for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; ++i)
|
||||||
delete m_Log[i];
|
delete m_Log[i];
|
||||||
|
|
||||||
delete m_fileLog;
|
delete m_fileLog;
|
||||||
delete m_consoleLog;
|
delete m_consoleLog;
|
||||||
delete m_debuggerLog;
|
delete m_debuggerLog;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LogManager::Log(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type,
|
void LogManager::Log(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type,
|
||||||
const char *file, int line, const char *format, va_list args)
|
const char *file, int line, const char *format, va_list args)
|
||||||
{
|
{
|
||||||
char temp[MAX_MSGLEN];
|
char temp[MAX_MSGLEN];
|
||||||
char msg[MAX_MSGLEN * 2];
|
char msg[MAX_MSGLEN * 2];
|
||||||
LogContainer *log = m_Log[type];
|
LogContainer *log = m_Log[type];
|
||||||
|
|
||||||
if (!log->IsEnabled() || level > log->GetLevel() || ! log->HasListeners())
|
if (!log->IsEnabled() || level > log->GetLevel() || ! log->HasListeners())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
CharArrayFromFormatV(temp, MAX_MSGLEN, format, args);
|
CharArrayFromFormatV(temp, MAX_MSGLEN, format, args);
|
||||||
|
|
||||||
static const char level_to_char[7] = "-NEWID";
|
static const char level_to_char[7] = "-NEWID";
|
||||||
sprintf(msg, "%s %s:%u %c[%s]: %s\n",
|
sprintf(msg, "%s %s:%u %c[%s]: %s\n",
|
||||||
Common::Timer::GetTimeFormatted().c_str(),
|
Common::Timer::GetTimeFormatted().c_str(),
|
||||||
file, line, level_to_char[(int)level],
|
file, line, level_to_char[(int)level],
|
||||||
log->GetShortName(), temp);
|
log->GetShortName(), temp);
|
||||||
#ifdef ANDROID
|
#ifdef ANDROID
|
||||||
Host_SysMessage(msg);
|
Host_SysMessage(msg);
|
||||||
#endif
|
#endif
|
||||||
printf(msg); // TODO(ShizZy): RemoveMe when I no longer need this
|
printf(msg); // TODO(ShizZy): RemoveMe when I no longer need this
|
||||||
log->Trigger(level, msg);
|
log->Trigger(level, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LogManager::Init()
|
void LogManager::Init()
|
||||||
{
|
{
|
||||||
m_logManager = new LogManager();
|
m_logManager = new LogManager();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LogManager::Shutdown()
|
void LogManager::Shutdown()
|
||||||
{
|
{
|
||||||
delete m_logManager;
|
delete m_logManager;
|
||||||
m_logManager = NULL;
|
m_logManager = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
LogContainer::LogContainer(const char* shortName, const char* fullName, bool enable)
|
LogContainer::LogContainer(const char* shortName, const char* fullName, bool enable)
|
||||||
: m_enable(enable)
|
: m_enable(enable)
|
||||||
{
|
{
|
||||||
strncpy(m_fullName, fullName, 128);
|
strncpy(m_fullName, fullName, 128);
|
||||||
strncpy(m_shortName, shortName, 32);
|
strncpy(m_shortName, shortName, 32);
|
||||||
m_level = LogTypes::LWARNING;
|
m_level = LogTypes::LWARNING;
|
||||||
}
|
}
|
||||||
|
|
||||||
// LogContainer
|
// LogContainer
|
||||||
void LogContainer::AddListener(LogListener *listener)
|
void LogContainer::AddListener(LogListener *listener)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lk(m_listeners_lock);
|
std::lock_guard<std::mutex> lk(m_listeners_lock);
|
||||||
m_listeners.insert(listener);
|
m_listeners.insert(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LogContainer::RemoveListener(LogListener *listener)
|
void LogContainer::RemoveListener(LogListener *listener)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lk(m_listeners_lock);
|
std::lock_guard<std::mutex> lk(m_listeners_lock);
|
||||||
m_listeners.erase(listener);
|
m_listeners.erase(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LogContainer::Trigger(LogTypes::LOG_LEVELS level, const char *msg)
|
void LogContainer::Trigger(LogTypes::LOG_LEVELS level, const char *msg)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lk(m_listeners_lock);
|
std::lock_guard<std::mutex> lk(m_listeners_lock);
|
||||||
|
|
||||||
std::set<LogListener*>::const_iterator i;
|
std::set<LogListener*>::const_iterator i;
|
||||||
for (i = m_listeners.begin(); i != m_listeners.end(); ++i)
|
for (i = m_listeners.begin(); i != m_listeners.end(); ++i)
|
||||||
{
|
{
|
||||||
(*i)->Log(level, msg);
|
(*i)->Log(level, msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FileLogListener::FileLogListener(const char *filename)
|
FileLogListener::FileLogListener(const char *filename)
|
||||||
{
|
{
|
||||||
OpenFStream(m_logfile, filename, std::ios::app);
|
OpenFStream(m_logfile, filename, std::ios::app);
|
||||||
SetEnable(true);
|
SetEnable(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileLogListener::Log(LogTypes::LOG_LEVELS, const char *msg)
|
void FileLogListener::Log(LogTypes::LOG_LEVELS, const char *msg)
|
||||||
{
|
{
|
||||||
if (!IsEnabled() || !IsValid())
|
if (!IsEnabled() || !IsValid())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lk(m_log_lock);
|
std::lock_guard<std::mutex> lk(m_log_lock);
|
||||||
m_logfile << msg << std::flush;
|
m_logfile << msg << std::flush;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DebuggerLogListener::Log(LogTypes::LOG_LEVELS, const char *msg)
|
void DebuggerLogListener::Log(LogTypes::LOG_LEVELS, const char *msg)
|
||||||
{
|
{
|
||||||
#if _MSC_VER
|
#if _MSC_VER
|
||||||
::OutputDebugStringA(msg);
|
::OutputDebugStringA(msg);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,65 +21,65 @@
|
||||||
class LogListener
|
class LogListener
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~LogListener() {}
|
virtual ~LogListener() {}
|
||||||
|
|
||||||
virtual void Log(LogTypes::LOG_LEVELS, const char *msg) = 0;
|
virtual void Log(LogTypes::LOG_LEVELS, const char *msg) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class FileLogListener : public LogListener
|
class FileLogListener : public LogListener
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
FileLogListener(const char *filename);
|
FileLogListener(const char *filename);
|
||||||
|
|
||||||
void Log(LogTypes::LOG_LEVELS, const char *msg);
|
void Log(LogTypes::LOG_LEVELS, const char *msg);
|
||||||
|
|
||||||
bool IsValid() { return !m_logfile.fail(); }
|
bool IsValid() { return !m_logfile.fail(); }
|
||||||
bool IsEnabled() const { return m_enable; }
|
bool IsEnabled() const { return m_enable; }
|
||||||
void SetEnable(bool enable) { m_enable = enable; }
|
void SetEnable(bool enable) { m_enable = enable; }
|
||||||
|
|
||||||
const char* GetName() const { return "file"; }
|
const char* GetName() const { return "file"; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::mutex m_log_lock;
|
std::mutex m_log_lock;
|
||||||
std::ofstream m_logfile;
|
std::ofstream m_logfile;
|
||||||
bool m_enable;
|
bool m_enable;
|
||||||
};
|
};
|
||||||
|
|
||||||
class DebuggerLogListener : public LogListener
|
class DebuggerLogListener : public LogListener
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void Log(LogTypes::LOG_LEVELS, const char *msg);
|
void Log(LogTypes::LOG_LEVELS, const char *msg);
|
||||||
};
|
};
|
||||||
|
|
||||||
class LogContainer
|
class LogContainer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
LogContainer(const char* shortName, const char* fullName, bool enable = false);
|
LogContainer(const char* shortName, const char* fullName, bool enable = false);
|
||||||
|
|
||||||
const char* GetShortName() const { return m_shortName; }
|
const char* GetShortName() const { return m_shortName; }
|
||||||
const char* GetFullName() const { return m_fullName; }
|
const char* GetFullName() const { return m_fullName; }
|
||||||
|
|
||||||
void AddListener(LogListener* listener);
|
void AddListener(LogListener* listener);
|
||||||
void RemoveListener(LogListener* listener);
|
void RemoveListener(LogListener* listener);
|
||||||
|
|
||||||
void Trigger(LogTypes::LOG_LEVELS, const char *msg);
|
void Trigger(LogTypes::LOG_LEVELS, const char *msg);
|
||||||
|
|
||||||
bool IsEnabled() const { return m_enable; }
|
bool IsEnabled() const { return m_enable; }
|
||||||
void SetEnable(bool enable) { m_enable = enable; }
|
void SetEnable(bool enable) { m_enable = enable; }
|
||||||
|
|
||||||
LogTypes::LOG_LEVELS GetLevel() const { return m_level; }
|
LogTypes::LOG_LEVELS GetLevel() const { return m_level; }
|
||||||
|
|
||||||
void SetLevel(LogTypes::LOG_LEVELS level) { m_level = level; }
|
void SetLevel(LogTypes::LOG_LEVELS level) { m_level = level; }
|
||||||
|
|
||||||
bool HasListeners() const { return !m_listeners.empty(); }
|
bool HasListeners() const { return !m_listeners.empty(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
char m_fullName[128];
|
char m_fullName[128];
|
||||||
char m_shortName[32];
|
char m_shortName[32];
|
||||||
bool m_enable;
|
bool m_enable;
|
||||||
LogTypes::LOG_LEVELS m_level;
|
LogTypes::LOG_LEVELS m_level;
|
||||||
std::mutex m_listeners_lock;
|
std::mutex m_listeners_lock;
|
||||||
std::set<LogListener*> m_listeners;
|
std::set<LogListener*> m_listeners;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ConsoleListener;
|
class ConsoleListener;
|
||||||
|
@ -87,83 +87,83 @@ class ConsoleListener;
|
||||||
class LogManager : NonCopyable
|
class LogManager : NonCopyable
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
LogContainer* m_Log[LogTypes::NUMBER_OF_LOGS];
|
LogContainer* m_Log[LogTypes::NUMBER_OF_LOGS];
|
||||||
FileLogListener *m_fileLog;
|
FileLogListener *m_fileLog;
|
||||||
ConsoleListener *m_consoleLog;
|
ConsoleListener *m_consoleLog;
|
||||||
DebuggerLogListener *m_debuggerLog;
|
DebuggerLogListener *m_debuggerLog;
|
||||||
static LogManager *m_logManager; // Singleton. Ugh.
|
static LogManager *m_logManager; // Singleton. Ugh.
|
||||||
|
|
||||||
LogManager();
|
LogManager();
|
||||||
~LogManager();
|
~LogManager();
|
||||||
public:
|
public:
|
||||||
|
|
||||||
static u32 GetMaxLevel() { return MAX_LOGLEVEL; }
|
static u32 GetMaxLevel() { return MAX_LOGLEVEL; }
|
||||||
|
|
||||||
void Log(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type,
|
void Log(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type,
|
||||||
const char *file, int line, const char *fmt, va_list args);
|
const char *file, int line, const char *fmt, va_list args);
|
||||||
|
|
||||||
void SetLogLevel(LogTypes::LOG_TYPE type, LogTypes::LOG_LEVELS level)
|
void SetLogLevel(LogTypes::LOG_TYPE type, LogTypes::LOG_LEVELS level)
|
||||||
{
|
{
|
||||||
m_Log[type]->SetLevel(level);
|
m_Log[type]->SetLevel(level);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetEnable(LogTypes::LOG_TYPE type, bool enable)
|
void SetEnable(LogTypes::LOG_TYPE type, bool enable)
|
||||||
{
|
{
|
||||||
m_Log[type]->SetEnable(enable);
|
m_Log[type]->SetEnable(enable);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsEnabled(LogTypes::LOG_TYPE type) const
|
bool IsEnabled(LogTypes::LOG_TYPE type) const
|
||||||
{
|
{
|
||||||
return m_Log[type]->IsEnabled();
|
return m_Log[type]->IsEnabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* GetShortName(LogTypes::LOG_TYPE type) const
|
const char* GetShortName(LogTypes::LOG_TYPE type) const
|
||||||
{
|
{
|
||||||
return m_Log[type]->GetShortName();
|
return m_Log[type]->GetShortName();
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* GetFullName(LogTypes::LOG_TYPE type) const
|
const char* GetFullName(LogTypes::LOG_TYPE type) const
|
||||||
{
|
{
|
||||||
return m_Log[type]->GetFullName();
|
return m_Log[type]->GetFullName();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddListener(LogTypes::LOG_TYPE type, LogListener *listener)
|
void AddListener(LogTypes::LOG_TYPE type, LogListener *listener)
|
||||||
{
|
{
|
||||||
m_Log[type]->AddListener(listener);
|
m_Log[type]->AddListener(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RemoveListener(LogTypes::LOG_TYPE type, LogListener *listener)
|
void RemoveListener(LogTypes::LOG_TYPE type, LogListener *listener)
|
||||||
{
|
{
|
||||||
m_Log[type]->RemoveListener(listener);
|
m_Log[type]->RemoveListener(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
FileLogListener *GetFileListener() const
|
FileLogListener *GetFileListener() const
|
||||||
{
|
{
|
||||||
return m_fileLog;
|
return m_fileLog;
|
||||||
}
|
}
|
||||||
|
|
||||||
ConsoleListener *GetConsoleListener() const
|
ConsoleListener *GetConsoleListener() const
|
||||||
{
|
{
|
||||||
return m_consoleLog;
|
return m_consoleLog;
|
||||||
}
|
}
|
||||||
|
|
||||||
DebuggerLogListener *GetDebuggerListener() const
|
DebuggerLogListener *GetDebuggerListener() const
|
||||||
{
|
{
|
||||||
return m_debuggerLog;
|
return m_debuggerLog;
|
||||||
}
|
}
|
||||||
|
|
||||||
static LogManager* GetInstance()
|
static LogManager* GetInstance()
|
||||||
{
|
{
|
||||||
return m_logManager;
|
return m_logManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SetInstance(LogManager *logManager)
|
static void SetInstance(LogManager *logManager)
|
||||||
{
|
{
|
||||||
m_logManager = logManager;
|
m_logManager = logManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Init();
|
static void Init();
|
||||||
static void Shutdown();
|
static void Shutdown();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _LOGMANAGER_H_
|
#endif // _LOGMANAGER_H_
|
||||||
|
|
|
@ -14,82 +14,82 @@ namespace MathUtil
|
||||||
|
|
||||||
u32 ClassifyDouble(double dvalue)
|
u32 ClassifyDouble(double dvalue)
|
||||||
{
|
{
|
||||||
// TODO: Optimize the below to be as fast as possible.
|
// TODO: Optimize the below to be as fast as possible.
|
||||||
IntDouble value;
|
IntDouble value;
|
||||||
value.d = dvalue;
|
value.d = dvalue;
|
||||||
u64 sign = value.i & DOUBLE_SIGN;
|
u64 sign = value.i & DOUBLE_SIGN;
|
||||||
u64 exp = value.i & DOUBLE_EXP;
|
u64 exp = value.i & DOUBLE_EXP;
|
||||||
if (exp > DOUBLE_ZERO && exp < DOUBLE_EXP)
|
if (exp > DOUBLE_ZERO && exp < DOUBLE_EXP)
|
||||||
{
|
{
|
||||||
// Nice normalized number.
|
// Nice normalized number.
|
||||||
return sign ? PPC_FPCLASS_NN : PPC_FPCLASS_PN;
|
return sign ? PPC_FPCLASS_NN : PPC_FPCLASS_PN;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
u64 mantissa = value.i & DOUBLE_FRAC;
|
u64 mantissa = value.i & DOUBLE_FRAC;
|
||||||
if (mantissa)
|
if (mantissa)
|
||||||
{
|
{
|
||||||
if (exp)
|
if (exp)
|
||||||
{
|
{
|
||||||
return PPC_FPCLASS_QNAN;
|
return PPC_FPCLASS_QNAN;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Denormalized number.
|
// Denormalized number.
|
||||||
return sign ? PPC_FPCLASS_ND : PPC_FPCLASS_PD;
|
return sign ? PPC_FPCLASS_ND : PPC_FPCLASS_PD;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (exp)
|
else if (exp)
|
||||||
{
|
{
|
||||||
//Infinite
|
//Infinite
|
||||||
return sign ? PPC_FPCLASS_NINF : PPC_FPCLASS_PINF;
|
return sign ? PPC_FPCLASS_NINF : PPC_FPCLASS_PINF;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//Zero
|
//Zero
|
||||||
return sign ? PPC_FPCLASS_NZ : PPC_FPCLASS_PZ;
|
return sign ? PPC_FPCLASS_NZ : PPC_FPCLASS_PZ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 ClassifyFloat(float fvalue)
|
u32 ClassifyFloat(float fvalue)
|
||||||
{
|
{
|
||||||
// TODO: Optimize the below to be as fast as possible.
|
// TODO: Optimize the below to be as fast as possible.
|
||||||
IntFloat value;
|
IntFloat value;
|
||||||
value.f = fvalue;
|
value.f = fvalue;
|
||||||
u32 sign = value.i & FLOAT_SIGN;
|
u32 sign = value.i & FLOAT_SIGN;
|
||||||
u32 exp = value.i & FLOAT_EXP;
|
u32 exp = value.i & FLOAT_EXP;
|
||||||
if (exp > FLOAT_ZERO && exp < FLOAT_EXP)
|
if (exp > FLOAT_ZERO && exp < FLOAT_EXP)
|
||||||
{
|
{
|
||||||
// Nice normalized number.
|
// Nice normalized number.
|
||||||
return sign ? PPC_FPCLASS_NN : PPC_FPCLASS_PN;
|
return sign ? PPC_FPCLASS_NN : PPC_FPCLASS_PN;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
u32 mantissa = value.i & FLOAT_FRAC;
|
u32 mantissa = value.i & FLOAT_FRAC;
|
||||||
if (mantissa)
|
if (mantissa)
|
||||||
{
|
{
|
||||||
if (exp)
|
if (exp)
|
||||||
{
|
{
|
||||||
return PPC_FPCLASS_QNAN; // Quiet NAN
|
return PPC_FPCLASS_QNAN; // Quiet NAN
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Denormalized number.
|
// Denormalized number.
|
||||||
return sign ? PPC_FPCLASS_ND : PPC_FPCLASS_PD;
|
return sign ? PPC_FPCLASS_ND : PPC_FPCLASS_PD;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (exp)
|
else if (exp)
|
||||||
{
|
{
|
||||||
// Infinite
|
// Infinite
|
||||||
return sign ? PPC_FPCLASS_NINF : PPC_FPCLASS_PINF;
|
return sign ? PPC_FPCLASS_NINF : PPC_FPCLASS_PINF;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//Zero
|
//Zero
|
||||||
return sign ? PPC_FPCLASS_NZ : PPC_FPCLASS_PZ;
|
return sign ? PPC_FPCLASS_NZ : PPC_FPCLASS_PZ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -97,116 +97,116 @@ u32 ClassifyFloat(float fvalue)
|
||||||
|
|
||||||
inline void MatrixMul(int n, const float *a, const float *b, float *result)
|
inline void MatrixMul(int n, const float *a, const float *b, float *result)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < n; ++i)
|
for (int i = 0; i < n; ++i)
|
||||||
{
|
{
|
||||||
for (int j = 0; j < n; ++j)
|
for (int j = 0; j < n; ++j)
|
||||||
{
|
{
|
||||||
float temp = 0;
|
float temp = 0;
|
||||||
for (int k = 0; k < n; ++k)
|
for (int k = 0; k < n; ++k)
|
||||||
{
|
{
|
||||||
temp += a[i * n + k] * b[k * n + j];
|
temp += a[i * n + k] * b[k * n + j];
|
||||||
}
|
}
|
||||||
result[i * n + j] = temp;
|
result[i * n + j] = temp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate sum of a float list
|
// Calculate sum of a float list
|
||||||
float MathFloatVectorSum(const std::vector<float>& Vec)
|
float MathFloatVectorSum(const std::vector<float>& Vec)
|
||||||
{
|
{
|
||||||
return std::accumulate(Vec.begin(), Vec.end(), 0.0f);
|
return std::accumulate(Vec.begin(), Vec.end(), 0.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Matrix33::LoadIdentity(Matrix33 &mtx)
|
void Matrix33::LoadIdentity(Matrix33 &mtx)
|
||||||
{
|
{
|
||||||
memset(mtx.data, 0, sizeof(mtx.data));
|
memset(mtx.data, 0, sizeof(mtx.data));
|
||||||
mtx.data[0] = 1.0f;
|
mtx.data[0] = 1.0f;
|
||||||
mtx.data[4] = 1.0f;
|
mtx.data[4] = 1.0f;
|
||||||
mtx.data[8] = 1.0f;
|
mtx.data[8] = 1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Matrix33::RotateX(Matrix33 &mtx, float rad)
|
void Matrix33::RotateX(Matrix33 &mtx, float rad)
|
||||||
{
|
{
|
||||||
float s = sin(rad);
|
float s = sin(rad);
|
||||||
float c = cos(rad);
|
float c = cos(rad);
|
||||||
memset(mtx.data, 0, sizeof(mtx.data));
|
memset(mtx.data, 0, sizeof(mtx.data));
|
||||||
mtx.data[0] = 1;
|
mtx.data[0] = 1;
|
||||||
mtx.data[4] = c;
|
mtx.data[4] = c;
|
||||||
mtx.data[5] = -s;
|
mtx.data[5] = -s;
|
||||||
mtx.data[7] = s;
|
mtx.data[7] = s;
|
||||||
mtx.data[8] = c;
|
mtx.data[8] = c;
|
||||||
}
|
}
|
||||||
void Matrix33::RotateY(Matrix33 &mtx, float rad)
|
void Matrix33::RotateY(Matrix33 &mtx, float rad)
|
||||||
{
|
{
|
||||||
float s = sin(rad);
|
float s = sin(rad);
|
||||||
float c = cos(rad);
|
float c = cos(rad);
|
||||||
memset(mtx.data, 0, sizeof(mtx.data));
|
memset(mtx.data, 0, sizeof(mtx.data));
|
||||||
mtx.data[0] = c;
|
mtx.data[0] = c;
|
||||||
mtx.data[2] = s;
|
mtx.data[2] = s;
|
||||||
mtx.data[4] = 1;
|
mtx.data[4] = 1;
|
||||||
mtx.data[6] = -s;
|
mtx.data[6] = -s;
|
||||||
mtx.data[8] = c;
|
mtx.data[8] = c;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Matrix33::Multiply(const Matrix33 &a, const Matrix33 &b, Matrix33 &result)
|
void Matrix33::Multiply(const Matrix33 &a, const Matrix33 &b, Matrix33 &result)
|
||||||
{
|
{
|
||||||
MatrixMul(3, a.data, b.data, result.data);
|
MatrixMul(3, a.data, b.data, result.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Matrix33::Multiply(const Matrix33 &a, const float vec[3], float result[3])
|
void Matrix33::Multiply(const Matrix33 &a, const float vec[3], float result[3])
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 3; ++i) {
|
for (int i = 0; i < 3; ++i) {
|
||||||
result[i] = 0;
|
result[i] = 0;
|
||||||
for (int k = 0; k < 3; ++k) {
|
for (int k = 0; k < 3; ++k) {
|
||||||
result[i] += a.data[i * 3 + k] * vec[k];
|
result[i] += a.data[i * 3 + k] * vec[k];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Matrix44::LoadIdentity(Matrix44 &mtx)
|
void Matrix44::LoadIdentity(Matrix44 &mtx)
|
||||||
{
|
{
|
||||||
memset(mtx.data, 0, sizeof(mtx.data));
|
memset(mtx.data, 0, sizeof(mtx.data));
|
||||||
mtx.data[0] = 1.0f;
|
mtx.data[0] = 1.0f;
|
||||||
mtx.data[5] = 1.0f;
|
mtx.data[5] = 1.0f;
|
||||||
mtx.data[10] = 1.0f;
|
mtx.data[10] = 1.0f;
|
||||||
mtx.data[15] = 1.0f;
|
mtx.data[15] = 1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Matrix44::LoadMatrix33(Matrix44 &mtx, const Matrix33 &m33)
|
void Matrix44::LoadMatrix33(Matrix44 &mtx, const Matrix33 &m33)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 3; ++i)
|
for (int i = 0; i < 3; ++i)
|
||||||
{
|
{
|
||||||
for (int j = 0; j < 3; ++j)
|
for (int j = 0; j < 3; ++j)
|
||||||
{
|
{
|
||||||
mtx.data[i * 4 + j] = m33.data[i * 3 + j];
|
mtx.data[i * 4 + j] = m33.data[i * 3 + j];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < 3; ++i)
|
for (int i = 0; i < 3; ++i)
|
||||||
{
|
{
|
||||||
mtx.data[i * 4 + 3] = 0;
|
mtx.data[i * 4 + 3] = 0;
|
||||||
mtx.data[i + 12] = 0;
|
mtx.data[i + 12] = 0;
|
||||||
}
|
}
|
||||||
mtx.data[15] = 1.0f;
|
mtx.data[15] = 1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Matrix44::Set(Matrix44 &mtx, const float mtxArray[16])
|
void Matrix44::Set(Matrix44 &mtx, const float mtxArray[16])
|
||||||
{
|
{
|
||||||
for(int i = 0; i < 16; ++i) {
|
for(int i = 0; i < 16; ++i) {
|
||||||
mtx.data[i] = mtxArray[i];
|
mtx.data[i] = mtxArray[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Matrix44::Translate(Matrix44 &mtx, const float vec[3])
|
void Matrix44::Translate(Matrix44 &mtx, const float vec[3])
|
||||||
{
|
{
|
||||||
LoadIdentity(mtx);
|
LoadIdentity(mtx);
|
||||||
mtx.data[3] = vec[0];
|
mtx.data[3] = vec[0];
|
||||||
mtx.data[7] = vec[1];
|
mtx.data[7] = vec[1];
|
||||||
mtx.data[11] = vec[2];
|
mtx.data[11] = vec[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
void Matrix44::Multiply(const Matrix44 &a, const Matrix44 &b, Matrix44 &result)
|
void Matrix44::Multiply(const Matrix44 &a, const Matrix44 &b, Matrix44 &result)
|
||||||
{
|
{
|
||||||
MatrixMul(4, a.data, b.data, result.data);
|
MatrixMul(4, a.data, b.data, result.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,74 +14,74 @@ namespace MathUtil
|
||||||
{
|
{
|
||||||
|
|
||||||
static const u64 DOUBLE_SIGN = 0x8000000000000000ULL,
|
static const u64 DOUBLE_SIGN = 0x8000000000000000ULL,
|
||||||
DOUBLE_EXP = 0x7FF0000000000000ULL,
|
DOUBLE_EXP = 0x7FF0000000000000ULL,
|
||||||
DOUBLE_FRAC = 0x000FFFFFFFFFFFFFULL,
|
DOUBLE_FRAC = 0x000FFFFFFFFFFFFFULL,
|
||||||
DOUBLE_ZERO = 0x0000000000000000ULL;
|
DOUBLE_ZERO = 0x0000000000000000ULL;
|
||||||
|
|
||||||
static const u32 FLOAT_SIGN = 0x80000000,
|
static const u32 FLOAT_SIGN = 0x80000000,
|
||||||
FLOAT_EXP = 0x7F800000,
|
FLOAT_EXP = 0x7F800000,
|
||||||
FLOAT_FRAC = 0x007FFFFF,
|
FLOAT_FRAC = 0x007FFFFF,
|
||||||
FLOAT_ZERO = 0x00000000;
|
FLOAT_ZERO = 0x00000000;
|
||||||
|
|
||||||
union IntDouble {
|
union IntDouble {
|
||||||
double d;
|
double d;
|
||||||
u64 i;
|
u64 i;
|
||||||
};
|
};
|
||||||
union IntFloat {
|
union IntFloat {
|
||||||
float f;
|
float f;
|
||||||
u32 i;
|
u32 i;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline bool IsNAN(double d)
|
inline bool IsNAN(double d)
|
||||||
{
|
{
|
||||||
IntDouble x; x.d = d;
|
IntDouble x; x.d = d;
|
||||||
return ( ((x.i & DOUBLE_EXP) == DOUBLE_EXP) &&
|
return ( ((x.i & DOUBLE_EXP) == DOUBLE_EXP) &&
|
||||||
((x.i & DOUBLE_FRAC) != DOUBLE_ZERO) );
|
((x.i & DOUBLE_FRAC) != DOUBLE_ZERO) );
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool IsQNAN(double d)
|
inline bool IsQNAN(double d)
|
||||||
{
|
{
|
||||||
IntDouble x; x.d = d;
|
IntDouble x; x.d = d;
|
||||||
return ( ((x.i & DOUBLE_EXP) == DOUBLE_EXP) &&
|
return ( ((x.i & DOUBLE_EXP) == DOUBLE_EXP) &&
|
||||||
((x.i & 0x0007fffffffffffULL) == 0x000000000000000ULL) &&
|
((x.i & 0x0007fffffffffffULL) == 0x000000000000000ULL) &&
|
||||||
((x.i & 0x000800000000000ULL) == 0x000800000000000ULL) );
|
((x.i & 0x000800000000000ULL) == 0x000800000000000ULL) );
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool IsSNAN(double d)
|
inline bool IsSNAN(double d)
|
||||||
{
|
{
|
||||||
IntDouble x; x.d = d;
|
IntDouble x; x.d = d;
|
||||||
return( ((x.i & DOUBLE_EXP) == DOUBLE_EXP) &&
|
return( ((x.i & DOUBLE_EXP) == DOUBLE_EXP) &&
|
||||||
((x.i & DOUBLE_FRAC) != DOUBLE_ZERO) &&
|
((x.i & DOUBLE_FRAC) != DOUBLE_ZERO) &&
|
||||||
((x.i & 0x0008000000000000ULL) == DOUBLE_ZERO) );
|
((x.i & 0x0008000000000000ULL) == DOUBLE_ZERO) );
|
||||||
}
|
}
|
||||||
|
|
||||||
inline float FlushToZero(float f)
|
inline float FlushToZero(float f)
|
||||||
{
|
{
|
||||||
IntFloat x; x.f = f;
|
IntFloat x; x.f = f;
|
||||||
if ((x.i & FLOAT_EXP) == 0)
|
if ((x.i & FLOAT_EXP) == 0)
|
||||||
x.i &= FLOAT_SIGN; // turn into signed zero
|
x.i &= FLOAT_SIGN; // turn into signed zero
|
||||||
return x.f;
|
return x.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline double FlushToZeroAsFloat(double d)
|
inline double FlushToZeroAsFloat(double d)
|
||||||
{
|
{
|
||||||
IntDouble x; x.d = d;
|
IntDouble x; x.d = d;
|
||||||
if ((x.i & DOUBLE_EXP) < 0x3800000000000000ULL)
|
if ((x.i & DOUBLE_EXP) < 0x3800000000000000ULL)
|
||||||
x.i &= DOUBLE_SIGN; // turn into signed zero
|
x.i &= DOUBLE_SIGN; // turn into signed zero
|
||||||
return x.d;
|
return x.d;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum PPCFpClass
|
enum PPCFpClass
|
||||||
{
|
{
|
||||||
PPC_FPCLASS_QNAN = 0x11,
|
PPC_FPCLASS_QNAN = 0x11,
|
||||||
PPC_FPCLASS_NINF = 0x9,
|
PPC_FPCLASS_NINF = 0x9,
|
||||||
PPC_FPCLASS_NN = 0x8,
|
PPC_FPCLASS_NN = 0x8,
|
||||||
PPC_FPCLASS_ND = 0x18,
|
PPC_FPCLASS_ND = 0x18,
|
||||||
PPC_FPCLASS_NZ = 0x12,
|
PPC_FPCLASS_NZ = 0x12,
|
||||||
PPC_FPCLASS_PZ = 0x2,
|
PPC_FPCLASS_PZ = 0x2,
|
||||||
PPC_FPCLASS_PD = 0x14,
|
PPC_FPCLASS_PD = 0x14,
|
||||||
PPC_FPCLASS_PN = 0x4,
|
PPC_FPCLASS_PN = 0x4,
|
||||||
PPC_FPCLASS_PINF = 0x5,
|
PPC_FPCLASS_PINF = 0x5,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Uses PowerPC conventions for the return value, so it can be easily
|
// Uses PowerPC conventions for the return value, so it can be easily
|
||||||
|
@ -93,42 +93,42 @@ u32 ClassifyFloat(float fvalue);
|
||||||
template<class T>
|
template<class T>
|
||||||
struct Rectangle
|
struct Rectangle
|
||||||
{
|
{
|
||||||
T left;
|
T left;
|
||||||
T top;
|
T top;
|
||||||
T right;
|
T right;
|
||||||
T bottom;
|
T bottom;
|
||||||
|
|
||||||
Rectangle()
|
Rectangle()
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
Rectangle(T theLeft, T theTop, T theRight, T theBottom)
|
Rectangle(T theLeft, T theTop, T theRight, T theBottom)
|
||||||
: left(theLeft), top(theTop), right(theRight), bottom(theBottom)
|
: left(theLeft), top(theTop), right(theRight), bottom(theBottom)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
bool operator==(const Rectangle& r) { return left==r.left && top==r.top && right==r.right && bottom==r.bottom; }
|
bool operator==(const Rectangle& r) { return left==r.left && top==r.top && right==r.right && bottom==r.bottom; }
|
||||||
|
|
||||||
T GetWidth() const { return abs(right - left); }
|
T GetWidth() const { return abs(right - left); }
|
||||||
T GetHeight() const { return abs(bottom - top); }
|
T GetHeight() const { return abs(bottom - top); }
|
||||||
|
|
||||||
// If the rectangle is in a coordinate system with a lower-left origin, use
|
// If the rectangle is in a coordinate system with a lower-left origin, use
|
||||||
// this Clamp.
|
// this Clamp.
|
||||||
void ClampLL(T x1, T y1, T x2, T y2)
|
void ClampLL(T x1, T y1, T x2, T y2)
|
||||||
{
|
{
|
||||||
if (left < x1) left = x1;
|
if (left < x1) left = x1;
|
||||||
if (right > x2) right = x2;
|
if (right > x2) right = x2;
|
||||||
if (top > y1) top = y1;
|
if (top > y1) top = y1;
|
||||||
if (bottom < y2) bottom = y2;
|
if (bottom < y2) bottom = y2;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the rectangle is in a coordinate system with an upper-left origin,
|
// If the rectangle is in a coordinate system with an upper-left origin,
|
||||||
// use this Clamp.
|
// use this Clamp.
|
||||||
void ClampUL(T x1, T y1, T x2, T y2)
|
void ClampUL(T x1, T y1, T x2, T y2)
|
||||||
{
|
{
|
||||||
if (left < x1) left = x1;
|
if (left < x1) left = x1;
|
||||||
if (right > x2) right = x2;
|
if (right > x2) right = x2;
|
||||||
if (top < y1) top = y1;
|
if (top < y1) top = y1;
|
||||||
if (bottom > y2) bottom = y2;
|
if (bottom > y2) bottom = y2;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace MathUtil
|
} // namespace MathUtil
|
||||||
|
@ -138,28 +138,28 @@ inline double pow2(double x) {return x * x;}
|
||||||
|
|
||||||
float MathFloatVectorSum(const std::vector<float>&);
|
float MathFloatVectorSum(const std::vector<float>&);
|
||||||
|
|
||||||
#define ROUND_UP(x, a) (((x) + (a) - 1) & ~((a) - 1))
|
#define ROUND_UP(x, a) (((x) + (a) - 1) & ~((a) - 1))
|
||||||
#define ROUND_DOWN(x, a) ((x) & ~((a) - 1))
|
#define ROUND_DOWN(x, a) ((x) & ~((a) - 1))
|
||||||
|
|
||||||
// Rounds down. 0 -> undefined
|
// Rounds down. 0 -> undefined
|
||||||
inline u64 Log2(u64 val)
|
inline u64 Log2(u64 val)
|
||||||
{
|
{
|
||||||
#if defined(__GNUC__)
|
#if defined(__GNUC__)
|
||||||
return 63 - __builtin_clzll(val);
|
return 63 - __builtin_clzll(val);
|
||||||
|
|
||||||
#elif defined(_MSC_VER) && defined(_M_X64)
|
#elif defined(_MSC_VER) && defined(_M_X64)
|
||||||
unsigned long result = -1;
|
unsigned long result = -1;
|
||||||
_BitScanReverse64(&result, val);
|
_BitScanReverse64(&result, val);
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
#else
|
#else
|
||||||
u64 result = -1;
|
u64 result = -1;
|
||||||
while (val != 0)
|
while (val != 0)
|
||||||
{
|
{
|
||||||
val >>= 1;
|
val >>= 1;
|
||||||
++result;
|
++result;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,32 +169,32 @@ inline u64 Log2(u64 val)
|
||||||
class Matrix33
|
class Matrix33
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static void LoadIdentity(Matrix33 &mtx);
|
static void LoadIdentity(Matrix33 &mtx);
|
||||||
|
|
||||||
// set mtx to be a rotation matrix around the x axis
|
// set mtx to be a rotation matrix around the x axis
|
||||||
static void RotateX(Matrix33 &mtx, float rad);
|
static void RotateX(Matrix33 &mtx, float rad);
|
||||||
// set mtx to be a rotation matrix around the y axis
|
// set mtx to be a rotation matrix around the y axis
|
||||||
static void RotateY(Matrix33 &mtx, float rad);
|
static void RotateY(Matrix33 &mtx, float rad);
|
||||||
|
|
||||||
// set result = a x b
|
// set result = a x b
|
||||||
static void Multiply(const Matrix33 &a, const Matrix33 &b, Matrix33 &result);
|
static void Multiply(const Matrix33 &a, const Matrix33 &b, Matrix33 &result);
|
||||||
static void Multiply(const Matrix33 &a, const float vec[3], float result[3]);
|
static void Multiply(const Matrix33 &a, const float vec[3], float result[3]);
|
||||||
|
|
||||||
float data[9];
|
float data[9];
|
||||||
};
|
};
|
||||||
|
|
||||||
class Matrix44
|
class Matrix44
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static void LoadIdentity(Matrix44 &mtx);
|
static void LoadIdentity(Matrix44 &mtx);
|
||||||
static void LoadMatrix33(Matrix44 &mtx, const Matrix33 &m33);
|
static void LoadMatrix33(Matrix44 &mtx, const Matrix33 &m33);
|
||||||
static void Set(Matrix44 &mtx, const float mtxArray[16]);
|
static void Set(Matrix44 &mtx, const float mtxArray[16]);
|
||||||
|
|
||||||
static void Translate(Matrix44 &mtx, const float vec[3]);
|
static void Translate(Matrix44 &mtx, const float vec[3]);
|
||||||
|
|
||||||
static void Multiply(const Matrix44 &a, const Matrix44 &b, Matrix44 &result);
|
static void Multiply(const Matrix44 &a, const Matrix44 &b, Matrix44 &result);
|
||||||
|
|
||||||
float data[16];
|
float data[16];
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _MATH_UTIL_H_
|
#endif // _MATH_UTIL_H_
|
||||||
|
|
|
@ -27,148 +27,148 @@
|
||||||
void* AllocateExecutableMemory(size_t size, bool low)
|
void* AllocateExecutableMemory(size_t size, bool low)
|
||||||
{
|
{
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
void* ptr = VirtualAlloc(0, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
|
void* ptr = VirtualAlloc(0, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
|
||||||
#else
|
#else
|
||||||
static char *map_hint = 0;
|
static char *map_hint = 0;
|
||||||
#if defined(__x86_64__) && !defined(MAP_32BIT)
|
#if defined(__x86_64__) && !defined(MAP_32BIT)
|
||||||
// This OS has no flag to enforce allocation below the 4 GB boundary,
|
// This OS has no flag to enforce allocation below the 4 GB boundary,
|
||||||
// but if we hint that we want a low address it is very likely we will
|
// but if we hint that we want a low address it is very likely we will
|
||||||
// get one.
|
// get one.
|
||||||
// An older version of this code used MAP_FIXED, but that has the side
|
// An older version of this code used MAP_FIXED, but that has the side
|
||||||
// effect of discarding already mapped pages that happen to be in the
|
// effect of discarding already mapped pages that happen to be in the
|
||||||
// requested virtual memory range (such as the emulated RAM, sometimes).
|
// requested virtual memory range (such as the emulated RAM, sometimes).
|
||||||
if (low && (!map_hint))
|
if (low && (!map_hint))
|
||||||
map_hint = (char*)round_page(512*1024*1024); /* 0.5 GB rounded up to the next page */
|
map_hint = (char*)round_page(512*1024*1024); /* 0.5 GB rounded up to the next page */
|
||||||
#endif
|
#endif
|
||||||
void* ptr = mmap(map_hint, size, PROT_READ | PROT_WRITE | PROT_EXEC,
|
void* ptr = mmap(map_hint, size, PROT_READ | PROT_WRITE | PROT_EXEC,
|
||||||
MAP_ANON | MAP_PRIVATE
|
MAP_ANON | MAP_PRIVATE
|
||||||
#if defined(__x86_64__) && defined(MAP_32BIT)
|
#if defined(__x86_64__) && defined(MAP_32BIT)
|
||||||
| (low ? MAP_32BIT : 0)
|
| (low ? MAP_32BIT : 0)
|
||||||
#endif
|
#endif
|
||||||
, -1, 0);
|
, -1, 0);
|
||||||
#endif /* defined(_WIN32) */
|
#endif /* defined(_WIN32) */
|
||||||
|
|
||||||
// printf("Mapped executable memory at %p (size %ld)\n", ptr,
|
// printf("Mapped executable memory at %p (size %ld)\n", ptr,
|
||||||
// (unsigned long)size);
|
// (unsigned long)size);
|
||||||
|
|
||||||
#if defined(__FreeBSD__)
|
#if defined(__FreeBSD__)
|
||||||
if (ptr == MAP_FAILED)
|
if (ptr == MAP_FAILED)
|
||||||
{
|
{
|
||||||
ptr = NULL;
|
ptr = NULL;
|
||||||
#else
|
#else
|
||||||
if (ptr == NULL)
|
if (ptr == NULL)
|
||||||
{
|
{
|
||||||
#endif
|
#endif
|
||||||
PanicAlert("Failed to allocate executable memory");
|
PanicAlert("Failed to allocate executable memory");
|
||||||
}
|
}
|
||||||
#if !defined(_WIN32) && defined(__x86_64__) && !defined(MAP_32BIT)
|
#if !defined(_WIN32) && defined(__x86_64__) && !defined(MAP_32BIT)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (low)
|
if (low)
|
||||||
{
|
{
|
||||||
map_hint += size;
|
map_hint += size;
|
||||||
map_hint = (char*)round_page(map_hint); /* round up to the next page */
|
map_hint = (char*)round_page(map_hint); /* round up to the next page */
|
||||||
// printf("Next map will (hopefully) be at %p\n", map_hint);
|
// printf("Next map will (hopefully) be at %p\n", map_hint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(_M_X64)
|
#if defined(_M_X64)
|
||||||
if ((u64)ptr >= 0x80000000 && low == true)
|
if ((u64)ptr >= 0x80000000 && low == true)
|
||||||
PanicAlert("Executable memory ended up above 2GB!");
|
PanicAlert("Executable memory ended up above 2GB!");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* AllocateMemoryPages(size_t size)
|
void* AllocateMemoryPages(size_t size)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
void* ptr = VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE);
|
void* ptr = VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE);
|
||||||
#else
|
#else
|
||||||
void* ptr = mmap(0, size, PROT_READ | PROT_WRITE,
|
void* ptr = mmap(0, size, PROT_READ | PROT_WRITE,
|
||||||
MAP_ANON | MAP_PRIVATE, -1, 0);
|
MAP_ANON | MAP_PRIVATE, -1, 0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// printf("Mapped memory at %p (size %ld)\n", ptr,
|
// printf("Mapped memory at %p (size %ld)\n", ptr,
|
||||||
// (unsigned long)size);
|
// (unsigned long)size);
|
||||||
|
|
||||||
if (ptr == NULL)
|
if (ptr == NULL)
|
||||||
PanicAlert("Failed to allocate raw memory");
|
PanicAlert("Failed to allocate raw memory");
|
||||||
|
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* AllocateAlignedMemory(size_t size,size_t alignment)
|
void* AllocateAlignedMemory(size_t size,size_t alignment)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
void* ptr = _aligned_malloc(size,alignment);
|
void* ptr = _aligned_malloc(size,alignment);
|
||||||
#else
|
#else
|
||||||
void* ptr = NULL;
|
void* ptr = NULL;
|
||||||
#ifdef ANDROID
|
#ifdef ANDROID
|
||||||
ptr = memalign(alignment, size);
|
ptr = memalign(alignment, size);
|
||||||
#else
|
#else
|
||||||
if (posix_memalign(&ptr, alignment, size) != 0)
|
if (posix_memalign(&ptr, alignment, size) != 0)
|
||||||
ERROR_LOG(MEMMAP, "Failed to allocate aligned memory");
|
ERROR_LOG(MEMMAP, "Failed to allocate aligned memory");
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// printf("Mapped memory at %p (size %ld)\n", ptr,
|
// printf("Mapped memory at %p (size %ld)\n", ptr,
|
||||||
// (unsigned long)size);
|
// (unsigned long)size);
|
||||||
|
|
||||||
if (ptr == NULL)
|
if (ptr == NULL)
|
||||||
PanicAlert("Failed to allocate aligned memory");
|
PanicAlert("Failed to allocate aligned memory");
|
||||||
|
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FreeMemoryPages(void* ptr, size_t size)
|
void FreeMemoryPages(void* ptr, size_t size)
|
||||||
{
|
{
|
||||||
if (ptr)
|
if (ptr)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
|
||||||
if (!VirtualFree(ptr, 0, MEM_RELEASE))
|
if (!VirtualFree(ptr, 0, MEM_RELEASE))
|
||||||
PanicAlert("FreeMemoryPages failed!\n%s", GetLastErrorMsg());
|
PanicAlert("FreeMemoryPages failed!\n%s", GetLastErrorMsg());
|
||||||
ptr = NULL; // Is this our responsibility?
|
ptr = NULL; // Is this our responsibility?
|
||||||
|
|
||||||
#else
|
#else
|
||||||
munmap(ptr, size);
|
munmap(ptr, size);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FreeAlignedMemory(void* ptr)
|
void FreeAlignedMemory(void* ptr)
|
||||||
{
|
{
|
||||||
if (ptr)
|
if (ptr)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
_aligned_free(ptr);
|
_aligned_free(ptr);
|
||||||
#else
|
#else
|
||||||
free(ptr);
|
free(ptr);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WriteProtectMemory(void* ptr, size_t size, bool allowExecute)
|
void WriteProtectMemory(void* ptr, size_t size, bool allowExecute)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
DWORD oldValue;
|
DWORD oldValue;
|
||||||
if (!VirtualProtect(ptr, size, allowExecute ? PAGE_EXECUTE_READ : PAGE_READONLY, &oldValue))
|
if (!VirtualProtect(ptr, size, allowExecute ? PAGE_EXECUTE_READ : PAGE_READONLY, &oldValue))
|
||||||
PanicAlert("WriteProtectMemory failed!\n%s", GetLastErrorMsg());
|
PanicAlert("WriteProtectMemory failed!\n%s", GetLastErrorMsg());
|
||||||
#else
|
#else
|
||||||
mprotect(ptr, size, allowExecute ? (PROT_READ | PROT_EXEC) : PROT_READ);
|
mprotect(ptr, size, allowExecute ? (PROT_READ | PROT_EXEC) : PROT_READ);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void UnWriteProtectMemory(void* ptr, size_t size, bool allowExecute)
|
void UnWriteProtectMemory(void* ptr, size_t size, bool allowExecute)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
DWORD oldValue;
|
DWORD oldValue;
|
||||||
if (!VirtualProtect(ptr, size, allowExecute ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE, &oldValue))
|
if (!VirtualProtect(ptr, size, allowExecute ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE, &oldValue))
|
||||||
PanicAlert("UnWriteProtectMemory failed!\n%s", GetLastErrorMsg());
|
PanicAlert("UnWriteProtectMemory failed!\n%s", GetLastErrorMsg());
|
||||||
#else
|
#else
|
||||||
mprotect(ptr, size, allowExecute ? (PROT_READ | PROT_WRITE | PROT_EXEC) : PROT_WRITE | PROT_READ);
|
mprotect(ptr, size, allowExecute ? (PROT_READ | PROT_WRITE | PROT_EXEC) : PROT_WRITE | PROT_READ);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,22 +176,22 @@ std::string MemUsage()
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#pragma comment(lib, "psapi")
|
#pragma comment(lib, "psapi")
|
||||||
DWORD processID = GetCurrentProcessId();
|
DWORD processID = GetCurrentProcessId();
|
||||||
HANDLE hProcess;
|
HANDLE hProcess;
|
||||||
PROCESS_MEMORY_COUNTERS pmc;
|
PROCESS_MEMORY_COUNTERS pmc;
|
||||||
std::string Ret;
|
std::string Ret;
|
||||||
|
|
||||||
// Print information about the memory usage of the process.
|
// Print information about the memory usage of the process.
|
||||||
|
|
||||||
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processID);
|
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processID);
|
||||||
if (NULL == hProcess) return "MemUsage Error";
|
if (NULL == hProcess) return "MemUsage Error";
|
||||||
|
|
||||||
if (GetProcessMemoryInfo(hProcess, &pmc, sizeof(pmc)))
|
if (GetProcessMemoryInfo(hProcess, &pmc, sizeof(pmc)))
|
||||||
Ret = StringFromFormat("%s K", ThousandSeparate(pmc.WorkingSetSize / 1024, 7).c_str());
|
Ret = StringFromFormat("%s K", ThousandSeparate(pmc.WorkingSetSize / 1024, 7).c_str());
|
||||||
|
|
||||||
CloseHandle(hProcess);
|
CloseHandle(hProcess);
|
||||||
return Ret;
|
return Ret;
|
||||||
#else
|
#else
|
||||||
return "";
|
return "";
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,20 +18,20 @@
|
||||||
// This function might change the error code.
|
// This function might change the error code.
|
||||||
const char* GetLastErrorMsg()
|
const char* GetLastErrorMsg()
|
||||||
{
|
{
|
||||||
static const size_t buff_size = 255;
|
static const size_t buff_size = 255;
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
static __declspec(thread) char err_str[buff_size] = {};
|
static __declspec(thread) char err_str[buff_size] = {};
|
||||||
|
|
||||||
FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(),
|
FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(),
|
||||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||||
err_str, buff_size, NULL);
|
err_str, buff_size, NULL);
|
||||||
#else
|
#else
|
||||||
static __thread char err_str[buff_size] = {};
|
static __thread char err_str[buff_size] = {};
|
||||||
|
|
||||||
// Thread safe (XSI-compliant)
|
// Thread safe (XSI-compliant)
|
||||||
strerror_r(errno, err_str, buff_size);
|
strerror_r(errno, err_str, buff_size);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return err_str;
|
return err_str;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,90 +18,90 @@ static StringTranslator str_translator = DefaultStringTranslator;
|
||||||
// wxWidgets is enabled we will use wxMsgAlert() that is defined in Main.cpp
|
// wxWidgets is enabled we will use wxMsgAlert() that is defined in Main.cpp
|
||||||
void RegisterMsgAlertHandler(MsgAlertHandler handler)
|
void RegisterMsgAlertHandler(MsgAlertHandler handler)
|
||||||
{
|
{
|
||||||
msg_handler = handler;
|
msg_handler = handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Select translation function. For wxWidgets use wxStringTranslator in Main.cpp
|
// Select translation function. For wxWidgets use wxStringTranslator in Main.cpp
|
||||||
void RegisterStringTranslator(StringTranslator translator)
|
void RegisterStringTranslator(StringTranslator translator)
|
||||||
{
|
{
|
||||||
str_translator = translator;
|
str_translator = translator;
|
||||||
}
|
}
|
||||||
|
|
||||||
// enable/disable the alert handler
|
// enable/disable the alert handler
|
||||||
void SetEnableAlert(bool enable)
|
void SetEnableAlert(bool enable)
|
||||||
{
|
{
|
||||||
AlertEnabled = enable;
|
AlertEnabled = enable;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is the first stop for gui alerts where the log is updated and the
|
// This is the first stop for gui alerts where the log is updated and the
|
||||||
// correct window is shown
|
// correct window is shown
|
||||||
bool MsgAlert(bool yes_no, int Style, const char* format, ...)
|
bool MsgAlert(bool yes_no, int Style, const char* format, ...)
|
||||||
{
|
{
|
||||||
// Read message and write it to the log
|
// Read message and write it to the log
|
||||||
std::string caption;
|
std::string caption;
|
||||||
char buffer[2048];
|
char buffer[2048];
|
||||||
|
|
||||||
static std::string info_caption;
|
static std::string info_caption;
|
||||||
static std::string warn_caption;
|
static std::string warn_caption;
|
||||||
static std::string ques_caption;
|
static std::string ques_caption;
|
||||||
static std::string crit_caption;
|
static std::string crit_caption;
|
||||||
|
|
||||||
if (!info_caption.length())
|
if (!info_caption.length())
|
||||||
{
|
{
|
||||||
info_caption = str_translator(_trans("Information"));
|
info_caption = str_translator(_trans("Information"));
|
||||||
ques_caption = str_translator(_trans("Question"));
|
ques_caption = str_translator(_trans("Question"));
|
||||||
warn_caption = str_translator(_trans("Warning"));
|
warn_caption = str_translator(_trans("Warning"));
|
||||||
crit_caption = str_translator(_trans("Critical"));
|
crit_caption = str_translator(_trans("Critical"));
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(Style)
|
switch(Style)
|
||||||
{
|
{
|
||||||
case INFORMATION:
|
case INFORMATION:
|
||||||
caption = info_caption;
|
caption = info_caption;
|
||||||
break;
|
break;
|
||||||
case QUESTION:
|
case QUESTION:
|
||||||
caption = ques_caption;
|
caption = ques_caption;
|
||||||
break;
|
break;
|
||||||
case WARNING:
|
case WARNING:
|
||||||
caption = warn_caption;
|
caption = warn_caption;
|
||||||
break;
|
break;
|
||||||
case CRITICAL:
|
case CRITICAL:
|
||||||
caption = crit_caption;
|
caption = crit_caption;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, format);
|
va_start(args, format);
|
||||||
CharArrayFromFormatV(buffer, sizeof(buffer)-1, str_translator(format).c_str(), args);
|
CharArrayFromFormatV(buffer, sizeof(buffer)-1, str_translator(format).c_str(), args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
||||||
ERROR_LOG(MASTER_LOG, "%s: %s", caption.c_str(), buffer);
|
ERROR_LOG(MASTER_LOG, "%s: %s", caption.c_str(), buffer);
|
||||||
|
|
||||||
// Don't ignore questions, especially AskYesNo, PanicYesNo could be ignored
|
// Don't ignore questions, especially AskYesNo, PanicYesNo could be ignored
|
||||||
if (msg_handler && (AlertEnabled || Style == QUESTION || Style == CRITICAL))
|
if (msg_handler && (AlertEnabled || Style == QUESTION || Style == CRITICAL))
|
||||||
return msg_handler(caption.c_str(), buffer, yes_no, Style);
|
return msg_handler(caption.c_str(), buffer, yes_no, Style);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Default non library dependent panic alert
|
// Default non library dependent panic alert
|
||||||
bool DefaultMsgHandler(const char* caption, const char* text, bool yes_no, int Style)
|
bool DefaultMsgHandler(const char* caption, const char* text, bool yes_no, int Style)
|
||||||
{
|
{
|
||||||
//#ifdef _WIN32
|
//#ifdef _WIN32
|
||||||
// int STYLE = MB_ICONINFORMATION;
|
// int STYLE = MB_ICONINFORMATION;
|
||||||
// if (Style == QUESTION) STYLE = MB_ICONQUESTION;
|
// if (Style == QUESTION) STYLE = MB_ICONQUESTION;
|
||||||
// if (Style == WARNING) STYLE = MB_ICONWARNING;
|
// if (Style == WARNING) STYLE = MB_ICONWARNING;
|
||||||
//
|
//
|
||||||
// return IDYES == MessageBox(0, UTF8ToTStr(text).c_str(), UTF8ToTStr(caption).c_str(), STYLE | (yes_no ? MB_YESNO : MB_OK));
|
// return IDYES == MessageBox(0, UTF8ToTStr(text).c_str(), UTF8ToTStr(caption).c_str(), STYLE | (yes_no ? MB_YESNO : MB_OK));
|
||||||
//#else
|
//#else
|
||||||
printf("%s\n", text);
|
printf("%s\n", text);
|
||||||
return true;
|
return true;
|
||||||
//#endif
|
//#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Default (non) translator
|
// Default (non) translator
|
||||||
std::string DefaultStringTranslator(const char* text)
|
std::string DefaultStringTranslator(const char* text)
|
||||||
{
|
{
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,10 +10,10 @@
|
||||||
// Message alerts
|
// Message alerts
|
||||||
enum MSG_TYPE
|
enum MSG_TYPE
|
||||||
{
|
{
|
||||||
INFORMATION,
|
INFORMATION,
|
||||||
QUESTION,
|
QUESTION,
|
||||||
WARNING,
|
WARNING,
|
||||||
CRITICAL
|
CRITICAL
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef bool (*MsgAlertHandler)(const char* caption, const char* text,
|
typedef bool (*MsgAlertHandler)(const char* caption, const char* text,
|
||||||
|
@ -25,49 +25,49 @@ void RegisterStringTranslator(StringTranslator translator);
|
||||||
|
|
||||||
extern bool MsgAlert(bool yes_no, int Style, const char* format, ...)
|
extern bool MsgAlert(bool yes_no, int Style, const char* format, ...)
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
__attribute__((format(printf, 3, 4)))
|
__attribute__((format(printf, 3, 4)))
|
||||||
#endif
|
#endif
|
||||||
;
|
;
|
||||||
void SetEnableAlert(bool enable);
|
void SetEnableAlert(bool enable);
|
||||||
|
|
||||||
#ifndef GEKKO
|
#ifndef GEKKO
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#define SuccessAlert(format, ...) MsgAlert(false, INFORMATION, format, __VA_ARGS__)
|
#define SuccessAlert(format, ...) MsgAlert(false, INFORMATION, format, __VA_ARGS__)
|
||||||
#define PanicAlert(format, ...) MsgAlert(false, WARNING, format, __VA_ARGS__)
|
#define PanicAlert(format, ...) MsgAlert(false, WARNING, format, __VA_ARGS__)
|
||||||
#define PanicYesNo(format, ...) MsgAlert(true, WARNING, format, __VA_ARGS__)
|
#define PanicYesNo(format, ...) MsgAlert(true, WARNING, format, __VA_ARGS__)
|
||||||
#define AskYesNo(format, ...) MsgAlert(true, QUESTION, format, __VA_ARGS__)
|
#define AskYesNo(format, ...) MsgAlert(true, QUESTION, format, __VA_ARGS__)
|
||||||
#define CriticalAlert(format, ...) MsgAlert(false, CRITICAL, format, __VA_ARGS__)
|
#define CriticalAlert(format, ...) MsgAlert(false, CRITICAL, format, __VA_ARGS__)
|
||||||
// Use these macros (that do the same thing) if the message should be translated.
|
// Use these macros (that do the same thing) if the message should be translated.
|
||||||
#define SuccessAlertT(format, ...) MsgAlert(false, INFORMATION, format, __VA_ARGS__)
|
#define SuccessAlertT(format, ...) MsgAlert(false, INFORMATION, format, __VA_ARGS__)
|
||||||
#define PanicAlertT(format, ...) MsgAlert(false, WARNING, format, __VA_ARGS__)
|
#define PanicAlertT(format, ...) MsgAlert(false, WARNING, format, __VA_ARGS__)
|
||||||
#define PanicYesNoT(format, ...) MsgAlert(true, WARNING, format, __VA_ARGS__)
|
#define PanicYesNoT(format, ...) MsgAlert(true, WARNING, format, __VA_ARGS__)
|
||||||
#define AskYesNoT(format, ...) MsgAlert(true, QUESTION, format, __VA_ARGS__)
|
#define AskYesNoT(format, ...) MsgAlert(true, QUESTION, format, __VA_ARGS__)
|
||||||
#define CriticalAlertT(format, ...) MsgAlert(false, CRITICAL, format, __VA_ARGS__)
|
#define CriticalAlertT(format, ...) MsgAlert(false, CRITICAL, format, __VA_ARGS__)
|
||||||
#else
|
#else
|
||||||
#define SuccessAlert(format, ...) MsgAlert(false, INFORMATION, format, ##__VA_ARGS__)
|
#define SuccessAlert(format, ...) MsgAlert(false, INFORMATION, format, ##__VA_ARGS__)
|
||||||
#define PanicAlert(format, ...) MsgAlert(false, WARNING, format, ##__VA_ARGS__)
|
#define PanicAlert(format, ...) MsgAlert(false, WARNING, format, ##__VA_ARGS__)
|
||||||
#define PanicYesNo(format, ...) MsgAlert(true, WARNING, format, ##__VA_ARGS__)
|
#define PanicYesNo(format, ...) MsgAlert(true, WARNING, format, ##__VA_ARGS__)
|
||||||
#define AskYesNo(format, ...) MsgAlert(true, QUESTION, format, ##__VA_ARGS__)
|
#define AskYesNo(format, ...) MsgAlert(true, QUESTION, format, ##__VA_ARGS__)
|
||||||
#define CriticalAlert(format, ...) MsgAlert(false, CRITICAL, format, ##__VA_ARGS__)
|
#define CriticalAlert(format, ...) MsgAlert(false, CRITICAL, format, ##__VA_ARGS__)
|
||||||
// Use these macros (that do the same thing) if the message should be translated.
|
// Use these macros (that do the same thing) if the message should be translated.
|
||||||
#define SuccessAlertT(format, ...) MsgAlert(false, INFORMATION, format, ##__VA_ARGS__)
|
#define SuccessAlertT(format, ...) MsgAlert(false, INFORMATION, format, ##__VA_ARGS__)
|
||||||
#define PanicAlertT(format, ...) MsgAlert(false, WARNING, format, ##__VA_ARGS__)
|
#define PanicAlertT(format, ...) MsgAlert(false, WARNING, format, ##__VA_ARGS__)
|
||||||
#define PanicYesNoT(format, ...) MsgAlert(true, WARNING, format, ##__VA_ARGS__)
|
#define PanicYesNoT(format, ...) MsgAlert(true, WARNING, format, ##__VA_ARGS__)
|
||||||
#define AskYesNoT(format, ...) MsgAlert(true, QUESTION, format, ##__VA_ARGS__)
|
#define AskYesNoT(format, ...) MsgAlert(true, QUESTION, format, ##__VA_ARGS__)
|
||||||
#define CriticalAlertT(format, ...) MsgAlert(false, CRITICAL, format, ##__VA_ARGS__)
|
#define CriticalAlertT(format, ...) MsgAlert(false, CRITICAL, format, ##__VA_ARGS__)
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
// GEKKO
|
// GEKKO
|
||||||
#define SuccessAlert(format, ...) ;
|
#define SuccessAlert(format, ...) ;
|
||||||
#define PanicAlert(format, ...) ;
|
#define PanicAlert(format, ...) ;
|
||||||
#define PanicYesNo(format, ...) ;
|
#define PanicYesNo(format, ...) ;
|
||||||
#define AskYesNo(format, ...) ;
|
#define AskYesNo(format, ...) ;
|
||||||
#define CriticalAlert(format, ...) ;
|
#define CriticalAlert(format, ...) ;
|
||||||
#define SuccessAlertT(format, ...) ;
|
#define SuccessAlertT(format, ...) ;
|
||||||
#define PanicAlertT(format, ...) ;
|
#define PanicAlertT(format, ...) ;
|
||||||
#define PanicYesNoT(format, ...) ;
|
#define PanicYesNoT(format, ...) ;
|
||||||
#define AskYesNoT(format, ...) ;
|
#define AskYesNoT(format, ...) ;
|
||||||
#define CriticalAlertT(format, ...) ;
|
#define CriticalAlertT(format, ...) ;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // _MSGHANDLER_H_
|
#endif // _MSGHANDLER_H_
|
||||||
|
|
|
@ -76,9 +76,9 @@
|
||||||
#define EMU_FASTCALL __fastcall
|
#define EMU_FASTCALL __fastcall
|
||||||
|
|
||||||
inline struct tm* localtime_r(const time_t *clock, struct tm *result) {
|
inline struct tm* localtime_r(const time_t *clock, struct tm *result) {
|
||||||
if (localtime_s(result, clock) == 0)
|
if (localtime_s(result, clock) == 0)
|
||||||
return result;
|
return result;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#ifndef CONDITION_VARIABLE_H_
|
#ifndef CONDITION_VARIABLE_H_
|
||||||
#define CONDITION_VARIABLE_H_
|
#define CONDITION_VARIABLE_H_
|
||||||
|
|
||||||
#define GCC_VER(x,y,z) ((x) * 10000 + (y) * 100 + (z))
|
#define GCC_VER(x,y,z) ((x) * 10000 + (y) * 100 + (z))
|
||||||
#define GCC_VERSION GCC_VER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
|
#define GCC_VERSION GCC_VER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
|
||||||
|
|
||||||
#ifndef __has_include
|
#ifndef __has_include
|
||||||
|
@ -47,121 +47,121 @@ namespace std
|
||||||
class condition_variable
|
class condition_variable
|
||||||
{
|
{
|
||||||
#if defined(_WIN32) && defined(USE_CONDITION_VARIABLES)
|
#if defined(_WIN32) && defined(USE_CONDITION_VARIABLES)
|
||||||
typedef CONDITION_VARIABLE native_type;
|
typedef CONDITION_VARIABLE native_type;
|
||||||
#elif defined(_WIN32)
|
#elif defined(_WIN32)
|
||||||
typedef HANDLE native_type;
|
typedef HANDLE native_type;
|
||||||
#else
|
#else
|
||||||
typedef pthread_cond_t native_type;
|
typedef pthread_cond_t native_type;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
#ifdef USE_EVENTS
|
#ifdef USE_EVENTS
|
||||||
typedef native_type native_handle_type;
|
typedef native_type native_handle_type;
|
||||||
#else
|
#else
|
||||||
typedef native_type* native_handle_type;
|
typedef native_type* native_handle_type;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
condition_variable()
|
condition_variable()
|
||||||
{
|
{
|
||||||
#if defined(_WIN32) && defined(USE_CONDITION_VARIABLES)
|
#if defined(_WIN32) && defined(USE_CONDITION_VARIABLES)
|
||||||
InitializeConditionVariable(&m_handle);
|
InitializeConditionVariable(&m_handle);
|
||||||
#elif defined(_WIN32)
|
#elif defined(_WIN32)
|
||||||
m_handle = CreateEvent(NULL, false, false, NULL);
|
m_handle = CreateEvent(NULL, false, false, NULL);
|
||||||
#else
|
#else
|
||||||
pthread_cond_init(&m_handle, NULL);
|
pthread_cond_init(&m_handle, NULL);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
~condition_variable()
|
~condition_variable()
|
||||||
{
|
{
|
||||||
#if defined(_WIN32) && !defined(USE_CONDITION_VARIABLES)
|
#if defined(_WIN32) && !defined(USE_CONDITION_VARIABLES)
|
||||||
CloseHandle(m_handle);
|
CloseHandle(m_handle);
|
||||||
#elif !defined(_WIN32)
|
#elif !defined(_WIN32)
|
||||||
pthread_cond_destroy(&m_handle);
|
pthread_cond_destroy(&m_handle);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
condition_variable(const condition_variable&) /*= delete*/;
|
condition_variable(const condition_variable&) /*= delete*/;
|
||||||
condition_variable& operator=(const condition_variable&) /*= delete*/;
|
condition_variable& operator=(const condition_variable&) /*= delete*/;
|
||||||
|
|
||||||
void notify_one()
|
void notify_one()
|
||||||
{
|
{
|
||||||
#if defined(_WIN32) && defined(USE_CONDITION_VARIABLES)
|
#if defined(_WIN32) && defined(USE_CONDITION_VARIABLES)
|
||||||
WakeConditionVariable(&m_handle);
|
WakeConditionVariable(&m_handle);
|
||||||
#elif defined(_WIN32)
|
#elif defined(_WIN32)
|
||||||
SetEvent(m_handle);
|
SetEvent(m_handle);
|
||||||
#else
|
#else
|
||||||
pthread_cond_signal(&m_handle);
|
pthread_cond_signal(&m_handle);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void notify_all()
|
void notify_all()
|
||||||
{
|
{
|
||||||
#if defined(_WIN32) && defined(USE_CONDITION_VARIABLES)
|
#if defined(_WIN32) && defined(USE_CONDITION_VARIABLES)
|
||||||
WakeAllConditionVariable(&m_handle);
|
WakeAllConditionVariable(&m_handle);
|
||||||
#elif defined(_WIN32)
|
#elif defined(_WIN32)
|
||||||
// TODO: broken
|
// TODO: broken
|
||||||
SetEvent(m_handle);
|
SetEvent(m_handle);
|
||||||
#else
|
#else
|
||||||
pthread_cond_broadcast(&m_handle);
|
pthread_cond_broadcast(&m_handle);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void wait(unique_lock<mutex>& lock)
|
void wait(unique_lock<mutex>& lock)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#ifdef USE_SRWLOCKS
|
#ifdef USE_SRWLOCKS
|
||||||
SleepConditionVariableSRW(&m_handle, lock.mutex()->native_handle(), INFINITE, 0);
|
SleepConditionVariableSRW(&m_handle, lock.mutex()->native_handle(), INFINITE, 0);
|
||||||
#elif defined(USE_CONDITION_VARIABLES)
|
#elif defined(USE_CONDITION_VARIABLES)
|
||||||
SleepConditionVariableCS(&m_handle, lock.mutex()->native_handle(), INFINITE);
|
SleepConditionVariableCS(&m_handle, lock.mutex()->native_handle(), INFINITE);
|
||||||
#else
|
#else
|
||||||
// TODO: broken, the unlock and wait need to be atomic
|
// TODO: broken, the unlock and wait need to be atomic
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
WaitForSingleObject(m_handle, INFINITE);
|
WaitForSingleObject(m_handle, INFINITE);
|
||||||
lock.lock();
|
lock.lock();
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
pthread_cond_wait(&m_handle, lock.mutex()->native_handle());
|
pthread_cond_wait(&m_handle, lock.mutex()->native_handle());
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Predicate>
|
template <class Predicate>
|
||||||
void wait(unique_lock<mutex>& lock, Predicate pred)
|
void wait(unique_lock<mutex>& lock, Predicate pred)
|
||||||
{
|
{
|
||||||
while (!pred())
|
while (!pred())
|
||||||
wait(lock);
|
wait(lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
//template <class Clock, class Duration>
|
//template <class Clock, class Duration>
|
||||||
//cv_status wait_until(unique_lock<mutex>& lock,
|
//cv_status wait_until(unique_lock<mutex>& lock,
|
||||||
// const chrono::time_point<Clock, Duration>& abs_time);
|
// const chrono::time_point<Clock, Duration>& abs_time);
|
||||||
|
|
||||||
//template <class Clock, class Duration, class Predicate>
|
//template <class Clock, class Duration, class Predicate>
|
||||||
// bool wait_until(unique_lock<mutex>& lock,
|
// bool wait_until(unique_lock<mutex>& lock,
|
||||||
// const chrono::time_point<Clock, Duration>& abs_time,
|
// const chrono::time_point<Clock, Duration>& abs_time,
|
||||||
// Predicate pred);
|
// Predicate pred);
|
||||||
|
|
||||||
//template <class Rep, class Period>
|
//template <class Rep, class Period>
|
||||||
//cv_status wait_for(unique_lock<mutex>& lock,
|
//cv_status wait_for(unique_lock<mutex>& lock,
|
||||||
// const chrono::duration<Rep, Period>& rel_time);
|
// const chrono::duration<Rep, Period>& rel_time);
|
||||||
|
|
||||||
//template <class Rep, class Period, class Predicate>
|
//template <class Rep, class Period, class Predicate>
|
||||||
// bool wait_for(unique_lock<mutex>& lock,
|
// bool wait_for(unique_lock<mutex>& lock,
|
||||||
// const chrono::duration<Rep, Period>& rel_time,
|
// const chrono::duration<Rep, Period>& rel_time,
|
||||||
// Predicate pred);
|
// Predicate pred);
|
||||||
|
|
||||||
native_handle_type native_handle()
|
native_handle_type native_handle()
|
||||||
{
|
{
|
||||||
#ifdef USE_EVENTS
|
#ifdef USE_EVENTS
|
||||||
return m_handle;
|
return m_handle;
|
||||||
#else
|
#else
|
||||||
return &m_handle;
|
return &m_handle;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
native_type m_handle;
|
native_type m_handle;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#ifndef MUTEX_H_
|
#ifndef MUTEX_H_
|
||||||
#define MUTEX_H_
|
#define MUTEX_H_
|
||||||
|
|
||||||
#define GCC_VER(x,y,z) ((x) * 10000 + (y) * 100 + (z))
|
#define GCC_VER(x,y,z) ((x) * 10000 + (y) * 100 + (z))
|
||||||
#define GCC_VERSION GCC_VER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
|
#define GCC_VERSION GCC_VER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
|
||||||
|
|
||||||
#ifndef __has_include
|
#ifndef __has_include
|
||||||
|
@ -46,72 +46,72 @@ namespace std
|
||||||
class recursive_mutex
|
class recursive_mutex
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
typedef CRITICAL_SECTION native_type;
|
typedef CRITICAL_SECTION native_type;
|
||||||
#else
|
#else
|
||||||
typedef pthread_mutex_t native_type;
|
typedef pthread_mutex_t native_type;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef native_type* native_handle_type;
|
typedef native_type* native_handle_type;
|
||||||
|
|
||||||
recursive_mutex(const recursive_mutex&) /*= delete*/;
|
recursive_mutex(const recursive_mutex&) /*= delete*/;
|
||||||
recursive_mutex& operator=(const recursive_mutex&) /*= delete*/;
|
recursive_mutex& operator=(const recursive_mutex&) /*= delete*/;
|
||||||
|
|
||||||
recursive_mutex()
|
recursive_mutex()
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
InitializeCriticalSection(&m_handle);
|
InitializeCriticalSection(&m_handle);
|
||||||
#else
|
#else
|
||||||
pthread_mutexattr_t attr;
|
pthread_mutexattr_t attr;
|
||||||
pthread_mutexattr_init(&attr);
|
pthread_mutexattr_init(&attr);
|
||||||
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
|
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
|
||||||
pthread_mutex_init(&m_handle, &attr);
|
pthread_mutex_init(&m_handle, &attr);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
~recursive_mutex()
|
~recursive_mutex()
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
DeleteCriticalSection(&m_handle);
|
DeleteCriticalSection(&m_handle);
|
||||||
#else
|
#else
|
||||||
pthread_mutex_destroy(&m_handle);
|
pthread_mutex_destroy(&m_handle);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void lock()
|
void lock()
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
EnterCriticalSection(&m_handle);
|
EnterCriticalSection(&m_handle);
|
||||||
#else
|
#else
|
||||||
pthread_mutex_lock(&m_handle);
|
pthread_mutex_lock(&m_handle);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void unlock()
|
void unlock()
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
LeaveCriticalSection(&m_handle);
|
LeaveCriticalSection(&m_handle);
|
||||||
#else
|
#else
|
||||||
pthread_mutex_unlock(&m_handle);
|
pthread_mutex_unlock(&m_handle);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool try_lock()
|
bool try_lock()
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
return (0 != TryEnterCriticalSection(&m_handle));
|
return (0 != TryEnterCriticalSection(&m_handle));
|
||||||
#else
|
#else
|
||||||
return !pthread_mutex_trylock(&m_handle);
|
return !pthread_mutex_trylock(&m_handle);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
native_handle_type native_handle()
|
native_handle_type native_handle()
|
||||||
{
|
{
|
||||||
return &m_handle;
|
return &m_handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
native_type m_handle;
|
native_type m_handle;
|
||||||
};
|
};
|
||||||
|
|
||||||
#if !defined(_WIN32) || defined(USE_SRWLOCKS)
|
#if !defined(_WIN32) || defined(USE_SRWLOCKS)
|
||||||
|
@ -119,74 +119,74 @@ private:
|
||||||
class mutex
|
class mutex
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
typedef SRWLOCK native_type;
|
typedef SRWLOCK native_type;
|
||||||
#else
|
#else
|
||||||
typedef pthread_mutex_t native_type;
|
typedef pthread_mutex_t native_type;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef native_type* native_handle_type;
|
typedef native_type* native_handle_type;
|
||||||
|
|
||||||
mutex(const mutex&) /*= delete*/;
|
mutex(const mutex&) /*= delete*/;
|
||||||
mutex& operator=(const mutex&) /*= delete*/;
|
mutex& operator=(const mutex&) /*= delete*/;
|
||||||
|
|
||||||
mutex()
|
mutex()
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
InitializeSRWLock(&m_handle);
|
InitializeSRWLock(&m_handle);
|
||||||
#else
|
#else
|
||||||
pthread_mutex_init(&m_handle, NULL);
|
pthread_mutex_init(&m_handle, NULL);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
~mutex()
|
~mutex()
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#else
|
#else
|
||||||
pthread_mutex_destroy(&m_handle);
|
pthread_mutex_destroy(&m_handle);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void lock()
|
void lock()
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
AcquireSRWLockExclusive(&m_handle);
|
AcquireSRWLockExclusive(&m_handle);
|
||||||
#else
|
#else
|
||||||
pthread_mutex_lock(&m_handle);
|
pthread_mutex_lock(&m_handle);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void unlock()
|
void unlock()
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
ReleaseSRWLockExclusive(&m_handle);
|
ReleaseSRWLockExclusive(&m_handle);
|
||||||
#else
|
#else
|
||||||
pthread_mutex_unlock(&m_handle);
|
pthread_mutex_unlock(&m_handle);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool try_lock()
|
bool try_lock()
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
// XXX TryAcquireSRWLockExclusive requires Windows 7!
|
// XXX TryAcquireSRWLockExclusive requires Windows 7!
|
||||||
// return (0 != TryAcquireSRWLockExclusive(&m_handle));
|
// return (0 != TryAcquireSRWLockExclusive(&m_handle));
|
||||||
return false;
|
return false;
|
||||||
#else
|
#else
|
||||||
return !pthread_mutex_trylock(&m_handle);
|
return !pthread_mutex_trylock(&m_handle);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
native_handle_type native_handle()
|
native_handle_type native_handle()
|
||||||
{
|
{
|
||||||
return &m_handle;
|
return &m_handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
native_type m_handle;
|
native_type m_handle;
|
||||||
};
|
};
|
||||||
|
|
||||||
#else
|
#else
|
||||||
typedef recursive_mutex mutex; // just use CriticalSections
|
typedef recursive_mutex mutex; // just use CriticalSections
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -198,165 +198,165 @@ template <class Mutex>
|
||||||
class lock_guard
|
class lock_guard
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef Mutex mutex_type;
|
typedef Mutex mutex_type;
|
||||||
|
|
||||||
explicit lock_guard(mutex_type& m)
|
explicit lock_guard(mutex_type& m)
|
||||||
: pm(m)
|
: pm(m)
|
||||||
{
|
{
|
||||||
m.lock();
|
m.lock();
|
||||||
}
|
}
|
||||||
|
|
||||||
lock_guard(mutex_type& m, adopt_lock_t)
|
lock_guard(mutex_type& m, adopt_lock_t)
|
||||||
: pm(m)
|
: pm(m)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
~lock_guard()
|
~lock_guard()
|
||||||
{
|
{
|
||||||
pm.unlock();
|
pm.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
lock_guard(lock_guard const&) /*= delete*/;
|
lock_guard(lock_guard const&) /*= delete*/;
|
||||||
lock_guard& operator=(lock_guard const&) /*= delete*/;
|
lock_guard& operator=(lock_guard const&) /*= delete*/;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
mutex_type& pm;
|
mutex_type& pm;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class Mutex>
|
template <class Mutex>
|
||||||
class unique_lock
|
class unique_lock
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef Mutex mutex_type;
|
typedef Mutex mutex_type;
|
||||||
|
|
||||||
unique_lock()
|
unique_lock()
|
||||||
: pm(NULL), owns(false)
|
: pm(NULL), owns(false)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
/*explicit*/ unique_lock(mutex_type& m)
|
/*explicit*/ unique_lock(mutex_type& m)
|
||||||
: pm(&m), owns(true)
|
: pm(&m), owns(true)
|
||||||
{
|
{
|
||||||
m.lock();
|
m.lock();
|
||||||
}
|
}
|
||||||
|
|
||||||
unique_lock(mutex_type& m, defer_lock_t)
|
unique_lock(mutex_type& m, defer_lock_t)
|
||||||
: pm(&m), owns(false)
|
: pm(&m), owns(false)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
unique_lock(mutex_type& m, try_to_lock_t)
|
unique_lock(mutex_type& m, try_to_lock_t)
|
||||||
: pm(&m), owns(m.try_lock())
|
: pm(&m), owns(m.try_lock())
|
||||||
{}
|
{}
|
||||||
|
|
||||||
unique_lock(mutex_type& m, adopt_lock_t)
|
unique_lock(mutex_type& m, adopt_lock_t)
|
||||||
: pm(&m), owns(true)
|
: pm(&m), owns(true)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
//template <class Clock, class Duration>
|
//template <class Clock, class Duration>
|
||||||
//unique_lock(mutex_type& m, const chrono::time_point<Clock, Duration>& abs_time);
|
//unique_lock(mutex_type& m, const chrono::time_point<Clock, Duration>& abs_time);
|
||||||
|
|
||||||
//template <class Rep, class Period>
|
//template <class Rep, class Period>
|
||||||
//unique_lock(mutex_type& m, const chrono::duration<Rep, Period>& rel_time);
|
//unique_lock(mutex_type& m, const chrono::duration<Rep, Period>& rel_time);
|
||||||
|
|
||||||
~unique_lock()
|
~unique_lock()
|
||||||
{
|
{
|
||||||
if (owns_lock())
|
if (owns_lock())
|
||||||
mutex()->unlock();
|
mutex()->unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_RVALUE_REFERENCES
|
#ifdef USE_RVALUE_REFERENCES
|
||||||
unique_lock& operator=(const unique_lock&) /*= delete*/;
|
unique_lock& operator=(const unique_lock&) /*= delete*/;
|
||||||
|
|
||||||
unique_lock& operator=(unique_lock&& other)
|
unique_lock& operator=(unique_lock&& other)
|
||||||
{
|
{
|
||||||
#else
|
#else
|
||||||
unique_lock& operator=(const unique_lock& u)
|
unique_lock& operator=(const unique_lock& u)
|
||||||
{
|
{
|
||||||
// ugly const_cast to get around lack of rvalue references
|
// ugly const_cast to get around lack of rvalue references
|
||||||
unique_lock& other = const_cast<unique_lock&>(u);
|
unique_lock& other = const_cast<unique_lock&>(u);
|
||||||
#endif
|
#endif
|
||||||
swap(other);
|
swap(other);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_RVALUE_REFERENCES
|
#ifdef USE_RVALUE_REFERENCES
|
||||||
unique_lock(const unique_lock&) /*= delete*/;
|
unique_lock(const unique_lock&) /*= delete*/;
|
||||||
|
|
||||||
unique_lock(unique_lock&& other)
|
unique_lock(unique_lock&& other)
|
||||||
: pm(NULL), owns(false)
|
: pm(NULL), owns(false)
|
||||||
{
|
{
|
||||||
#else
|
#else
|
||||||
unique_lock(const unique_lock& u)
|
unique_lock(const unique_lock& u)
|
||||||
: pm(NULL), owns(false)
|
: pm(NULL), owns(false)
|
||||||
{
|
{
|
||||||
// ugly const_cast to get around lack of rvalue references
|
// ugly const_cast to get around lack of rvalue references
|
||||||
unique_lock& other = const_cast<unique_lock&>(u);
|
unique_lock& other = const_cast<unique_lock&>(u);
|
||||||
#endif
|
#endif
|
||||||
swap(other);
|
swap(other);
|
||||||
}
|
}
|
||||||
|
|
||||||
void lock()
|
void lock()
|
||||||
{
|
{
|
||||||
mutex()->lock();
|
mutex()->lock();
|
||||||
owns = true;
|
owns = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool try_lock()
|
bool try_lock()
|
||||||
{
|
{
|
||||||
owns = mutex()->try_lock();
|
owns = mutex()->try_lock();
|
||||||
return owns;
|
return owns;
|
||||||
}
|
}
|
||||||
|
|
||||||
//template <class Rep, class Period>
|
//template <class Rep, class Period>
|
||||||
//bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
|
//bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
|
||||||
//template <class Clock, class Duration>
|
//template <class Clock, class Duration>
|
||||||
//bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
|
//bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
|
||||||
|
|
||||||
void unlock()
|
void unlock()
|
||||||
{
|
{
|
||||||
mutex()->unlock();
|
mutex()->unlock();
|
||||||
owns = false;
|
owns = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void swap(unique_lock& u)
|
void swap(unique_lock& u)
|
||||||
{
|
{
|
||||||
std::swap(pm, u.pm);
|
std::swap(pm, u.pm);
|
||||||
std::swap(owns, u.owns);
|
std::swap(owns, u.owns);
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_type* release()
|
mutex_type* release()
|
||||||
{
|
{
|
||||||
auto const ret = mutex();
|
auto const ret = mutex();
|
||||||
|
|
||||||
pm = NULL;
|
pm = NULL;
|
||||||
owns = false;
|
owns = false;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool owns_lock() const
|
bool owns_lock() const
|
||||||
{
|
{
|
||||||
return owns;
|
return owns;
|
||||||
}
|
}
|
||||||
|
|
||||||
//explicit operator bool () const
|
//explicit operator bool () const
|
||||||
//{
|
//{
|
||||||
// return owns_lock();
|
// return owns_lock();
|
||||||
//}
|
//}
|
||||||
|
|
||||||
mutex_type* mutex() const
|
mutex_type* mutex() const
|
||||||
{
|
{
|
||||||
return pm;
|
return pm;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
mutex_type* pm;
|
mutex_type* pm;
|
||||||
bool owns;
|
bool owns;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class Mutex>
|
template <class Mutex>
|
||||||
void swap(unique_lock<Mutex>& x, unique_lock<Mutex>& y)
|
void swap(unique_lock<Mutex>& x, unique_lock<Mutex>& y)
|
||||||
{
|
{
|
||||||
x.swap(y);
|
x.swap(y);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#ifndef STD_THREAD_H_
|
#ifndef STD_THREAD_H_
|
||||||
#define STD_THREAD_H_
|
#define STD_THREAD_H_
|
||||||
|
|
||||||
#define GCC_VER(x,y,z) ((x) * 10000 + (y) * 100 + (z))
|
#define GCC_VER(x,y,z) ((x) * 10000 + (y) * 100 + (z))
|
||||||
#define GCC_VERSION GCC_VER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
|
#define GCC_VERSION GCC_VER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
|
||||||
|
|
||||||
#ifndef __has_include
|
#ifndef __has_include
|
||||||
|
@ -77,209 +77,209 @@ namespace std
|
||||||
class thread
|
class thread
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef THREAD_HANDLE native_handle_type;
|
typedef THREAD_HANDLE native_handle_type;
|
||||||
|
|
||||||
class id
|
class id
|
||||||
{
|
{
|
||||||
friend class thread;
|
friend class thread;
|
||||||
public:
|
public:
|
||||||
id() : m_thread(0) {}
|
id() : m_thread(0) {}
|
||||||
id(THREAD_ID _id) : m_thread(_id) {}
|
id(THREAD_ID _id) : m_thread(_id) {}
|
||||||
|
|
||||||
bool operator==(const id& rhs) const
|
bool operator==(const id& rhs) const
|
||||||
{
|
{
|
||||||
return m_thread == rhs.m_thread;
|
return m_thread == rhs.m_thread;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator!=(const id& rhs) const
|
bool operator!=(const id& rhs) const
|
||||||
{
|
{
|
||||||
return !(*this == rhs);
|
return !(*this == rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator<(const id& rhs) const
|
bool operator<(const id& rhs) const
|
||||||
{
|
{
|
||||||
return m_thread < rhs.m_thread;
|
return m_thread < rhs.m_thread;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
THREAD_ID m_thread;
|
THREAD_ID m_thread;
|
||||||
};
|
};
|
||||||
|
|
||||||
// no variadic template support in msvc
|
// no variadic template support in msvc
|
||||||
//template <typename C, typename... A>
|
//template <typename C, typename... A>
|
||||||
//thread(C&& func, A&&... args);
|
//thread(C&& func, A&&... args);
|
||||||
|
|
||||||
template <typename C>
|
template <typename C>
|
||||||
thread(C func)
|
thread(C func)
|
||||||
{
|
{
|
||||||
StartThread(new Func<C>(func));
|
StartThread(new Func<C>(func));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename C, typename A>
|
template <typename C, typename A>
|
||||||
thread(C func, A arg)
|
thread(C func, A arg)
|
||||||
{
|
{
|
||||||
StartThread(new FuncArg<C, A>(func, arg));
|
StartThread(new FuncArg<C, A>(func, arg));
|
||||||
}
|
}
|
||||||
|
|
||||||
thread() /*= default;*/ {}
|
thread() /*= default;*/ {}
|
||||||
|
|
||||||
#ifdef USE_RVALUE_REFERENCES
|
#ifdef USE_RVALUE_REFERENCES
|
||||||
thread(const thread&) /*= delete*/;
|
thread(const thread&) /*= delete*/;
|
||||||
|
|
||||||
thread(thread&& other)
|
thread(thread&& other)
|
||||||
{
|
{
|
||||||
#else
|
#else
|
||||||
thread(const thread& t)
|
thread(const thread& t)
|
||||||
{
|
{
|
||||||
// ugly const_cast to get around lack of rvalue references
|
// ugly const_cast to get around lack of rvalue references
|
||||||
thread& other = const_cast<thread&>(t);
|
thread& other = const_cast<thread&>(t);
|
||||||
#endif
|
#endif
|
||||||
swap(other);
|
swap(other);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_RVALUE_REFERENCES
|
#ifdef USE_RVALUE_REFERENCES
|
||||||
thread& operator=(const thread&) /*= delete*/;
|
thread& operator=(const thread&) /*= delete*/;
|
||||||
|
|
||||||
thread& operator=(thread&& other)
|
thread& operator=(thread&& other)
|
||||||
{
|
{
|
||||||
#else
|
#else
|
||||||
thread& operator=(const thread& t)
|
thread& operator=(const thread& t)
|
||||||
{
|
{
|
||||||
// ugly const_cast to get around lack of rvalue references
|
// ugly const_cast to get around lack of rvalue references
|
||||||
thread& other = const_cast<thread&>(t);
|
thread& other = const_cast<thread&>(t);
|
||||||
#endif
|
#endif
|
||||||
if (joinable())
|
if (joinable())
|
||||||
detach();
|
detach();
|
||||||
swap(other);
|
swap(other);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
~thread()
|
~thread()
|
||||||
{
|
{
|
||||||
if (joinable())
|
if (joinable())
|
||||||
detach();
|
detach();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool joinable() const
|
bool joinable() const
|
||||||
{
|
{
|
||||||
return m_id != id();
|
return m_id != id();
|
||||||
}
|
}
|
||||||
|
|
||||||
id get_id() const
|
id get_id() const
|
||||||
{
|
{
|
||||||
return m_id;
|
return m_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
native_handle_type native_handle()
|
native_handle_type native_handle()
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
return m_handle;
|
return m_handle;
|
||||||
#else
|
#else
|
||||||
return m_id.m_thread;
|
return m_id.m_thread;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void join()
|
void join()
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
WaitForSingleObject(m_handle, INFINITE);
|
WaitForSingleObject(m_handle, INFINITE);
|
||||||
detach();
|
detach();
|
||||||
#else
|
#else
|
||||||
pthread_join(m_id.m_thread, NULL);
|
pthread_join(m_id.m_thread, NULL);
|
||||||
m_id = id();
|
m_id = id();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void detach()
|
void detach()
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
CloseHandle(m_handle);
|
CloseHandle(m_handle);
|
||||||
#else
|
#else
|
||||||
pthread_detach(m_id.m_thread);
|
pthread_detach(m_id.m_thread);
|
||||||
#endif
|
#endif
|
||||||
m_id = id();
|
m_id = id();
|
||||||
}
|
}
|
||||||
|
|
||||||
void swap(thread& other)
|
void swap(thread& other)
|
||||||
{
|
{
|
||||||
std::swap(m_id, other.m_id);
|
std::swap(m_id, other.m_id);
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
std::swap(m_handle, other.m_handle);
|
std::swap(m_handle, other.m_handle);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned hardware_concurrency()
|
static unsigned hardware_concurrency()
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
SYSTEM_INFO sysinfo;
|
SYSTEM_INFO sysinfo;
|
||||||
GetSystemInfo(&sysinfo);
|
GetSystemInfo(&sysinfo);
|
||||||
return static_cast<unsigned>(sysinfo.dwNumberOfProcessors);
|
return static_cast<unsigned>(sysinfo.dwNumberOfProcessors);
|
||||||
#else
|
#else
|
||||||
return 0;
|
return 0;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
id m_id;
|
id m_id;
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
native_handle_type m_handle;
|
native_handle_type m_handle;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
template <typename F>
|
template <typename F>
|
||||||
void StartThread(F* param)
|
void StartThread(F* param)
|
||||||
{
|
{
|
||||||
#ifdef USE_BEGINTHREADEX
|
#ifdef USE_BEGINTHREADEX
|
||||||
m_handle = (HANDLE)_beginthreadex(NULL, 0, &RunAndDelete<F>, param, 0, &m_id.m_thread);
|
m_handle = (HANDLE)_beginthreadex(NULL, 0, &RunAndDelete<F>, param, 0, &m_id.m_thread);
|
||||||
#elif defined(_WIN32)
|
#elif defined(_WIN32)
|
||||||
m_handle = CreateThread(NULL, 0, &RunAndDelete<F>, param, 0, &m_id.m_thread);
|
m_handle = CreateThread(NULL, 0, &RunAndDelete<F>, param, 0, &m_id.m_thread);
|
||||||
#else
|
#else
|
||||||
pthread_attr_t attr;
|
pthread_attr_t attr;
|
||||||
pthread_attr_init(&attr);
|
pthread_attr_init(&attr);
|
||||||
pthread_attr_setstacksize(&attr, 1024 * 1024);
|
pthread_attr_setstacksize(&attr, 1024 * 1024);
|
||||||
if (pthread_create(&m_id.m_thread, &attr, &RunAndDelete<F>, param))
|
if (pthread_create(&m_id.m_thread, &attr, &RunAndDelete<F>, param))
|
||||||
m_id = id();
|
m_id = id();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename C>
|
template <typename C>
|
||||||
class Func
|
class Func
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Func(C _func) : func(_func) {}
|
Func(C _func) : func(_func) {}
|
||||||
|
|
||||||
void Run() { func(); }
|
void Run() { func(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
C const func;
|
C const func;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename C, typename A>
|
template <typename C, typename A>
|
||||||
class FuncArg
|
class FuncArg
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
FuncArg(C _func, A _arg) : func(_func), arg(_arg) {}
|
FuncArg(C _func, A _arg) : func(_func), arg(_arg) {}
|
||||||
|
|
||||||
void Run() { func(arg); }
|
void Run() { func(arg); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
C const func;
|
C const func;
|
||||||
A arg;
|
A arg;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename F>
|
template <typename F>
|
||||||
static THREAD_RETURN RunAndDelete(void* param)
|
static THREAD_RETURN RunAndDelete(void* param)
|
||||||
{
|
{
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||||
#endif
|
#endif
|
||||||
static_cast<F*>(param)->Run();
|
static_cast<F*>(param)->Run();
|
||||||
delete static_cast<F*>(param);
|
delete static_cast<F*>(param);
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
[pool release];
|
[pool release];
|
||||||
#endif
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace this_thread
|
namespace this_thread
|
||||||
|
@ -288,24 +288,24 @@ namespace this_thread
|
||||||
inline void yield()
|
inline void yield()
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
SwitchToThread();
|
SwitchToThread();
|
||||||
#else
|
#else
|
||||||
sleep(0);
|
sleep(0);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
inline thread::id get_id()
|
inline thread::id get_id()
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
return GetCurrentThreadId();
|
return GetCurrentThreadId();
|
||||||
#else
|
#else
|
||||||
return pthread_self();
|
return pthread_self();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace this_thread
|
} // namespace this_thread
|
||||||
|
|
||||||
} // namespace std
|
} // namespace std
|
||||||
|
|
||||||
#undef USE_RVALUE_REFERENCES
|
#undef USE_RVALUE_REFERENCES
|
||||||
#undef USE_BEGINTHREADEX
|
#undef USE_BEGINTHREADEX
|
||||||
|
|
|
@ -11,131 +11,131 @@
|
||||||
#include "string_util.h"
|
#include "string_util.h"
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
#else
|
#else
|
||||||
#include <iconv.h>
|
#include <iconv.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// faster than sscanf
|
// faster than sscanf
|
||||||
bool AsciiToHex(const char* _szValue, u32& result)
|
bool AsciiToHex(const char* _szValue, u32& result)
|
||||||
{
|
{
|
||||||
char *endptr = NULL;
|
char *endptr = NULL;
|
||||||
const u32 value = strtoul(_szValue, &endptr, 16);
|
const u32 value = strtoul(_szValue, &endptr, 16);
|
||||||
|
|
||||||
if (!endptr || *endptr)
|
if (!endptr || *endptr)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
result = value;
|
result = value;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CharArrayFromFormatV(char* out, int outsize, const char* format, va_list args)
|
bool CharArrayFromFormatV(char* out, int outsize, const char* format, va_list args)
|
||||||
{
|
{
|
||||||
int writtenCount;
|
int writtenCount;
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
// You would think *printf are simple, right? Iterate on each character,
|
// You would think *printf are simple, right? Iterate on each character,
|
||||||
// if it's a format specifier handle it properly, etc.
|
// if it's a format specifier handle it properly, etc.
|
||||||
//
|
//
|
||||||
// Nooooo. Not according to the C standard.
|
// Nooooo. Not according to the C standard.
|
||||||
//
|
//
|
||||||
// According to the C99 standard (7.19.6.1 "The fprintf function")
|
// According to the C99 standard (7.19.6.1 "The fprintf function")
|
||||||
// The format shall be a multibyte character sequence
|
// The format shall be a multibyte character sequence
|
||||||
//
|
//
|
||||||
// Because some character encodings might have '%' signs in the middle of
|
// Because some character encodings might have '%' signs in the middle of
|
||||||
// a multibyte sequence (SJIS for example only specifies that the first
|
// a multibyte sequence (SJIS for example only specifies that the first
|
||||||
// byte of a 2 byte sequence is "high", the second byte can be anything),
|
// byte of a 2 byte sequence is "high", the second byte can be anything),
|
||||||
// printf functions have to decode the multibyte sequences and try their
|
// printf functions have to decode the multibyte sequences and try their
|
||||||
// best to not screw up.
|
// best to not screw up.
|
||||||
//
|
//
|
||||||
// Unfortunately, on Windows, the locale for most languages is not UTF-8
|
// Unfortunately, on Windows, the locale for most languages is not UTF-8
|
||||||
// as we would need. Notably, for zh_TW, Windows chooses EUC-CN as the
|
// as we would need. Notably, for zh_TW, Windows chooses EUC-CN as the
|
||||||
// locale, and completely fails when trying to decode UTF-8 as EUC-CN.
|
// locale, and completely fails when trying to decode UTF-8 as EUC-CN.
|
||||||
//
|
//
|
||||||
// On the other hand, the fix is simple: because we use UTF-8, no such
|
// On the other hand, the fix is simple: because we use UTF-8, no such
|
||||||
// multibyte handling is required as we can simply assume that no '%' char
|
// multibyte handling is required as we can simply assume that no '%' char
|
||||||
// will be present in the middle of a multibyte sequence.
|
// will be present in the middle of a multibyte sequence.
|
||||||
//
|
//
|
||||||
// This is why we lookup an ANSI (cp1252) locale here and use _vsnprintf_l.
|
// This is why we lookup an ANSI (cp1252) locale here and use _vsnprintf_l.
|
||||||
static locale_t c_locale = NULL;
|
static locale_t c_locale = NULL;
|
||||||
if (!c_locale)
|
if (!c_locale)
|
||||||
c_locale = _create_locale(LC_ALL, ".1252");
|
c_locale = _create_locale(LC_ALL, ".1252");
|
||||||
writtenCount = _vsnprintf_l(out, outsize, format, c_locale, args);
|
writtenCount = _vsnprintf_l(out, outsize, format, c_locale, args);
|
||||||
#else
|
#else
|
||||||
writtenCount = vsnprintf(out, outsize, format, args);
|
writtenCount = vsnprintf(out, outsize, format, args);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (writtenCount > 0 && writtenCount < outsize)
|
if (writtenCount > 0 && writtenCount < outsize)
|
||||||
{
|
{
|
||||||
out[writtenCount] = '\0';
|
out[writtenCount] = '\0';
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
out[outsize - 1] = '\0';
|
out[outsize - 1] = '\0';
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string StringFromFormat(const char* format, ...)
|
std::string StringFromFormat(const char* format, ...)
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
char *buf = NULL;
|
char *buf = NULL;
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
int required = 0;
|
int required = 0;
|
||||||
|
|
||||||
va_start(args, format);
|
va_start(args, format);
|
||||||
required = _vscprintf(format, args);
|
required = _vscprintf(format, args);
|
||||||
buf = new char[required + 1];
|
buf = new char[required + 1];
|
||||||
CharArrayFromFormatV(buf, required + 1, format, args);
|
CharArrayFromFormatV(buf, required + 1, format, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
||||||
std::string temp = buf;
|
std::string temp = buf;
|
||||||
delete[] buf;
|
delete[] buf;
|
||||||
#else
|
#else
|
||||||
va_start(args, format);
|
va_start(args, format);
|
||||||
if (vasprintf(&buf, format, args) < 0)
|
if (vasprintf(&buf, format, args) < 0)
|
||||||
ERROR_LOG(COMMON, "Unable to allocate memory for string");
|
ERROR_LOG(COMMON, "Unable to allocate memory for string");
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
||||||
std::string temp = buf;
|
std::string temp = buf;
|
||||||
free(buf);
|
free(buf);
|
||||||
#endif
|
#endif
|
||||||
return temp;
|
return temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
// For Debugging. Read out an u8 array.
|
// For Debugging. Read out an u8 array.
|
||||||
std::string ArrayToString(const u8 *data, u32 size, int line_len, bool spaces)
|
std::string ArrayToString(const u8 *data, u32 size, int line_len, bool spaces)
|
||||||
{
|
{
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
oss << std::setfill('0') << std::hex;
|
oss << std::setfill('0') << std::hex;
|
||||||
|
|
||||||
for (int line = 0; size; ++data, --size)
|
for (int line = 0; size; ++data, --size)
|
||||||
{
|
{
|
||||||
oss << std::setw(2) << (int)*data;
|
oss << std::setw(2) << (int)*data;
|
||||||
|
|
||||||
if (line_len == ++line)
|
if (line_len == ++line)
|
||||||
{
|
{
|
||||||
oss << '\n';
|
oss << '\n';
|
||||||
line = 0;
|
line = 0;
|
||||||
}
|
}
|
||||||
else if (spaces)
|
else if (spaces)
|
||||||
oss << ' ';
|
oss << ' ';
|
||||||
}
|
}
|
||||||
|
|
||||||
return oss.str();
|
return oss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Turns " hej " into "hej". Also handles tabs.
|
// Turns " hej " into "hej". Also handles tabs.
|
||||||
std::string StripSpaces(const std::string &str)
|
std::string StripSpaces(const std::string &str)
|
||||||
{
|
{
|
||||||
const size_t s = str.find_first_not_of(" \t\r\n");
|
const size_t s = str.find_first_not_of(" \t\r\n");
|
||||||
|
|
||||||
if (str.npos != s)
|
if (str.npos != s)
|
||||||
return str.substr(s, str.find_last_not_of(" \t\r\n") - s + 1);
|
return str.substr(s, str.find_last_not_of(" \t\r\n") - s + 1);
|
||||||
else
|
else
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
// "\"hello\"" is turned to "hello"
|
// "\"hello\"" is turned to "hello"
|
||||||
|
@ -143,137 +143,137 @@ std::string StripSpaces(const std::string &str)
|
||||||
// ends, as done by StripSpaces above, for example.
|
// ends, as done by StripSpaces above, for example.
|
||||||
std::string StripQuotes(const std::string& s)
|
std::string StripQuotes(const std::string& s)
|
||||||
{
|
{
|
||||||
if (s.size() && '\"' == s[0] && '\"' == *s.rbegin())
|
if (s.size() && '\"' == s[0] && '\"' == *s.rbegin())
|
||||||
return s.substr(1, s.size() - 2);
|
return s.substr(1, s.size() - 2);
|
||||||
else
|
else
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TryParse(const std::string &str, u32 *const output)
|
bool TryParse(const std::string &str, u32 *const output)
|
||||||
{
|
{
|
||||||
char *endptr = NULL;
|
char *endptr = NULL;
|
||||||
|
|
||||||
// Reset errno to a value other than ERANGE
|
// Reset errno to a value other than ERANGE
|
||||||
errno = 0;
|
errno = 0;
|
||||||
|
|
||||||
unsigned long value = strtoul(str.c_str(), &endptr, 0);
|
unsigned long value = strtoul(str.c_str(), &endptr, 0);
|
||||||
|
|
||||||
if (!endptr || *endptr)
|
if (!endptr || *endptr)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (errno == ERANGE)
|
if (errno == ERANGE)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
#if ULONG_MAX > UINT_MAX
|
#if ULONG_MAX > UINT_MAX
|
||||||
if (value >= 0x100000000ull
|
if (value >= 0x100000000ull
|
||||||
&& value <= 0xFFFFFFFF00000000ull)
|
&& value <= 0xFFFFFFFF00000000ull)
|
||||||
return false;
|
return false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
*output = static_cast<u32>(value);
|
*output = static_cast<u32>(value);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TryParse(const std::string &str, bool *const output)
|
bool TryParse(const std::string &str, bool *const output)
|
||||||
{
|
{
|
||||||
if ("1" == str || !strcasecmp("true", str.c_str()))
|
if ("1" == str || !strcasecmp("true", str.c_str()))
|
||||||
*output = true;
|
*output = true;
|
||||||
else if ("0" == str || !strcasecmp("false", str.c_str()))
|
else if ("0" == str || !strcasecmp("false", str.c_str()))
|
||||||
*output = false;
|
*output = false;
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string StringFromInt(int value)
|
std::string StringFromInt(int value)
|
||||||
{
|
{
|
||||||
char temp[16];
|
char temp[16];
|
||||||
sprintf(temp, "%i", value);
|
sprintf(temp, "%i", value);
|
||||||
return temp;
|
return temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string StringFromBool(bool value)
|
std::string StringFromBool(bool value)
|
||||||
{
|
{
|
||||||
return value ? "True" : "False";
|
return value ? "True" : "False";
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SplitPath(const std::string& full_path, std::string* _pPath, std::string* _pFilename, std::string* _pExtension)
|
bool SplitPath(const std::string& full_path, std::string* _pPath, std::string* _pFilename, std::string* _pExtension)
|
||||||
{
|
{
|
||||||
if (full_path.empty())
|
if (full_path.empty())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
size_t dir_end = full_path.find_last_of("/"
|
size_t dir_end = full_path.find_last_of("/"
|
||||||
// windows needs the : included for something like just "C:" to be considered a directory
|
// windows needs the : included for something like just "C:" to be considered a directory
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
":"
|
":"
|
||||||
#endif
|
#endif
|
||||||
);
|
);
|
||||||
if (std::string::npos == dir_end)
|
if (std::string::npos == dir_end)
|
||||||
dir_end = 0;
|
dir_end = 0;
|
||||||
else
|
else
|
||||||
dir_end += 1;
|
dir_end += 1;
|
||||||
|
|
||||||
size_t fname_end = full_path.rfind('.');
|
size_t fname_end = full_path.rfind('.');
|
||||||
if (fname_end < dir_end || std::string::npos == fname_end)
|
if (fname_end < dir_end || std::string::npos == fname_end)
|
||||||
fname_end = full_path.size();
|
fname_end = full_path.size();
|
||||||
|
|
||||||
if (_pPath)
|
if (_pPath)
|
||||||
*_pPath = full_path.substr(0, dir_end);
|
*_pPath = full_path.substr(0, dir_end);
|
||||||
|
|
||||||
if (_pFilename)
|
if (_pFilename)
|
||||||
*_pFilename = full_path.substr(dir_end, fname_end - dir_end);
|
*_pFilename = full_path.substr(dir_end, fname_end - dir_end);
|
||||||
|
|
||||||
if (_pExtension)
|
if (_pExtension)
|
||||||
*_pExtension = full_path.substr(fname_end);
|
*_pExtension = full_path.substr(fname_end);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BuildCompleteFilename(std::string& _CompleteFilename, const std::string& _Path, const std::string& _Filename)
|
void BuildCompleteFilename(std::string& _CompleteFilename, const std::string& _Path, const std::string& _Filename)
|
||||||
{
|
{
|
||||||
_CompleteFilename = _Path;
|
_CompleteFilename = _Path;
|
||||||
|
|
||||||
// check for seperator
|
// check for seperator
|
||||||
if (DIR_SEP_CHR != *_CompleteFilename.rbegin())
|
if (DIR_SEP_CHR != *_CompleteFilename.rbegin())
|
||||||
_CompleteFilename += DIR_SEP_CHR;
|
_CompleteFilename += DIR_SEP_CHR;
|
||||||
|
|
||||||
// add the filename
|
// add the filename
|
||||||
_CompleteFilename += _Filename;
|
_CompleteFilename += _Filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SplitString(const std::string& str, const char delim, std::vector<std::string>& output)
|
void SplitString(const std::string& str, const char delim, std::vector<std::string>& output)
|
||||||
{
|
{
|
||||||
std::istringstream iss(str);
|
std::istringstream iss(str);
|
||||||
output.resize(1);
|
output.resize(1);
|
||||||
|
|
||||||
while (std::getline(iss, *output.rbegin(), delim))
|
while (std::getline(iss, *output.rbegin(), delim))
|
||||||
output.push_back("");
|
output.push_back("");
|
||||||
|
|
||||||
output.pop_back();
|
output.pop_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string TabsToSpaces(int tab_size, const std::string &in)
|
std::string TabsToSpaces(int tab_size, const std::string &in)
|
||||||
{
|
{
|
||||||
const std::string spaces(tab_size, ' ');
|
const std::string spaces(tab_size, ' ');
|
||||||
std::string out(in);
|
std::string out(in);
|
||||||
|
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
while (out.npos != (i = out.find('\t')))
|
while (out.npos != (i = out.find('\t')))
|
||||||
out.replace(i, 1, spaces);
|
out.replace(i, 1, spaces);
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ReplaceAll(std::string result, const std::string& src, const std::string& dest)
|
std::string ReplaceAll(std::string result, const std::string& src, const std::string& dest)
|
||||||
{
|
{
|
||||||
while(1)
|
while(1)
|
||||||
{
|
{
|
||||||
size_t pos = result.find(src);
|
size_t pos = result.find(src);
|
||||||
if (pos == std::string::npos) break;
|
if (pos == std::string::npos) break;
|
||||||
result.replace(pos, src.size(), dest);
|
result.replace(pos, src.size(), dest);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// UriDecode and UriEncode are from http://www.codeguru.com/cpp/cpp/string/conversions/print.php/c12759
|
// UriDecode and UriEncode are from http://www.codeguru.com/cpp/cpp/string/conversions/print.php/c12759
|
||||||
|
@ -287,161 +287,161 @@ std::string ReplaceAll(std::string result, const std::string& src, const std::st
|
||||||
|
|
||||||
const char HEX2DEC[256] =
|
const char HEX2DEC[256] =
|
||||||
{
|
{
|
||||||
/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
|
/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
|
||||||
/* 0 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
|
/* 0 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
|
||||||
/* 1 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
|
/* 1 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
|
||||||
/* 2 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
|
/* 2 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
|
||||||
/* 3 */ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,16,16, 16,16,16,16,
|
/* 3 */ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,16,16, 16,16,16,16,
|
||||||
|
|
||||||
/* 4 */ 16,10,11,12, 13,14,15,16, 16,16,16,16, 16,16,16,16,
|
/* 4 */ 16,10,11,12, 13,14,15,16, 16,16,16,16, 16,16,16,16,
|
||||||
/* 5 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
|
/* 5 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
|
||||||
/* 6 */ 16,10,11,12, 13,14,15,16, 16,16,16,16, 16,16,16,16,
|
/* 6 */ 16,10,11,12, 13,14,15,16, 16,16,16,16, 16,16,16,16,
|
||||||
/* 7 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
|
/* 7 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
|
||||||
|
|
||||||
/* 8 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
|
/* 8 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
|
||||||
/* 9 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
|
/* 9 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
|
||||||
/* A */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
|
/* A */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
|
||||||
/* B */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
|
/* B */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
|
||||||
|
|
||||||
/* C */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
|
/* C */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
|
||||||
/* D */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
|
/* D */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
|
||||||
/* E */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
|
/* E */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
|
||||||
/* F */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16
|
/* F */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16
|
||||||
};
|
};
|
||||||
|
|
||||||
std::string UriDecode(const std::string & sSrc)
|
std::string UriDecode(const std::string & sSrc)
|
||||||
{
|
{
|
||||||
// Note from RFC1630: "Sequences which start with a percent sign
|
// Note from RFC1630: "Sequences which start with a percent sign
|
||||||
// but are not followed by two hexadecimal characters (0-9, A-F) are reserved
|
// but are not followed by two hexadecimal characters (0-9, A-F) are reserved
|
||||||
// for future extension"
|
// for future extension"
|
||||||
|
|
||||||
const unsigned char * pSrc = (const unsigned char *)sSrc.c_str();
|
const unsigned char * pSrc = (const unsigned char *)sSrc.c_str();
|
||||||
const size_t SRC_LEN = sSrc.length();
|
const size_t SRC_LEN = sSrc.length();
|
||||||
const unsigned char * const SRC_END = pSrc + SRC_LEN;
|
const unsigned char * const SRC_END = pSrc + SRC_LEN;
|
||||||
const unsigned char * const SRC_LAST_DEC = SRC_END - 2; // last decodable '%'
|
const unsigned char * const SRC_LAST_DEC = SRC_END - 2; // last decodable '%'
|
||||||
|
|
||||||
char * const pStart = new char[SRC_LEN];
|
char * const pStart = new char[SRC_LEN];
|
||||||
char * pEnd = pStart;
|
char * pEnd = pStart;
|
||||||
|
|
||||||
while (pSrc < SRC_LAST_DEC)
|
while (pSrc < SRC_LAST_DEC)
|
||||||
{
|
{
|
||||||
if (*pSrc == '%')
|
if (*pSrc == '%')
|
||||||
{
|
{
|
||||||
char dec1, dec2;
|
char dec1, dec2;
|
||||||
if (16 != (dec1 = HEX2DEC[*(pSrc + 1)])
|
if (16 != (dec1 = HEX2DEC[*(pSrc + 1)])
|
||||||
&& 16 != (dec2 = HEX2DEC[*(pSrc + 2)]))
|
&& 16 != (dec2 = HEX2DEC[*(pSrc + 2)]))
|
||||||
{
|
{
|
||||||
*pEnd++ = (dec1 << 4) + dec2;
|
*pEnd++ = (dec1 << 4) + dec2;
|
||||||
pSrc += 3;
|
pSrc += 3;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*pEnd++ = *pSrc++;
|
*pEnd++ = *pSrc++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// the last 2- chars
|
// the last 2- chars
|
||||||
while (pSrc < SRC_END)
|
while (pSrc < SRC_END)
|
||||||
*pEnd++ = *pSrc++;
|
*pEnd++ = *pSrc++;
|
||||||
|
|
||||||
std::string sResult(pStart, pEnd);
|
std::string sResult(pStart, pEnd);
|
||||||
delete [] pStart;
|
delete [] pStart;
|
||||||
return sResult;
|
return sResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only alphanum is safe.
|
// Only alphanum is safe.
|
||||||
const char SAFE[256] =
|
const char SAFE[256] =
|
||||||
{
|
{
|
||||||
/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
|
/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
|
||||||
/* 0 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
|
/* 0 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
|
||||||
/* 1 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
|
/* 1 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
|
||||||
/* 2 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
|
/* 2 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
|
||||||
/* 3 */ 1,1,1,1, 1,1,1,1, 1,1,0,0, 0,0,0,0,
|
/* 3 */ 1,1,1,1, 1,1,1,1, 1,1,0,0, 0,0,0,0,
|
||||||
|
|
||||||
/* 4 */ 0,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1,
|
/* 4 */ 0,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1,
|
||||||
/* 5 */ 1,1,1,1, 1,1,1,1, 1,1,1,0, 0,0,0,0,
|
/* 5 */ 1,1,1,1, 1,1,1,1, 1,1,1,0, 0,0,0,0,
|
||||||
/* 6 */ 0,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1,
|
/* 6 */ 0,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1,
|
||||||
/* 7 */ 1,1,1,1, 1,1,1,1, 1,1,1,0, 0,0,0,0,
|
/* 7 */ 1,1,1,1, 1,1,1,1, 1,1,1,0, 0,0,0,0,
|
||||||
|
|
||||||
/* 8 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
|
/* 8 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
|
||||||
/* 9 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
|
/* 9 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
|
||||||
/* A */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
|
/* A */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
|
||||||
/* B */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
|
/* B */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
|
||||||
|
|
||||||
/* C */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
|
/* C */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
|
||||||
/* D */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
|
/* D */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
|
||||||
/* E */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
|
/* E */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
|
||||||
/* F */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0
|
/* F */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0
|
||||||
};
|
};
|
||||||
|
|
||||||
std::string UriEncode(const std::string & sSrc)
|
std::string UriEncode(const std::string & sSrc)
|
||||||
{
|
{
|
||||||
const char DEC2HEX[16 + 1] = "0123456789ABCDEF";
|
const char DEC2HEX[16 + 1] = "0123456789ABCDEF";
|
||||||
const unsigned char * pSrc = (const unsigned char *)sSrc.c_str();
|
const unsigned char * pSrc = (const unsigned char *)sSrc.c_str();
|
||||||
const size_t SRC_LEN = sSrc.length();
|
const size_t SRC_LEN = sSrc.length();
|
||||||
unsigned char * const pStart = new unsigned char[SRC_LEN * 3];
|
unsigned char * const pStart = new unsigned char[SRC_LEN * 3];
|
||||||
unsigned char * pEnd = pStart;
|
unsigned char * pEnd = pStart;
|
||||||
const unsigned char * const SRC_END = pSrc + SRC_LEN;
|
const unsigned char * const SRC_END = pSrc + SRC_LEN;
|
||||||
|
|
||||||
for (; pSrc < SRC_END; ++pSrc)
|
for (; pSrc < SRC_END; ++pSrc)
|
||||||
{
|
{
|
||||||
if (SAFE[*pSrc])
|
if (SAFE[*pSrc])
|
||||||
*pEnd++ = *pSrc;
|
*pEnd++ = *pSrc;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// escape this char
|
// escape this char
|
||||||
*pEnd++ = '%';
|
*pEnd++ = '%';
|
||||||
*pEnd++ = DEC2HEX[*pSrc >> 4];
|
*pEnd++ = DEC2HEX[*pSrc >> 4];
|
||||||
*pEnd++ = DEC2HEX[*pSrc & 0x0F];
|
*pEnd++ = DEC2HEX[*pSrc & 0x0F];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string sResult((char *)pStart, (char *)pEnd);
|
std::string sResult((char *)pStart, (char *)pEnd);
|
||||||
delete [] pStart;
|
delete [] pStart;
|
||||||
return sResult;
|
return sResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
|
||||||
std::string UTF16ToUTF8(const std::wstring& input)
|
std::string UTF16ToUTF8(const std::wstring& input)
|
||||||
{
|
{
|
||||||
auto const size = WideCharToMultiByte(CP_UTF8, 0, input.data(), input.size(), nullptr, 0, nullptr, nullptr);
|
auto const size = WideCharToMultiByte(CP_UTF8, 0, input.data(), input.size(), nullptr, 0, nullptr, nullptr);
|
||||||
|
|
||||||
std::string output;
|
std::string output;
|
||||||
output.resize(size);
|
output.resize(size);
|
||||||
|
|
||||||
if (size == 0 || size != WideCharToMultiByte(CP_UTF8, 0, input.data(), input.size(), &output[0], output.size(), nullptr, nullptr))
|
if (size == 0 || size != WideCharToMultiByte(CP_UTF8, 0, input.data(), input.size(), &output[0], output.size(), nullptr, nullptr))
|
||||||
output.clear();
|
output.clear();
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::wstring CPToUTF16(u32 code_page, const std::string& input)
|
std::wstring CPToUTF16(u32 code_page, const std::string& input)
|
||||||
{
|
{
|
||||||
auto const size = MultiByteToWideChar(code_page, 0, input.data(), input.size(), nullptr, 0);
|
auto const size = MultiByteToWideChar(code_page, 0, input.data(), input.size(), nullptr, 0);
|
||||||
|
|
||||||
std::wstring output;
|
std::wstring output;
|
||||||
output.resize(size);
|
output.resize(size);
|
||||||
|
|
||||||
if (size == 0 || size != MultiByteToWideChar(code_page, 0, input.data(), input.size(), &output[0], output.size()))
|
if (size == 0 || size != MultiByteToWideChar(code_page, 0, input.data(), input.size(), &output[0], output.size()))
|
||||||
output.clear();
|
output.clear();
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::wstring UTF8ToUTF16(const std::string& input)
|
std::wstring UTF8ToUTF16(const std::string& input)
|
||||||
{
|
{
|
||||||
return CPToUTF16(CP_UTF8, input);
|
return CPToUTF16(CP_UTF8, input);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string SHIFTJISToUTF8(const std::string& input)
|
std::string SHIFTJISToUTF8(const std::string& input)
|
||||||
{
|
{
|
||||||
return UTF16ToUTF8(CPToUTF16(932, input));
|
return UTF16ToUTF8(CPToUTF16(932, input));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string CP1252ToUTF8(const std::string& input)
|
std::string CP1252ToUTF8(const std::string& input)
|
||||||
{
|
{
|
||||||
return UTF16ToUTF8(CPToUTF16(1252, input));
|
return UTF16ToUTF8(CPToUTF16(1252, input));
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
@ -449,83 +449,83 @@ std::string CP1252ToUTF8(const std::string& input)
|
||||||
template <typename T>
|
template <typename T>
|
||||||
std::string CodeToUTF8(const char* fromcode, const std::basic_string<T>& input)
|
std::string CodeToUTF8(const char* fromcode, const std::basic_string<T>& input)
|
||||||
{
|
{
|
||||||
std::string result;
|
std::string result;
|
||||||
|
|
||||||
iconv_t const conv_desc = iconv_open("UTF-8", fromcode);
|
iconv_t const conv_desc = iconv_open("UTF-8", fromcode);
|
||||||
if ((iconv_t)-1 == conv_desc)
|
if ((iconv_t)-1 == conv_desc)
|
||||||
{
|
{
|
||||||
ERROR_LOG(COMMON, "Iconv initialization failure [%s]: %s", fromcode, strerror(errno));
|
ERROR_LOG(COMMON, "Iconv initialization failure [%s]: %s", fromcode, strerror(errno));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
size_t const in_bytes = sizeof(T) * input.size();
|
size_t const in_bytes = sizeof(T) * input.size();
|
||||||
size_t const out_buffer_size = 4 * in_bytes;
|
size_t const out_buffer_size = 4 * in_bytes;
|
||||||
|
|
||||||
std::string out_buffer;
|
std::string out_buffer;
|
||||||
out_buffer.resize(out_buffer_size);
|
out_buffer.resize(out_buffer_size);
|
||||||
|
|
||||||
auto src_buffer = &input[0];
|
auto src_buffer = &input[0];
|
||||||
size_t src_bytes = in_bytes;
|
size_t src_bytes = in_bytes;
|
||||||
auto dst_buffer = &out_buffer[0];
|
auto dst_buffer = &out_buffer[0];
|
||||||
size_t dst_bytes = out_buffer.size();
|
size_t dst_bytes = out_buffer.size();
|
||||||
|
|
||||||
while (src_bytes != 0)
|
while (src_bytes != 0)
|
||||||
{
|
{
|
||||||
size_t const iconv_result = iconv(conv_desc, (char**)(&src_buffer), &src_bytes,
|
size_t const iconv_result = iconv(conv_desc, (char**)(&src_buffer), &src_bytes,
|
||||||
&dst_buffer, &dst_bytes);
|
&dst_buffer, &dst_bytes);
|
||||||
|
|
||||||
if ((size_t)-1 == iconv_result)
|
if ((size_t)-1 == iconv_result)
|
||||||
{
|
{
|
||||||
if (EILSEQ == errno || EINVAL == errno)
|
if (EILSEQ == errno || EINVAL == errno)
|
||||||
{
|
{
|
||||||
// Try to skip the bad character
|
// Try to skip the bad character
|
||||||
if (src_bytes != 0)
|
if (src_bytes != 0)
|
||||||
{
|
{
|
||||||
--src_bytes;
|
--src_bytes;
|
||||||
++src_buffer;
|
++src_buffer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ERROR_LOG(COMMON, "iconv failure [%s]: %s", fromcode, strerror(errno));
|
ERROR_LOG(COMMON, "iconv failure [%s]: %s", fromcode, strerror(errno));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
out_buffer.resize(out_buffer_size - dst_bytes);
|
out_buffer.resize(out_buffer_size - dst_bytes);
|
||||||
out_buffer.swap(result);
|
out_buffer.swap(result);
|
||||||
|
|
||||||
iconv_close(conv_desc);
|
iconv_close(conv_desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string CP1252ToUTF8(const std::string& input)
|
std::string CP1252ToUTF8(const std::string& input)
|
||||||
{
|
{
|
||||||
//return CodeToUTF8("CP1252//TRANSLIT", input);
|
//return CodeToUTF8("CP1252//TRANSLIT", input);
|
||||||
//return CodeToUTF8("CP1252//IGNORE", input);
|
//return CodeToUTF8("CP1252//IGNORE", input);
|
||||||
return CodeToUTF8("CP1252", input);
|
return CodeToUTF8("CP1252", input);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string SHIFTJISToUTF8(const std::string& input)
|
std::string SHIFTJISToUTF8(const std::string& input)
|
||||||
{
|
{
|
||||||
//return CodeToUTF8("CP932", input);
|
//return CodeToUTF8("CP932", input);
|
||||||
return CodeToUTF8("SJIS", input);
|
return CodeToUTF8("SJIS", input);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string UTF16ToUTF8(const std::wstring& input)
|
std::string UTF16ToUTF8(const std::wstring& input)
|
||||||
{
|
{
|
||||||
std::string result =
|
std::string result =
|
||||||
// CodeToUTF8("UCS-2", input);
|
// CodeToUTF8("UCS-2", input);
|
||||||
// CodeToUTF8("UCS-2LE", input);
|
// CodeToUTF8("UCS-2LE", input);
|
||||||
// CodeToUTF8("UTF-16", input);
|
// CodeToUTF8("UTF-16", input);
|
||||||
CodeToUTF8("UTF-16LE", input);
|
CodeToUTF8("UTF-16LE", input);
|
||||||
|
|
||||||
// TODO: why is this needed?
|
// TODO: why is this needed?
|
||||||
result.erase(std::remove(result.begin(), result.end(), 0x00), result.end());
|
result.erase(std::remove(result.begin(), result.end(), 0x00), result.end());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -21,10 +21,10 @@ bool CharArrayFromFormatV(char* out, int outsize, const char* format, va_list ar
|
||||||
template<size_t Count>
|
template<size_t Count>
|
||||||
inline void CharArrayFromFormat(char (& out)[Count], const char* format, ...)
|
inline void CharArrayFromFormat(char (& out)[Count], const char* format, ...)
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, format);
|
va_start(args, format);
|
||||||
CharArrayFromFormatV(out, Count, format, args);
|
CharArrayFromFormatV(out, Count, format, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Good
|
// Good
|
||||||
|
@ -37,15 +37,15 @@ std::string StripQuotes(const std::string &s);
|
||||||
template <typename I>
|
template <typename I>
|
||||||
std::string ThousandSeparate(I value, int spaces = 0)
|
std::string ThousandSeparate(I value, int spaces = 0)
|
||||||
{
|
{
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
|
|
||||||
// std::locale("") seems to be broken on many platforms
|
// std::locale("") seems to be broken on many platforms
|
||||||
#if defined _WIN32 || (defined __linux__ && !defined __clang__)
|
#if defined _WIN32 || (defined __linux__ && !defined __clang__)
|
||||||
oss.imbue(std::locale(""));
|
oss.imbue(std::locale(""));
|
||||||
#endif
|
#endif
|
||||||
oss << std::setw(spaces) << value;
|
oss << std::setw(spaces) << value;
|
||||||
|
|
||||||
return oss.str();
|
return oss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string StringFromInt(int value);
|
std::string StringFromInt(int value);
|
||||||
|
@ -57,16 +57,16 @@ bool TryParse(const std::string &str, u32 *output);
|
||||||
template <typename N>
|
template <typename N>
|
||||||
static bool TryParse(const std::string &str, N *const output)
|
static bool TryParse(const std::string &str, N *const output)
|
||||||
{
|
{
|
||||||
std::istringstream iss(str);
|
std::istringstream iss(str);
|
||||||
|
|
||||||
N tmp = 0;
|
N tmp = 0;
|
||||||
if (iss >> tmp)
|
if (iss >> tmp)
|
||||||
{
|
{
|
||||||
*output = tmp;
|
*output = tmp;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: kill this
|
// TODO: kill this
|
||||||
|
|
|
@ -63,426 +63,426 @@
|
||||||
|
|
||||||
template <typename T, typename F>
|
template <typename T, typename F>
|
||||||
struct swap_struct_t {
|
struct swap_struct_t {
|
||||||
typedef swap_struct_t<T, F> swapped_t;
|
typedef swap_struct_t<T, F> swapped_t;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
T value;
|
T value;
|
||||||
|
|
||||||
static T swap(T v) {
|
static T swap(T v) {
|
||||||
return F::swap(v);
|
return F::swap(v);
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
T const swap() const {
|
T const swap() const {
|
||||||
return swap(value);
|
return swap(value);
|
||||||
|
|
||||||
}
|
}
|
||||||
swap_struct_t() : value((T)0) {}
|
swap_struct_t() : value((T)0) {}
|
||||||
swap_struct_t(const T &v): value(swap(v)) {}
|
swap_struct_t(const T &v): value(swap(v)) {}
|
||||||
|
|
||||||
template <typename S>
|
template <typename S>
|
||||||
swapped_t& operator=(const S &source) {
|
swapped_t& operator=(const S &source) {
|
||||||
value = swap((T)source);
|
value = swap((T)source);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
operator long() const { return (long)swap(); }
|
operator long() const { return (long)swap(); }
|
||||||
operator s8() const { return (s8)swap(); }
|
operator s8() const { return (s8)swap(); }
|
||||||
operator u8() const { return (u8)swap(); }
|
operator u8() const { return (u8)swap(); }
|
||||||
operator s16() const { return (s16)swap(); }
|
operator s16() const { return (s16)swap(); }
|
||||||
operator u16() const { return (u16)swap(); }
|
operator u16() const { return (u16)swap(); }
|
||||||
operator s32() const { return (s32)swap(); }
|
operator s32() const { return (s32)swap(); }
|
||||||
operator u32() const { return (u32)swap(); }
|
operator u32() const { return (u32)swap(); }
|
||||||
operator s64() const { return (s64)swap(); }
|
operator s64() const { return (s64)swap(); }
|
||||||
operator u64() const { return (u64)swap(); }
|
operator u64() const { return (u64)swap(); }
|
||||||
operator float() const { return (float)swap(); }
|
operator float() const { return (float)swap(); }
|
||||||
operator double() const { return (double)swap(); }
|
operator double() const { return (double)swap(); }
|
||||||
|
|
||||||
// +v
|
// +v
|
||||||
swapped_t operator +() const {
|
swapped_t operator +() const {
|
||||||
return +swap();
|
return +swap();
|
||||||
}
|
}
|
||||||
// -v
|
// -v
|
||||||
swapped_t operator -() const {
|
swapped_t operator -() const {
|
||||||
return -swap();
|
return -swap();
|
||||||
}
|
}
|
||||||
|
|
||||||
// v / 5
|
// v / 5
|
||||||
swapped_t operator/(const swapped_t &i) const {
|
swapped_t operator/(const swapped_t &i) const {
|
||||||
return swap() / i.swap();
|
return swap() / i.swap();
|
||||||
}
|
}
|
||||||
template <typename S>
|
template <typename S>
|
||||||
swapped_t operator/(const S &i) const {
|
swapped_t operator/(const S &i) const {
|
||||||
return swap() / i;
|
return swap() / i;
|
||||||
}
|
}
|
||||||
|
|
||||||
// v * 5
|
// v * 5
|
||||||
swapped_t operator*(const swapped_t &i) const {
|
swapped_t operator*(const swapped_t &i) const {
|
||||||
return swap() * i.swap();
|
return swap() * i.swap();
|
||||||
}
|
}
|
||||||
template <typename S>
|
template <typename S>
|
||||||
swapped_t operator*(const S &i) const {
|
swapped_t operator*(const S &i) const {
|
||||||
return swap() * i;
|
return swap() * i;
|
||||||
}
|
}
|
||||||
|
|
||||||
// v + 5
|
// v + 5
|
||||||
swapped_t operator+(const swapped_t &i) const {
|
swapped_t operator+(const swapped_t &i) const {
|
||||||
return swap() + i.swap();
|
return swap() + i.swap();
|
||||||
}
|
}
|
||||||
template <typename S>
|
template <typename S>
|
||||||
swapped_t operator+(const S &i) const {
|
swapped_t operator+(const S &i) const {
|
||||||
return swap() + (T)i;
|
return swap() + (T)i;
|
||||||
}
|
}
|
||||||
// v - 5
|
// v - 5
|
||||||
swapped_t operator-(const swapped_t &i) const {
|
swapped_t operator-(const swapped_t &i) const {
|
||||||
return swap() - i.swap();
|
return swap() - i.swap();
|
||||||
}
|
}
|
||||||
template <typename S>
|
template <typename S>
|
||||||
swapped_t operator-(const S &i) const {
|
swapped_t operator-(const S &i) const {
|
||||||
return swap() - (T)i;
|
return swap() - (T)i;
|
||||||
}
|
}
|
||||||
|
|
||||||
// v += 5
|
// v += 5
|
||||||
swapped_t& operator+=(const swapped_t &i) {
|
swapped_t& operator+=(const swapped_t &i) {
|
||||||
value = swap(swap() + i.swap());
|
value = swap(swap() + i.swap());
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
template <typename S>
|
template <typename S>
|
||||||
swapped_t& operator+=(const S &i) {
|
swapped_t& operator+=(const S &i) {
|
||||||
value = swap(swap() + (T)i);
|
value = swap(swap() + (T)i);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
// v -= 5
|
// v -= 5
|
||||||
swapped_t& operator-=(const swapped_t &i) {
|
swapped_t& operator-=(const swapped_t &i) {
|
||||||
value = swap(swap() - i.swap());
|
value = swap(swap() - i.swap());
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
template <typename S>
|
template <typename S>
|
||||||
swapped_t& operator-=(const S &i) {
|
swapped_t& operator-=(const S &i) {
|
||||||
value = swap(swap() - (T)i);
|
value = swap(swap() - (T)i);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ++v
|
// ++v
|
||||||
swapped_t& operator++() {
|
swapped_t& operator++() {
|
||||||
value = swap(swap()+1);
|
value = swap(swap()+1);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
// --v
|
// --v
|
||||||
swapped_t& operator--() {
|
swapped_t& operator--() {
|
||||||
value = swap(swap()-1);
|
value = swap(swap()-1);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
// v++
|
// v++
|
||||||
swapped_t operator++(int) {
|
swapped_t operator++(int) {
|
||||||
swapped_t old = *this;
|
swapped_t old = *this;
|
||||||
value = swap(swap()+1);
|
value = swap(swap()+1);
|
||||||
return old;
|
return old;
|
||||||
}
|
}
|
||||||
// v--
|
// v--
|
||||||
swapped_t operator--(int) {
|
swapped_t operator--(int) {
|
||||||
swapped_t old = *this;
|
swapped_t old = *this;
|
||||||
value = swap(swap()-1);
|
value = swap(swap()-1);
|
||||||
return old;
|
return old;
|
||||||
}
|
}
|
||||||
// Comparaison
|
// Comparaison
|
||||||
// v == i
|
// v == i
|
||||||
bool operator==(const swapped_t &i) const {
|
bool operator==(const swapped_t &i) const {
|
||||||
return swap() == i.swap();
|
return swap() == i.swap();
|
||||||
}
|
}
|
||||||
template <typename S>
|
template <typename S>
|
||||||
bool operator==(const S &i) const {
|
bool operator==(const S &i) const {
|
||||||
return swap() == i;
|
return swap() == i;
|
||||||
}
|
}
|
||||||
|
|
||||||
// v != i
|
// v != i
|
||||||
bool operator!=(const swapped_t &i) const {
|
bool operator!=(const swapped_t &i) const {
|
||||||
return swap() != i.swap();
|
return swap() != i.swap();
|
||||||
}
|
}
|
||||||
template <typename S>
|
template <typename S>
|
||||||
bool operator!=(const S &i) const {
|
bool operator!=(const S &i) const {
|
||||||
return swap() != i;
|
return swap() != i;
|
||||||
}
|
}
|
||||||
|
|
||||||
// v > i
|
// v > i
|
||||||
bool operator>(const swapped_t &i) const {
|
bool operator>(const swapped_t &i) const {
|
||||||
return swap() > i.swap();
|
return swap() > i.swap();
|
||||||
}
|
}
|
||||||
template <typename S>
|
template <typename S>
|
||||||
bool operator>(const S &i) const {
|
bool operator>(const S &i) const {
|
||||||
return swap() > i;
|
return swap() > i;
|
||||||
}
|
}
|
||||||
|
|
||||||
// v < i
|
// v < i
|
||||||
bool operator<(const swapped_t &i) const {
|
bool operator<(const swapped_t &i) const {
|
||||||
return swap() < i.swap();
|
return swap() < i.swap();
|
||||||
}
|
}
|
||||||
template <typename S>
|
template <typename S>
|
||||||
bool operator<(const S &i) const {
|
bool operator<(const S &i) const {
|
||||||
return swap() < i;
|
return swap() < i;
|
||||||
}
|
}
|
||||||
|
|
||||||
// v >= i
|
// v >= i
|
||||||
bool operator>=(const swapped_t &i) const {
|
bool operator>=(const swapped_t &i) const {
|
||||||
return swap() >= i.swap();
|
return swap() >= i.swap();
|
||||||
}
|
}
|
||||||
template <typename S>
|
template <typename S>
|
||||||
bool operator>=(const S &i) const {
|
bool operator>=(const S &i) const {
|
||||||
return swap() >= i;
|
return swap() >= i;
|
||||||
}
|
}
|
||||||
|
|
||||||
// v <= i
|
// v <= i
|
||||||
bool operator<=(const swapped_t &i) const {
|
bool operator<=(const swapped_t &i) const {
|
||||||
return swap() <= i.swap();
|
return swap() <= i.swap();
|
||||||
}
|
}
|
||||||
template <typename S>
|
template <typename S>
|
||||||
bool operator<=(const S &i) const {
|
bool operator<=(const S &i) const {
|
||||||
return swap() <= i;
|
return swap() <= i;
|
||||||
}
|
}
|
||||||
|
|
||||||
// logical
|
// logical
|
||||||
swapped_t operator !() const {
|
swapped_t operator !() const {
|
||||||
return !swap();
|
return !swap();
|
||||||
}
|
}
|
||||||
|
|
||||||
// bitmath
|
// bitmath
|
||||||
swapped_t operator ~() const {
|
swapped_t operator ~() const {
|
||||||
return ~swap();
|
return ~swap();
|
||||||
}
|
}
|
||||||
|
|
||||||
swapped_t operator &(const swapped_t &b) const {
|
swapped_t operator &(const swapped_t &b) const {
|
||||||
return swap() & b.swap();
|
return swap() & b.swap();
|
||||||
}
|
}
|
||||||
template <typename S>
|
template <typename S>
|
||||||
swapped_t operator &(const S &b) const {
|
swapped_t operator &(const S &b) const {
|
||||||
return swap() & b;
|
return swap() & b;
|
||||||
}
|
}
|
||||||
swapped_t& operator &=(const swapped_t &b) {
|
swapped_t& operator &=(const swapped_t &b) {
|
||||||
value = swap(swap() & b.swap());
|
value = swap(swap() & b.swap());
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
template <typename S>
|
template <typename S>
|
||||||
swapped_t& operator &=(const S b) {
|
swapped_t& operator &=(const S b) {
|
||||||
value = swap(swap() & b);
|
value = swap(swap() & b);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
swapped_t operator |(const swapped_t &b) const {
|
swapped_t operator |(const swapped_t &b) const {
|
||||||
return swap() | b.swap();
|
return swap() | b.swap();
|
||||||
}
|
}
|
||||||
template <typename S>
|
template <typename S>
|
||||||
swapped_t operator |(const S &b) const {
|
swapped_t operator |(const S &b) const {
|
||||||
return swap() | b;
|
return swap() | b;
|
||||||
}
|
}
|
||||||
swapped_t& operator |=(const swapped_t &b) {
|
swapped_t& operator |=(const swapped_t &b) {
|
||||||
value = swap(swap() | b.swap());
|
value = swap(swap() | b.swap());
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
template <typename S>
|
template <typename S>
|
||||||
swapped_t& operator |=(const S &b) {
|
swapped_t& operator |=(const S &b) {
|
||||||
value = swap(swap() | b);
|
value = swap(swap() | b);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
swapped_t operator ^(const swapped_t &b) const {
|
swapped_t operator ^(const swapped_t &b) const {
|
||||||
return swap() ^ b.swap();
|
return swap() ^ b.swap();
|
||||||
}
|
}
|
||||||
template <typename S>
|
template <typename S>
|
||||||
swapped_t operator ^(const S &b) const {
|
swapped_t operator ^(const S &b) const {
|
||||||
return swap() ^ b;
|
return swap() ^ b;
|
||||||
}
|
}
|
||||||
swapped_t& operator ^=(const swapped_t &b) {
|
swapped_t& operator ^=(const swapped_t &b) {
|
||||||
value = swap(swap() ^ b.swap());
|
value = swap(swap() ^ b.swap());
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
template <typename S>
|
template <typename S>
|
||||||
swapped_t& operator ^=(const S &b) {
|
swapped_t& operator ^=(const S &b) {
|
||||||
value = swap(swap() ^ b);
|
value = swap(swap() ^ b);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename S>
|
template <typename S>
|
||||||
swapped_t operator <<(const S &b) const {
|
swapped_t operator <<(const S &b) const {
|
||||||
return swap() << b;
|
return swap() << b;
|
||||||
}
|
}
|
||||||
template <typename S>
|
template <typename S>
|
||||||
swapped_t& operator <<=(const S &b) const {
|
swapped_t& operator <<=(const S &b) const {
|
||||||
value = swap(swap() << b);
|
value = swap(swap() << b);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename S>
|
template <typename S>
|
||||||
swapped_t operator >>(const S &b) const {
|
swapped_t operator >>(const S &b) const {
|
||||||
return swap() >> b;
|
return swap() >> b;
|
||||||
}
|
}
|
||||||
template <typename S>
|
template <typename S>
|
||||||
swapped_t& operator >>=(const S &b) const {
|
swapped_t& operator >>=(const S &b) const {
|
||||||
value = swap(swap() >> b);
|
value = swap(swap() >> b);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Member
|
// Member
|
||||||
/** todo **/
|
/** todo **/
|
||||||
|
|
||||||
|
|
||||||
// Arithmetics
|
// Arithmetics
|
||||||
template <typename S, typename T2, typename F2>
|
template <typename S, typename T2, typename F2>
|
||||||
friend S operator+(const S &p, const swapped_t v);
|
friend S operator+(const S &p, const swapped_t v);
|
||||||
|
|
||||||
template <typename S, typename T2, typename F2>
|
template <typename S, typename T2, typename F2>
|
||||||
friend S operator-(const S &p, const swapped_t v);
|
friend S operator-(const S &p, const swapped_t v);
|
||||||
|
|
||||||
template <typename S, typename T2, typename F2>
|
template <typename S, typename T2, typename F2>
|
||||||
friend S operator/(const S &p, const swapped_t v);
|
friend S operator/(const S &p, const swapped_t v);
|
||||||
|
|
||||||
template <typename S, typename T2, typename F2>
|
template <typename S, typename T2, typename F2>
|
||||||
friend S operator*(const S &p, const swapped_t v);
|
friend S operator*(const S &p, const swapped_t v);
|
||||||
|
|
||||||
template <typename S, typename T2, typename F2>
|
template <typename S, typename T2, typename F2>
|
||||||
friend S operator%(const S &p, const swapped_t v);
|
friend S operator%(const S &p, const swapped_t v);
|
||||||
|
|
||||||
// Arithmetics + assignements
|
// Arithmetics + assignements
|
||||||
template <typename S, typename T2, typename F2>
|
template <typename S, typename T2, typename F2>
|
||||||
friend S operator+=(const S &p, const swapped_t v);
|
friend S operator+=(const S &p, const swapped_t v);
|
||||||
|
|
||||||
template <typename S, typename T2, typename F2>
|
template <typename S, typename T2, typename F2>
|
||||||
friend S operator-=(const S &p, const swapped_t v);
|
friend S operator-=(const S &p, const swapped_t v);
|
||||||
|
|
||||||
// Bitmath
|
// Bitmath
|
||||||
template <typename S, typename T2, typename F2>
|
template <typename S, typename T2, typename F2>
|
||||||
friend S operator&(const S &p, const swapped_t v);
|
friend S operator&(const S &p, const swapped_t v);
|
||||||
|
|
||||||
// Comparison
|
// Comparison
|
||||||
template <typename S, typename T2, typename F2>
|
template <typename S, typename T2, typename F2>
|
||||||
friend bool operator<(const S &p, const swapped_t v);
|
friend bool operator<(const S &p, const swapped_t v);
|
||||||
|
|
||||||
template <typename S, typename T2, typename F2>
|
template <typename S, typename T2, typename F2>
|
||||||
friend bool operator>(const S &p, const swapped_t v);
|
friend bool operator>(const S &p, const swapped_t v);
|
||||||
|
|
||||||
template <typename S, typename T2, typename F2>
|
template <typename S, typename T2, typename F2>
|
||||||
friend bool operator<=(const S &p, const swapped_t v);
|
friend bool operator<=(const S &p, const swapped_t v);
|
||||||
|
|
||||||
template <typename S, typename T2, typename F2>
|
template <typename S, typename T2, typename F2>
|
||||||
friend bool operator>=(const S &p, const swapped_t v);
|
friend bool operator>=(const S &p, const swapped_t v);
|
||||||
|
|
||||||
template <typename S, typename T2, typename F2>
|
template <typename S, typename T2, typename F2>
|
||||||
friend bool operator!=(const S &p, const swapped_t v);
|
friend bool operator!=(const S &p, const swapped_t v);
|
||||||
|
|
||||||
template <typename S, typename T2, typename F2>
|
template <typename S, typename T2, typename F2>
|
||||||
friend bool operator==(const S &p, const swapped_t v);
|
friend bool operator==(const S &p, const swapped_t v);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// Arithmetics
|
// Arithmetics
|
||||||
template <typename S, typename T, typename F>
|
template <typename S, typename T, typename F>
|
||||||
S operator+(const S &i, const swap_struct_t<T, F> v) {
|
S operator+(const S &i, const swap_struct_t<T, F> v) {
|
||||||
return i + v.swap();
|
return i + v.swap();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename S, typename T, typename F>
|
template <typename S, typename T, typename F>
|
||||||
S operator-(const S &i, const swap_struct_t<T, F> v) {
|
S operator-(const S &i, const swap_struct_t<T, F> v) {
|
||||||
return i - v.swap();
|
return i - v.swap();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename S, typename T, typename F>
|
template <typename S, typename T, typename F>
|
||||||
S operator/(const S &i, const swap_struct_t<T, F> v) {
|
S operator/(const S &i, const swap_struct_t<T, F> v) {
|
||||||
return i / v.swap();
|
return i / v.swap();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename S, typename T, typename F>
|
template <typename S, typename T, typename F>
|
||||||
S operator*(const S &i, const swap_struct_t<T, F> v) {
|
S operator*(const S &i, const swap_struct_t<T, F> v) {
|
||||||
return i * v.swap();
|
return i * v.swap();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename S, typename T, typename F>
|
template <typename S, typename T, typename F>
|
||||||
S operator%(const S &i, const swap_struct_t<T, F> v) {
|
S operator%(const S &i, const swap_struct_t<T, F> v) {
|
||||||
return i % v.swap();
|
return i % v.swap();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Arithmetics + assignements
|
// Arithmetics + assignements
|
||||||
template <typename S, typename T, typename F>
|
template <typename S, typename T, typename F>
|
||||||
S &operator+=(S &i, const swap_struct_t<T, F> v) {
|
S &operator+=(S &i, const swap_struct_t<T, F> v) {
|
||||||
i += v.swap();
|
i += v.swap();
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename S, typename T, typename F>
|
template <typename S, typename T, typename F>
|
||||||
S &operator-=(S &i, const swap_struct_t<T, F> v) {
|
S &operator-=(S &i, const swap_struct_t<T, F> v) {
|
||||||
i -= v.swap();
|
i -= v.swap();
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Logical
|
// Logical
|
||||||
template <typename S, typename T, typename F>
|
template <typename S, typename T, typename F>
|
||||||
S operator&(const S &i, const swap_struct_t<T, F> v) {
|
S operator&(const S &i, const swap_struct_t<T, F> v) {
|
||||||
return i & v.swap();
|
return i & v.swap();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename S, typename T, typename F>
|
template <typename S, typename T, typename F>
|
||||||
S operator&(const swap_struct_t<T, F> v, const S &i) {
|
S operator&(const swap_struct_t<T, F> v, const S &i) {
|
||||||
return (S)(v.swap() & i);
|
return (S)(v.swap() & i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Comparaison
|
// Comparaison
|
||||||
template <typename S, typename T, typename F>
|
template <typename S, typename T, typename F>
|
||||||
bool operator<(const S &p, const swap_struct_t<T, F> v) {
|
bool operator<(const S &p, const swap_struct_t<T, F> v) {
|
||||||
return p < v.swap();
|
return p < v.swap();
|
||||||
}
|
}
|
||||||
template <typename S, typename T, typename F>
|
template <typename S, typename T, typename F>
|
||||||
bool operator>(const S &p, const swap_struct_t<T, F> v) {
|
bool operator>(const S &p, const swap_struct_t<T, F> v) {
|
||||||
return p > v.swap();
|
return p > v.swap();
|
||||||
}
|
}
|
||||||
template <typename S, typename T, typename F>
|
template <typename S, typename T, typename F>
|
||||||
bool operator<=(const S &p, const swap_struct_t<T, F> v) {
|
bool operator<=(const S &p, const swap_struct_t<T, F> v) {
|
||||||
return p <= v.swap();
|
return p <= v.swap();
|
||||||
}
|
}
|
||||||
template <typename S, typename T, typename F>
|
template <typename S, typename T, typename F>
|
||||||
bool operator>=(const S &p, const swap_struct_t<T, F> v) {
|
bool operator>=(const S &p, const swap_struct_t<T, F> v) {
|
||||||
return p >= v.swap();
|
return p >= v.swap();
|
||||||
}
|
}
|
||||||
template <typename S, typename T, typename F>
|
template <typename S, typename T, typename F>
|
||||||
bool operator!=(const S &p, const swap_struct_t<T, F> v) {
|
bool operator!=(const S &p, const swap_struct_t<T, F> v) {
|
||||||
return p != v.swap();
|
return p != v.swap();
|
||||||
}
|
}
|
||||||
template <typename S, typename T, typename F>
|
template <typename S, typename T, typename F>
|
||||||
bool operator==(const S &p, const swap_struct_t<T, F> v) {
|
bool operator==(const S &p, const swap_struct_t<T, F> v) {
|
||||||
return p == v.swap();
|
return p == v.swap();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct swap_64_t {
|
struct swap_64_t {
|
||||||
static T swap(T x) {
|
static T swap(T x) {
|
||||||
return (T)bswap64(*(u64 *)&x);
|
return (T)bswap64(*(u64 *)&x);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct swap_32_t {
|
struct swap_32_t {
|
||||||
static T swap(T x) {
|
static T swap(T x) {
|
||||||
return (T)bswap32(*(u32 *)&x);
|
return (T)bswap32(*(u32 *)&x);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct swap_16_t {
|
struct swap_16_t {
|
||||||
static T swap(T x) {
|
static T swap(T x) {
|
||||||
return (T)bswap16(*(u16 *)&x);
|
return (T)bswap16(*(u16 *)&x);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct swap_float_t {
|
struct swap_float_t {
|
||||||
static T swap(T x) {
|
static T swap(T x) {
|
||||||
return (T)bswapf(*(float *)&x);
|
return (T)bswapf(*(float *)&x);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct swap_double_t {
|
struct swap_double_t {
|
||||||
static T swap(T x) {
|
static T swap(T x) {
|
||||||
return (T)bswapd(*(double *)&x);
|
return (T)bswapd(*(double *)&x);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#if COMMON_LITTLE_ENDIAN
|
#if COMMON_LITTLE_ENDIAN
|
||||||
|
|
|
@ -21,110 +21,110 @@ namespace Common
|
||||||
int CurrentThreadId()
|
int CurrentThreadId()
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
return GetCurrentThreadId();
|
return GetCurrentThreadId();
|
||||||
#elif defined __APPLE__
|
#elif defined __APPLE__
|
||||||
return mach_thread_self();
|
return mach_thread_self();
|
||||||
#else
|
#else
|
||||||
return 0;
|
return 0;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
|
||||||
void SetThreadAffinity(std::thread::native_handle_type thread, u32 mask)
|
void SetThreadAffinity(std::thread::native_handle_type thread, u32 mask)
|
||||||
{
|
{
|
||||||
SetThreadAffinityMask(thread, mask);
|
SetThreadAffinityMask(thread, mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetCurrentThreadAffinity(u32 mask)
|
void SetCurrentThreadAffinity(u32 mask)
|
||||||
{
|
{
|
||||||
SetThreadAffinityMask(GetCurrentThread(), mask);
|
SetThreadAffinityMask(GetCurrentThread(), mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Supporting functions
|
// Supporting functions
|
||||||
void SleepCurrentThread(int ms)
|
void SleepCurrentThread(int ms)
|
||||||
{
|
{
|
||||||
Sleep(ms);
|
Sleep(ms);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SwitchCurrentThread()
|
void SwitchCurrentThread()
|
||||||
{
|
{
|
||||||
SwitchToThread();
|
SwitchToThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sets the debugger-visible name of the current thread.
|
// Sets the debugger-visible name of the current thread.
|
||||||
// Uses undocumented (actually, it is now documented) trick.
|
// Uses undocumented (actually, it is now documented) trick.
|
||||||
// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vsdebug/html/vxtsksettingthreadname.asp
|
// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vsdebug/html/vxtsksettingthreadname.asp
|
||||||
|
|
||||||
// This is implemented much nicer in upcoming msvc++, see:
|
// This is implemented much nicer in upcoming msvc++, see:
|
||||||
// http://msdn.microsoft.com/en-us/library/xcb2z8hs(VS.100).aspx
|
// http://msdn.microsoft.com/en-us/library/xcb2z8hs(VS.100).aspx
|
||||||
void SetCurrentThreadName(const char* szThreadName)
|
void SetCurrentThreadName(const char* szThreadName)
|
||||||
{
|
{
|
||||||
static const DWORD MS_VC_EXCEPTION = 0x406D1388;
|
static const DWORD MS_VC_EXCEPTION = 0x406D1388;
|
||||||
|
|
||||||
#pragma pack(push,8)
|
#pragma pack(push,8)
|
||||||
struct THREADNAME_INFO
|
struct THREADNAME_INFO
|
||||||
{
|
{
|
||||||
DWORD dwType; // must be 0x1000
|
DWORD dwType; // must be 0x1000
|
||||||
LPCSTR szName; // pointer to name (in user addr space)
|
LPCSTR szName; // pointer to name (in user addr space)
|
||||||
DWORD dwThreadID; // thread ID (-1=caller thread)
|
DWORD dwThreadID; // thread ID (-1=caller thread)
|
||||||
DWORD dwFlags; // reserved for future use, must be zero
|
DWORD dwFlags; // reserved for future use, must be zero
|
||||||
} info;
|
} info;
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
info.dwType = 0x1000;
|
info.dwType = 0x1000;
|
||||||
info.szName = szThreadName;
|
info.szName = szThreadName;
|
||||||
info.dwThreadID = -1; //dwThreadID;
|
info.dwThreadID = -1; //dwThreadID;
|
||||||
info.dwFlags = 0;
|
info.dwFlags = 0;
|
||||||
|
|
||||||
__try
|
__try
|
||||||
{
|
{
|
||||||
RaiseException(MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(ULONG_PTR), (ULONG_PTR*)&info);
|
RaiseException(MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(ULONG_PTR), (ULONG_PTR*)&info);
|
||||||
}
|
}
|
||||||
__except(EXCEPTION_CONTINUE_EXECUTION)
|
__except(EXCEPTION_CONTINUE_EXECUTION)
|
||||||
{}
|
{}
|
||||||
}
|
}
|
||||||
|
|
||||||
#else // !WIN32, so must be POSIX threads
|
#else // !WIN32, so must be POSIX threads
|
||||||
|
|
||||||
void SetThreadAffinity(std::thread::native_handle_type thread, u32 mask)
|
void SetThreadAffinity(std::thread::native_handle_type thread, u32 mask)
|
||||||
{
|
{
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
thread_policy_set(pthread_mach_thread_np(thread),
|
thread_policy_set(pthread_mach_thread_np(thread),
|
||||||
THREAD_AFFINITY_POLICY, (integer_t *)&mask, 1);
|
THREAD_AFFINITY_POLICY, (integer_t *)&mask, 1);
|
||||||
#elif (defined __linux__ || defined BSD4_4) && !(defined ANDROID)
|
#elif (defined __linux__ || defined BSD4_4) && !(defined ANDROID)
|
||||||
cpu_set_t cpu_set;
|
cpu_set_t cpu_set;
|
||||||
CPU_ZERO(&cpu_set);
|
CPU_ZERO(&cpu_set);
|
||||||
|
|
||||||
for (int i = 0; i != sizeof(mask) * 8; ++i)
|
for (int i = 0; i != sizeof(mask) * 8; ++i)
|
||||||
if ((mask >> i) & 1)
|
if ((mask >> i) & 1)
|
||||||
CPU_SET(i, &cpu_set);
|
CPU_SET(i, &cpu_set);
|
||||||
|
|
||||||
pthread_setaffinity_np(thread, sizeof(cpu_set), &cpu_set);
|
pthread_setaffinity_np(thread, sizeof(cpu_set), &cpu_set);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetCurrentThreadAffinity(u32 mask)
|
void SetCurrentThreadAffinity(u32 mask)
|
||||||
{
|
{
|
||||||
SetThreadAffinity(pthread_self(), mask);
|
SetThreadAffinity(pthread_self(), mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SleepCurrentThread(int ms)
|
void SleepCurrentThread(int ms)
|
||||||
{
|
{
|
||||||
usleep(1000 * ms);
|
usleep(1000 * ms);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SwitchCurrentThread()
|
void SwitchCurrentThread()
|
||||||
{
|
{
|
||||||
usleep(1000 * 1);
|
usleep(1000 * 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetCurrentThreadName(const char* szThreadName)
|
void SetCurrentThreadName(const char* szThreadName)
|
||||||
{
|
{
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
pthread_setname_np(szThreadName);
|
pthread_setname_np(szThreadName);
|
||||||
#else
|
#else
|
||||||
pthread_setname_np(pthread_self(), szThreadName);
|
pthread_setname_np(pthread_self(), szThreadName);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,125 +32,125 @@ int CurrentThreadId();
|
||||||
|
|
||||||
void SetThreadAffinity(std::thread::native_handle_type thread, u32 mask);
|
void SetThreadAffinity(std::thread::native_handle_type thread, u32 mask);
|
||||||
void SetCurrentThreadAffinity(u32 mask);
|
void SetCurrentThreadAffinity(u32 mask);
|
||||||
|
|
||||||
class Event
|
class Event
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Event()
|
Event()
|
||||||
: is_set(false)
|
: is_set(false)
|
||||||
{};
|
{};
|
||||||
|
|
||||||
void Set()
|
void Set()
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lk(m_mutex);
|
std::lock_guard<std::mutex> lk(m_mutex);
|
||||||
if (!is_set)
|
if (!is_set)
|
||||||
{
|
{
|
||||||
is_set = true;
|
is_set = true;
|
||||||
m_condvar.notify_one();
|
m_condvar.notify_one();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Wait()
|
void Wait()
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lk(m_mutex);
|
std::unique_lock<std::mutex> lk(m_mutex);
|
||||||
m_condvar.wait(lk, IsSet(this));
|
m_condvar.wait(lk, IsSet(this));
|
||||||
is_set = false;
|
is_set = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Reset()
|
void Reset()
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lk(m_mutex);
|
std::unique_lock<std::mutex> lk(m_mutex);
|
||||||
// no other action required, since wait loops on the predicate and any lingering signal will get cleared on the first iteration
|
// no other action required, since wait loops on the predicate and any lingering signal will get cleared on the first iteration
|
||||||
is_set = false;
|
is_set = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class IsSet
|
class IsSet
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
IsSet(const Event* ev)
|
IsSet(const Event* ev)
|
||||||
: m_event(ev)
|
: m_event(ev)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
bool operator()()
|
bool operator()()
|
||||||
{
|
{
|
||||||
return m_event->is_set;
|
return m_event->is_set;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const Event* const m_event;
|
const Event* const m_event;
|
||||||
};
|
};
|
||||||
|
|
||||||
volatile bool is_set;
|
volatile bool is_set;
|
||||||
std::condition_variable m_condvar;
|
std::condition_variable m_condvar;
|
||||||
std::mutex m_mutex;
|
std::mutex m_mutex;
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: doesn't work on windows with (count > 2)
|
// TODO: doesn't work on windows with (count > 2)
|
||||||
class Barrier
|
class Barrier
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Barrier(size_t count)
|
Barrier(size_t count)
|
||||||
: m_count(count), m_waiting(0)
|
: m_count(count), m_waiting(0)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
// block until "count" threads call Sync()
|
// block until "count" threads call Sync()
|
||||||
bool Sync()
|
bool Sync()
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lk(m_mutex);
|
std::unique_lock<std::mutex> lk(m_mutex);
|
||||||
|
|
||||||
// TODO: broken when next round of Sync()s
|
// TODO: broken when next round of Sync()s
|
||||||
// is entered before all waiting threads return from the notify_all
|
// is entered before all waiting threads return from the notify_all
|
||||||
|
|
||||||
if (m_count == ++m_waiting)
|
if (m_count == ++m_waiting)
|
||||||
{
|
{
|
||||||
m_waiting = 0;
|
m_waiting = 0;
|
||||||
m_condvar.notify_all();
|
m_condvar.notify_all();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_condvar.wait(lk, IsDoneWating(this));
|
m_condvar.wait(lk, IsDoneWating(this));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class IsDoneWating
|
class IsDoneWating
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
IsDoneWating(const Barrier* bar)
|
IsDoneWating(const Barrier* bar)
|
||||||
: m_bar(bar)
|
: m_bar(bar)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
bool operator()()
|
bool operator()()
|
||||||
{
|
{
|
||||||
return (0 == m_bar->m_waiting);
|
return (0 == m_bar->m_waiting);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const Barrier* const m_bar;
|
const Barrier* const m_bar;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::condition_variable m_condvar;
|
std::condition_variable m_condvar;
|
||||||
std::mutex m_mutex;
|
std::mutex m_mutex;
|
||||||
const size_t m_count;
|
const size_t m_count;
|
||||||
volatile size_t m_waiting;
|
volatile size_t m_waiting;
|
||||||
};
|
};
|
||||||
|
|
||||||
void SleepCurrentThread(int ms);
|
void SleepCurrentThread(int ms);
|
||||||
void SwitchCurrentThread(); // On Linux, this is equal to sleep 1ms
|
void SwitchCurrentThread(); // On Linux, this is equal to sleep 1ms
|
||||||
|
|
||||||
// Use this function during a spin-wait to make the current thread
|
// Use this function during a spin-wait to make the current thread
|
||||||
// relax while another thread is working. This may be more efficient
|
// relax while another thread is working. This may be more efficient
|
||||||
// than using events because event functions use kernel calls.
|
// than using events because event functions use kernel calls.
|
||||||
inline void YieldCPU()
|
inline void YieldCPU()
|
||||||
{
|
{
|
||||||
std::this_thread::yield();
|
std::this_thread::yield();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetCurrentThreadName(const char *name);
|
void SetCurrentThreadName(const char *name);
|
||||||
|
|
||||||
} // namespace Common
|
} // namespace Common
|
||||||
|
|
||||||
#endif // _THREAD_H_
|
#endif // _THREAD_H_
|
||||||
|
|
|
@ -24,23 +24,23 @@
|
||||||
|
|
||||||
class ThunkManager : public Gen::XCodeBlock
|
class ThunkManager : public Gen::XCodeBlock
|
||||||
{
|
{
|
||||||
std::map<void *, const u8 *> thunks;
|
std::map<void *, const u8 *> thunks;
|
||||||
|
|
||||||
const u8 *save_regs;
|
const u8 *save_regs;
|
||||||
const u8 *load_regs;
|
const u8 *load_regs;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ThunkManager() {
|
ThunkManager() {
|
||||||
Init();
|
Init();
|
||||||
}
|
}
|
||||||
~ThunkManager() {
|
~ThunkManager() {
|
||||||
Shutdown();
|
Shutdown();
|
||||||
}
|
}
|
||||||
void *ProtectFunction(void *function, int num_params);
|
void *ProtectFunction(void *function, int num_params);
|
||||||
private:
|
private:
|
||||||
void Init();
|
void Init();
|
||||||
void Shutdown();
|
void Shutdown();
|
||||||
void Reset();
|
void Reset();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _THUNK_H_
|
#endif // _THUNK_H_
|
||||||
|
|
|
@ -22,11 +22,11 @@ namespace Common
|
||||||
u32 Timer::GetTimeMs()
|
u32 Timer::GetTimeMs()
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
return timeGetTime();
|
return timeGetTime();
|
||||||
#else
|
#else
|
||||||
struct timeval t;
|
struct timeval t;
|
||||||
(void)gettimeofday(&t, NULL);
|
(void)gettimeofday(&t, NULL);
|
||||||
return ((u32)(t.tv_sec * 1000 + t.tv_usec / 1000));
|
return ((u32)(t.tv_sec * 1000 + t.tv_usec / 1000));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,31 +36,31 @@ u32 Timer::GetTimeMs()
|
||||||
|
|
||||||
// Set initial values for the class
|
// Set initial values for the class
|
||||||
Timer::Timer()
|
Timer::Timer()
|
||||||
: m_LastTime(0), m_StartTime(0), m_Running(false)
|
: m_LastTime(0), m_StartTime(0), m_Running(false)
|
||||||
{
|
{
|
||||||
Update();
|
Update();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write the starting time
|
// Write the starting time
|
||||||
void Timer::Start()
|
void Timer::Start()
|
||||||
{
|
{
|
||||||
m_StartTime = GetTimeMs();
|
m_StartTime = GetTimeMs();
|
||||||
m_Running = true;
|
m_Running = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stop the timer
|
// Stop the timer
|
||||||
void Timer::Stop()
|
void Timer::Stop()
|
||||||
{
|
{
|
||||||
// Write the final time
|
// Write the final time
|
||||||
m_LastTime = GetTimeMs();
|
m_LastTime = GetTimeMs();
|
||||||
m_Running = false;
|
m_Running = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the last time variable
|
// Update the last time variable
|
||||||
void Timer::Update()
|
void Timer::Update()
|
||||||
{
|
{
|
||||||
m_LastTime = GetTimeMs();
|
m_LastTime = GetTimeMs();
|
||||||
//TODO(ector) - QPF
|
//TODO(ector) - QPF
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------
|
// -------------------------------------
|
||||||
|
@ -70,125 +70,125 @@ void Timer::Update()
|
||||||
// Get the number of milliseconds since the last Update()
|
// Get the number of milliseconds since the last Update()
|
||||||
u64 Timer::GetTimeDifference()
|
u64 Timer::GetTimeDifference()
|
||||||
{
|
{
|
||||||
return GetTimeMs() - m_LastTime;
|
return GetTimeMs() - m_LastTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the time difference since the last Update() to the starting time.
|
// Add the time difference since the last Update() to the starting time.
|
||||||
// This is used to compensate for a paused game.
|
// This is used to compensate for a paused game.
|
||||||
void Timer::AddTimeDifference()
|
void Timer::AddTimeDifference()
|
||||||
{
|
{
|
||||||
m_StartTime += GetTimeDifference();
|
m_StartTime += GetTimeDifference();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the time elapsed since the Start()
|
// Get the time elapsed since the Start()
|
||||||
u64 Timer::GetTimeElapsed()
|
u64 Timer::GetTimeElapsed()
|
||||||
{
|
{
|
||||||
// If we have not started yet, return 1 (because then I don't
|
// If we have not started yet, return 1 (because then I don't
|
||||||
// have to change the FPS calculation in CoreRerecording.cpp .
|
// have to change the FPS calculation in CoreRerecording.cpp .
|
||||||
if (m_StartTime == 0) return 1;
|
if (m_StartTime == 0) return 1;
|
||||||
|
|
||||||
// Return the final timer time if the timer is stopped
|
// Return the final timer time if the timer is stopped
|
||||||
if (!m_Running) return (m_LastTime - m_StartTime);
|
if (!m_Running) return (m_LastTime - m_StartTime);
|
||||||
|
|
||||||
return (GetTimeMs() - m_StartTime);
|
return (GetTimeMs() - m_StartTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the formatted time elapsed since the Start()
|
// Get the formatted time elapsed since the Start()
|
||||||
std::string Timer::GetTimeElapsedFormatted() const
|
std::string Timer::GetTimeElapsedFormatted() const
|
||||||
{
|
{
|
||||||
// If we have not started yet, return zero
|
// If we have not started yet, return zero
|
||||||
if (m_StartTime == 0)
|
if (m_StartTime == 0)
|
||||||
return "00:00:00:000";
|
return "00:00:00:000";
|
||||||
|
|
||||||
// The number of milliseconds since the start.
|
// The number of milliseconds since the start.
|
||||||
// Use a different value if the timer is stopped.
|
// Use a different value if the timer is stopped.
|
||||||
u64 Milliseconds;
|
u64 Milliseconds;
|
||||||
if (m_Running)
|
if (m_Running)
|
||||||
Milliseconds = GetTimeMs() - m_StartTime;
|
Milliseconds = GetTimeMs() - m_StartTime;
|
||||||
else
|
else
|
||||||
Milliseconds = m_LastTime - m_StartTime;
|
Milliseconds = m_LastTime - m_StartTime;
|
||||||
// Seconds
|
// Seconds
|
||||||
u32 Seconds = (u32)(Milliseconds / 1000);
|
u32 Seconds = (u32)(Milliseconds / 1000);
|
||||||
// Minutes
|
// Minutes
|
||||||
u32 Minutes = Seconds / 60;
|
u32 Minutes = Seconds / 60;
|
||||||
// Hours
|
// Hours
|
||||||
u32 Hours = Minutes / 60;
|
u32 Hours = Minutes / 60;
|
||||||
|
|
||||||
std::string TmpStr = StringFromFormat("%02i:%02i:%02i:%03i",
|
std::string TmpStr = StringFromFormat("%02i:%02i:%02i:%03i",
|
||||||
Hours, Minutes % 60, Seconds % 60, Milliseconds % 1000);
|
Hours, Minutes % 60, Seconds % 60, Milliseconds % 1000);
|
||||||
return TmpStr;
|
return TmpStr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get current time
|
// Get current time
|
||||||
void Timer::IncreaseResolution()
|
void Timer::IncreaseResolution()
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
timeBeginPeriod(1);
|
timeBeginPeriod(1);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Timer::RestoreResolution()
|
void Timer::RestoreResolution()
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
timeEndPeriod(1);
|
timeEndPeriod(1);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the number of seconds since January 1 1970
|
// Get the number of seconds since January 1 1970
|
||||||
u64 Timer::GetTimeSinceJan1970()
|
u64 Timer::GetTimeSinceJan1970()
|
||||||
{
|
{
|
||||||
time_t ltime;
|
time_t ltime;
|
||||||
time(<ime);
|
time(<ime);
|
||||||
return((u64)ltime);
|
return((u64)ltime);
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 Timer::GetLocalTimeSinceJan1970()
|
u64 Timer::GetLocalTimeSinceJan1970()
|
||||||
{
|
{
|
||||||
time_t sysTime, tzDiff, tzDST;
|
time_t sysTime, tzDiff, tzDST;
|
||||||
struct tm * gmTime;
|
struct tm * gmTime;
|
||||||
|
|
||||||
time(&sysTime);
|
time(&sysTime);
|
||||||
|
|
||||||
// Account for DST where needed
|
// Account for DST where needed
|
||||||
gmTime = localtime(&sysTime);
|
gmTime = localtime(&sysTime);
|
||||||
if(gmTime->tm_isdst == 1)
|
if(gmTime->tm_isdst == 1)
|
||||||
tzDST = 3600;
|
tzDST = 3600;
|
||||||
else
|
else
|
||||||
tzDST = 0;
|
tzDST = 0;
|
||||||
|
|
||||||
// Lazy way to get local time in sec
|
// Lazy way to get local time in sec
|
||||||
gmTime = gmtime(&sysTime);
|
gmTime = gmtime(&sysTime);
|
||||||
tzDiff = sysTime - mktime(gmTime);
|
tzDiff = sysTime - mktime(gmTime);
|
||||||
|
|
||||||
return (u64)(sysTime + tzDiff + tzDST);
|
return (u64)(sysTime + tzDiff + tzDST);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the current time formatted as Minutes:Seconds:Milliseconds
|
// Return the current time formatted as Minutes:Seconds:Milliseconds
|
||||||
// in the form 00:00:000.
|
// in the form 00:00:000.
|
||||||
std::string Timer::GetTimeFormatted()
|
std::string Timer::GetTimeFormatted()
|
||||||
{
|
{
|
||||||
time_t sysTime;
|
time_t sysTime;
|
||||||
struct tm * gmTime;
|
struct tm * gmTime;
|
||||||
char formattedTime[13];
|
char formattedTime[13];
|
||||||
char tmp[13];
|
char tmp[13];
|
||||||
|
|
||||||
time(&sysTime);
|
time(&sysTime);
|
||||||
gmTime = localtime(&sysTime);
|
gmTime = localtime(&sysTime);
|
||||||
|
|
||||||
strftime(tmp, 6, "%M:%S", gmTime);
|
strftime(tmp, 6, "%M:%S", gmTime);
|
||||||
|
|
||||||
// Now tack on the milliseconds
|
// Now tack on the milliseconds
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
struct timeb tp;
|
struct timeb tp;
|
||||||
(void)::ftime(&tp);
|
(void)::ftime(&tp);
|
||||||
sprintf(formattedTime, "%s:%03i", tmp, tp.millitm);
|
sprintf(formattedTime, "%s:%03i", tmp, tp.millitm);
|
||||||
#else
|
#else
|
||||||
struct timeval t;
|
struct timeval t;
|
||||||
(void)gettimeofday(&t, NULL);
|
(void)gettimeofday(&t, NULL);
|
||||||
sprintf(formattedTime, "%s:%03d", tmp, (int)(t.tv_usec / 1000));
|
sprintf(formattedTime, "%s:%03d", tmp, (int)(t.tv_usec / 1000));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return std::string(formattedTime);
|
return std::string(formattedTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns a timestamp with decimals for precise time comparisons
|
// Returns a timestamp with decimals for precise time comparisons
|
||||||
|
@ -196,31 +196,31 @@ std::string Timer::GetTimeFormatted()
|
||||||
double Timer::GetDoubleTime()
|
double Timer::GetDoubleTime()
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
struct timeb tp;
|
struct timeb tp;
|
||||||
(void)::ftime(&tp);
|
(void)::ftime(&tp);
|
||||||
#else
|
#else
|
||||||
struct timeval t;
|
struct timeval t;
|
||||||
(void)gettimeofday(&t, NULL);
|
(void)gettimeofday(&t, NULL);
|
||||||
#endif
|
#endif
|
||||||
// Get continuous timestamp
|
// Get continuous timestamp
|
||||||
u64 TmpSeconds = Common::Timer::GetTimeSinceJan1970();
|
u64 TmpSeconds = Common::Timer::GetTimeSinceJan1970();
|
||||||
|
|
||||||
// Remove a few years. We only really want enough seconds to make
|
// Remove a few years. We only really want enough seconds to make
|
||||||
// sure that we are detecting actual actions, perhaps 60 seconds is
|
// sure that we are detecting actual actions, perhaps 60 seconds is
|
||||||
// enough really, but I leave a year of seconds anyway, in case the
|
// enough really, but I leave a year of seconds anyway, in case the
|
||||||
// user's clock is incorrect or something like that.
|
// user's clock is incorrect or something like that.
|
||||||
TmpSeconds = TmpSeconds - (38 * 365 * 24 * 60 * 60);
|
TmpSeconds = TmpSeconds - (38 * 365 * 24 * 60 * 60);
|
||||||
|
|
||||||
// Make a smaller integer that fits in the double
|
// Make a smaller integer that fits in the double
|
||||||
u32 Seconds = (u32)TmpSeconds;
|
u32 Seconds = (u32)TmpSeconds;
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
double ms = tp.millitm / 1000.0 / 1000.0;
|
double ms = tp.millitm / 1000.0 / 1000.0;
|
||||||
#else
|
#else
|
||||||
double ms = t.tv_usec / 1000000.0;
|
double ms = t.tv_usec / 1000000.0;
|
||||||
#endif
|
#endif
|
||||||
double TmpTime = Seconds + ms;
|
double TmpTime = Seconds + ms;
|
||||||
|
|
||||||
return TmpTime;
|
return TmpTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // Namespace Common
|
} // Namespace Common
|
||||||
|
|
|
@ -13,32 +13,32 @@ namespace Common
|
||||||
class Timer
|
class Timer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Timer();
|
Timer();
|
||||||
|
|
||||||
void Start();
|
void Start();
|
||||||
void Stop();
|
void Stop();
|
||||||
void Update();
|
void Update();
|
||||||
|
|
||||||
// The time difference is always returned in milliseconds, regardless of alternative internal representation
|
// The time difference is always returned in milliseconds, regardless of alternative internal representation
|
||||||
u64 GetTimeDifference();
|
u64 GetTimeDifference();
|
||||||
void AddTimeDifference();
|
void AddTimeDifference();
|
||||||
|
|
||||||
static void IncreaseResolution();
|
static void IncreaseResolution();
|
||||||
static void RestoreResolution();
|
static void RestoreResolution();
|
||||||
static u64 GetTimeSinceJan1970();
|
static u64 GetTimeSinceJan1970();
|
||||||
static u64 GetLocalTimeSinceJan1970();
|
static u64 GetLocalTimeSinceJan1970();
|
||||||
static double GetDoubleTime();
|
static double GetDoubleTime();
|
||||||
|
|
||||||
static std::string GetTimeFormatted();
|
static std::string GetTimeFormatted();
|
||||||
std::string GetTimeElapsedFormatted() const;
|
std::string GetTimeElapsedFormatted() const;
|
||||||
u64 GetTimeElapsed();
|
u64 GetTimeElapsed();
|
||||||
|
|
||||||
static u32 GetTimeMs();
|
static u32 GetTimeMs();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
u64 m_LastTime;
|
u64 m_LastTime;
|
||||||
u64 m_StartTime;
|
u64 m_StartTime;
|
||||||
bool m_Running;
|
bool m_Running;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // Namespace Common
|
} // Namespace Common
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
|
|
||||||
// is start of UTF sequence
|
// is start of UTF sequence
|
||||||
inline bool isutf(char c) {
|
inline bool isutf(char c) {
|
||||||
return (c & 0xC0) != 0x80;
|
return (c & 0xC0) != 0x80;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const u32 offsetsFromUTF8[6] = {
|
static const u32 offsetsFromUTF8[6] = {
|
||||||
|
@ -47,7 +47,7 @@ static const u8 trailingBytesForUTF8[256] = {
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||||
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5,
|
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* returns length of next utf-8 sequence */
|
/* returns length of next utf-8 sequence */
|
||||||
|
@ -405,59 +405,59 @@ int u8_is_locale_utf8(const char *locale)
|
||||||
}
|
}
|
||||||
|
|
||||||
int UTF8StringNonASCIICount(const char *utf8string) {
|
int UTF8StringNonASCIICount(const char *utf8string) {
|
||||||
UTF8 utf(utf8string);
|
UTF8 utf(utf8string);
|
||||||
int count = 0;
|
int count = 0;
|
||||||
while (!utf.end()) {
|
while (!utf.end()) {
|
||||||
int c = utf.next();
|
int c = utf.next();
|
||||||
if (c > 127)
|
if (c > 127)
|
||||||
++count;
|
++count;
|
||||||
}
|
}
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UTF8StringHasNonASCII(const char *utf8string) {
|
bool UTF8StringHasNonASCII(const char *utf8string) {
|
||||||
return UTF8StringNonASCIICount(utf8string) > 0;
|
return UTF8StringNonASCIICount(utf8string) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
|
||||||
std::string ConvertWStringToUTF8(const wchar_t *wstr) {
|
std::string ConvertWStringToUTF8(const wchar_t *wstr) {
|
||||||
int len = (int)wcslen(wstr);
|
int len = (int)wcslen(wstr);
|
||||||
int size = (int)WideCharToMultiByte(CP_UTF8, 0, wstr, len, 0, 0, NULL, NULL);
|
int size = (int)WideCharToMultiByte(CP_UTF8, 0, wstr, len, 0, 0, NULL, NULL);
|
||||||
std::string s;
|
std::string s;
|
||||||
s.resize(size);
|
s.resize(size);
|
||||||
if (size > 0) {
|
if (size > 0) {
|
||||||
WideCharToMultiByte(CP_UTF8, 0, wstr, len, &s[0], size, NULL, NULL);
|
WideCharToMultiByte(CP_UTF8, 0, wstr, len, &s[0], size, NULL, NULL);
|
||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ConvertWStringToUTF8(const std::wstring &wstr) {
|
std::string ConvertWStringToUTF8(const std::wstring &wstr) {
|
||||||
int len = (int)wstr.size();
|
int len = (int)wstr.size();
|
||||||
int size = (int)WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), len, 0, 0, NULL, NULL);
|
int size = (int)WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), len, 0, 0, NULL, NULL);
|
||||||
std::string s;
|
std::string s;
|
||||||
s.resize(size);
|
s.resize(size);
|
||||||
if (size > 0) {
|
if (size > 0) {
|
||||||
WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), len, &s[0], size, NULL, NULL);
|
WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), len, &s[0], size, NULL, NULL);
|
||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConvertUTF8ToWString(wchar_t *dest, size_t destSize, const std::string &source) {
|
void ConvertUTF8ToWString(wchar_t *dest, size_t destSize, const std::string &source) {
|
||||||
int len = (int)source.size();
|
int len = (int)source.size();
|
||||||
int size = (int)MultiByteToWideChar(CP_UTF8, 0, source.c_str(), len, NULL, 0);
|
int size = (int)MultiByteToWideChar(CP_UTF8, 0, source.c_str(), len, NULL, 0);
|
||||||
MultiByteToWideChar(CP_UTF8, 0, source.c_str(), len, dest, std::min((int)destSize, size));
|
MultiByteToWideChar(CP_UTF8, 0, source.c_str(), len, dest, std::min((int)destSize, size));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::wstring ConvertUTF8ToWString(const std::string &source) {
|
std::wstring ConvertUTF8ToWString(const std::string &source) {
|
||||||
int len = (int)source.size();
|
int len = (int)source.size();
|
||||||
int size = (int)MultiByteToWideChar(CP_UTF8, 0, source.c_str(), len, NULL, 0);
|
int size = (int)MultiByteToWideChar(CP_UTF8, 0, source.c_str(), len, NULL, 0);
|
||||||
std::wstring str;
|
std::wstring str;
|
||||||
str.resize(size);
|
str.resize(size);
|
||||||
if (size > 0) {
|
if (size > 0) {
|
||||||
MultiByteToWideChar(CP_UTF8, 0, source.c_str(), len, &str[0], size);
|
MultiByteToWideChar(CP_UTF8, 0, source.c_str(), len, &str[0], size);
|
||||||
}
|
}
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -25,29 +25,29 @@ int u8_strlen(const char *s);
|
||||||
|
|
||||||
class UTF8 {
|
class UTF8 {
|
||||||
public:
|
public:
|
||||||
static const u32 INVALID = (u32)-1;
|
static const u32 INVALID = (u32)-1;
|
||||||
UTF8(const char *c) : c_(c), index_(0) {}
|
UTF8(const char *c) : c_(c), index_(0) {}
|
||||||
bool end() const { return c_[index_] == 0; }
|
bool end() const { return c_[index_] == 0; }
|
||||||
u32 next() {
|
u32 next() {
|
||||||
return u8_nextchar(c_, &index_);
|
return u8_nextchar(c_, &index_);
|
||||||
}
|
}
|
||||||
u32 peek() {
|
u32 peek() {
|
||||||
int tempIndex = index_;
|
int tempIndex = index_;
|
||||||
return u8_nextchar(c_, &tempIndex);
|
return u8_nextchar(c_, &tempIndex);
|
||||||
}
|
}
|
||||||
int length() const {
|
int length() const {
|
||||||
return u8_strlen(c_);
|
return u8_strlen(c_);
|
||||||
}
|
}
|
||||||
int byteIndex() const {
|
int byteIndex() const {
|
||||||
return index_;
|
return index_;
|
||||||
}
|
}
|
||||||
static int encode(char *dest, u32 ch) {
|
static int encode(char *dest, u32 ch) {
|
||||||
return u8_wc_toutf8(dest, ch);
|
return u8_wc_toutf8(dest, ch);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const char *c_;
|
const char *c_;
|
||||||
int index_;
|
int index_;
|
||||||
};
|
};
|
||||||
|
|
||||||
int UTF8StringNonASCIICount(const char *utf8string);
|
int UTF8StringNonASCIICount(const char *utf8string);
|
||||||
|
|
|
@ -6,22 +6,22 @@
|
||||||
#include "scm_rev.h"
|
#include "scm_rev.h"
|
||||||
|
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
#define BUILD_TYPE_STR "Debug "
|
#define BUILD_TYPE_STR "Debug "
|
||||||
#elif defined DEBUGFAST
|
#elif defined DEBUGFAST
|
||||||
#define BUILD_TYPE_STR "DebugFast "
|
#define BUILD_TYPE_STR "DebugFast "
|
||||||
#else
|
#else
|
||||||
#define BUILD_TYPE_STR ""
|
#define BUILD_TYPE_STR ""
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const char *scm_rev_str = "emu "
|
const char *scm_rev_str = "emu "
|
||||||
#if !SCM_IS_MASTER
|
#if !SCM_IS_MASTER
|
||||||
"[" SCM_BRANCH_STR "] "
|
"[" SCM_BRANCH_STR "] "
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __INTEL_COMPILER
|
#ifdef __INTEL_COMPILER
|
||||||
BUILD_TYPE_STR SCM_DESC_STR "-ICC";
|
BUILD_TYPE_STR SCM_DESC_STR "-ICC";
|
||||||
#else
|
#else
|
||||||
BUILD_TYPE_STR SCM_DESC_STR;
|
BUILD_TYPE_STR SCM_DESC_STR;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _M_X64
|
#ifdef _M_X64
|
||||||
|
@ -29,7 +29,7 @@ const char *scm_rev_str = "emu "
|
||||||
#else
|
#else
|
||||||
#ifdef _M_ARM
|
#ifdef _M_ARM
|
||||||
#define NP_ARCH "ARM"
|
#define NP_ARCH "ARM"
|
||||||
#else
|
#else
|
||||||
#define NP_ARCH "x86"
|
#define NP_ARCH "x86"
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue