From 0e30426deff8094dfbe3b087056978815407bd2a Mon Sep 17 00:00:00 2001 From: "Thomas \"elfprince13\" Dickerson" Date: Thu, 5 Jan 2017 17:19:19 -0500 Subject: [PATCH 1/9] Eliminated a handful of deprecation warnings, as well as inconsistent handling of FS operations in OS X --- Engine/source/platform/profiler.cpp | 30 +++--- Engine/source/platformMac/macFileIO.mm | 138 ++++++++++++++----------- 2 files changed, 96 insertions(+), 72 deletions(-) diff --git a/Engine/source/platform/profiler.cpp b/Engine/source/platform/profiler.cpp index c978b9ac2..7460ad315 100644 --- a/Engine/source/platform/profiler.cpp +++ b/Engine/source/platform/profiler.cpp @@ -27,7 +27,7 @@ #endif #if defined(TORQUE_OS_MAC) -#include // For high resolution timer +#include #endif #include "core/stream/fileStream.h" @@ -135,20 +135,26 @@ U32 endHighResolutionTimer(U32 time[2]) void startHighResolutionTimer(U32 time[2]) { - UnsignedWide t; - Microseconds(&t); - time[0] = t.lo; - time[1] = t.hi; + U64 now = mach_absolute_time(); + AssertFatal(sizeof(U32[2]) == sizeof(U64), "Can't pack mach_absolute_time into U32[2]"); + memcpy(time, &now, sizeof(U64)); } U32 endHighResolutionTimer(U32 time[2]) { - UnsignedWide t; - Microseconds(&t); - return t.lo - time[0]; - // given that we're returning a 32 bit integer, and this is unsigned subtraction... - // it will just wrap around, we don't need the upper word of the time. - // NOTE: the code assumes that more than 3 hrs will not go by between calls to startHighResolutionTimer() and endHighResolutionTimer(). - // I mean... that damn well better not happen anyway. + static mach_timebase_info_data_t sTimebaseInfo = {0, 0}; + + U64 now = mach_absolute_time(); + AssertFatal(sizeof(U32[2]) == sizeof(U64), "Can't pack mach_absolute_time into U32[2]"); + U64 then; + memcpy(&then, time, sizeof(U64)); + + if(sTimebaseInfo.denom == 0){ + mach_timebase_info(&sTimebaseInfo); + } + // Handle the micros/nanos conversion first, because shedding a few bits is better than overflowing. + U64 elapsedMicros = ((now - then) / 1000) * sTimebaseInfo.numer / sTimebaseInfo.denom; + + return (U32)elapsedMicros; // Just truncate, and hope we didn't overflow } #else diff --git a/Engine/source/platformMac/macFileIO.mm b/Engine/source/platformMac/macFileIO.mm index 26dca66bb..2815b5af4 100644 --- a/Engine/source/platformMac/macFileIO.mm +++ b/Engine/source/platformMac/macFileIO.mm @@ -68,46 +68,54 @@ bool dFileTouch(const char *path) //----------------------------------------------------------------------------- bool dPathCopy(const char* source, const char* dest, bool nooverwrite) { - NSFileManager *manager = [NSFileManager defaultManager]; - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - - NSString *nsource = [[NSString stringWithUTF8String:source] stringByStandardizingPath]; - NSString *ndest = [[NSString stringWithUTF8String:dest] stringByStandardizingPath]; - NSString *ndestFolder = [ndest stringByDeletingLastPathComponent]; - - if(! [manager fileExistsAtPath:nsource]) - { - Con::errorf("dPathCopy: no file exists at %s",source); - return false; - } - - if( [manager fileExistsAtPath:ndest] ) - { - if(nooverwrite) - { - Con::errorf("dPathCopy: file already exists at %s",dest); - return false; - } - Con::warnf("Deleting files at path: %s", dest); - bool deleted = [manager removeFileAtPath:ndest handler:nil]; - if(!deleted) - { - Con::errorf("Copy failed! Could not delete files at path: %s", dest); - return false; - } - } - - if([manager fileExistsAtPath:ndestFolder] == NO) - { - ndestFolder = [ndestFolder stringByAppendingString:@"/"]; // createpath requires a trailing slash - Platform::createPath([ndestFolder UTF8String]); - } - - bool ret = [manager copyPath:nsource toPath:ndest handler:nil]; - - [pool release]; - return ret; - + if(source == NULL || dest == NULL) + return false; + + @autoreleasepool { + NSFileManager *manager = [NSFileManager defaultManager]; + + NSString *nsource = [manager stringWithFileSystemRepresentation:source length:dStrlen(source)]; + NSString *ndest = [manager stringWithFileSystemRepresentation:dest length:dStrlen(dest)]; + NSString *ndestFolder = [ndest stringByDeletingLastPathComponent]; + + if(! [manager fileExistsAtPath:nsource]) + { + Con::errorf("dPathCopy: no file exists at %s",source); + return false; + } + + if( [manager fileExistsAtPath:ndest] ) + { + if(nooverwrite) + { + Con::errorf("dPathCopy: file already exists at %s",dest); + return false; + } + Con::warnf("Deleting files at path: %s", dest); + if(![manager removeItemAtPath:ndest error:nil] || [manager fileExistsAtPath:ndest]) + { + Con::errorf("Copy failed! Could not delete files at path: %s", dest); + return false; + } + } + + if([manager fileExistsAtPath:ndestFolder] == NO) + { + ndestFolder = [ndestFolder stringByAppendingString:@"/"]; // createpath requires a trailing slash + Platform::createPath([ndestFolder UTF8String]); + } + + bool ret = [manager copyItemAtPath:nsource toPath:ndest error:nil]; + // n.b.: The "success" semantics don't guarantee a copy actually took place, so we'll verify + // because this is surprising behavior for a method called copy. + if( ![manager fileExistsAtPath:ndest] ) + { + Con::warnf("The filemanager returned success, but the file was not copied. Something strange is happening"); + ret = false; + } + return ret; + } + } //----------------------------------------------------------------------------- @@ -116,26 +124,36 @@ bool dFileRename(const char *source, const char *dest) { if(source == NULL || dest == NULL) return false; - - NSFileManager *manager = [NSFileManager defaultManager]; - - NSString *nsource = [manager stringWithFileSystemRepresentation:source length:dStrlen(source)]; - NSString *ndest = [manager stringWithFileSystemRepresentation:dest length:dStrlen(dest)]; - - if(! [manager fileExistsAtPath:nsource]) - { - Con::errorf("dFileRename: no file exists at %s",source); - return false; - } - - if( [manager fileExistsAtPath:ndest] ) - { - Con::warnf("dFileRename: Deleting files at path: %s", dest); - } - - bool ret = [manager movePath:nsource toPath:ndest handler:nil]; - - return ret; + + @autoreleasepool { + NSFileManager *manager = [NSFileManager defaultManager]; + + NSString *nsource = [manager stringWithFileSystemRepresentation:source length:dStrlen(source)]; + NSString *ndest = [manager stringWithFileSystemRepresentation:dest length:dStrlen(dest)]; + + if(! [manager fileExistsAtPath:nsource]) + { + Con::errorf("dFileRename: no file exists at %s",source); + return false; + } + + if( [manager fileExistsAtPath:ndest] ) + { + Con::warnf("dFileRename: Deleting files at path: %s", dest); + } + + bool ret = [manager moveItemAtPath:nsource toPath:ndest error:nil]; + // n.b.: The "success" semantics don't guarantee a move actually took place, so we'll verify + // because this is surprising behavior for a method called rename. + + if( ![manager fileExistsAtPath:ndest] ) + { + Con::warnf("The filemanager returned success, but the file was not moved. Something strange is happening"); + ret = false; + } + + return ret; + } } //----------------------------------------------------------------------------- From 710a2a9b7bbe5c81e5f57a5314a954d0bc5bd971 Mon Sep 17 00:00:00 2001 From: "Thomas \"elfprince13\" Dickerson" Date: Thu, 5 Jan 2017 17:23:48 -0500 Subject: [PATCH 2/9] Revert "Net tests were failing to compile because 'static members' weren't actually being declared as members..." This reverts commit 32f726dcc6727bcba04b5e30e571bdf63b1fbc3c. --- Engine/source/platform/platformNet.cpp | 9 +++++---- Engine/source/platform/platformNet.h | 6 ------ Engine/source/platform/test/netTest.cpp | 16 ++++++++-------- 3 files changed, 13 insertions(+), 18 deletions(-) diff --git a/Engine/source/platform/platformNet.cpp b/Engine/source/platform/platformNet.cpp index b598b96a6..4d5b6ca18 100644 --- a/Engine/source/platform/platformNet.cpp +++ b/Engine/source/platform/platformNet.cpp @@ -491,10 +491,11 @@ template T ReservedSocketList::resolve(NetSocket socketToResolve) EntryType &entry = mSocketList[socketToResolve.getHandle()]; return entry.used ? entry.value : -1; } -ConnectionNotifyEvent* Net::smConnectionNotify = NULL; -ConnectionAcceptedEvent* Net::smConnectionAccept = NULL; -ConnectionReceiveEvent* Net::smConnectionReceive = NULL; -PacketReceiveEvent* Net::smPacketReceive = NULL; + +static ConnectionNotifyEvent* smConnectionNotify = NULL; +static ConnectionAcceptedEvent* smConnectionAccept = NULL; +static ConnectionReceiveEvent* smConnectionReceive = NULL; +static PacketReceiveEvent* smPacketReceive = NULL; ConnectionNotifyEvent& Net::getConnectionNotifyEvent() { diff --git a/Engine/source/platform/platformNet.h b/Engine/source/platform/platformNet.h index 4e8de1d70..1ffb780e9 100644 --- a/Engine/source/platform/platformNet.h +++ b/Engine/source/platform/platformNet.h @@ -214,12 +214,6 @@ struct Net static bool smMulticastEnabled; static bool smIpv4Enabled; static bool smIpv6Enabled; - - static ConnectionNotifyEvent* smConnectionNotify; - static ConnectionAcceptedEvent* smConnectionAccept; - static ConnectionReceiveEvent* smConnectionReceive; - static PacketReceiveEvent* smPacketReceive; - static bool init(); static void shutdown(); diff --git a/Engine/source/platform/test/netTest.cpp b/Engine/source/platform/test/netTest.cpp index 741e89ce0..889d150f2 100644 --- a/Engine/source/platform/test/netTest.cpp +++ b/Engine/source/platform/test/netTest.cpp @@ -76,8 +76,8 @@ TEST(Net, TCPRequest) handler.mDataReceived = 0; // Hook into the signals. - Net::smConnectionNotify ->notify(&handler, &TcpHandle::notify); - Net::smConnectionReceive->notify(&handler, &TcpHandle::receive); + Net::smConnectionNotify .notify(&handler, &TcpHandle::notify); + Net::smConnectionReceive.notify(&handler, &TcpHandle::receive); // Open a TCP connection to garagegames.com handler.mSocket = Net::openConnectTo("72.246.107.193:80"); @@ -85,8 +85,8 @@ TEST(Net, TCPRequest) while(Process::processEvents() && (Platform::getRealMilliseconds() < limit) ) {} // Unhook from the signals. - Net::smConnectionNotify ->remove(&handler, &TcpHandle::notify); - Net::smConnectionReceive->remove(&handler, &TcpHandle::receive); + Net::smConnectionNotify .remove(&handler, &TcpHandle::notify); + Net::smConnectionReceive.remove(&handler, &TcpHandle::receive); EXPECT_GT(handler.mDataReceived, 0) << "Didn't get any data back!"; @@ -139,8 +139,8 @@ struct JournalHandle mDataReceived = 0; // Hook into the signals. - Net::smConnectionNotify ->notify(this, &JournalHandle::notify); - Net::smConnectionReceive->notify(this, &JournalHandle::receive); + Net::smConnectionNotify .notify(this, &JournalHandle::notify); + Net::smConnectionReceive.notify(this, &JournalHandle::receive); // Open a TCP connection to garagegames.com mSocket = Net::openConnectTo("72.246.107.193:80"); @@ -149,8 +149,8 @@ struct JournalHandle while(Process::processEvents()) {} // Unhook from the signals. - Net::smConnectionNotify ->remove(this, &JournalHandle::notify); - Net::smConnectionReceive->remove(this, &JournalHandle::receive); + Net::smConnectionNotify .remove(this, &JournalHandle::notify); + Net::smConnectionReceive.remove(this, &JournalHandle::receive); EXPECT_GT(mDataReceived, 0) << "Didn't get any data back!"; From b31e0ad2dadfdd92026919055b182177a1865d28 Mon Sep 17 00:00:00 2001 From: "Thomas \"elfprince13\" Dickerson" Date: Fri, 6 Jan 2017 17:36:29 -0500 Subject: [PATCH 3/9] Attempting to fix tabs and space --- Engine/source/platform/profiler.cpp | 1090 ++++++++++----------- Engine/source/platformMac/macFileIO.mm | 1240 ++++++++++++------------ 2 files changed, 1165 insertions(+), 1165 deletions(-) diff --git a/Engine/source/platform/profiler.cpp b/Engine/source/platform/profiler.cpp index 7460ad315..5569f5bbe 100644 --- a/Engine/source/platform/profiler.cpp +++ b/Engine/source/platform/profiler.cpp @@ -48,15 +48,15 @@ Profiler *gProfiler = NULL; //#define TORQUE_PROFILER_DEBUG // Machinery to record the stack of node names, as a debugging aid to find -// mismatched PROFILE_START and PROFILE_END blocks. We profile from the +// mismatched PROFILE_START and PROFILE_END blocks. We profile from the // beginning to catch profile block errors that occur when torque is starting up. #ifdef TORQUE_PROFILER_DEBUG Vector gProfilerNodeStack; #define TORQUE_PROFILE_AT_ENGINE_START true #define PROFILER_DEBUG_PUSH_NODE( nodename ) \ - gProfilerNodeStack.push_back( nodename ); +gProfilerNodeStack.push_back( nodename ); #define PROFILER_DEBUG_POP_NODE() \ - gProfilerNodeStack.pop_back(); +gProfilerNodeStack.pop_back(); #else #define TORQUE_PROFILE_AT_ENGINE_START false #define PROFILER_DEBUG_PUSH_NODE( nodename ) ; @@ -67,45 +67,45 @@ Vector gProfilerNodeStack; // platform specific get hires times... void startHighResolutionTimer(U32 time[2]) { - //time[0] = Platform::getRealMilliseconds(); - - __asm - { - push eax - push edx - push ecx - rdtsc - mov ecx, time - mov DWORD PTR [ecx], eax - mov DWORD PTR [ecx + 4], edx - pop ecx - pop edx - pop eax - } + //time[0] = Platform::getRealMilliseconds(); + + __asm + { + push eax + push edx + push ecx + rdtsc + mov ecx, time + mov DWORD PTR [ecx], eax + mov DWORD PTR [ecx + 4], edx + pop ecx + pop edx + pop eax + } } U32 endHighResolutionTimer(U32 time[2]) { - U32 ticks; - //ticks = Platform::getRealMilliseconds() - time[0]; - //return ticks; - - __asm - { - push eax - push edx - push ecx - //db 0fh, 31h - rdtsc - mov ecx, time - sub edx, DWORD PTR [ecx+4] - sbb eax, DWORD PTR [ecx] - mov DWORD PTR ticks, eax - pop ecx - pop edx - pop eax - } - return ticks; + U32 ticks; + //ticks = Platform::getRealMilliseconds() - time[0]; + //return ticks; + + __asm + { + push eax + push edx + push ecx + //db 0fh, 31h + rdtsc + mov ecx, time + sub edx, DWORD PTR [ecx+4] + sbb eax, DWORD PTR [ecx] + mov DWORD PTR ticks, eax + pop ecx + pop edx + pop eax + } + return ticks; } #elif defined(TORQUE_SUPPORTS_GCC_INLINE_X86_ASM) @@ -113,22 +113,22 @@ U32 endHighResolutionTimer(U32 time[2]) // platform specific get hires times... void startHighResolutionTimer(U32 time[2]) { - __asm__ __volatile__( - "rdtsc\n" - : "=a" (time[0]), "=d" (time[1]) - ); + __asm__ __volatile__( + "rdtsc\n" + : "=a" (time[0]), "=d" (time[1]) + ); } U32 endHighResolutionTimer(U32 time[2]) { - U32 ticks; - __asm__ __volatile__( - "rdtsc\n" - "sub 0x4(%%ecx), %%edx\n" - "sbb (%%ecx), %%eax\n" - : "=a" (ticks) : "c" (time) - ); - return ticks; + U32 ticks; + __asm__ __volatile__( + "rdtsc\n" + "sub 0x4(%%ecx), %%edx\n" + "sbb (%%ecx), %%eax\n" + : "=a" (ticks) : "c" (time) + ); + return ticks; } #elif defined(TORQUE_OS_MAC) @@ -161,551 +161,551 @@ U32 endHighResolutionTimer(U32 time[2]) { void startHighResolutionTimer(U32 time[2]) { - time[0] = Platform::getRealMilliseconds(); + time[0] = Platform::getRealMilliseconds(); } U32 endHighResolutionTimer(U32 time[2]) { - U32 ticks = Platform::getRealMilliseconds() - time[0]; - return ticks; + U32 ticks = Platform::getRealMilliseconds() - time[0]; + return ticks; } #endif Profiler::Profiler() { - mMaxStackDepth = MaxStackDepth; - mCurrentHash = 0; - - mCurrentProfilerData = (ProfilerData *) malloc(sizeof(ProfilerData)); - mCurrentProfilerData->mRoot = NULL; - mCurrentProfilerData->mNextForRoot = NULL; - mCurrentProfilerData->mNextProfilerData = NULL; - mCurrentProfilerData->mNextHash = NULL; - mCurrentProfilerData->mParent = NULL; - mCurrentProfilerData->mNextSibling = NULL; - mCurrentProfilerData->mFirstChild = NULL; - mCurrentProfilerData->mLastSeenProfiler = NULL; - mCurrentProfilerData->mHash = 0; - mCurrentProfilerData->mSubDepth = 0; - mCurrentProfilerData->mInvokeCount = 0; - mCurrentProfilerData->mTotalTime = 0; - mCurrentProfilerData->mSubTime = 0; -#ifdef TORQUE_ENABLE_PROFILE_PATH - mCurrentProfilerData->mPath = ""; + mMaxStackDepth = MaxStackDepth; + mCurrentHash = 0; + + mCurrentProfilerData = (ProfilerData *) malloc(sizeof(ProfilerData)); + mCurrentProfilerData->mRoot = NULL; + mCurrentProfilerData->mNextForRoot = NULL; + mCurrentProfilerData->mNextProfilerData = NULL; + mCurrentProfilerData->mNextHash = NULL; + mCurrentProfilerData->mParent = NULL; + mCurrentProfilerData->mNextSibling = NULL; + mCurrentProfilerData->mFirstChild = NULL; + mCurrentProfilerData->mLastSeenProfiler = NULL; + mCurrentProfilerData->mHash = 0; + mCurrentProfilerData->mSubDepth = 0; + mCurrentProfilerData->mInvokeCount = 0; + mCurrentProfilerData->mTotalTime = 0; + mCurrentProfilerData->mSubTime = 0; +#ifdef TORQUE_ENABLE_PROFILE_PATH + mCurrentProfilerData->mPath = ""; #endif - mRootProfilerData = mCurrentProfilerData; - - for(U32 i = 0; i < ProfilerData::HashTableSize; i++) - mCurrentProfilerData->mChildHash[i] = 0; - - mProfileList = NULL; - - mEnabled = TORQUE_PROFILE_AT_ENGINE_START; - mNextEnable = TORQUE_PROFILE_AT_ENGINE_START; - mStackDepth = 0; - gProfiler = this; - mDumpToConsole = false; - mDumpToFile = false; - mDumpFileName[0] = '\0'; + mRootProfilerData = mCurrentProfilerData; + + for(U32 i = 0; i < ProfilerData::HashTableSize; i++) + mCurrentProfilerData->mChildHash[i] = 0; + + mProfileList = NULL; + + mEnabled = TORQUE_PROFILE_AT_ENGINE_START; + mNextEnable = TORQUE_PROFILE_AT_ENGINE_START; + mStackDepth = 0; + gProfiler = this; + mDumpToConsole = false; + mDumpToFile = false; + mDumpFileName[0] = '\0'; } Profiler::~Profiler() { - reset(); - free(mRootProfilerData); - gProfiler = NULL; + reset(); + free(mRootProfilerData); + gProfiler = NULL; } void Profiler::reset() { - mEnabled = false; // in case we're in a profiler call. - ProfilerData * head = mProfileList; - ProfilerData * curr = head; - - while ( curr ) - { - head = curr->mNextProfilerData; - free( curr ); - - if ( head ) - curr = head; - else - curr = NULL; - } - - mProfileList = NULL; - - for(ProfilerRootData *walk = ProfilerRootData::sRootList; walk; walk = walk->mNextRoot) - { - walk->mFirstProfilerData = 0; - walk->mTotalTime = 0; - walk->mSubTime = 0; - walk->mTotalInvokeCount = 0; - } - mCurrentProfilerData = mRootProfilerData; - mCurrentProfilerData->mNextForRoot = 0; - mCurrentProfilerData->mFirstChild = 0; - for(U32 i = 0; i < ProfilerData::HashTableSize; i++) - mCurrentProfilerData->mChildHash[i] = 0; - mCurrentProfilerData->mInvokeCount = 0; - mCurrentProfilerData->mTotalTime = 0; - mCurrentProfilerData->mSubTime = 0; - mCurrentProfilerData->mSubDepth = 0; - mCurrentProfilerData->mLastSeenProfiler = 0; + mEnabled = false; // in case we're in a profiler call. + ProfilerData * head = mProfileList; + ProfilerData * curr = head; + + while ( curr ) + { + head = curr->mNextProfilerData; + free( curr ); + + if ( head ) + curr = head; + else + curr = NULL; + } + + mProfileList = NULL; + + for(ProfilerRootData *walk = ProfilerRootData::sRootList; walk; walk = walk->mNextRoot) + { + walk->mFirstProfilerData = 0; + walk->mTotalTime = 0; + walk->mSubTime = 0; + walk->mTotalInvokeCount = 0; + } + mCurrentProfilerData = mRootProfilerData; + mCurrentProfilerData->mNextForRoot = 0; + mCurrentProfilerData->mFirstChild = 0; + for(U32 i = 0; i < ProfilerData::HashTableSize; i++) + mCurrentProfilerData->mChildHash[i] = 0; + mCurrentProfilerData->mInvokeCount = 0; + mCurrentProfilerData->mTotalTime = 0; + mCurrentProfilerData->mSubTime = 0; + mCurrentProfilerData->mSubDepth = 0; + mCurrentProfilerData->mLastSeenProfiler = 0; } static Profiler aProfiler; // allocate the global profiler ProfilerRootData::ProfilerRootData(const char *name) { - for(ProfilerRootData *walk = sRootList; walk; walk = walk->mNextRoot) - if(!dStrcmp(walk->mName, name)) - AssertFatal( false, avar( "Duplicate profile name: %s", name ) ); - - mName = name; - mNameHash = _StringTable::hashString(name); - mNextRoot = sRootList; - sRootList = this; - mTotalTime = 0; - mTotalInvokeCount = 0; - mFirstProfilerData = NULL; - mEnabled = true; + for(ProfilerRootData *walk = sRootList; walk; walk = walk->mNextRoot) + if(!dStrcmp(walk->mName, name)) + AssertFatal( false, avar( "Duplicate profile name: %s", name ) ); + + mName = name; + mNameHash = _StringTable::hashString(name); + mNextRoot = sRootList; + sRootList = this; + mTotalTime = 0; + mTotalInvokeCount = 0; + mFirstProfilerData = NULL; + mEnabled = true; } void Profiler::validate() { - for(ProfilerRootData *walk = ProfilerRootData::sRootList; walk; walk = walk->mNextRoot) - { - for(ProfilerData *dp = walk->mFirstProfilerData; dp; dp = dp->mNextForRoot) - { - if(dp->mRoot != walk) - Platform::debugBreak(); - // check if it's in the parent's list... - ProfilerData *wk; - for(wk = dp->mParent->mFirstChild; wk; wk = wk->mNextSibling) - if(wk == dp) - break; - if(!wk) - Platform::debugBreak(); - for(wk = dp->mParent->mChildHash[walk->mNameHash & (ProfilerData::HashTableSize - 1)] ; - wk; wk = wk->mNextHash) - if(wk == dp) - break; - if(!wk) - Platform::debugBreak(); - } - } + for(ProfilerRootData *walk = ProfilerRootData::sRootList; walk; walk = walk->mNextRoot) + { + for(ProfilerData *dp = walk->mFirstProfilerData; dp; dp = dp->mNextForRoot) + { + if(dp->mRoot != walk) + Platform::debugBreak(); + // check if it's in the parent's list... + ProfilerData *wk; + for(wk = dp->mParent->mFirstChild; wk; wk = wk->mNextSibling) + if(wk == dp) + break; + if(!wk) + Platform::debugBreak(); + for(wk = dp->mParent->mChildHash[walk->mNameHash & (ProfilerData::HashTableSize - 1)] ; + wk; wk = wk->mNextHash) + if(wk == dp) + break; + if(!wk) + Platform::debugBreak(); + } + } } #ifdef TORQUE_ENABLE_PROFILE_PATH const char * Profiler::getProfilePath() { #ifdef TORQUE_MULTITHREAD - // Ignore non-main-thread profiler activity. - if( !ThreadManager::isMainThread() ) - return "[non-main thread]"; + // Ignore non-main-thread profiler activity. + if( !ThreadManager::isMainThread() ) + return "[non-main thread]"; #endif - - return (mEnabled && mCurrentProfilerData) ? mCurrentProfilerData->mPath : "na"; + + return (mEnabled && mCurrentProfilerData) ? mCurrentProfilerData->mPath : "na"; } #endif #ifdef TORQUE_ENABLE_PROFILE_PATH const char * Profiler::constructProfilePath(ProfilerData * pd) { - if (pd->mParent) - { - const bool saveEnable = gProfiler->mEnabled; - gProfiler->mEnabled = false; - - const char * connector = " -> "; - U32 len = dStrlen(pd->mParent->mPath); - if (!len) - connector = ""; - len += dStrlen(connector); - len += dStrlen(pd->mRoot->mName); - - U32 mark = FrameAllocator::getWaterMark(); - char * buf = (char*)FrameAllocator::alloc(len+1); - dStrcpy(buf,pd->mParent->mPath); - dStrcat(buf,connector); - dStrcat(buf,pd->mRoot->mName); - const char * ret = StringTable->insert(buf); - FrameAllocator::setWaterMark(mark); - - gProfiler->mEnabled = saveEnable; - - return ret; - } - return "root"; + if (pd->mParent) + { + const bool saveEnable = gProfiler->mEnabled; + gProfiler->mEnabled = false; + + const char * connector = " -> "; + U32 len = dStrlen(pd->mParent->mPath); + if (!len) + connector = ""; + len += dStrlen(connector); + len += dStrlen(pd->mRoot->mName); + + U32 mark = FrameAllocator::getWaterMark(); + char * buf = (char*)FrameAllocator::alloc(len+1); + dStrcpy(buf,pd->mParent->mPath); + dStrcat(buf,connector); + dStrcat(buf,pd->mRoot->mName); + const char * ret = StringTable->insert(buf); + FrameAllocator::setWaterMark(mark); + + gProfiler->mEnabled = saveEnable; + + return ret; + } + return "root"; } #endif void Profiler::hashPush(ProfilerRootData *root) { #ifdef TORQUE_MULTITHREAD - // Ignore non-main-thread profiler activity. - if( !ThreadManager::isMainThread() ) - return; + // Ignore non-main-thread profiler activity. + if( !ThreadManager::isMainThread() ) + return; #endif - - mStackDepth++; - PROFILER_DEBUG_PUSH_NODE(root->mName); - AssertFatal(mStackDepth <= mMaxStackDepth, - "Stack overflow in profiler. You may have mismatched PROFILE_START and PROFILE_ENDs"); - if(!mEnabled) - return; - - ProfilerData *nextProfiler = NULL; - if(!root->mEnabled || mCurrentProfilerData->mRoot == root) - { - mCurrentProfilerData->mSubDepth++; - return; - } - - if(mCurrentProfilerData->mLastSeenProfiler && - mCurrentProfilerData->mLastSeenProfiler->mRoot == root) - nextProfiler = mCurrentProfilerData->mLastSeenProfiler; - - if(!nextProfiler) - { - // first see if it's in the hash table... - U32 index = root->mNameHash & (ProfilerData::HashTableSize - 1); - nextProfiler = mCurrentProfilerData->mChildHash[index]; - while(nextProfiler) - { - if(nextProfiler->mRoot == root) - break; - nextProfiler = nextProfiler->mNextHash; - } - if(!nextProfiler) - { - nextProfiler = (ProfilerData *) malloc(sizeof(ProfilerData)); - for(U32 i = 0; i < ProfilerData::HashTableSize; i++) - nextProfiler->mChildHash[i] = 0; - - nextProfiler->mRoot = root; - nextProfiler->mNextForRoot = root->mFirstProfilerData; - root->mFirstProfilerData = nextProfiler; - - nextProfiler->mNextProfilerData = mProfileList; - mProfileList = nextProfiler; - - nextProfiler->mNextHash = mCurrentProfilerData->mChildHash[index]; - mCurrentProfilerData->mChildHash[index] = nextProfiler; - - nextProfiler->mParent = mCurrentProfilerData; - nextProfiler->mNextSibling = mCurrentProfilerData->mFirstChild; - mCurrentProfilerData->mFirstChild = nextProfiler; - nextProfiler->mFirstChild = NULL; - nextProfiler->mLastSeenProfiler = NULL; - nextProfiler->mHash = root->mNameHash; - nextProfiler->mInvokeCount = 0; - nextProfiler->mTotalTime = 0; - nextProfiler->mSubTime = 0; - nextProfiler->mSubDepth = 0; + + mStackDepth++; + PROFILER_DEBUG_PUSH_NODE(root->mName); + AssertFatal(mStackDepth <= mMaxStackDepth, + "Stack overflow in profiler. You may have mismatched PROFILE_START and PROFILE_ENDs"); + if(!mEnabled) + return; + + ProfilerData *nextProfiler = NULL; + if(!root->mEnabled || mCurrentProfilerData->mRoot == root) + { + mCurrentProfilerData->mSubDepth++; + return; + } + + if(mCurrentProfilerData->mLastSeenProfiler && + mCurrentProfilerData->mLastSeenProfiler->mRoot == root) + nextProfiler = mCurrentProfilerData->mLastSeenProfiler; + + if(!nextProfiler) + { + // first see if it's in the hash table... + U32 index = root->mNameHash & (ProfilerData::HashTableSize - 1); + nextProfiler = mCurrentProfilerData->mChildHash[index]; + while(nextProfiler) + { + if(nextProfiler->mRoot == root) + break; + nextProfiler = nextProfiler->mNextHash; + } + if(!nextProfiler) + { + nextProfiler = (ProfilerData *) malloc(sizeof(ProfilerData)); + for(U32 i = 0; i < ProfilerData::HashTableSize; i++) + nextProfiler->mChildHash[i] = 0; + + nextProfiler->mRoot = root; + nextProfiler->mNextForRoot = root->mFirstProfilerData; + root->mFirstProfilerData = nextProfiler; + + nextProfiler->mNextProfilerData = mProfileList; + mProfileList = nextProfiler; + + nextProfiler->mNextHash = mCurrentProfilerData->mChildHash[index]; + mCurrentProfilerData->mChildHash[index] = nextProfiler; + + nextProfiler->mParent = mCurrentProfilerData; + nextProfiler->mNextSibling = mCurrentProfilerData->mFirstChild; + mCurrentProfilerData->mFirstChild = nextProfiler; + nextProfiler->mFirstChild = NULL; + nextProfiler->mLastSeenProfiler = NULL; + nextProfiler->mHash = root->mNameHash; + nextProfiler->mInvokeCount = 0; + nextProfiler->mTotalTime = 0; + nextProfiler->mSubTime = 0; + nextProfiler->mSubDepth = 0; #ifdef TORQUE_ENABLE_PROFILE_PATH - nextProfiler->mPath = constructProfilePath(nextProfiler); + nextProfiler->mPath = constructProfilePath(nextProfiler); #endif - } - } - root->mTotalInvokeCount++; - nextProfiler->mInvokeCount++; - startHighResolutionTimer(nextProfiler->mStartTime); - mCurrentProfilerData->mLastSeenProfiler = nextProfiler; - mCurrentProfilerData = nextProfiler; + } + } + root->mTotalInvokeCount++; + nextProfiler->mInvokeCount++; + startHighResolutionTimer(nextProfiler->mStartTime); + mCurrentProfilerData->mLastSeenProfiler = nextProfiler; + mCurrentProfilerData = nextProfiler; } void Profiler::enable(bool enabled) { - mNextEnable = enabled; + mNextEnable = enabled; } void Profiler::dumpToConsole() { - mDumpToConsole = true; - mDumpToFile = false; - mDumpFileName[0] = '\0'; + mDumpToConsole = true; + mDumpToFile = false; + mDumpFileName[0] = '\0'; } void Profiler::dumpToFile(const char* fileName) { - AssertFatal(dStrlen(fileName) < DumpFileNameLength, "Error, dump filename too long"); - mDumpToFile = true; - mDumpToConsole = false; - dStrcpy(mDumpFileName, fileName); + AssertFatal(dStrlen(fileName) < DumpFileNameLength, "Error, dump filename too long"); + mDumpToFile = true; + mDumpToConsole = false; + dStrcpy(mDumpFileName, fileName); } void Profiler::hashPop(ProfilerRootData *expected) { #ifdef TORQUE_MULTITHREAD - // Ignore non-main-thread profiler activity. - if( !ThreadManager::isMainThread() ) - return; + // Ignore non-main-thread profiler activity. + if( !ThreadManager::isMainThread() ) + return; #endif - - mStackDepth--; - PROFILER_DEBUG_POP_NODE(); - AssertFatal(mStackDepth >= 0, "Stack underflow in profiler. You may have mismatched PROFILE_START and PROFILE_ENDs"); - if(mEnabled) - { - if(mCurrentProfilerData->mSubDepth) - { - mCurrentProfilerData->mSubDepth--; - return; - } - - if(expected) - { - AssertISV(expected == mCurrentProfilerData->mRoot, "Profiler::hashPop - didn't get expected ProfilerRoot!"); - } - - F64 fElapsed = endHighResolutionTimer(mCurrentProfilerData->mStartTime); - - mCurrentProfilerData->mTotalTime += fElapsed; - mCurrentProfilerData->mParent->mSubTime += fElapsed; // mark it in the parent as well... - mCurrentProfilerData->mRoot->mTotalTime += fElapsed; - if(mCurrentProfilerData->mParent->mRoot) - mCurrentProfilerData->mParent->mRoot->mSubTime += fElapsed; // mark it in the parent as well... - - mCurrentProfilerData = mCurrentProfilerData->mParent; - } - if(mStackDepth == 0) - { - // apply the next enable... - if(mDumpToConsole || mDumpToFile) - { - dump(); - startHighResolutionTimer(mCurrentProfilerData->mStartTime); - } - if(!mEnabled && mNextEnable) - startHighResolutionTimer(mCurrentProfilerData->mStartTime); - + + mStackDepth--; + PROFILER_DEBUG_POP_NODE(); + AssertFatal(mStackDepth >= 0, "Stack underflow in profiler. You may have mismatched PROFILE_START and PROFILE_ENDs"); + if(mEnabled) + { + if(mCurrentProfilerData->mSubDepth) + { + mCurrentProfilerData->mSubDepth--; + return; + } + + if(expected) + { + AssertISV(expected == mCurrentProfilerData->mRoot, "Profiler::hashPop - didn't get expected ProfilerRoot!"); + } + + F64 fElapsed = endHighResolutionTimer(mCurrentProfilerData->mStartTime); + + mCurrentProfilerData->mTotalTime += fElapsed; + mCurrentProfilerData->mParent->mSubTime += fElapsed; // mark it in the parent as well... + mCurrentProfilerData->mRoot->mTotalTime += fElapsed; + if(mCurrentProfilerData->mParent->mRoot) + mCurrentProfilerData->mParent->mRoot->mSubTime += fElapsed; // mark it in the parent as well... + + mCurrentProfilerData = mCurrentProfilerData->mParent; + } + if(mStackDepth == 0) + { + // apply the next enable... + if(mDumpToConsole || mDumpToFile) + { + dump(); + startHighResolutionTimer(mCurrentProfilerData->mStartTime); + } + if(!mEnabled && mNextEnable) + startHighResolutionTimer(mCurrentProfilerData->mStartTime); + #if defined(TORQUE_OS_WIN) - // The high performance counters under win32 are unreliable when running on multiple - // processors. When the profiler is enabled, we restrict Torque to a single processor. - if(mNextEnable != mEnabled) - { - - if(mNextEnable) - { - Con::warnf("Warning: forcing the Torque profiler thread to run only on cpu 1."); - SetThreadAffinityMask(GetCurrentThread(), 1); - } - else - { - Con::warnf("Warning: the Torque profiler thread may now run on any cpu."); - DWORD_PTR procMask; - DWORD_PTR sysMask; - GetProcessAffinityMask( GetCurrentProcess(), &procMask, &sysMask); - SetThreadAffinityMask( GetCurrentThread(), procMask); - } - } + // The high performance counters under win32 are unreliable when running on multiple + // processors. When the profiler is enabled, we restrict Torque to a single processor. + if(mNextEnable != mEnabled) + { + + if(mNextEnable) + { + Con::warnf("Warning: forcing the Torque profiler thread to run only on cpu 1."); + SetThreadAffinityMask(GetCurrentThread(), 1); + } + else + { + Con::warnf("Warning: the Torque profiler thread may now run on any cpu."); + DWORD_PTR procMask; + DWORD_PTR sysMask; + GetProcessAffinityMask( GetCurrentProcess(), &procMask, &sysMask); + SetThreadAffinityMask( GetCurrentThread(), procMask); + } + } #endif - - mEnabled = mNextEnable; - } + + mEnabled = mNextEnable; + } } static S32 QSORT_CALLBACK rootDataCompare(const void *s1, const void *s2) { - const ProfilerRootData *r1 = *((ProfilerRootData **) s1); - const ProfilerRootData *r2 = *((ProfilerRootData **) s2); - if((r2->mTotalTime - r2->mSubTime) > (r1->mTotalTime - r1->mSubTime)) - return 1; - return -1; + const ProfilerRootData *r1 = *((ProfilerRootData **) s1); + const ProfilerRootData *r2 = *((ProfilerRootData **) s2); + if((r2->mTotalTime - r2->mSubTime) > (r1->mTotalTime - r1->mSubTime)) + return 1; + return -1; } static void profilerDataDumpRecurse(ProfilerData *data, char *buffer, U32 bufferLen, F64 totalTime) { - // dump out this one: - Con::printf("%7.3f %7.3f %8d %s%s", - 100 * data->mTotalTime / totalTime, - 100 * (data->mTotalTime - data->mSubTime) / totalTime, - data->mInvokeCount, - buffer, - data->mRoot ? data->mRoot->mName : "ROOT" ); - data->mTotalTime = 0; - data->mSubTime = 0; - data->mInvokeCount = 0; - - buffer[bufferLen] = ' '; - buffer[bufferLen+1] = ' '; - buffer[bufferLen+2] = 0; - // sort data's children... - ProfilerData *list = NULL; - while(data->mFirstChild) - { - ProfilerData *ins = data->mFirstChild; - data->mFirstChild = ins->mNextSibling; - ProfilerData **walk = &list; - while(*walk && (*walk)->mTotalTime > ins->mTotalTime) - walk = &(*walk)->mNextSibling; - ins->mNextSibling = *walk; - *walk = ins; - } - data->mFirstChild = list; - while(list) - { - if(list->mInvokeCount) - profilerDataDumpRecurse(list, buffer, bufferLen + 2, totalTime); - list = list->mNextSibling; - } - buffer[bufferLen] = 0; + // dump out this one: + Con::printf("%7.3f %7.3f %8d %s%s", + 100 * data->mTotalTime / totalTime, + 100 * (data->mTotalTime - data->mSubTime) / totalTime, + data->mInvokeCount, + buffer, + data->mRoot ? data->mRoot->mName : "ROOT" ); + data->mTotalTime = 0; + data->mSubTime = 0; + data->mInvokeCount = 0; + + buffer[bufferLen] = ' '; + buffer[bufferLen+1] = ' '; + buffer[bufferLen+2] = 0; + // sort data's children... + ProfilerData *list = NULL; + while(data->mFirstChild) + { + ProfilerData *ins = data->mFirstChild; + data->mFirstChild = ins->mNextSibling; + ProfilerData **walk = &list; + while(*walk && (*walk)->mTotalTime > ins->mTotalTime) + walk = &(*walk)->mNextSibling; + ins->mNextSibling = *walk; + *walk = ins; + } + data->mFirstChild = list; + while(list) + { + if(list->mInvokeCount) + profilerDataDumpRecurse(list, buffer, bufferLen + 2, totalTime); + list = list->mNextSibling; + } + buffer[bufferLen] = 0; } static void profilerDataDumpRecurseFile(ProfilerData *data, char *buffer, U32 bufferLen, F64 totalTime, FileStream& fws) { - char pbuffer[256]; - dSprintf(pbuffer, 255, "%7.3f %7.3f %8d %s%s\n", - 100 * data->mTotalTime / totalTime, - 100 * (data->mTotalTime - data->mSubTime) / totalTime, - data->mInvokeCount, - buffer, - data->mRoot ? data->mRoot->mName : "ROOT" ); - fws.write(dStrlen(pbuffer), pbuffer); - data->mTotalTime = 0; - data->mSubTime = 0; - data->mInvokeCount = 0; - - buffer[bufferLen] = ' '; - buffer[bufferLen+1] = ' '; - buffer[bufferLen+2] = 0; - // sort data's children... - ProfilerData *list = NULL; - while(data->mFirstChild) - { - ProfilerData *ins = data->mFirstChild; - data->mFirstChild = ins->mNextSibling; - ProfilerData **walk = &list; - while(*walk && (*walk)->mTotalTime > ins->mTotalTime) - walk = &(*walk)->mNextSibling; - ins->mNextSibling = *walk; - *walk = ins; - } - data->mFirstChild = list; - while(list) - { - if(list->mInvokeCount) - profilerDataDumpRecurseFile(list, buffer, bufferLen + 2, totalTime, fws); - list = list->mNextSibling; - } - buffer[bufferLen] = 0; + char pbuffer[256]; + dSprintf(pbuffer, 255, "%7.3f %7.3f %8d %s%s\n", + 100 * data->mTotalTime / totalTime, + 100 * (data->mTotalTime - data->mSubTime) / totalTime, + data->mInvokeCount, + buffer, + data->mRoot ? data->mRoot->mName : "ROOT" ); + fws.write(dStrlen(pbuffer), pbuffer); + data->mTotalTime = 0; + data->mSubTime = 0; + data->mInvokeCount = 0; + + buffer[bufferLen] = ' '; + buffer[bufferLen+1] = ' '; + buffer[bufferLen+2] = 0; + // sort data's children... + ProfilerData *list = NULL; + while(data->mFirstChild) + { + ProfilerData *ins = data->mFirstChild; + data->mFirstChild = ins->mNextSibling; + ProfilerData **walk = &list; + while(*walk && (*walk)->mTotalTime > ins->mTotalTime) + walk = &(*walk)->mNextSibling; + ins->mNextSibling = *walk; + *walk = ins; + } + data->mFirstChild = list; + while(list) + { + if(list->mInvokeCount) + profilerDataDumpRecurseFile(list, buffer, bufferLen + 2, totalTime, fws); + list = list->mNextSibling; + } + buffer[bufferLen] = 0; } void Profiler::dump() { - bool enableSave = mEnabled; - mEnabled = false; - mStackDepth++; - // may have some profiled calls... gotta turn em off. - - Vector rootVector; - F64 totalTime = 0; - for(ProfilerRootData *walk = ProfilerRootData::sRootList; walk; walk = walk->mNextRoot) - { - totalTime += walk->mTotalTime - walk->mSubTime; - rootVector.push_back(walk); - } - dQsort((void *) &rootVector[0], rootVector.size(), sizeof(ProfilerRootData *), rootDataCompare); - - - if (mDumpToConsole == true) - { - Con::printf("Profiler Data Dump:"); - Con::printf("Ordered by non-sub total time -"); - Con::printf("%%NSTime %% Time Invoke # Name"); - for(U32 i = 0; i < rootVector.size(); i++) - { - Con::printf("%7.3f %7.3f %8d %s", - 100 * (rootVector[i]->mTotalTime - rootVector[i]->mSubTime) / totalTime, - 100 * rootVector[i]->mTotalTime / totalTime, - rootVector[i]->mTotalInvokeCount, - rootVector[i]->mName); - rootVector[i]->mTotalInvokeCount = 0; - rootVector[i]->mTotalTime = 0; - rootVector[i]->mSubTime = 0; - } - Con::printf(""); - Con::printf("Ordered by stack trace total time -"); - Con::printf("%% Time %% NSTime Invoke # Name"); - - mCurrentProfilerData->mTotalTime = endHighResolutionTimer(mCurrentProfilerData->mStartTime); - - char depthBuffer[MaxStackDepth * 2 + 1]; - depthBuffer[0] = 0; - profilerDataDumpRecurse(mCurrentProfilerData, depthBuffer, 0, totalTime); - mEnabled = enableSave; - mStackDepth--; - } - else if (mDumpToFile == true && mDumpFileName[0] != '\0') - { - FileStream fws; - bool success = fws.open(mDumpFileName, Torque::FS::File::Write); - AssertFatal(success, "Cannot write profile dump to specified file!"); - char buffer[1024]; - - dStrcpy(buffer, "Profiler Data Dump:\n"); - fws.write(dStrlen(buffer), buffer); - dStrcpy(buffer, "Ordered by non-sub total time -\n"); - fws.write(dStrlen(buffer), buffer); - dStrcpy(buffer, "%%NSTime %% Time Invoke # Name\n"); - fws.write(dStrlen(buffer), buffer); - - for(U32 i = 0; i < rootVector.size(); i++) - { - dSprintf(buffer, 1023, "%7.3f %7.3f %8d %s\n", - 100 * (rootVector[i]->mTotalTime - rootVector[i]->mSubTime) / totalTime, - 100 * rootVector[i]->mTotalTime / totalTime, - rootVector[i]->mTotalInvokeCount, - rootVector[i]->mName); - fws.write(dStrlen(buffer), buffer); - - rootVector[i]->mTotalInvokeCount = 0; - rootVector[i]->mTotalTime = 0; - rootVector[i]->mSubTime = 0; - } - dStrcpy(buffer, "\nOrdered by non-sub total time -\n"); - fws.write(dStrlen(buffer), buffer); - dStrcpy(buffer, "%%NSTime %% Time Invoke # Name\n"); - fws.write(dStrlen(buffer), buffer); - - mCurrentProfilerData->mTotalTime = endHighResolutionTimer(mCurrentProfilerData->mStartTime); - - char depthBuffer[MaxStackDepth * 2 + 1]; - depthBuffer[0] = 0; - profilerDataDumpRecurseFile(mCurrentProfilerData, depthBuffer, 0, totalTime, fws); - mEnabled = enableSave; - mStackDepth--; - - fws.close(); - } - - mDumpToConsole = false; - mDumpToFile = false; - mDumpFileName[0] = '\0'; + bool enableSave = mEnabled; + mEnabled = false; + mStackDepth++; + // may have some profiled calls... gotta turn em off. + + Vector rootVector; + F64 totalTime = 0; + for(ProfilerRootData *walk = ProfilerRootData::sRootList; walk; walk = walk->mNextRoot) + { + totalTime += walk->mTotalTime - walk->mSubTime; + rootVector.push_back(walk); + } + dQsort((void *) &rootVector[0], rootVector.size(), sizeof(ProfilerRootData *), rootDataCompare); + + + if (mDumpToConsole == true) + { + Con::printf("Profiler Data Dump:"); + Con::printf("Ordered by non-sub total time -"); + Con::printf("%%NSTime %% Time Invoke # Name"); + for(U32 i = 0; i < rootVector.size(); i++) + { + Con::printf("%7.3f %7.3f %8d %s", + 100 * (rootVector[i]->mTotalTime - rootVector[i]->mSubTime) / totalTime, + 100 * rootVector[i]->mTotalTime / totalTime, + rootVector[i]->mTotalInvokeCount, + rootVector[i]->mName); + rootVector[i]->mTotalInvokeCount = 0; + rootVector[i]->mTotalTime = 0; + rootVector[i]->mSubTime = 0; + } + Con::printf(""); + Con::printf("Ordered by stack trace total time -"); + Con::printf("%% Time %% NSTime Invoke # Name"); + + mCurrentProfilerData->mTotalTime = endHighResolutionTimer(mCurrentProfilerData->mStartTime); + + char depthBuffer[MaxStackDepth * 2 + 1]; + depthBuffer[0] = 0; + profilerDataDumpRecurse(mCurrentProfilerData, depthBuffer, 0, totalTime); + mEnabled = enableSave; + mStackDepth--; + } + else if (mDumpToFile == true && mDumpFileName[0] != '\0') + { + FileStream fws; + bool success = fws.open(mDumpFileName, Torque::FS::File::Write); + AssertFatal(success, "Cannot write profile dump to specified file!"); + char buffer[1024]; + + dStrcpy(buffer, "Profiler Data Dump:\n"); + fws.write(dStrlen(buffer), buffer); + dStrcpy(buffer, "Ordered by non-sub total time -\n"); + fws.write(dStrlen(buffer), buffer); + dStrcpy(buffer, "%%NSTime %% Time Invoke # Name\n"); + fws.write(dStrlen(buffer), buffer); + + for(U32 i = 0; i < rootVector.size(); i++) + { + dSprintf(buffer, 1023, "%7.3f %7.3f %8d %s\n", + 100 * (rootVector[i]->mTotalTime - rootVector[i]->mSubTime) / totalTime, + 100 * rootVector[i]->mTotalTime / totalTime, + rootVector[i]->mTotalInvokeCount, + rootVector[i]->mName); + fws.write(dStrlen(buffer), buffer); + + rootVector[i]->mTotalInvokeCount = 0; + rootVector[i]->mTotalTime = 0; + rootVector[i]->mSubTime = 0; + } + dStrcpy(buffer, "\nOrdered by non-sub total time -\n"); + fws.write(dStrlen(buffer), buffer); + dStrcpy(buffer, "%%NSTime %% Time Invoke # Name\n"); + fws.write(dStrlen(buffer), buffer); + + mCurrentProfilerData->mTotalTime = endHighResolutionTimer(mCurrentProfilerData->mStartTime); + + char depthBuffer[MaxStackDepth * 2 + 1]; + depthBuffer[0] = 0; + profilerDataDumpRecurseFile(mCurrentProfilerData, depthBuffer, 0, totalTime, fws); + mEnabled = enableSave; + mStackDepth--; + + fws.close(); + } + + mDumpToConsole = false; + mDumpToFile = false; + mDumpFileName[0] = '\0'; } void Profiler::enableMarker(const char *marker, bool enable) { - reset(); - U32 markerLen = dStrlen(marker); - if(markerLen == 0) - return; - bool sn = marker[markerLen - 1] == '*'; - for(ProfilerRootData *data = ProfilerRootData::sRootList; data; data = data->mNextRoot) - { - if(sn) - { - if(!dStrncmp(marker, data->mName, markerLen - 1)) - data->mEnabled = enable; - } - else - { - if(!dStrcmp(marker, data->mName)) - data->mEnabled = enable; - } - } + reset(); + U32 markerLen = dStrlen(marker); + if(markerLen == 0) + return; + bool sn = marker[markerLen - 1] == '*'; + for(ProfilerRootData *data = ProfilerRootData::sRootList; data; data = data->mNextRoot) + { + if(sn) + { + if(!dStrncmp(marker, data->mName, markerLen - 1)) + data->mEnabled = enable; + } + else + { + if(!dStrcmp(marker, data->mName)) + data->mEnabled = enable; + } + } } //============================================================================= @@ -715,65 +715,65 @@ void Profiler::enableMarker(const char *marker, bool enable) //----------------------------------------------------------------------------- -DefineEngineFunction( profilerMarkerEnable, void, ( const char* markerName, bool enable ), ( true ), - "@brief Enable or disable a specific profile.\n\n" - "@param enable Optional paramater to enable or disable the profile.\n" - "@param markerName Name of a specific marker to enable or disable.\n" - "@note Calling this function will first call profilerReset(), clearing all data from profiler. " - "All profile markers are enabled by default.\n\n" - "@ingroup Debugging") +DefineEngineFunction( profilerMarkerEnable, void, ( const char* markerName, bool enable ), ( true ), + "@brief Enable or disable a specific profile.\n\n" + "@param enable Optional paramater to enable or disable the profile.\n" + "@param markerName Name of a specific marker to enable or disable.\n" + "@note Calling this function will first call profilerReset(), clearing all data from profiler. " + "All profile markers are enabled by default.\n\n" + "@ingroup Debugging") { - if( gProfiler ) - gProfiler->enableMarker( markerName, enable ); + if( gProfiler ) + gProfiler->enableMarker( markerName, enable ); } //----------------------------------------------------------------------------- DefineEngineFunction( profilerEnable, void, ( bool enable ),, - "@brief Enables or disables the profiler.\n\n" - "Data is only gathered while the profiler is enabled.\n\n" - "@note Profiler is not available in shipping builds.\n" - "T3D has predefined profiling areas surrounded by markers, " - "but you may need to define additional markers (in C++) around areas you wish to profile," - " by using the PROFILE_START( markerName ); and PROFILE_END(); macros.\n\n" - "@ingroup Debugging\n" ) + "@brief Enables or disables the profiler.\n\n" + "Data is only gathered while the profiler is enabled.\n\n" + "@note Profiler is not available in shipping builds.\n" + "T3D has predefined profiling areas surrounded by markers, " + "but you may need to define additional markers (in C++) around areas you wish to profile," + " by using the PROFILE_START( markerName ); and PROFILE_END(); macros.\n\n" + "@ingroup Debugging\n" ) { - if(gProfiler) - gProfiler->enable(enable); + if(gProfiler) + gProfiler->enable(enable); } DefineEngineFunction(profilerDump, void, (),, - "@brief Dumps current profiling stats to the console window.\n\n" - "@note Markers disabled with profilerMarkerEnable() will be skipped over. " - "If the profiler is currently running, it will be disabled.\n" - "@ingroup Debugging") + "@brief Dumps current profiling stats to the console window.\n\n" + "@note Markers disabled with profilerMarkerEnable() will be skipped over. " + "If the profiler is currently running, it will be disabled.\n" + "@ingroup Debugging") { - if(gProfiler) - gProfiler->dumpToConsole(); + if(gProfiler) + gProfiler->dumpToConsole(); } DefineEngineFunction( profilerDumpToFile, void, ( const char* fileName ),, - "@brief Dumps current profiling stats to a file.\n\n" - "@note If the profiler is currently running, it will be disabled.\n" - "@param fileName Name and path of file to save profiling stats to. Must use forward slashes (/). " - "Will attempt to create the file if it does not already exist.\n" - "@tsexample\n" - "profilerDumpToFile( \"C:/Torque/log1.txt\" );\n" - "@endtsexample\n\n" - "@ingroup Debugging" ) + "@brief Dumps current profiling stats to a file.\n\n" + "@note If the profiler is currently running, it will be disabled.\n" + "@param fileName Name and path of file to save profiling stats to. Must use forward slashes (/). " + "Will attempt to create the file if it does not already exist.\n" + "@tsexample\n" + "profilerDumpToFile( \"C:/Torque/log1.txt\" );\n" + "@endtsexample\n\n" + "@ingroup Debugging" ) { - if(gProfiler) - gProfiler->dumpToFile(fileName); + if(gProfiler) + gProfiler->dumpToFile(fileName); } DefineEngineFunction( profilerReset, void, (),, - "@brief Resets the profiler, clearing it of all its data.\n\n" - "If the profiler is currently running, it will first be disabled. " - "All markers will retain their current enabled/disabled status.\n\n" - "@ingroup Debugging" ) + "@brief Resets the profiler, clearing it of all its data.\n\n" + "If the profiler is currently running, it will first be disabled. " + "All markers will retain their current enabled/disabled status.\n\n" + "@ingroup Debugging" ) { - if(gProfiler) - gProfiler->reset(); + if(gProfiler) + gProfiler->reset(); } #endif diff --git a/Engine/source/platformMac/macFileIO.mm b/Engine/source/platformMac/macFileIO.mm index 2815b5af4..90efbd303 100644 --- a/Engine/source/platformMac/macFileIO.mm +++ b/Engine/source/platformMac/macFileIO.mm @@ -46,24 +46,24 @@ bool dFileDelete(const char * name) { - if(!name ) - return(false); - - if (dStrlen(name) > MAX_MAC_PATH_LONG) - Con::warnf("dFileDelete: Filename length is pretty long..."); - - return(remove(name) == 0); // remove returns 0 on success + if(!name ) + return(false); + + if (dStrlen(name) > MAX_MAC_PATH_LONG) + Con::warnf("dFileDelete: Filename length is pretty long..."); + + return(remove(name) == 0); // remove returns 0 on success } //----------------------------------------------------------------------------- bool dFileTouch(const char *path) { - if (!path || !*path) - return false; - - // set file at path's modification and access times to now. - return( utimes( path, NULL) == 0); // utimes returns 0 on success. + if (!path || !*path) + return false; + + // set file at path's modification and access times to now. + return( utimes( path, NULL) == 0); // utimes returns 0 on success. } //----------------------------------------------------------------------------- bool dPathCopy(const char* source, const char* dest, bool nooverwrite) @@ -122,8 +122,8 @@ bool dPathCopy(const char* source, const char* dest, bool nooverwrite) bool dFileRename(const char *source, const char *dest) { - if(source == NULL || dest == NULL) - return false; + if(source == NULL || dest == NULL) + return false; @autoreleasepool { NSFileManager *manager = [NSFileManager defaultManager]; @@ -167,7 +167,7 @@ bool dFileRename(const char *source, const char *dest) File::File() : currentStatus(Closed), capability(0) { - handle = NULL; + handle = NULL; } //----------------------------------------------------------------------------- @@ -179,8 +179,8 @@ File::File() //----------------------------------------------------------------------------- File::~File() { - close(); - handle = NULL; + close(); + handle = NULL; } @@ -194,61 +194,61 @@ File::~File() //----------------------------------------------------------------------------- File::FileStatus File::open(const char *filename, const AccessMode openMode) { - if (dStrlen(filename) > MAX_MAC_PATH_LONG) - Con::warnf("File::open: Filename length is pretty long..."); - - // Close the file if it was already open... - if (currentStatus != Closed) - close(); - - // create the appropriate type of file... - switch (openMode) - { - case Read: - handle = (void *)fopen(filename, "rb"); // read only - break; - case Write: - handle = (void *)fopen(filename, "wb"); // write only - break; - case ReadWrite: - handle = (void *)fopen(filename, "ab+"); // write(append) and read - break; - case WriteAppend: - handle = (void *)fopen(filename, "ab"); // write(append) only - break; - default: - AssertFatal(false, "File::open: bad access mode"); - } - - // handle not created successfully - if (handle == NULL) - return setStatus(); - - // successfully created file, so set the file capabilities... - switch (openMode) - { - case Read: - capability = FileRead; - break; - case Write: - case WriteAppend: - capability = FileWrite; - break; - case ReadWrite: - capability = FileRead | FileWrite; - break; - default: - AssertFatal(false, "File::open: bad access mode"); - } - - // must set the file status before setting the position. - currentStatus = Ok; - - if (openMode == ReadWrite) - setPosition(0); - - // success! - return currentStatus; + if (dStrlen(filename) > MAX_MAC_PATH_LONG) + Con::warnf("File::open: Filename length is pretty long..."); + + // Close the file if it was already open... + if (currentStatus != Closed) + close(); + + // create the appropriate type of file... + switch (openMode) + { + case Read: + handle = (void *)fopen(filename, "rb"); // read only + break; + case Write: + handle = (void *)fopen(filename, "wb"); // write only + break; + case ReadWrite: + handle = (void *)fopen(filename, "ab+"); // write(append) and read + break; + case WriteAppend: + handle = (void *)fopen(filename, "ab"); // write(append) only + break; + default: + AssertFatal(false, "File::open: bad access mode"); + } + + // handle not created successfully + if (handle == NULL) + return setStatus(); + + // successfully created file, so set the file capabilities... + switch (openMode) + { + case Read: + capability = FileRead; + break; + case Write: + case WriteAppend: + capability = FileWrite; + break; + case ReadWrite: + capability = FileRead | FileWrite; + break; + default: + AssertFatal(false, "File::open: bad access mode"); + } + + // must set the file status before setting the position. + currentStatus = Ok; + + if (openMode == ReadWrite) + setPosition(0); + + // success! + return currentStatus; } //----------------------------------------------------------------------------- @@ -256,10 +256,10 @@ File::FileStatus File::open(const char *filename, const AccessMode openMode) //----------------------------------------------------------------------------- U32 File::getPosition() const { - AssertFatal(currentStatus != Closed , "File::getPosition: file closed"); - AssertFatal(handle != NULL, "File::getPosition: invalid file handle"); - - return ftell((FILE*)handle); + AssertFatal(currentStatus != Closed , "File::getPosition: file closed"); + AssertFatal(handle != NULL, "File::getPosition: invalid file handle"); + + return ftell((FILE*)handle); } //----------------------------------------------------------------------------- @@ -276,41 +276,41 @@ U32 File::getPosition() const //----------------------------------------------------------------------------- File::FileStatus File::setPosition(S32 position, bool absolutePos) { - AssertFatal(Closed != currentStatus, "File::setPosition: file closed"); - AssertFatal(handle != NULL, "File::setPosition: invalid file handle"); - - if (currentStatus != Ok && currentStatus != EOS ) - return currentStatus; - - U32 finalPos; - if(absolutePos) - { - // absolute position - AssertFatal(0 <= position, "File::setPosition: negative absolute position"); - // position beyond EOS is OK - fseek((FILE*)handle, position, SEEK_SET); - finalPos = ftell((FILE*)handle); - } - else - { - // relative position - AssertFatal((getPosition() + position) >= 0, "File::setPosition: negative relative position"); - // position beyond EOS is OK - fseek((FILE*)handle, position, SEEK_CUR); - finalPos = ftell((FILE*)handle); - } - - // ftell returns -1 on error. set error status - if (0xffffffff == finalPos) - return setStatus(); - - // success, at end of file - else if (finalPos >= getSize()) - return currentStatus = EOS; - - // success! - else - return currentStatus = Ok; + AssertFatal(Closed != currentStatus, "File::setPosition: file closed"); + AssertFatal(handle != NULL, "File::setPosition: invalid file handle"); + + if (currentStatus != Ok && currentStatus != EOS ) + return currentStatus; + + U32 finalPos; + if(absolutePos) + { + // absolute position + AssertFatal(0 <= position, "File::setPosition: negative absolute position"); + // position beyond EOS is OK + fseek((FILE*)handle, position, SEEK_SET); + finalPos = ftell((FILE*)handle); + } + else + { + // relative position + AssertFatal((getPosition() + position) >= 0, "File::setPosition: negative relative position"); + // position beyond EOS is OK + fseek((FILE*)handle, position, SEEK_CUR); + finalPos = ftell((FILE*)handle); + } + + // ftell returns -1 on error. set error status + if (0xffffffff == finalPos) + return setStatus(); + + // success, at end of file + else if (finalPos >= getSize()) + return currentStatus = EOS; + + // success! + else + return currentStatus = Ok; } //----------------------------------------------------------------------------- @@ -320,21 +320,21 @@ File::FileStatus File::setPosition(S32 position, bool absolutePos) //----------------------------------------------------------------------------- U32 File::getSize() const { - AssertWarn(Closed != currentStatus, "File::getSize: file closed"); - AssertFatal(handle != NULL, "File::getSize: invalid file handle"); - - if (Ok == currentStatus || EOS == currentStatus) - { - struct stat statData; - - if(fstat(fileno((FILE*)handle), &statData) != 0) - return 0; - - // return the size in bytes - return statData.st_size; - } - - return 0; + AssertWarn(Closed != currentStatus, "File::getSize: file closed"); + AssertFatal(handle != NULL, "File::getSize: invalid file handle"); + + if (Ok == currentStatus || EOS == currentStatus) + { + struct stat statData; + + if(fstat(fileno((FILE*)handle), &statData) != 0) + return 0; + + // return the size in bytes + return statData.st_size; + } + + return 0; } //----------------------------------------------------------------------------- @@ -344,14 +344,14 @@ U32 File::getSize() const //----------------------------------------------------------------------------- File::FileStatus File::flush() { - AssertFatal(Closed != currentStatus, "File::flush: file closed"); - AssertFatal(handle != NULL, "File::flush: invalid file handle"); - AssertFatal(true == hasCapability(FileWrite), "File::flush: cannot flush a read-only file"); - - if (fflush((FILE*)handle) != 0) - return setStatus(); - else - return currentStatus = Ok; + AssertFatal(Closed != currentStatus, "File::flush: file closed"); + AssertFatal(handle != NULL, "File::flush: invalid file handle"); + AssertFatal(true == hasCapability(FileWrite), "File::flush: cannot flush a read-only file"); + + if (fflush((FILE*)handle) != 0) + return setStatus(); + else + return currentStatus = Ok; } //----------------------------------------------------------------------------- @@ -361,18 +361,18 @@ File::FileStatus File::flush() //----------------------------------------------------------------------------- File::FileStatus File::close() { - // check if it's already closed... - if (Closed == currentStatus) - return currentStatus; - - // it's not, so close it... - if (handle != NULL) - { - if (fclose((FILE*)handle) != 0) - return setStatus(); - } - handle = NULL; - return currentStatus = Closed; + // check if it's already closed... + if (Closed == currentStatus) + return currentStatus; + + // it's not, so close it... + if (handle != NULL) + { + if (fclose((FILE*)handle) != 0) + return setStatus(); + } + handle = NULL; + return currentStatus = Closed; } //----------------------------------------------------------------------------- @@ -380,7 +380,7 @@ File::FileStatus File::close() //----------------------------------------------------------------------------- File::FileStatus File::getStatus() const { - return currentStatus; + return currentStatus; } //----------------------------------------------------------------------------- @@ -388,20 +388,20 @@ File::FileStatus File::getStatus() const //----------------------------------------------------------------------------- File::FileStatus File::setStatus() { - switch (errno) - { - case EACCES: // permission denied - currentStatus = IOError; - break; - case EBADF: // Bad File Pointer - case EINVAL: // Invalid argument - case ENOENT: // file not found - case ENAMETOOLONG: - default: - currentStatus = UnknownError; - } - - return currentStatus; + switch (errno) + { + case EACCES: // permission denied + currentStatus = IOError; + break; + case EBADF: // Bad File Pointer + case EINVAL: // Invalid argument + case ENOENT: // file not found + case ENAMETOOLONG: + default: + currentStatus = UnknownError; + } + + return currentStatus; } //----------------------------------------------------------------------------- @@ -409,7 +409,7 @@ File::FileStatus File::setStatus() //----------------------------------------------------------------------------- File::FileStatus File::setStatus(File::FileStatus status) { - return currentStatus = status; + return currentStatus = status; } //----------------------------------------------------------------------------- @@ -420,28 +420,28 @@ File::FileStatus File::setStatus(File::FileStatus status) //----------------------------------------------------------------------------- File::FileStatus File::read(U32 size, char *dst, U32 *bytesRead) { - AssertFatal(Closed != currentStatus, "File::read: file closed"); - AssertFatal(handle != NULL, "File::read: invalid file handle"); - AssertFatal(NULL != dst, "File::read: NULL destination pointer"); - AssertFatal(true == hasCapability(FileRead), "File::read: file lacks capability"); - AssertWarn(0 != size, "File::read: size of zero"); - - if (Ok != currentStatus || 0 == size) - return currentStatus; - - // read from stream - U32 nBytes = fread(dst, 1, size, (FILE*)handle); - - // did we hit the end of the stream? - if( nBytes != size) - currentStatus = EOS; - - // if bytesRead is a valid pointer, send number of bytes read there. - if(bytesRead) - *bytesRead = nBytes; - - // successfully read size bytes - return currentStatus; + AssertFatal(Closed != currentStatus, "File::read: file closed"); + AssertFatal(handle != NULL, "File::read: invalid file handle"); + AssertFatal(NULL != dst, "File::read: NULL destination pointer"); + AssertFatal(true == hasCapability(FileRead), "File::read: file lacks capability"); + AssertWarn(0 != size, "File::read: size of zero"); + + if (Ok != currentStatus || 0 == size) + return currentStatus; + + // read from stream + U32 nBytes = fread(dst, 1, size, (FILE*)handle); + + // did we hit the end of the stream? + if( nBytes != size) + currentStatus = EOS; + + // if bytesRead is a valid pointer, send number of bytes read there. + if(bytesRead) + *bytesRead = nBytes; + + // successfully read size bytes + return currentStatus; } //----------------------------------------------------------------------------- @@ -452,28 +452,28 @@ File::FileStatus File::read(U32 size, char *dst, U32 *bytesRead) //----------------------------------------------------------------------------- File::FileStatus File::write(U32 size, const char *src, U32 *bytesWritten) { - AssertFatal(Closed != currentStatus, "File::write: file closed"); - AssertFatal(handle != NULL, "File::write: invalid file handle"); - AssertFatal(NULL != src, "File::write: NULL source pointer"); - AssertFatal(true == hasCapability(FileWrite), "File::write: file lacks capability"); - AssertWarn(0 != size, "File::write: size of zero"); - - if ((Ok != currentStatus && EOS != currentStatus) || 0 == size) - return currentStatus; - - // write bytes to the stream - U32 nBytes = fwrite(src, 1, size,(FILE*)handle); - - // if we couldn't write everything, we've got a problem. set error status. - if(nBytes != size) - setStatus(); - - // if bytesWritten is a valid pointer, put number of bytes read there. - if(bytesWritten) - *bytesWritten = nBytes; - - // return current File status, whether good or ill. - return currentStatus; + AssertFatal(Closed != currentStatus, "File::write: file closed"); + AssertFatal(handle != NULL, "File::write: invalid file handle"); + AssertFatal(NULL != src, "File::write: NULL source pointer"); + AssertFatal(true == hasCapability(FileWrite), "File::write: file lacks capability"); + AssertWarn(0 != size, "File::write: size of zero"); + + if ((Ok != currentStatus && EOS != currentStatus) || 0 == size) + return currentStatus; + + // write bytes to the stream + U32 nBytes = fwrite(src, 1, size,(FILE*)handle); + + // if we couldn't write everything, we've got a problem. set error status. + if(nBytes != size) + setStatus(); + + // if bytesWritten is a valid pointer, put number of bytes read there. + if(bytesWritten) + *bytesWritten = nBytes; + + // return current File status, whether good or ill. + return currentStatus; } @@ -482,17 +482,17 @@ File::FileStatus File::write(U32 size, const char *src, U32 *bytesWritten) //----------------------------------------------------------------------------- bool File::hasCapability(Capability cap) const { - return (0 != (U32(cap) & capability)); + return (0 != (U32(cap) & capability)); } //----------------------------------------------------------------------------- S32 Platform::compareFileTimes(const FileTime &a, const FileTime &b) { - if(a > b) - return 1; - if(a < b) - return -1; - return 0; + if(a > b) + return 1; + if(a < b) + return -1; + return 0; } @@ -501,100 +501,100 @@ S32 Platform::compareFileTimes(const FileTime &a, const FileTime &b) //----------------------------------------------------------------------------- bool Platform::getFileTimes(const char *path, FileTime *createTime, FileTime *modifyTime) { - // MacOSX is NOT guaranteed to be running off a HFS volume, - // and UNIX does not keep a record of a file's creation time anywhere. - // So instead of creation time we return changed time, - // just like the Linux platform impl does. - - if (!path || !*path) - return false; - - struct stat statData; - - if (stat(path, &statData) == -1) - return false; - - if(createTime) - *createTime = statData.st_ctime; - - if(modifyTime) - *modifyTime = statData.st_mtime; - - return true; + // MacOSX is NOT guaranteed to be running off a HFS volume, + // and UNIX does not keep a record of a file's creation time anywhere. + // So instead of creation time we return changed time, + // just like the Linux platform impl does. + + if (!path || !*path) + return false; + + struct stat statData; + + if (stat(path, &statData) == -1) + return false; + + if(createTime) + *createTime = statData.st_ctime; + + if(modifyTime) + *modifyTime = statData.st_mtime; + + return true; } //----------------------------------------------------------------------------- bool Platform::createPath(const char *file) { - // if the path exists, we're done. - struct stat statData; - if( stat(file, &statData) == 0 ) - { - return true; // exists, rejoice. - } - - Con::warnf( "creating path %s", file ); - - // get the parent path. - // we're not using basename because it's not thread safe. - U32 len = dStrlen(file); - char parent[len]; - bool isDirPath = false; - - dStrncpy(parent,file,len); - parent[len] = '\0'; - if(parent[len - 1] == '/') - { - parent[len - 1] = '\0'; // cut off the trailing slash, if there is one - isDirPath = true; // we got a trailing slash, so file is a directory. - } - - // recusively create the parent path. - // only recurse if newpath has a slash that isn't a leading slash. - char *slash = dStrrchr(parent,'/'); - if( slash && slash != parent) - { - // snip the path just after the last slash. - slash[1] = '\0'; - // recusively create the parent path. fail if parent path creation failed. - if(!Platform::createPath(parent)) - return false; - } - - // create *file if it is a directory path. - if(isDirPath) - { - // try to create the directory - if( mkdir(file, 0777) != 0) // app may reside in global apps dir, and so must be writable to all. - return false; - } - - return true; + // if the path exists, we're done. + struct stat statData; + if( stat(file, &statData) == 0 ) + { + return true; // exists, rejoice. + } + + Con::warnf( "creating path %s", file ); + + // get the parent path. + // we're not using basename because it's not thread safe. + U32 len = dStrlen(file); + char parent[len]; + bool isDirPath = false; + + dStrncpy(parent,file,len); + parent[len] = '\0'; + if(parent[len - 1] == '/') + { + parent[len - 1] = '\0'; // cut off the trailing slash, if there is one + isDirPath = true; // we got a trailing slash, so file is a directory. + } + + // recusively create the parent path. + // only recurse if newpath has a slash that isn't a leading slash. + char *slash = dStrrchr(parent,'/'); + if( slash && slash != parent) + { + // snip the path just after the last slash. + slash[1] = '\0'; + // recusively create the parent path. fail if parent path creation failed. + if(!Platform::createPath(parent)) + return false; + } + + // create *file if it is a directory path. + if(isDirPath) + { + // try to create the directory + if( mkdir(file, 0777) != 0) // app may reside in global apps dir, and so must be writable to all. + return false; + } + + return true; } //----------------------------------------------------------------------------- bool Platform::cdFileExists(const char *filePath, const char *volumeName, S32 serialNum) { - return true; + return true; } #pragma mark ---- Directories ---- //----------------------------------------------------------------------------- StringTableEntry Platform::getCurrentDirectory() { - // get the current directory, the one that would be opened if we did a fopen(".") - char* cwd = getcwd(NULL, 0); - StringTableEntry ret = StringTable->insert(cwd); - free(cwd); - return ret; + // get the current directory, the one that would be opened if we did a fopen(".") + char* cwd = getcwd(NULL, 0); + StringTableEntry ret = StringTable->insert(cwd); + free(cwd); + return ret; } //----------------------------------------------------------------------------- bool Platform::setCurrentDirectory(StringTableEntry newDir) { - return (chdir(newDir) == 0); + return (chdir(newDir) == 0); } //----------------------------------------------------------------------------- @@ -602,7 +602,7 @@ bool Platform::setCurrentDirectory(StringTableEntry newDir) // helper func for getWorkingDirectory bool isMainDotCsPresent(NSString* dir) { - return [[NSFileManager defaultManager] fileExistsAtPath:[dir stringByAppendingPathComponent:@"main.cs"]] == YES; + return [[NSFileManager defaultManager] fileExistsAtPath:[dir stringByAppendingPathComponent:@"main.cs"]] == YES; } //----------------------------------------------------------------------------- @@ -619,119 +619,119 @@ bool isMainDotCsPresent(NSString* dir) /// experience when you distribute your app. StringTableEntry Platform::getExecutablePath() { - static const char* cwd = NULL; - - // this isn't actually being used due to some static constructors at bundle load time - // calling this method (before there is a chance to set it) - // for instance, FMOD sound provider (this should be fixed in FMOD as it is with windows) - if (!cwd && torque_getexecutablepath()) - { - // we're in a plugin using the cinterface - cwd = torque_getexecutablepath(); - chdir(cwd); - } - else if(!cwd) - { - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - - //first check the cwd for main.cs - static char buf[4096]; - NSString* currentDir = [[NSString alloc ] initWithUTF8String:getcwd(buf,(4096 * sizeof(char))) ]; - - if (isMainDotCsPresent(currentDir)) - { - cwd = buf; - [pool release]; - [currentDir release]; - return cwd; - } - - NSString* string = [[NSBundle mainBundle] pathForResource:@"main" ofType:@"cs"]; - if(!string) - string = [[NSBundle mainBundle] bundlePath]; - - string = [string stringByDeletingLastPathComponent]; - AssertISV(isMainDotCsPresent(string), "Platform::getExecutablePath - Failed to find main.cs!"); - cwd = dStrdup([string UTF8String]); - chdir(cwd); - [pool release]; - [currentDir release]; - } - - return cwd; + static const char* cwd = NULL; + + // this isn't actually being used due to some static constructors at bundle load time + // calling this method (before there is a chance to set it) + // for instance, FMOD sound provider (this should be fixed in FMOD as it is with windows) + if (!cwd && torque_getexecutablepath()) + { + // we're in a plugin using the cinterface + cwd = torque_getexecutablepath(); + chdir(cwd); + } + else if(!cwd) + { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + + //first check the cwd for main.cs + static char buf[4096]; + NSString* currentDir = [[NSString alloc ] initWithUTF8String:getcwd(buf,(4096 * sizeof(char))) ]; + + if (isMainDotCsPresent(currentDir)) + { + cwd = buf; + [pool release]; + [currentDir release]; + return cwd; + } + + NSString* string = [[NSBundle mainBundle] pathForResource:@"main" ofType:@"cs"]; + if(!string) + string = [[NSBundle mainBundle] bundlePath]; + + string = [string stringByDeletingLastPathComponent]; + AssertISV(isMainDotCsPresent(string), "Platform::getExecutablePath - Failed to find main.cs!"); + cwd = dStrdup([string UTF8String]); + chdir(cwd); + [pool release]; + [currentDir release]; + } + + return cwd; } //----------------------------------------------------------------------------- StringTableEntry Platform::getExecutableName() { - static const char* name = NULL; - if(!name) - name = [[[[NSBundle mainBundle] bundlePath] lastPathComponent] UTF8String]; - - return name; + static const char* name = NULL; + if(!name) + name = [[[[NSBundle mainBundle] bundlePath] lastPathComponent] UTF8String]; + + return name; } //----------------------------------------------------------------------------- bool Platform::isFile(const char *path) { - if (!path || !*path) - return false; - - // make sure we can stat the file - struct stat statData; - if( stat(path, &statData) < 0 ) - { - // Since file does not exist on disk see if it exists in a zip file loaded - return Torque::FS::IsFile(path); - } - - // now see if it's a regular file - if( (statData.st_mode & S_IFMT) == S_IFREG) - return true; - - return false; + if (!path || !*path) + return false; + + // make sure we can stat the file + struct stat statData; + if( stat(path, &statData) < 0 ) + { + // Since file does not exist on disk see if it exists in a zip file loaded + return Torque::FS::IsFile(path); + } + + // now see if it's a regular file + if( (statData.st_mode & S_IFMT) == S_IFREG) + return true; + + return false; } //----------------------------------------------------------------------------- bool Platform::isDirectory(const char *path) { - if (!path || !*path) - return false; - - // make sure we can stat the file - struct stat statData; - if( stat(path, &statData) < 0 ) - return false; - - // now see if it's a directory - if( (statData.st_mode & S_IFMT) == S_IFDIR) - return true; - - return false; + if (!path || !*path) + return false; + + // make sure we can stat the file + struct stat statData; + if( stat(path, &statData) < 0 ) + return false; + + // now see if it's a directory + if( (statData.st_mode & S_IFMT) == S_IFDIR) + return true; + + return false; } S32 Platform::getFileSize(const char* pFilePath) { - if (!pFilePath || !*pFilePath) - return 0; - - struct stat statData; - if( stat(pFilePath, &statData) < 0 ) - return 0; - - // and return it's size in bytes - return (S32)statData.st_size; + if (!pFilePath || !*pFilePath) + return 0; + + struct stat statData; + if( stat(pFilePath, &statData) < 0 ) + return 0; + + // and return it's size in bytes + return (S32)statData.st_size; } //----------------------------------------------------------------------------- bool Platform::isSubDirectory(const char *pathParent, const char *pathSub) { - char fullpath[MAX_MAC_PATH_LONG]; - dStrcpyl(fullpath, MAX_MAC_PATH_LONG, pathParent, "/", pathSub, NULL); - return isDirectory((const char *)fullpath); + char fullpath[MAX_MAC_PATH_LONG]; + dStrcpyl(fullpath, MAX_MAC_PATH_LONG, pathParent, "/", pathSub, NULL); + return isDirectory((const char *)fullpath); } //----------------------------------------------------------------------------- @@ -739,250 +739,250 @@ bool Platform::isSubDirectory(const char *pathParent, const char *pathSub) // ensures that the entry is a directory, and isnt on the ignore lists. inline bool isGoodDirectory(dirent* entry) { - return (entry->d_type == DT_DIR // is a dir - && dStrcmp(entry->d_name,".") != 0 // not here - && dStrcmp(entry->d_name,"..") != 0 // not parent - && !Platform::isExcludedDirectory(entry->d_name)); // not excluded + return (entry->d_type == DT_DIR // is a dir + && dStrcmp(entry->d_name,".") != 0 // not here + && dStrcmp(entry->d_name,"..") != 0 // not parent + && !Platform::isExcludedDirectory(entry->d_name)); // not excluded } //----------------------------------------------------------------------------- bool Platform::hasSubDirectory(const char *path) { - DIR *dir; - dirent *entry; - - dir = opendir(path); - if(!dir) - return false; // we got a bad path, so no, it has no subdirectory. - - while( (entry = readdir(dir)) ) - { - if(isGoodDirectory(entry) ) - { - closedir(dir); - return true; // we have a subdirectory, that isnt on the exclude list. - } - } - - closedir(dir); - return false; // either this dir had no subdirectories, or they were all on the exclude list. + DIR *dir; + dirent *entry; + + dir = opendir(path); + if(!dir) + return false; // we got a bad path, so no, it has no subdirectory. + + while( (entry = readdir(dir)) ) + { + if(isGoodDirectory(entry) ) + { + closedir(dir); + return true; // we have a subdirectory, that isnt on the exclude list. + } + } + + closedir(dir); + return false; // either this dir had no subdirectories, or they were all on the exclude list. } bool Platform::fileDelete(const char * name) { - return dFileDelete(name); + return dFileDelete(name); } static bool recurseDumpDirectories(const char *basePath, const char *subPath, Vector &directoryVector, S32 currentDepth, S32 recurseDepth, bool noBasePath) { - char Path[1024]; - DIR *dip; - struct dirent *d; - - dsize_t trLen = basePath ? dStrlen(basePath) : 0; - dsize_t subtrLen = subPath ? dStrlen(subPath) : 0; - char trail = trLen > 0 ? basePath[trLen - 1] : '\0'; - char subTrail = subtrLen > 0 ? subPath[subtrLen - 1] : '\0'; - - if (trail == '/') - { - if (subPath && (dStrncmp(subPath, "", 1) != 0)) - { - if (subTrail == '/') - dSprintf(Path, 1024, "%s%s", basePath, subPath); - else - dSprintf(Path, 1024, "%s%s/", basePath, subPath); - } - else - dSprintf(Path, 1024, "%s", basePath); - } - else - { - if (subPath && (dStrncmp(subPath, "", 1) != 0)) - { - if (subTrail == '/') - dSprintf(Path, 1024, "%s%s", basePath, subPath); - else - dSprintf(Path, 1024, "%s%s/", basePath, subPath); - } - else - dSprintf(Path, 1024, "%s/", basePath); - } - - dip = opendir(Path); - if (dip == NULL) - return false; - - ////////////////////////////////////////////////////////////////////////// - // add path to our return list ( provided it is valid ) - ////////////////////////////////////////////////////////////////////////// - if (!Platform::isExcludedDirectory(subPath)) - { - if (noBasePath) - { - // We have a path and it's not an empty string or an excluded directory - if ( (subPath && (dStrncmp (subPath, "", 1) != 0)) ) - directoryVector.push_back(StringTable->insert(subPath)); - } - else - { - if ( (subPath && (dStrncmp(subPath, "", 1) != 0)) ) - { - char szPath[1024]; - dMemset(szPath, 0, 1024); - if (trail == '/') - { - if ((basePath[dStrlen(basePath) - 1]) != '/') - dSprintf(szPath, 1024, "%s%s", basePath, &subPath[1]); - else - dSprintf(szPath, 1024, "%s%s", basePath, subPath); - } - else - { - if ((basePath[dStrlen(basePath) - 1]) != '/') - dSprintf(szPath, 1024, "%s%s", basePath, subPath); - else - dSprintf(szPath, 1024, "%s/%s", basePath, subPath); - } - - directoryVector.push_back(StringTable->insert(szPath)); - } - else - directoryVector.push_back(StringTable->insert(basePath)); - } - } - ////////////////////////////////////////////////////////////////////////// - // Iterate through and grab valid directories - ////////////////////////////////////////////////////////////////////////// - - while (d = readdir(dip)) - { - bool isDir; - isDir = false; - if (d->d_type == DT_UNKNOWN) - { - char child [1024]; - if ((Path[dStrlen(Path) - 1] == '/')) - dSprintf(child, 1024, "%s%s", Path, d->d_name); - else - dSprintf(child, 1024, "%s/%s", Path, d->d_name); - isDir = Platform::isDirectory (child); - } - else if (d->d_type & DT_DIR) - isDir = true; - - if ( isDir ) - { - if (dStrcmp(d->d_name, ".") == 0 || - dStrcmp(d->d_name, "..") == 0) - continue; - if (Platform::isExcludedDirectory(d->d_name)) - continue; - if ( (subPath && (dStrncmp(subPath, "", 1) != 0)) ) - { - char child[1024]; - if ((subPath[dStrlen(subPath) - 1] == '/')) - dSprintf(child, 1024, "%s%s", subPath, d->d_name); - else - dSprintf(child, 1024, "%s/%s", subPath, d->d_name); - if (currentDepth < recurseDepth || recurseDepth == -1 ) - recurseDumpDirectories(basePath, child, directoryVector, - currentDepth + 1, recurseDepth, - noBasePath); - } - else - { - char child[1024]; - if ( (basePath[dStrlen(basePath) - 1]) == '/') - dStrcpy (child, d->d_name); - else - dSprintf(child, 1024, "/%s", d->d_name); - if (currentDepth < recurseDepth || recurseDepth == -1) - recurseDumpDirectories(basePath, child, directoryVector, - currentDepth + 1, recurseDepth, - noBasePath); - } - } - } - closedir(dip); - return true; + char Path[1024]; + DIR *dip; + struct dirent *d; + + dsize_t trLen = basePath ? dStrlen(basePath) : 0; + dsize_t subtrLen = subPath ? dStrlen(subPath) : 0; + char trail = trLen > 0 ? basePath[trLen - 1] : '\0'; + char subTrail = subtrLen > 0 ? subPath[subtrLen - 1] : '\0'; + + if (trail == '/') + { + if (subPath && (dStrncmp(subPath, "", 1) != 0)) + { + if (subTrail == '/') + dSprintf(Path, 1024, "%s%s", basePath, subPath); + else + dSprintf(Path, 1024, "%s%s/", basePath, subPath); + } + else + dSprintf(Path, 1024, "%s", basePath); + } + else + { + if (subPath && (dStrncmp(subPath, "", 1) != 0)) + { + if (subTrail == '/') + dSprintf(Path, 1024, "%s%s", basePath, subPath); + else + dSprintf(Path, 1024, "%s%s/", basePath, subPath); + } + else + dSprintf(Path, 1024, "%s/", basePath); + } + + dip = opendir(Path); + if (dip == NULL) + return false; + + ////////////////////////////////////////////////////////////////////////// + // add path to our return list ( provided it is valid ) + ////////////////////////////////////////////////////////////////////////// + if (!Platform::isExcludedDirectory(subPath)) + { + if (noBasePath) + { + // We have a path and it's not an empty string or an excluded directory + if ( (subPath && (dStrncmp (subPath, "", 1) != 0)) ) + directoryVector.push_back(StringTable->insert(subPath)); + } + else + { + if ( (subPath && (dStrncmp(subPath, "", 1) != 0)) ) + { + char szPath[1024]; + dMemset(szPath, 0, 1024); + if (trail == '/') + { + if ((basePath[dStrlen(basePath) - 1]) != '/') + dSprintf(szPath, 1024, "%s%s", basePath, &subPath[1]); + else + dSprintf(szPath, 1024, "%s%s", basePath, subPath); + } + else + { + if ((basePath[dStrlen(basePath) - 1]) != '/') + dSprintf(szPath, 1024, "%s%s", basePath, subPath); + else + dSprintf(szPath, 1024, "%s/%s", basePath, subPath); + } + + directoryVector.push_back(StringTable->insert(szPath)); + } + else + directoryVector.push_back(StringTable->insert(basePath)); + } + } + ////////////////////////////////////////////////////////////////////////// + // Iterate through and grab valid directories + ////////////////////////////////////////////////////////////////////////// + + while (d = readdir(dip)) + { + bool isDir; + isDir = false; + if (d->d_type == DT_UNKNOWN) + { + char child [1024]; + if ((Path[dStrlen(Path) - 1] == '/')) + dSprintf(child, 1024, "%s%s", Path, d->d_name); + else + dSprintf(child, 1024, "%s/%s", Path, d->d_name); + isDir = Platform::isDirectory (child); + } + else if (d->d_type & DT_DIR) + isDir = true; + + if ( isDir ) + { + if (dStrcmp(d->d_name, ".") == 0 || + dStrcmp(d->d_name, "..") == 0) + continue; + if (Platform::isExcludedDirectory(d->d_name)) + continue; + if ( (subPath && (dStrncmp(subPath, "", 1) != 0)) ) + { + char child[1024]; + if ((subPath[dStrlen(subPath) - 1] == '/')) + dSprintf(child, 1024, "%s%s", subPath, d->d_name); + else + dSprintf(child, 1024, "%s/%s", subPath, d->d_name); + if (currentDepth < recurseDepth || recurseDepth == -1 ) + recurseDumpDirectories(basePath, child, directoryVector, + currentDepth + 1, recurseDepth, + noBasePath); + } + else + { + char child[1024]; + if ( (basePath[dStrlen(basePath) - 1]) == '/') + dStrcpy (child, d->d_name); + else + dSprintf(child, 1024, "/%s", d->d_name); + if (currentDepth < recurseDepth || recurseDepth == -1) + recurseDumpDirectories(basePath, child, directoryVector, + currentDepth + 1, recurseDepth, + noBasePath); + } + } + } + closedir(dip); + return true; } //----------------------------------------------------------------------------- bool Platform::dumpDirectories(const char *path, Vector &directoryVector, S32 depth, bool noBasePath) { - bool retVal = recurseDumpDirectories(path, "", directoryVector, 0, depth, noBasePath); - clearExcludedDirectories(); - return retVal; + bool retVal = recurseDumpDirectories(path, "", directoryVector, 0, depth, noBasePath); + clearExcludedDirectories(); + return retVal; } //----------------------------------------------------------------------------- static bool recurseDumpPath(const char* curPath, Vector& fileVector, U32 depth) { - DIR *dir; - dirent *entry; - - // be sure it opens. - dir = opendir(curPath); - if(!dir) - return false; - - // look inside the current directory - while( (entry = readdir(dir)) ) - { - // construct the full file path. we need this to get the file size and to recurse - U32 len = dStrlen(curPath) + entry->d_namlen + 2; - char pathbuf[len]; - dSprintf( pathbuf, len, "%s/%s", curPath, entry->d_name); - pathbuf[len] = '\0'; - - // ok, deal with directories and files seperately. - if( entry->d_type == DT_DIR ) - { - if( depth == 0) - continue; - - // filter out dirs we dont want. - if( !isGoodDirectory(entry) ) - continue; - - // recurse into the dir - recurseDumpPath( pathbuf, fileVector, depth-1); - } - else - { - //add the file entry to the list - // unlike recurseDumpDirectories(), we need to return more complex info here. - U32 fileSize = Platform::getFileSize(pathbuf); - fileVector.increment(); - Platform::FileInfo& rInfo = fileVector.last(); - rInfo.pFullPath = StringTable->insert(curPath); - rInfo.pFileName = StringTable->insert(entry->d_name); - rInfo.fileSize = fileSize; - } - } - closedir(dir); - return true; - + DIR *dir; + dirent *entry; + + // be sure it opens. + dir = opendir(curPath); + if(!dir) + return false; + + // look inside the current directory + while( (entry = readdir(dir)) ) + { + // construct the full file path. we need this to get the file size and to recurse + U32 len = dStrlen(curPath) + entry->d_namlen + 2; + char pathbuf[len]; + dSprintf( pathbuf, len, "%s/%s", curPath, entry->d_name); + pathbuf[len] = '\0'; + + // ok, deal with directories and files seperately. + if( entry->d_type == DT_DIR ) + { + if( depth == 0) + continue; + + // filter out dirs we dont want. + if( !isGoodDirectory(entry) ) + continue; + + // recurse into the dir + recurseDumpPath( pathbuf, fileVector, depth-1); + } + else + { + //add the file entry to the list + // unlike recurseDumpDirectories(), we need to return more complex info here. + U32 fileSize = Platform::getFileSize(pathbuf); + fileVector.increment(); + Platform::FileInfo& rInfo = fileVector.last(); + rInfo.pFullPath = StringTable->insert(curPath); + rInfo.pFileName = StringTable->insert(entry->d_name); + rInfo.fileSize = fileSize; + } + } + closedir(dir); + return true; + } //----------------------------------------------------------------------------- bool Platform::dumpPath(const char *path, Vector& fileVector, S32 depth) { - PROFILE_START(dumpPath); - int len = dStrlen(path); - char newpath[len+1]; - - dStrncpy(newpath,path,len); - newpath[len] = '\0'; // null terminate - if(newpath[len - 1] == '/') - newpath[len - 1] = '\0'; // cut off the trailing slash, if there is one - - bool ret = recurseDumpPath( newpath, fileVector, depth); - PROFILE_END(); - - return ret; + PROFILE_START(dumpPath); + int len = dStrlen(path); + char newpath[len+1]; + + dStrncpy(newpath,path,len); + newpath[len] = '\0'; // null terminate + if(newpath[len - 1] == '/') + newpath[len - 1] = '\0'; // cut off the trailing slash, if there is one + + bool ret = recurseDumpPath( newpath, fileVector, depth); + PROFILE_END(); + + return ret; } // TODO: implement stringToFileTime() @@ -993,57 +993,57 @@ bool Platform::fileTimeToString(FileTime * time, char * string, U32 strLen) { re //----------------------------------------------------------------------------- #if defined(TORQUE_DEBUG) ConsoleFunction(testHasSubdir,void,2,2,"tests platform::hasSubDirectory") { - Con::printf("testing %s",(const char*)argv[1]); - Platform::addExcludedDirectory(".svn"); - if(Platform::hasSubDirectory(argv[1])) - Con::printf(" has subdir"); - else - Con::printf(" does not have subdir"); + Con::printf("testing %s",(const char*)argv[1]); + Platform::addExcludedDirectory(".svn"); + if(Platform::hasSubDirectory(argv[1])) + Con::printf(" has subdir"); + else + Con::printf(" does not have subdir"); } ConsoleFunction(testDumpDirectories,void,4,4,"testDumpDirectories('path', int depth, bool noBasePath)") { - Vector paths; - const S32 depth = dAtoi(argv[2]); - const bool noBasePath = dAtob(argv[3]); - - Platform::addExcludedDirectory(".svn"); - - Platform::dumpDirectories(argv[1], paths, depth, noBasePath); - - Con::printf("Dumping directories starting from %s with depth %i", (const char*)argv[1],depth); - - for(Vector::iterator itr = paths.begin(); itr != paths.end(); itr++) { - Con::printf(*itr); - } - + Vector paths; + const S32 depth = dAtoi(argv[2]); + const bool noBasePath = dAtob(argv[3]); + + Platform::addExcludedDirectory(".svn"); + + Platform::dumpDirectories(argv[1], paths, depth, noBasePath); + + Con::printf("Dumping directories starting from %s with depth %i", (const char*)argv[1],depth); + + for(Vector::iterator itr = paths.begin(); itr != paths.end(); itr++) { + Con::printf(*itr); + } + } ConsoleFunction(testDumpPaths, void, 3, 3, "testDumpPaths('path', int depth)") { - Vector files; - S32 depth = dAtoi(argv[2]); - - Platform::addExcludedDirectory(".svn"); - - Platform::dumpPath(argv[1], files, depth); - - for(Vector::iterator itr = files.begin(); itr != files.end(); itr++) { - Con::printf("%s/%s",itr->pFullPath, itr->pFileName); - } + Vector files; + S32 depth = dAtoi(argv[2]); + + Platform::addExcludedDirectory(".svn"); + + Platform::dumpPath(argv[1], files, depth); + + for(Vector::iterator itr = files.begin(); itr != files.end(); itr++) { + Con::printf("%s/%s",itr->pFullPath, itr->pFileName); + } } //----------------------------------------------------------------------------- ConsoleFunction(testFileTouch, bool , 2,2, "testFileTouch('path')") { - return dFileTouch(argv[1]); + return dFileTouch(argv[1]); } ConsoleFunction(testGetFileTimes, bool, 2,2, "testGetFileTimes('path')") { - FileTime create, modify; - bool ok = Platform::getFileTimes(argv[1], &create, &modify); - Con::printf("%s Platform::getFileTimes %i, %i", ok ? "+OK" : "-FAIL", create, modify); - return ok; + FileTime create, modify; + bool ok = Platform::getFileTimes(argv[1], &create, &modify); + Con::printf("%s Platform::getFileTimes %i, %i", ok ? "+OK" : "-FAIL", create, modify); + return ok; } #endif From 9c69cd32e85dea8e41f8a4f16d91a071c55c1c90 Mon Sep 17 00:00:00 2001 From: "Thomas \"elfprince13\" Dickerson" Date: Fri, 6 Jan 2017 17:45:09 -0500 Subject: [PATCH 4/9] Attempting to fix tabs and space (again) --- Engine/source/platform/profiler.cpp | 2 +- Engine/source/platformMac/macFileIO.mm | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Engine/source/platform/profiler.cpp b/Engine/source/platform/profiler.cpp index 5569f5bbe..69d3089e1 100644 --- a/Engine/source/platform/profiler.cpp +++ b/Engine/source/platform/profiler.cpp @@ -611,7 +611,7 @@ void Profiler::dump() if (mDumpToConsole == true) - { + { Con::printf("Profiler Data Dump:"); Con::printf("Ordered by non-sub total time -"); Con::printf("%%NSTime %% Time Invoke # Name"); diff --git a/Engine/source/platformMac/macFileIO.mm b/Engine/source/platformMac/macFileIO.mm index 90efbd303..236a95282 100644 --- a/Engine/source/platformMac/macFileIO.mm +++ b/Engine/source/platformMac/macFileIO.mm @@ -999,7 +999,7 @@ ConsoleFunction(testHasSubdir,void,2,2,"tests platform::hasSubDirectory") { Con::printf(" has subdir"); else Con::printf(" does not have subdir"); -} +} ConsoleFunction(testDumpDirectories,void,4,4,"testDumpDirectories('path', int depth, bool noBasePath)") { Vector paths; From e554fc7f93d1f8941ea029cd06eddc941490739b Mon Sep 17 00:00:00 2001 From: "Thomas \"elfprince13\" Dickerson" Date: Fri, 6 Jan 2017 17:45:38 -0500 Subject: [PATCH 5/9] undo spurious changes used to trigger dirty for tabs and spaces --- Engine/source/platform/profiler.cpp | 1114 ++++++++++++------------ Engine/source/platformMac/macFileIO.mm | 2 +- 2 files changed, 558 insertions(+), 558 deletions(-) diff --git a/Engine/source/platform/profiler.cpp b/Engine/source/platform/profiler.cpp index 69d3089e1..1fa089c6e 100644 --- a/Engine/source/platform/profiler.cpp +++ b/Engine/source/platform/profiler.cpp @@ -67,45 +67,45 @@ gProfilerNodeStack.pop_back(); // platform specific get hires times... void startHighResolutionTimer(U32 time[2]) { - //time[0] = Platform::getRealMilliseconds(); - - __asm - { - push eax - push edx - push ecx - rdtsc - mov ecx, time - mov DWORD PTR [ecx], eax - mov DWORD PTR [ecx + 4], edx - pop ecx - pop edx - pop eax - } + //time[0] = Platform::getRealMilliseconds(); + + __asm + { + push eax + push edx + push ecx + rdtsc + mov ecx, time + mov DWORD PTR [ecx], eax + mov DWORD PTR [ecx + 4], edx + pop ecx + pop edx + pop eax + } } U32 endHighResolutionTimer(U32 time[2]) { - U32 ticks; - //ticks = Platform::getRealMilliseconds() - time[0]; - //return ticks; - - __asm - { - push eax - push edx - push ecx - //db 0fh, 31h - rdtsc - mov ecx, time - sub edx, DWORD PTR [ecx+4] - sbb eax, DWORD PTR [ecx] - mov DWORD PTR ticks, eax - pop ecx - pop edx - pop eax - } - return ticks; + U32 ticks; + //ticks = Platform::getRealMilliseconds() - time[0]; + //return ticks; + + __asm + { + push eax + push edx + push ecx + //db 0fh, 31h + rdtsc + mov ecx, time + sub edx, DWORD PTR [ecx+4] + sbb eax, DWORD PTR [ecx] + mov DWORD PTR ticks, eax + pop ecx + pop edx + pop eax + } + return ticks; } #elif defined(TORQUE_SUPPORTS_GCC_INLINE_X86_ASM) @@ -113,599 +113,599 @@ U32 endHighResolutionTimer(U32 time[2]) // platform specific get hires times... void startHighResolutionTimer(U32 time[2]) { - __asm__ __volatile__( - "rdtsc\n" - : "=a" (time[0]), "=d" (time[1]) - ); + __asm__ __volatile__( + "rdtsc\n" + : "=a" (time[0]), "=d" (time[1]) + ); } U32 endHighResolutionTimer(U32 time[2]) { - U32 ticks; - __asm__ __volatile__( - "rdtsc\n" - "sub 0x4(%%ecx), %%edx\n" - "sbb (%%ecx), %%eax\n" - : "=a" (ticks) : "c" (time) - ); - return ticks; + U32 ticks; + __asm__ __volatile__( + "rdtsc\n" + "sub 0x4(%%ecx), %%edx\n" + "sbb (%%ecx), %%eax\n" + : "=a" (ticks) : "c" (time) + ); + return ticks; } #elif defined(TORQUE_OS_MAC) void startHighResolutionTimer(U32 time[2]) { - U64 now = mach_absolute_time(); - AssertFatal(sizeof(U32[2]) == sizeof(U64), "Can't pack mach_absolute_time into U32[2]"); - memcpy(time, &now, sizeof(U64)); + U64 now = mach_absolute_time(); + AssertFatal(sizeof(U32[2]) == sizeof(U64), "Can't pack mach_absolute_time into U32[2]"); + memcpy(time, &now, sizeof(U64)); } U32 endHighResolutionTimer(U32 time[2]) { - static mach_timebase_info_data_t sTimebaseInfo = {0, 0}; - - U64 now = mach_absolute_time(); - AssertFatal(sizeof(U32[2]) == sizeof(U64), "Can't pack mach_absolute_time into U32[2]"); - U64 then; - memcpy(&then, time, sizeof(U64)); - - if(sTimebaseInfo.denom == 0){ - mach_timebase_info(&sTimebaseInfo); - } - // Handle the micros/nanos conversion first, because shedding a few bits is better than overflowing. - U64 elapsedMicros = ((now - then) / 1000) * sTimebaseInfo.numer / sTimebaseInfo.denom; - - return (U32)elapsedMicros; // Just truncate, and hope we didn't overflow + static mach_timebase_info_data_t sTimebaseInfo = {0, 0}; + + U64 now = mach_absolute_time(); + AssertFatal(sizeof(U32[2]) == sizeof(U64), "Can't pack mach_absolute_time into U32[2]"); + U64 then; + memcpy(&then, time, sizeof(U64)); + + if(sTimebaseInfo.denom == 0){ + mach_timebase_info(&sTimebaseInfo); + } + // Handle the micros/nanos conversion first, because shedding a few bits is better than overflowing. + U64 elapsedMicros = ((now - then) / 1000) * sTimebaseInfo.numer / sTimebaseInfo.denom; + + return (U32)elapsedMicros; // Just truncate, and hope we didn't overflow } #else void startHighResolutionTimer(U32 time[2]) { - time[0] = Platform::getRealMilliseconds(); + time[0] = Platform::getRealMilliseconds(); } U32 endHighResolutionTimer(U32 time[2]) { - U32 ticks = Platform::getRealMilliseconds() - time[0]; - return ticks; + U32 ticks = Platform::getRealMilliseconds() - time[0]; + return ticks; } #endif Profiler::Profiler() { - mMaxStackDepth = MaxStackDepth; - mCurrentHash = 0; - - mCurrentProfilerData = (ProfilerData *) malloc(sizeof(ProfilerData)); - mCurrentProfilerData->mRoot = NULL; - mCurrentProfilerData->mNextForRoot = NULL; - mCurrentProfilerData->mNextProfilerData = NULL; - mCurrentProfilerData->mNextHash = NULL; - mCurrentProfilerData->mParent = NULL; - mCurrentProfilerData->mNextSibling = NULL; - mCurrentProfilerData->mFirstChild = NULL; - mCurrentProfilerData->mLastSeenProfiler = NULL; - mCurrentProfilerData->mHash = 0; - mCurrentProfilerData->mSubDepth = 0; - mCurrentProfilerData->mInvokeCount = 0; - mCurrentProfilerData->mTotalTime = 0; - mCurrentProfilerData->mSubTime = 0; + mMaxStackDepth = MaxStackDepth; + mCurrentHash = 0; + + mCurrentProfilerData = (ProfilerData *) malloc(sizeof(ProfilerData)); + mCurrentProfilerData->mRoot = NULL; + mCurrentProfilerData->mNextForRoot = NULL; + mCurrentProfilerData->mNextProfilerData = NULL; + mCurrentProfilerData->mNextHash = NULL; + mCurrentProfilerData->mParent = NULL; + mCurrentProfilerData->mNextSibling = NULL; + mCurrentProfilerData->mFirstChild = NULL; + mCurrentProfilerData->mLastSeenProfiler = NULL; + mCurrentProfilerData->mHash = 0; + mCurrentProfilerData->mSubDepth = 0; + mCurrentProfilerData->mInvokeCount = 0; + mCurrentProfilerData->mTotalTime = 0; + mCurrentProfilerData->mSubTime = 0; #ifdef TORQUE_ENABLE_PROFILE_PATH - mCurrentProfilerData->mPath = ""; + mCurrentProfilerData->mPath = ""; #endif - mRootProfilerData = mCurrentProfilerData; - - for(U32 i = 0; i < ProfilerData::HashTableSize; i++) - mCurrentProfilerData->mChildHash[i] = 0; - - mProfileList = NULL; - - mEnabled = TORQUE_PROFILE_AT_ENGINE_START; - mNextEnable = TORQUE_PROFILE_AT_ENGINE_START; - mStackDepth = 0; - gProfiler = this; - mDumpToConsole = false; - mDumpToFile = false; - mDumpFileName[0] = '\0'; + mRootProfilerData = mCurrentProfilerData; + + for(U32 i = 0; i < ProfilerData::HashTableSize; i++) + mCurrentProfilerData->mChildHash[i] = 0; + + mProfileList = NULL; + + mEnabled = TORQUE_PROFILE_AT_ENGINE_START; + mNextEnable = TORQUE_PROFILE_AT_ENGINE_START; + mStackDepth = 0; + gProfiler = this; + mDumpToConsole = false; + mDumpToFile = false; + mDumpFileName[0] = '\0'; } Profiler::~Profiler() { - reset(); - free(mRootProfilerData); - gProfiler = NULL; + reset(); + free(mRootProfilerData); + gProfiler = NULL; } void Profiler::reset() { - mEnabled = false; // in case we're in a profiler call. - ProfilerData * head = mProfileList; - ProfilerData * curr = head; - - while ( curr ) - { - head = curr->mNextProfilerData; - free( curr ); - - if ( head ) - curr = head; - else - curr = NULL; - } - - mProfileList = NULL; - - for(ProfilerRootData *walk = ProfilerRootData::sRootList; walk; walk = walk->mNextRoot) - { - walk->mFirstProfilerData = 0; - walk->mTotalTime = 0; - walk->mSubTime = 0; - walk->mTotalInvokeCount = 0; - } - mCurrentProfilerData = mRootProfilerData; - mCurrentProfilerData->mNextForRoot = 0; - mCurrentProfilerData->mFirstChild = 0; - for(U32 i = 0; i < ProfilerData::HashTableSize; i++) - mCurrentProfilerData->mChildHash[i] = 0; - mCurrentProfilerData->mInvokeCount = 0; - mCurrentProfilerData->mTotalTime = 0; - mCurrentProfilerData->mSubTime = 0; - mCurrentProfilerData->mSubDepth = 0; - mCurrentProfilerData->mLastSeenProfiler = 0; + mEnabled = false; // in case we're in a profiler call. + ProfilerData * head = mProfileList; + ProfilerData * curr = head; + + while ( curr ) + { + head = curr->mNextProfilerData; + free( curr ); + + if ( head ) + curr = head; + else + curr = NULL; + } + + mProfileList = NULL; + + for(ProfilerRootData *walk = ProfilerRootData::sRootList; walk; walk = walk->mNextRoot) + { + walk->mFirstProfilerData = 0; + walk->mTotalTime = 0; + walk->mSubTime = 0; + walk->mTotalInvokeCount = 0; + } + mCurrentProfilerData = mRootProfilerData; + mCurrentProfilerData->mNextForRoot = 0; + mCurrentProfilerData->mFirstChild = 0; + for(U32 i = 0; i < ProfilerData::HashTableSize; i++) + mCurrentProfilerData->mChildHash[i] = 0; + mCurrentProfilerData->mInvokeCount = 0; + mCurrentProfilerData->mTotalTime = 0; + mCurrentProfilerData->mSubTime = 0; + mCurrentProfilerData->mSubDepth = 0; + mCurrentProfilerData->mLastSeenProfiler = 0; } static Profiler aProfiler; // allocate the global profiler ProfilerRootData::ProfilerRootData(const char *name) { - for(ProfilerRootData *walk = sRootList; walk; walk = walk->mNextRoot) - if(!dStrcmp(walk->mName, name)) - AssertFatal( false, avar( "Duplicate profile name: %s", name ) ); - - mName = name; - mNameHash = _StringTable::hashString(name); - mNextRoot = sRootList; - sRootList = this; - mTotalTime = 0; - mTotalInvokeCount = 0; - mFirstProfilerData = NULL; - mEnabled = true; + for(ProfilerRootData *walk = sRootList; walk; walk = walk->mNextRoot) + if(!dStrcmp(walk->mName, name)) + AssertFatal( false, avar( "Duplicate profile name: %s", name ) ); + + mName = name; + mNameHash = _StringTable::hashString(name); + mNextRoot = sRootList; + sRootList = this; + mTotalTime = 0; + mTotalInvokeCount = 0; + mFirstProfilerData = NULL; + mEnabled = true; } void Profiler::validate() { - for(ProfilerRootData *walk = ProfilerRootData::sRootList; walk; walk = walk->mNextRoot) - { - for(ProfilerData *dp = walk->mFirstProfilerData; dp; dp = dp->mNextForRoot) - { - if(dp->mRoot != walk) - Platform::debugBreak(); - // check if it's in the parent's list... - ProfilerData *wk; - for(wk = dp->mParent->mFirstChild; wk; wk = wk->mNextSibling) - if(wk == dp) - break; - if(!wk) - Platform::debugBreak(); - for(wk = dp->mParent->mChildHash[walk->mNameHash & (ProfilerData::HashTableSize - 1)] ; - wk; wk = wk->mNextHash) - if(wk == dp) - break; - if(!wk) - Platform::debugBreak(); - } - } + for(ProfilerRootData *walk = ProfilerRootData::sRootList; walk; walk = walk->mNextRoot) + { + for(ProfilerData *dp = walk->mFirstProfilerData; dp; dp = dp->mNextForRoot) + { + if(dp->mRoot != walk) + Platform::debugBreak(); + // check if it's in the parent's list... + ProfilerData *wk; + for(wk = dp->mParent->mFirstChild; wk; wk = wk->mNextSibling) + if(wk == dp) + break; + if(!wk) + Platform::debugBreak(); + for(wk = dp->mParent->mChildHash[walk->mNameHash & (ProfilerData::HashTableSize - 1)] ; + wk; wk = wk->mNextHash) + if(wk == dp) + break; + if(!wk) + Platform::debugBreak(); + } + } } #ifdef TORQUE_ENABLE_PROFILE_PATH const char * Profiler::getProfilePath() { #ifdef TORQUE_MULTITHREAD - // Ignore non-main-thread profiler activity. - if( !ThreadManager::isMainThread() ) - return "[non-main thread]"; + // Ignore non-main-thread profiler activity. + if( !ThreadManager::isMainThread() ) + return "[non-main thread]"; #endif - - return (mEnabled && mCurrentProfilerData) ? mCurrentProfilerData->mPath : "na"; + + return (mEnabled && mCurrentProfilerData) ? mCurrentProfilerData->mPath : "na"; } #endif #ifdef TORQUE_ENABLE_PROFILE_PATH const char * Profiler::constructProfilePath(ProfilerData * pd) { - if (pd->mParent) - { - const bool saveEnable = gProfiler->mEnabled; - gProfiler->mEnabled = false; - - const char * connector = " -> "; - U32 len = dStrlen(pd->mParent->mPath); - if (!len) - connector = ""; - len += dStrlen(connector); - len += dStrlen(pd->mRoot->mName); - - U32 mark = FrameAllocator::getWaterMark(); - char * buf = (char*)FrameAllocator::alloc(len+1); - dStrcpy(buf,pd->mParent->mPath); - dStrcat(buf,connector); - dStrcat(buf,pd->mRoot->mName); - const char * ret = StringTable->insert(buf); - FrameAllocator::setWaterMark(mark); - - gProfiler->mEnabled = saveEnable; - - return ret; - } - return "root"; + if (pd->mParent) + { + const bool saveEnable = gProfiler->mEnabled; + gProfiler->mEnabled = false; + + const char * connector = " -> "; + U32 len = dStrlen(pd->mParent->mPath); + if (!len) + connector = ""; + len += dStrlen(connector); + len += dStrlen(pd->mRoot->mName); + + U32 mark = FrameAllocator::getWaterMark(); + char * buf = (char*)FrameAllocator::alloc(len+1); + dStrcpy(buf,pd->mParent->mPath); + dStrcat(buf,connector); + dStrcat(buf,pd->mRoot->mName); + const char * ret = StringTable->insert(buf); + FrameAllocator::setWaterMark(mark); + + gProfiler->mEnabled = saveEnable; + + return ret; + } + return "root"; } #endif void Profiler::hashPush(ProfilerRootData *root) { #ifdef TORQUE_MULTITHREAD - // Ignore non-main-thread profiler activity. - if( !ThreadManager::isMainThread() ) - return; + // Ignore non-main-thread profiler activity. + if( !ThreadManager::isMainThread() ) + return; #endif - - mStackDepth++; - PROFILER_DEBUG_PUSH_NODE(root->mName); - AssertFatal(mStackDepth <= mMaxStackDepth, - "Stack overflow in profiler. You may have mismatched PROFILE_START and PROFILE_ENDs"); - if(!mEnabled) - return; - - ProfilerData *nextProfiler = NULL; - if(!root->mEnabled || mCurrentProfilerData->mRoot == root) - { - mCurrentProfilerData->mSubDepth++; - return; - } - - if(mCurrentProfilerData->mLastSeenProfiler && - mCurrentProfilerData->mLastSeenProfiler->mRoot == root) - nextProfiler = mCurrentProfilerData->mLastSeenProfiler; - - if(!nextProfiler) - { - // first see if it's in the hash table... - U32 index = root->mNameHash & (ProfilerData::HashTableSize - 1); - nextProfiler = mCurrentProfilerData->mChildHash[index]; - while(nextProfiler) - { - if(nextProfiler->mRoot == root) - break; - nextProfiler = nextProfiler->mNextHash; - } - if(!nextProfiler) - { - nextProfiler = (ProfilerData *) malloc(sizeof(ProfilerData)); - for(U32 i = 0; i < ProfilerData::HashTableSize; i++) - nextProfiler->mChildHash[i] = 0; - - nextProfiler->mRoot = root; - nextProfiler->mNextForRoot = root->mFirstProfilerData; - root->mFirstProfilerData = nextProfiler; - - nextProfiler->mNextProfilerData = mProfileList; - mProfileList = nextProfiler; - - nextProfiler->mNextHash = mCurrentProfilerData->mChildHash[index]; - mCurrentProfilerData->mChildHash[index] = nextProfiler; - - nextProfiler->mParent = mCurrentProfilerData; - nextProfiler->mNextSibling = mCurrentProfilerData->mFirstChild; - mCurrentProfilerData->mFirstChild = nextProfiler; - nextProfiler->mFirstChild = NULL; - nextProfiler->mLastSeenProfiler = NULL; - nextProfiler->mHash = root->mNameHash; - nextProfiler->mInvokeCount = 0; - nextProfiler->mTotalTime = 0; - nextProfiler->mSubTime = 0; - nextProfiler->mSubDepth = 0; + + mStackDepth++; + PROFILER_DEBUG_PUSH_NODE(root->mName); + AssertFatal(mStackDepth <= mMaxStackDepth, + "Stack overflow in profiler. You may have mismatched PROFILE_START and PROFILE_ENDs"); + if(!mEnabled) + return; + + ProfilerData *nextProfiler = NULL; + if(!root->mEnabled || mCurrentProfilerData->mRoot == root) + { + mCurrentProfilerData->mSubDepth++; + return; + } + + if(mCurrentProfilerData->mLastSeenProfiler && + mCurrentProfilerData->mLastSeenProfiler->mRoot == root) + nextProfiler = mCurrentProfilerData->mLastSeenProfiler; + + if(!nextProfiler) + { + // first see if it's in the hash table... + U32 index = root->mNameHash & (ProfilerData::HashTableSize - 1); + nextProfiler = mCurrentProfilerData->mChildHash[index]; + while(nextProfiler) + { + if(nextProfiler->mRoot == root) + break; + nextProfiler = nextProfiler->mNextHash; + } + if(!nextProfiler) + { + nextProfiler = (ProfilerData *) malloc(sizeof(ProfilerData)); + for(U32 i = 0; i < ProfilerData::HashTableSize; i++) + nextProfiler->mChildHash[i] = 0; + + nextProfiler->mRoot = root; + nextProfiler->mNextForRoot = root->mFirstProfilerData; + root->mFirstProfilerData = nextProfiler; + + nextProfiler->mNextProfilerData = mProfileList; + mProfileList = nextProfiler; + + nextProfiler->mNextHash = mCurrentProfilerData->mChildHash[index]; + mCurrentProfilerData->mChildHash[index] = nextProfiler; + + nextProfiler->mParent = mCurrentProfilerData; + nextProfiler->mNextSibling = mCurrentProfilerData->mFirstChild; + mCurrentProfilerData->mFirstChild = nextProfiler; + nextProfiler->mFirstChild = NULL; + nextProfiler->mLastSeenProfiler = NULL; + nextProfiler->mHash = root->mNameHash; + nextProfiler->mInvokeCount = 0; + nextProfiler->mTotalTime = 0; + nextProfiler->mSubTime = 0; + nextProfiler->mSubDepth = 0; #ifdef TORQUE_ENABLE_PROFILE_PATH - nextProfiler->mPath = constructProfilePath(nextProfiler); + nextProfiler->mPath = constructProfilePath(nextProfiler); #endif - } - } - root->mTotalInvokeCount++; - nextProfiler->mInvokeCount++; - startHighResolutionTimer(nextProfiler->mStartTime); - mCurrentProfilerData->mLastSeenProfiler = nextProfiler; - mCurrentProfilerData = nextProfiler; + } + } + root->mTotalInvokeCount++; + nextProfiler->mInvokeCount++; + startHighResolutionTimer(nextProfiler->mStartTime); + mCurrentProfilerData->mLastSeenProfiler = nextProfiler; + mCurrentProfilerData = nextProfiler; } void Profiler::enable(bool enabled) { - mNextEnable = enabled; + mNextEnable = enabled; } void Profiler::dumpToConsole() { - mDumpToConsole = true; - mDumpToFile = false; - mDumpFileName[0] = '\0'; + mDumpToConsole = true; + mDumpToFile = false; + mDumpFileName[0] = '\0'; } void Profiler::dumpToFile(const char* fileName) { - AssertFatal(dStrlen(fileName) < DumpFileNameLength, "Error, dump filename too long"); - mDumpToFile = true; - mDumpToConsole = false; - dStrcpy(mDumpFileName, fileName); + AssertFatal(dStrlen(fileName) < DumpFileNameLength, "Error, dump filename too long"); + mDumpToFile = true; + mDumpToConsole = false; + dStrcpy(mDumpFileName, fileName); } void Profiler::hashPop(ProfilerRootData *expected) { #ifdef TORQUE_MULTITHREAD - // Ignore non-main-thread profiler activity. - if( !ThreadManager::isMainThread() ) - return; + // Ignore non-main-thread profiler activity. + if( !ThreadManager::isMainThread() ) + return; #endif - - mStackDepth--; - PROFILER_DEBUG_POP_NODE(); - AssertFatal(mStackDepth >= 0, "Stack underflow in profiler. You may have mismatched PROFILE_START and PROFILE_ENDs"); - if(mEnabled) - { - if(mCurrentProfilerData->mSubDepth) - { - mCurrentProfilerData->mSubDepth--; - return; - } - - if(expected) - { - AssertISV(expected == mCurrentProfilerData->mRoot, "Profiler::hashPop - didn't get expected ProfilerRoot!"); - } - - F64 fElapsed = endHighResolutionTimer(mCurrentProfilerData->mStartTime); - - mCurrentProfilerData->mTotalTime += fElapsed; - mCurrentProfilerData->mParent->mSubTime += fElapsed; // mark it in the parent as well... - mCurrentProfilerData->mRoot->mTotalTime += fElapsed; - if(mCurrentProfilerData->mParent->mRoot) - mCurrentProfilerData->mParent->mRoot->mSubTime += fElapsed; // mark it in the parent as well... - - mCurrentProfilerData = mCurrentProfilerData->mParent; - } - if(mStackDepth == 0) - { - // apply the next enable... - if(mDumpToConsole || mDumpToFile) - { - dump(); - startHighResolutionTimer(mCurrentProfilerData->mStartTime); - } - if(!mEnabled && mNextEnable) - startHighResolutionTimer(mCurrentProfilerData->mStartTime); - + + mStackDepth--; + PROFILER_DEBUG_POP_NODE(); + AssertFatal(mStackDepth >= 0, "Stack underflow in profiler. You may have mismatched PROFILE_START and PROFILE_ENDs"); + if(mEnabled) + { + if(mCurrentProfilerData->mSubDepth) + { + mCurrentProfilerData->mSubDepth--; + return; + } + + if(expected) + { + AssertISV(expected == mCurrentProfilerData->mRoot, "Profiler::hashPop - didn't get expected ProfilerRoot!"); + } + + F64 fElapsed = endHighResolutionTimer(mCurrentProfilerData->mStartTime); + + mCurrentProfilerData->mTotalTime += fElapsed; + mCurrentProfilerData->mParent->mSubTime += fElapsed; // mark it in the parent as well... + mCurrentProfilerData->mRoot->mTotalTime += fElapsed; + if(mCurrentProfilerData->mParent->mRoot) + mCurrentProfilerData->mParent->mRoot->mSubTime += fElapsed; // mark it in the parent as well... + + mCurrentProfilerData = mCurrentProfilerData->mParent; + } + if(mStackDepth == 0) + { + // apply the next enable... + if(mDumpToConsole || mDumpToFile) + { + dump(); + startHighResolutionTimer(mCurrentProfilerData->mStartTime); + } + if(!mEnabled && mNextEnable) + startHighResolutionTimer(mCurrentProfilerData->mStartTime); + #if defined(TORQUE_OS_WIN) - // The high performance counters under win32 are unreliable when running on multiple - // processors. When the profiler is enabled, we restrict Torque to a single processor. - if(mNextEnable != mEnabled) - { - - if(mNextEnable) - { - Con::warnf("Warning: forcing the Torque profiler thread to run only on cpu 1."); - SetThreadAffinityMask(GetCurrentThread(), 1); - } - else - { - Con::warnf("Warning: the Torque profiler thread may now run on any cpu."); - DWORD_PTR procMask; - DWORD_PTR sysMask; - GetProcessAffinityMask( GetCurrentProcess(), &procMask, &sysMask); - SetThreadAffinityMask( GetCurrentThread(), procMask); - } - } + // The high performance counters under win32 are unreliable when running on multiple + // processors. When the profiler is enabled, we restrict Torque to a single processor. + if(mNextEnable != mEnabled) + { + + if(mNextEnable) + { + Con::warnf("Warning: forcing the Torque profiler thread to run only on cpu 1."); + SetThreadAffinityMask(GetCurrentThread(), 1); + } + else + { + Con::warnf("Warning: the Torque profiler thread may now run on any cpu."); + DWORD_PTR procMask; + DWORD_PTR sysMask; + GetProcessAffinityMask( GetCurrentProcess(), &procMask, &sysMask); + SetThreadAffinityMask( GetCurrentThread(), procMask); + } + } #endif - - mEnabled = mNextEnable; - } + + mEnabled = mNextEnable; + } } static S32 QSORT_CALLBACK rootDataCompare(const void *s1, const void *s2) { - const ProfilerRootData *r1 = *((ProfilerRootData **) s1); - const ProfilerRootData *r2 = *((ProfilerRootData **) s2); - if((r2->mTotalTime - r2->mSubTime) > (r1->mTotalTime - r1->mSubTime)) - return 1; - return -1; + const ProfilerRootData *r1 = *((ProfilerRootData **) s1); + const ProfilerRootData *r2 = *((ProfilerRootData **) s2); + if((r2->mTotalTime - r2->mSubTime) > (r1->mTotalTime - r1->mSubTime)) + return 1; + return -1; } static void profilerDataDumpRecurse(ProfilerData *data, char *buffer, U32 bufferLen, F64 totalTime) { - // dump out this one: - Con::printf("%7.3f %7.3f %8d %s%s", - 100 * data->mTotalTime / totalTime, - 100 * (data->mTotalTime - data->mSubTime) / totalTime, - data->mInvokeCount, - buffer, - data->mRoot ? data->mRoot->mName : "ROOT" ); - data->mTotalTime = 0; - data->mSubTime = 0; - data->mInvokeCount = 0; - - buffer[bufferLen] = ' '; - buffer[bufferLen+1] = ' '; - buffer[bufferLen+2] = 0; - // sort data's children... - ProfilerData *list = NULL; - while(data->mFirstChild) - { - ProfilerData *ins = data->mFirstChild; - data->mFirstChild = ins->mNextSibling; - ProfilerData **walk = &list; - while(*walk && (*walk)->mTotalTime > ins->mTotalTime) - walk = &(*walk)->mNextSibling; - ins->mNextSibling = *walk; - *walk = ins; - } - data->mFirstChild = list; - while(list) - { - if(list->mInvokeCount) - profilerDataDumpRecurse(list, buffer, bufferLen + 2, totalTime); - list = list->mNextSibling; - } - buffer[bufferLen] = 0; + // dump out this one: + Con::printf("%7.3f %7.3f %8d %s%s", + 100 * data->mTotalTime / totalTime, + 100 * (data->mTotalTime - data->mSubTime) / totalTime, + data->mInvokeCount, + buffer, + data->mRoot ? data->mRoot->mName : "ROOT" ); + data->mTotalTime = 0; + data->mSubTime = 0; + data->mInvokeCount = 0; + + buffer[bufferLen] = ' '; + buffer[bufferLen+1] = ' '; + buffer[bufferLen+2] = 0; + // sort data's children... + ProfilerData *list = NULL; + while(data->mFirstChild) + { + ProfilerData *ins = data->mFirstChild; + data->mFirstChild = ins->mNextSibling; + ProfilerData **walk = &list; + while(*walk && (*walk)->mTotalTime > ins->mTotalTime) + walk = &(*walk)->mNextSibling; + ins->mNextSibling = *walk; + *walk = ins; + } + data->mFirstChild = list; + while(list) + { + if(list->mInvokeCount) + profilerDataDumpRecurse(list, buffer, bufferLen + 2, totalTime); + list = list->mNextSibling; + } + buffer[bufferLen] = 0; } static void profilerDataDumpRecurseFile(ProfilerData *data, char *buffer, U32 bufferLen, F64 totalTime, FileStream& fws) { - char pbuffer[256]; - dSprintf(pbuffer, 255, "%7.3f %7.3f %8d %s%s\n", - 100 * data->mTotalTime / totalTime, - 100 * (data->mTotalTime - data->mSubTime) / totalTime, - data->mInvokeCount, - buffer, - data->mRoot ? data->mRoot->mName : "ROOT" ); - fws.write(dStrlen(pbuffer), pbuffer); - data->mTotalTime = 0; - data->mSubTime = 0; - data->mInvokeCount = 0; - - buffer[bufferLen] = ' '; - buffer[bufferLen+1] = ' '; - buffer[bufferLen+2] = 0; - // sort data's children... - ProfilerData *list = NULL; - while(data->mFirstChild) - { - ProfilerData *ins = data->mFirstChild; - data->mFirstChild = ins->mNextSibling; - ProfilerData **walk = &list; - while(*walk && (*walk)->mTotalTime > ins->mTotalTime) - walk = &(*walk)->mNextSibling; - ins->mNextSibling = *walk; - *walk = ins; - } - data->mFirstChild = list; - while(list) - { - if(list->mInvokeCount) - profilerDataDumpRecurseFile(list, buffer, bufferLen + 2, totalTime, fws); - list = list->mNextSibling; - } - buffer[bufferLen] = 0; + char pbuffer[256]; + dSprintf(pbuffer, 255, "%7.3f %7.3f %8d %s%s\n", + 100 * data->mTotalTime / totalTime, + 100 * (data->mTotalTime - data->mSubTime) / totalTime, + data->mInvokeCount, + buffer, + data->mRoot ? data->mRoot->mName : "ROOT" ); + fws.write(dStrlen(pbuffer), pbuffer); + data->mTotalTime = 0; + data->mSubTime = 0; + data->mInvokeCount = 0; + + buffer[bufferLen] = ' '; + buffer[bufferLen+1] = ' '; + buffer[bufferLen+2] = 0; + // sort data's children... + ProfilerData *list = NULL; + while(data->mFirstChild) + { + ProfilerData *ins = data->mFirstChild; + data->mFirstChild = ins->mNextSibling; + ProfilerData **walk = &list; + while(*walk && (*walk)->mTotalTime > ins->mTotalTime) + walk = &(*walk)->mNextSibling; + ins->mNextSibling = *walk; + *walk = ins; + } + data->mFirstChild = list; + while(list) + { + if(list->mInvokeCount) + profilerDataDumpRecurseFile(list, buffer, bufferLen + 2, totalTime, fws); + list = list->mNextSibling; + } + buffer[bufferLen] = 0; } void Profiler::dump() { - bool enableSave = mEnabled; - mEnabled = false; - mStackDepth++; - // may have some profiled calls... gotta turn em off. - - Vector rootVector; - F64 totalTime = 0; - for(ProfilerRootData *walk = ProfilerRootData::sRootList; walk; walk = walk->mNextRoot) - { - totalTime += walk->mTotalTime - walk->mSubTime; - rootVector.push_back(walk); - } - dQsort((void *) &rootVector[0], rootVector.size(), sizeof(ProfilerRootData *), rootDataCompare); - - - if (mDumpToConsole == true) - { - Con::printf("Profiler Data Dump:"); - Con::printf("Ordered by non-sub total time -"); - Con::printf("%%NSTime %% Time Invoke # Name"); - for(U32 i = 0; i < rootVector.size(); i++) - { - Con::printf("%7.3f %7.3f %8d %s", - 100 * (rootVector[i]->mTotalTime - rootVector[i]->mSubTime) / totalTime, - 100 * rootVector[i]->mTotalTime / totalTime, - rootVector[i]->mTotalInvokeCount, - rootVector[i]->mName); - rootVector[i]->mTotalInvokeCount = 0; - rootVector[i]->mTotalTime = 0; - rootVector[i]->mSubTime = 0; - } - Con::printf(""); - Con::printf("Ordered by stack trace total time -"); - Con::printf("%% Time %% NSTime Invoke # Name"); - - mCurrentProfilerData->mTotalTime = endHighResolutionTimer(mCurrentProfilerData->mStartTime); - - char depthBuffer[MaxStackDepth * 2 + 1]; - depthBuffer[0] = 0; - profilerDataDumpRecurse(mCurrentProfilerData, depthBuffer, 0, totalTime); - mEnabled = enableSave; - mStackDepth--; - } - else if (mDumpToFile == true && mDumpFileName[0] != '\0') - { - FileStream fws; - bool success = fws.open(mDumpFileName, Torque::FS::File::Write); - AssertFatal(success, "Cannot write profile dump to specified file!"); - char buffer[1024]; - - dStrcpy(buffer, "Profiler Data Dump:\n"); - fws.write(dStrlen(buffer), buffer); - dStrcpy(buffer, "Ordered by non-sub total time -\n"); - fws.write(dStrlen(buffer), buffer); - dStrcpy(buffer, "%%NSTime %% Time Invoke # Name\n"); - fws.write(dStrlen(buffer), buffer); - - for(U32 i = 0; i < rootVector.size(); i++) - { - dSprintf(buffer, 1023, "%7.3f %7.3f %8d %s\n", - 100 * (rootVector[i]->mTotalTime - rootVector[i]->mSubTime) / totalTime, - 100 * rootVector[i]->mTotalTime / totalTime, - rootVector[i]->mTotalInvokeCount, - rootVector[i]->mName); - fws.write(dStrlen(buffer), buffer); - - rootVector[i]->mTotalInvokeCount = 0; - rootVector[i]->mTotalTime = 0; - rootVector[i]->mSubTime = 0; - } - dStrcpy(buffer, "\nOrdered by non-sub total time -\n"); - fws.write(dStrlen(buffer), buffer); - dStrcpy(buffer, "%%NSTime %% Time Invoke # Name\n"); - fws.write(dStrlen(buffer), buffer); - - mCurrentProfilerData->mTotalTime = endHighResolutionTimer(mCurrentProfilerData->mStartTime); - - char depthBuffer[MaxStackDepth * 2 + 1]; - depthBuffer[0] = 0; - profilerDataDumpRecurseFile(mCurrentProfilerData, depthBuffer, 0, totalTime, fws); - mEnabled = enableSave; - mStackDepth--; - - fws.close(); - } - - mDumpToConsole = false; - mDumpToFile = false; - mDumpFileName[0] = '\0'; + bool enableSave = mEnabled; + mEnabled = false; + mStackDepth++; + // may have some profiled calls... gotta turn em off. + + Vector rootVector; + F64 totalTime = 0; + for(ProfilerRootData *walk = ProfilerRootData::sRootList; walk; walk = walk->mNextRoot) + { + totalTime += walk->mTotalTime - walk->mSubTime; + rootVector.push_back(walk); + } + dQsort((void *) &rootVector[0], rootVector.size(), sizeof(ProfilerRootData *), rootDataCompare); + + + if (mDumpToConsole == true) + { + Con::printf("Profiler Data Dump:"); + Con::printf("Ordered by non-sub total time -"); + Con::printf("%%NSTime %% Time Invoke # Name"); + for(U32 i = 0; i < rootVector.size(); i++) + { + Con::printf("%7.3f %7.3f %8d %s", + 100 * (rootVector[i]->mTotalTime - rootVector[i]->mSubTime) / totalTime, + 100 * rootVector[i]->mTotalTime / totalTime, + rootVector[i]->mTotalInvokeCount, + rootVector[i]->mName); + rootVector[i]->mTotalInvokeCount = 0; + rootVector[i]->mTotalTime = 0; + rootVector[i]->mSubTime = 0; + } + Con::printf(""); + Con::printf("Ordered by stack trace total time -"); + Con::printf("%% Time %% NSTime Invoke # Name"); + + mCurrentProfilerData->mTotalTime = endHighResolutionTimer(mCurrentProfilerData->mStartTime); + + char depthBuffer[MaxStackDepth * 2 + 1]; + depthBuffer[0] = 0; + profilerDataDumpRecurse(mCurrentProfilerData, depthBuffer, 0, totalTime); + mEnabled = enableSave; + mStackDepth--; + } + else if (mDumpToFile == true && mDumpFileName[0] != '\0') + { + FileStream fws; + bool success = fws.open(mDumpFileName, Torque::FS::File::Write); + AssertFatal(success, "Cannot write profile dump to specified file!"); + char buffer[1024]; + + dStrcpy(buffer, "Profiler Data Dump:\n"); + fws.write(dStrlen(buffer), buffer); + dStrcpy(buffer, "Ordered by non-sub total time -\n"); + fws.write(dStrlen(buffer), buffer); + dStrcpy(buffer, "%%NSTime %% Time Invoke # Name\n"); + fws.write(dStrlen(buffer), buffer); + + for(U32 i = 0; i < rootVector.size(); i++) + { + dSprintf(buffer, 1023, "%7.3f %7.3f %8d %s\n", + 100 * (rootVector[i]->mTotalTime - rootVector[i]->mSubTime) / totalTime, + 100 * rootVector[i]->mTotalTime / totalTime, + rootVector[i]->mTotalInvokeCount, + rootVector[i]->mName); + fws.write(dStrlen(buffer), buffer); + + rootVector[i]->mTotalInvokeCount = 0; + rootVector[i]->mTotalTime = 0; + rootVector[i]->mSubTime = 0; + } + dStrcpy(buffer, "\nOrdered by non-sub total time -\n"); + fws.write(dStrlen(buffer), buffer); + dStrcpy(buffer, "%%NSTime %% Time Invoke # Name\n"); + fws.write(dStrlen(buffer), buffer); + + mCurrentProfilerData->mTotalTime = endHighResolutionTimer(mCurrentProfilerData->mStartTime); + + char depthBuffer[MaxStackDepth * 2 + 1]; + depthBuffer[0] = 0; + profilerDataDumpRecurseFile(mCurrentProfilerData, depthBuffer, 0, totalTime, fws); + mEnabled = enableSave; + mStackDepth--; + + fws.close(); + } + + mDumpToConsole = false; + mDumpToFile = false; + mDumpFileName[0] = '\0'; } void Profiler::enableMarker(const char *marker, bool enable) { - reset(); - U32 markerLen = dStrlen(marker); - if(markerLen == 0) - return; - bool sn = marker[markerLen - 1] == '*'; - for(ProfilerRootData *data = ProfilerRootData::sRootList; data; data = data->mNextRoot) - { - if(sn) - { - if(!dStrncmp(marker, data->mName, markerLen - 1)) - data->mEnabled = enable; - } - else - { - if(!dStrcmp(marker, data->mName)) - data->mEnabled = enable; - } - } + reset(); + U32 markerLen = dStrlen(marker); + if(markerLen == 0) + return; + bool sn = marker[markerLen - 1] == '*'; + for(ProfilerRootData *data = ProfilerRootData::sRootList; data; data = data->mNextRoot) + { + if(sn) + { + if(!dStrncmp(marker, data->mName, markerLen - 1)) + data->mEnabled = enable; + } + else + { + if(!dStrcmp(marker, data->mName)) + data->mEnabled = enable; + } + } } //============================================================================= @@ -716,64 +716,64 @@ void Profiler::enableMarker(const char *marker, bool enable) //----------------------------------------------------------------------------- DefineEngineFunction( profilerMarkerEnable, void, ( const char* markerName, bool enable ), ( true ), - "@brief Enable or disable a specific profile.\n\n" - "@param enable Optional paramater to enable or disable the profile.\n" - "@param markerName Name of a specific marker to enable or disable.\n" - "@note Calling this function will first call profilerReset(), clearing all data from profiler. " - "All profile markers are enabled by default.\n\n" - "@ingroup Debugging") + "@brief Enable or disable a specific profile.\n\n" + "@param enable Optional paramater to enable or disable the profile.\n" + "@param markerName Name of a specific marker to enable or disable.\n" + "@note Calling this function will first call profilerReset(), clearing all data from profiler. " + "All profile markers are enabled by default.\n\n" + "@ingroup Debugging") { - if( gProfiler ) - gProfiler->enableMarker( markerName, enable ); + if( gProfiler ) + gProfiler->enableMarker( markerName, enable ); } //----------------------------------------------------------------------------- DefineEngineFunction( profilerEnable, void, ( bool enable ),, - "@brief Enables or disables the profiler.\n\n" - "Data is only gathered while the profiler is enabled.\n\n" - "@note Profiler is not available in shipping builds.\n" - "T3D has predefined profiling areas surrounded by markers, " - "but you may need to define additional markers (in C++) around areas you wish to profile," - " by using the PROFILE_START( markerName ); and PROFILE_END(); macros.\n\n" - "@ingroup Debugging\n" ) + "@brief Enables or disables the profiler.\n\n" + "Data is only gathered while the profiler is enabled.\n\n" + "@note Profiler is not available in shipping builds.\n" + "T3D has predefined profiling areas surrounded by markers, " + "but you may need to define additional markers (in C++) around areas you wish to profile," + " by using the PROFILE_START( markerName ); and PROFILE_END(); macros.\n\n" + "@ingroup Debugging\n" ) { - if(gProfiler) - gProfiler->enable(enable); + if(gProfiler) + gProfiler->enable(enable); } DefineEngineFunction(profilerDump, void, (),, - "@brief Dumps current profiling stats to the console window.\n\n" - "@note Markers disabled with profilerMarkerEnable() will be skipped over. " - "If the profiler is currently running, it will be disabled.\n" - "@ingroup Debugging") + "@brief Dumps current profiling stats to the console window.\n\n" + "@note Markers disabled with profilerMarkerEnable() will be skipped over. " + "If the profiler is currently running, it will be disabled.\n" + "@ingroup Debugging") { - if(gProfiler) - gProfiler->dumpToConsole(); + if(gProfiler) + gProfiler->dumpToConsole(); } DefineEngineFunction( profilerDumpToFile, void, ( const char* fileName ),, - "@brief Dumps current profiling stats to a file.\n\n" - "@note If the profiler is currently running, it will be disabled.\n" - "@param fileName Name and path of file to save profiling stats to. Must use forward slashes (/). " - "Will attempt to create the file if it does not already exist.\n" - "@tsexample\n" - "profilerDumpToFile( \"C:/Torque/log1.txt\" );\n" - "@endtsexample\n\n" - "@ingroup Debugging" ) + "@brief Dumps current profiling stats to a file.\n\n" + "@note If the profiler is currently running, it will be disabled.\n" + "@param fileName Name and path of file to save profiling stats to. Must use forward slashes (/). " + "Will attempt to create the file if it does not already exist.\n" + "@tsexample\n" + "profilerDumpToFile( \"C:/Torque/log1.txt\" );\n" + "@endtsexample\n\n" + "@ingroup Debugging" ) { - if(gProfiler) - gProfiler->dumpToFile(fileName); + if(gProfiler) + gProfiler->dumpToFile(fileName); } DefineEngineFunction( profilerReset, void, (),, - "@brief Resets the profiler, clearing it of all its data.\n\n" - "If the profiler is currently running, it will first be disabled. " - "All markers will retain their current enabled/disabled status.\n\n" - "@ingroup Debugging" ) + "@brief Resets the profiler, clearing it of all its data.\n\n" + "If the profiler is currently running, it will first be disabled. " + "All markers will retain their current enabled/disabled status.\n\n" + "@ingroup Debugging" ) { - if(gProfiler) - gProfiler->reset(); + if(gProfiler) + gProfiler->reset(); } #endif diff --git a/Engine/source/platformMac/macFileIO.mm b/Engine/source/platformMac/macFileIO.mm index 236a95282..90efbd303 100644 --- a/Engine/source/platformMac/macFileIO.mm +++ b/Engine/source/platformMac/macFileIO.mm @@ -999,7 +999,7 @@ ConsoleFunction(testHasSubdir,void,2,2,"tests platform::hasSubDirectory") { Con::printf(" has subdir"); else Con::printf(" does not have subdir"); -} +} ConsoleFunction(testDumpDirectories,void,4,4,"testDumpDirectories('path', int depth, bool noBasePath)") { Vector paths; From 0adab546783b2f361d4f63dda62012555b0fb721 Mon Sep 17 00:00:00 2001 From: "Thomas \"elfprince13\" Dickerson" Date: Fri, 6 Jan 2017 17:54:19 -0500 Subject: [PATCH 6/9] one more go-round --- Engine/source/platform/profiler.cpp | 16 ++++++++-------- Engine/source/platformMac/macFileIO.mm | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Engine/source/platform/profiler.cpp b/Engine/source/platform/profiler.cpp index 1fa089c6e..1083b6d08 100644 --- a/Engine/source/platform/profiler.cpp +++ b/Engine/source/platform/profiler.cpp @@ -114,20 +114,20 @@ U32 endHighResolutionTimer(U32 time[2]) void startHighResolutionTimer(U32 time[2]) { __asm__ __volatile__( - "rdtsc\n" - : "=a" (time[0]), "=d" (time[1]) - ); + "rdtsc\n" + : "=a" (time[0]), "=d" (time[1]) + ); } U32 endHighResolutionTimer(U32 time[2]) { U32 ticks; __asm__ __volatile__( - "rdtsc\n" - "sub 0x4(%%ecx), %%edx\n" - "sbb (%%ecx), %%eax\n" - : "=a" (ticks) : "c" (time) - ); + "rdtsc\n" + "sub 0x4(%%ecx), %%edx\n" + "sbb (%%ecx), %%eax\n" + : "=a" (ticks) : "c" (time) + ); return ticks; } diff --git a/Engine/source/platformMac/macFileIO.mm b/Engine/source/platformMac/macFileIO.mm index 90efbd303..a7b0f3f88 100644 --- a/Engine/source/platformMac/macFileIO.mm +++ b/Engine/source/platformMac/macFileIO.mm @@ -994,7 +994,7 @@ bool Platform::fileTimeToString(FileTime * time, char * string, U32 strLen) { re #if defined(TORQUE_DEBUG) ConsoleFunction(testHasSubdir,void,2,2,"tests platform::hasSubDirectory") { Con::printf("testing %s",(const char*)argv[1]); - Platform::addExcludedDirectory(".svn"); + Platform::addExcludedDirectory(".svn"); if(Platform::hasSubDirectory(argv[1])) Con::printf(" has subdir"); else From 76e02b41f7803830d0885bc59043f5f09682a486 Mon Sep 17 00:00:00 2001 From: "Thomas \"elfprince13\" Dickerson" Date: Fri, 6 Jan 2017 17:54:37 -0500 Subject: [PATCH 7/9] one more go-round --- Engine/source/platformMac/macFileIO.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Engine/source/platformMac/macFileIO.mm b/Engine/source/platformMac/macFileIO.mm index a7b0f3f88..90efbd303 100644 --- a/Engine/source/platformMac/macFileIO.mm +++ b/Engine/source/platformMac/macFileIO.mm @@ -994,7 +994,7 @@ bool Platform::fileTimeToString(FileTime * time, char * string, U32 strLen) { re #if defined(TORQUE_DEBUG) ConsoleFunction(testHasSubdir,void,2,2,"tests platform::hasSubDirectory") { Con::printf("testing %s",(const char*)argv[1]); - Platform::addExcludedDirectory(".svn"); + Platform::addExcludedDirectory(".svn"); if(Platform::hasSubDirectory(argv[1])) Con::printf(" has subdir"); else From a4c51b825c5078f98a6c1c3689a41f9306b8288b Mon Sep 17 00:00:00 2001 From: "Thomas \"elfprince13\" Dickerson" Date: Fri, 6 Jan 2017 17:55:44 -0500 Subject: [PATCH 8/9] this is getting old --- Engine/source/platformMac/macFileIO.mm | 1396 ++++++++++++------------ 1 file changed, 698 insertions(+), 698 deletions(-) diff --git a/Engine/source/platformMac/macFileIO.mm b/Engine/source/platformMac/macFileIO.mm index 90efbd303..7c9b68eda 100644 --- a/Engine/source/platformMac/macFileIO.mm +++ b/Engine/source/platformMac/macFileIO.mm @@ -46,114 +46,114 @@ bool dFileDelete(const char * name) { - if(!name ) - return(false); - - if (dStrlen(name) > MAX_MAC_PATH_LONG) - Con::warnf("dFileDelete: Filename length is pretty long..."); - - return(remove(name) == 0); // remove returns 0 on success + if(!name ) + return(false); + + if (dStrlen(name) > MAX_MAC_PATH_LONG) + Con::warnf("dFileDelete: Filename length is pretty long..."); + + return(remove(name) == 0); // remove returns 0 on success } //----------------------------------------------------------------------------- bool dFileTouch(const char *path) { - if (!path || !*path) - return false; - - // set file at path's modification and access times to now. - return( utimes( path, NULL) == 0); // utimes returns 0 on success. + if (!path || !*path) + return false; + + // set file at path's modification and access times to now. + return( utimes( path, NULL) == 0); // utimes returns 0 on success. } //----------------------------------------------------------------------------- bool dPathCopy(const char* source, const char* dest, bool nooverwrite) { - if(source == NULL || dest == NULL) - return false; - - @autoreleasepool { - NSFileManager *manager = [NSFileManager defaultManager]; - - NSString *nsource = [manager stringWithFileSystemRepresentation:source length:dStrlen(source)]; - NSString *ndest = [manager stringWithFileSystemRepresentation:dest length:dStrlen(dest)]; - NSString *ndestFolder = [ndest stringByDeletingLastPathComponent]; - - if(! [manager fileExistsAtPath:nsource]) - { - Con::errorf("dPathCopy: no file exists at %s",source); - return false; - } - - if( [manager fileExistsAtPath:ndest] ) - { - if(nooverwrite) - { - Con::errorf("dPathCopy: file already exists at %s",dest); - return false; - } - Con::warnf("Deleting files at path: %s", dest); - if(![manager removeItemAtPath:ndest error:nil] || [manager fileExistsAtPath:ndest]) - { - Con::errorf("Copy failed! Could not delete files at path: %s", dest); - return false; - } - } - - if([manager fileExistsAtPath:ndestFolder] == NO) - { - ndestFolder = [ndestFolder stringByAppendingString:@"/"]; // createpath requires a trailing slash - Platform::createPath([ndestFolder UTF8String]); - } - - bool ret = [manager copyItemAtPath:nsource toPath:ndest error:nil]; - // n.b.: The "success" semantics don't guarantee a copy actually took place, so we'll verify - // because this is surprising behavior for a method called copy. - if( ![manager fileExistsAtPath:ndest] ) - { - Con::warnf("The filemanager returned success, but the file was not copied. Something strange is happening"); - ret = false; - } - return ret; - } - + if(source == NULL || dest == NULL) + return false; + + @autoreleasepool { + NSFileManager *manager = [NSFileManager defaultManager]; + + NSString *nsource = [manager stringWithFileSystemRepresentation:source length:dStrlen(source)]; + NSString *ndest = [manager stringWithFileSystemRepresentation:dest length:dStrlen(dest)]; + NSString *ndestFolder = [ndest stringByDeletingLastPathComponent]; + + if(! [manager fileExistsAtPath:nsource]) + { + Con::errorf("dPathCopy: no file exists at %s",source); + return false; + } + + if( [manager fileExistsAtPath:ndest] ) + { + if(nooverwrite) + { + Con::errorf("dPathCopy: file already exists at %s",dest); + return false; + } + Con::warnf("Deleting files at path: %s", dest); + if(![manager removeItemAtPath:ndest error:nil] || [manager fileExistsAtPath:ndest]) + { + Con::errorf("Copy failed! Could not delete files at path: %s", dest); + return false; + } + } + + if([manager fileExistsAtPath:ndestFolder] == NO) + { + ndestFolder = [ndestFolder stringByAppendingString:@"/"]; // createpath requires a trailing slash + Platform::createPath([ndestFolder UTF8String]); + } + + bool ret = [manager copyItemAtPath:nsource toPath:ndest error:nil]; + // n.b.: The "success" semantics don't guarantee a copy actually took place, so we'll verify + // because this is surprising behavior for a method called copy. + if( ![manager fileExistsAtPath:ndest] ) + { + Con::warnf("The filemanager returned success, but the file was not copied. Something strange is happening"); + ret = false; + } + return ret; + } + } //----------------------------------------------------------------------------- bool dFileRename(const char *source, const char *dest) { - if(source == NULL || dest == NULL) - return false; - - @autoreleasepool { - NSFileManager *manager = [NSFileManager defaultManager]; - - NSString *nsource = [manager stringWithFileSystemRepresentation:source length:dStrlen(source)]; - NSString *ndest = [manager stringWithFileSystemRepresentation:dest length:dStrlen(dest)]; - - if(! [manager fileExistsAtPath:nsource]) - { - Con::errorf("dFileRename: no file exists at %s",source); - return false; - } - - if( [manager fileExistsAtPath:ndest] ) - { - Con::warnf("dFileRename: Deleting files at path: %s", dest); - } - - bool ret = [manager moveItemAtPath:nsource toPath:ndest error:nil]; - // n.b.: The "success" semantics don't guarantee a move actually took place, so we'll verify - // because this is surprising behavior for a method called rename. - - if( ![manager fileExistsAtPath:ndest] ) - { - Con::warnf("The filemanager returned success, but the file was not moved. Something strange is happening"); - ret = false; - } - - return ret; - } + if(source == NULL || dest == NULL) + return false; + + @autoreleasepool { + NSFileManager *manager = [NSFileManager defaultManager]; + + NSString *nsource = [manager stringWithFileSystemRepresentation:source length:dStrlen(source)]; + NSString *ndest = [manager stringWithFileSystemRepresentation:dest length:dStrlen(dest)]; + + if(! [manager fileExistsAtPath:nsource]) + { + Con::errorf("dFileRename: no file exists at %s",source); + return false; + } + + if( [manager fileExistsAtPath:ndest] ) + { + Con::warnf("dFileRename: Deleting files at path: %s", dest); + } + + bool ret = [manager moveItemAtPath:nsource toPath:ndest error:nil]; + // n.b.: The "success" semantics don't guarantee a move actually took place, so we'll verify + // because this is surprising behavior for a method called rename. + + if( ![manager fileExistsAtPath:ndest] ) + { + Con::warnf("The filemanager returned success, but the file was not moved. Something strange is happening"); + ret = false; + } + + return ret; + } } //----------------------------------------------------------------------------- @@ -167,7 +167,7 @@ bool dFileRename(const char *source, const char *dest) File::File() : currentStatus(Closed), capability(0) { - handle = NULL; + handle = NULL; } //----------------------------------------------------------------------------- @@ -179,8 +179,8 @@ File::File() //----------------------------------------------------------------------------- File::~File() { - close(); - handle = NULL; + close(); + handle = NULL; } @@ -194,61 +194,61 @@ File::~File() //----------------------------------------------------------------------------- File::FileStatus File::open(const char *filename, const AccessMode openMode) { - if (dStrlen(filename) > MAX_MAC_PATH_LONG) - Con::warnf("File::open: Filename length is pretty long..."); - - // Close the file if it was already open... - if (currentStatus != Closed) - close(); - - // create the appropriate type of file... - switch (openMode) - { - case Read: - handle = (void *)fopen(filename, "rb"); // read only - break; - case Write: - handle = (void *)fopen(filename, "wb"); // write only - break; - case ReadWrite: - handle = (void *)fopen(filename, "ab+"); // write(append) and read - break; - case WriteAppend: - handle = (void *)fopen(filename, "ab"); // write(append) only - break; - default: - AssertFatal(false, "File::open: bad access mode"); - } - - // handle not created successfully - if (handle == NULL) - return setStatus(); - - // successfully created file, so set the file capabilities... - switch (openMode) - { - case Read: - capability = FileRead; - break; - case Write: - case WriteAppend: - capability = FileWrite; - break; - case ReadWrite: - capability = FileRead | FileWrite; - break; - default: - AssertFatal(false, "File::open: bad access mode"); - } - - // must set the file status before setting the position. - currentStatus = Ok; - - if (openMode == ReadWrite) - setPosition(0); - - // success! - return currentStatus; + if (dStrlen(filename) > MAX_MAC_PATH_LONG) + Con::warnf("File::open: Filename length is pretty long..."); + + // Close the file if it was already open... + if (currentStatus != Closed) + close(); + + // create the appropriate type of file... + switch (openMode) + { + case Read: + handle = (void *)fopen(filename, "rb"); // read only + break; + case Write: + handle = (void *)fopen(filename, "wb"); // write only + break; + case ReadWrite: + handle = (void *)fopen(filename, "ab+"); // write(append) and read + break; + case WriteAppend: + handle = (void *)fopen(filename, "ab"); // write(append) only + break; + default: + AssertFatal(false, "File::open: bad access mode"); + } + + // handle not created successfully + if (handle == NULL) + return setStatus(); + + // successfully created file, so set the file capabilities... + switch (openMode) + { + case Read: + capability = FileRead; + break; + case Write: + case WriteAppend: + capability = FileWrite; + break; + case ReadWrite: + capability = FileRead | FileWrite; + break; + default: + AssertFatal(false, "File::open: bad access mode"); + } + + // must set the file status before setting the position. + currentStatus = Ok; + + if (openMode == ReadWrite) + setPosition(0); + + // success! + return currentStatus; } //----------------------------------------------------------------------------- @@ -256,10 +256,10 @@ File::FileStatus File::open(const char *filename, const AccessMode openMode) //----------------------------------------------------------------------------- U32 File::getPosition() const { - AssertFatal(currentStatus != Closed , "File::getPosition: file closed"); - AssertFatal(handle != NULL, "File::getPosition: invalid file handle"); - - return ftell((FILE*)handle); + AssertFatal(currentStatus != Closed , "File::getPosition: file closed"); + AssertFatal(handle != NULL, "File::getPosition: invalid file handle"); + + return ftell((FILE*)handle); } //----------------------------------------------------------------------------- @@ -276,41 +276,41 @@ U32 File::getPosition() const //----------------------------------------------------------------------------- File::FileStatus File::setPosition(S32 position, bool absolutePos) { - AssertFatal(Closed != currentStatus, "File::setPosition: file closed"); - AssertFatal(handle != NULL, "File::setPosition: invalid file handle"); - - if (currentStatus != Ok && currentStatus != EOS ) - return currentStatus; - - U32 finalPos; - if(absolutePos) - { - // absolute position - AssertFatal(0 <= position, "File::setPosition: negative absolute position"); - // position beyond EOS is OK - fseek((FILE*)handle, position, SEEK_SET); - finalPos = ftell((FILE*)handle); - } - else - { - // relative position - AssertFatal((getPosition() + position) >= 0, "File::setPosition: negative relative position"); - // position beyond EOS is OK - fseek((FILE*)handle, position, SEEK_CUR); - finalPos = ftell((FILE*)handle); - } - - // ftell returns -1 on error. set error status - if (0xffffffff == finalPos) - return setStatus(); - - // success, at end of file - else if (finalPos >= getSize()) - return currentStatus = EOS; - - // success! - else - return currentStatus = Ok; + AssertFatal(Closed != currentStatus, "File::setPosition: file closed"); + AssertFatal(handle != NULL, "File::setPosition: invalid file handle"); + + if (currentStatus != Ok && currentStatus != EOS ) + return currentStatus; + + U32 finalPos; + if(absolutePos) + { + // absolute position + AssertFatal(0 <= position, "File::setPosition: negative absolute position"); + // position beyond EOS is OK + fseek((FILE*)handle, position, SEEK_SET); + finalPos = ftell((FILE*)handle); + } + else + { + // relative position + AssertFatal((getPosition() + position) >= 0, "File::setPosition: negative relative position"); + // position beyond EOS is OK + fseek((FILE*)handle, position, SEEK_CUR); + finalPos = ftell((FILE*)handle); + } + + // ftell returns -1 on error. set error status + if (0xffffffff == finalPos) + return setStatus(); + + // success, at end of file + else if (finalPos >= getSize()) + return currentStatus = EOS; + + // success! + else + return currentStatus = Ok; } //----------------------------------------------------------------------------- @@ -320,21 +320,21 @@ File::FileStatus File::setPosition(S32 position, bool absolutePos) //----------------------------------------------------------------------------- U32 File::getSize() const { - AssertWarn(Closed != currentStatus, "File::getSize: file closed"); - AssertFatal(handle != NULL, "File::getSize: invalid file handle"); - - if (Ok == currentStatus || EOS == currentStatus) - { - struct stat statData; - - if(fstat(fileno((FILE*)handle), &statData) != 0) - return 0; - - // return the size in bytes - return statData.st_size; - } - - return 0; + AssertWarn(Closed != currentStatus, "File::getSize: file closed"); + AssertFatal(handle != NULL, "File::getSize: invalid file handle"); + + if (Ok == currentStatus || EOS == currentStatus) + { + struct stat statData; + + if(fstat(fileno((FILE*)handle), &statData) != 0) + return 0; + + // return the size in bytes + return statData.st_size; + } + + return 0; } //----------------------------------------------------------------------------- @@ -344,14 +344,14 @@ U32 File::getSize() const //----------------------------------------------------------------------------- File::FileStatus File::flush() { - AssertFatal(Closed != currentStatus, "File::flush: file closed"); - AssertFatal(handle != NULL, "File::flush: invalid file handle"); - AssertFatal(true == hasCapability(FileWrite), "File::flush: cannot flush a read-only file"); - - if (fflush((FILE*)handle) != 0) - return setStatus(); - else - return currentStatus = Ok; + AssertFatal(Closed != currentStatus, "File::flush: file closed"); + AssertFatal(handle != NULL, "File::flush: invalid file handle"); + AssertFatal(true == hasCapability(FileWrite), "File::flush: cannot flush a read-only file"); + + if (fflush((FILE*)handle) != 0) + return setStatus(); + else + return currentStatus = Ok; } //----------------------------------------------------------------------------- @@ -361,18 +361,18 @@ File::FileStatus File::flush() //----------------------------------------------------------------------------- File::FileStatus File::close() { - // check if it's already closed... - if (Closed == currentStatus) - return currentStatus; - - // it's not, so close it... - if (handle != NULL) - { - if (fclose((FILE*)handle) != 0) - return setStatus(); - } - handle = NULL; - return currentStatus = Closed; + // check if it's already closed... + if (Closed == currentStatus) + return currentStatus; + + // it's not, so close it... + if (handle != NULL) + { + if (fclose((FILE*)handle) != 0) + return setStatus(); + } + handle = NULL; + return currentStatus = Closed; } //----------------------------------------------------------------------------- @@ -380,7 +380,7 @@ File::FileStatus File::close() //----------------------------------------------------------------------------- File::FileStatus File::getStatus() const { - return currentStatus; + return currentStatus; } //----------------------------------------------------------------------------- @@ -388,20 +388,20 @@ File::FileStatus File::getStatus() const //----------------------------------------------------------------------------- File::FileStatus File::setStatus() { - switch (errno) - { - case EACCES: // permission denied - currentStatus = IOError; - break; - case EBADF: // Bad File Pointer - case EINVAL: // Invalid argument - case ENOENT: // file not found - case ENAMETOOLONG: - default: - currentStatus = UnknownError; - } - - return currentStatus; + switch (errno) + { + case EACCES: // permission denied + currentStatus = IOError; + break; + case EBADF: // Bad File Pointer + case EINVAL: // Invalid argument + case ENOENT: // file not found + case ENAMETOOLONG: + default: + currentStatus = UnknownError; + } + + return currentStatus; } //----------------------------------------------------------------------------- @@ -409,7 +409,7 @@ File::FileStatus File::setStatus() //----------------------------------------------------------------------------- File::FileStatus File::setStatus(File::FileStatus status) { - return currentStatus = status; + return currentStatus = status; } //----------------------------------------------------------------------------- @@ -420,28 +420,28 @@ File::FileStatus File::setStatus(File::FileStatus status) //----------------------------------------------------------------------------- File::FileStatus File::read(U32 size, char *dst, U32 *bytesRead) { - AssertFatal(Closed != currentStatus, "File::read: file closed"); - AssertFatal(handle != NULL, "File::read: invalid file handle"); - AssertFatal(NULL != dst, "File::read: NULL destination pointer"); - AssertFatal(true == hasCapability(FileRead), "File::read: file lacks capability"); - AssertWarn(0 != size, "File::read: size of zero"); - - if (Ok != currentStatus || 0 == size) - return currentStatus; - - // read from stream - U32 nBytes = fread(dst, 1, size, (FILE*)handle); - - // did we hit the end of the stream? - if( nBytes != size) - currentStatus = EOS; - - // if bytesRead is a valid pointer, send number of bytes read there. - if(bytesRead) - *bytesRead = nBytes; - - // successfully read size bytes - return currentStatus; + AssertFatal(Closed != currentStatus, "File::read: file closed"); + AssertFatal(handle != NULL, "File::read: invalid file handle"); + AssertFatal(NULL != dst, "File::read: NULL destination pointer"); + AssertFatal(true == hasCapability(FileRead), "File::read: file lacks capability"); + AssertWarn(0 != size, "File::read: size of zero"); + + if (Ok != currentStatus || 0 == size) + return currentStatus; + + // read from stream + U32 nBytes = fread(dst, 1, size, (FILE*)handle); + + // did we hit the end of the stream? + if( nBytes != size) + currentStatus = EOS; + + // if bytesRead is a valid pointer, send number of bytes read there. + if(bytesRead) + *bytesRead = nBytes; + + // successfully read size bytes + return currentStatus; } //----------------------------------------------------------------------------- @@ -452,28 +452,28 @@ File::FileStatus File::read(U32 size, char *dst, U32 *bytesRead) //----------------------------------------------------------------------------- File::FileStatus File::write(U32 size, const char *src, U32 *bytesWritten) { - AssertFatal(Closed != currentStatus, "File::write: file closed"); - AssertFatal(handle != NULL, "File::write: invalid file handle"); - AssertFatal(NULL != src, "File::write: NULL source pointer"); - AssertFatal(true == hasCapability(FileWrite), "File::write: file lacks capability"); - AssertWarn(0 != size, "File::write: size of zero"); - - if ((Ok != currentStatus && EOS != currentStatus) || 0 == size) - return currentStatus; - - // write bytes to the stream - U32 nBytes = fwrite(src, 1, size,(FILE*)handle); - - // if we couldn't write everything, we've got a problem. set error status. - if(nBytes != size) - setStatus(); - - // if bytesWritten is a valid pointer, put number of bytes read there. - if(bytesWritten) - *bytesWritten = nBytes; - - // return current File status, whether good or ill. - return currentStatus; + AssertFatal(Closed != currentStatus, "File::write: file closed"); + AssertFatal(handle != NULL, "File::write: invalid file handle"); + AssertFatal(NULL != src, "File::write: NULL source pointer"); + AssertFatal(true == hasCapability(FileWrite), "File::write: file lacks capability"); + AssertWarn(0 != size, "File::write: size of zero"); + + if ((Ok != currentStatus && EOS != currentStatus) || 0 == size) + return currentStatus; + + // write bytes to the stream + U32 nBytes = fwrite(src, 1, size,(FILE*)handle); + + // if we couldn't write everything, we've got a problem. set error status. + if(nBytes != size) + setStatus(); + + // if bytesWritten is a valid pointer, put number of bytes read there. + if(bytesWritten) + *bytesWritten = nBytes; + + // return current File status, whether good or ill. + return currentStatus; } @@ -482,17 +482,17 @@ File::FileStatus File::write(U32 size, const char *src, U32 *bytesWritten) //----------------------------------------------------------------------------- bool File::hasCapability(Capability cap) const { - return (0 != (U32(cap) & capability)); + return (0 != (U32(cap) & capability)); } //----------------------------------------------------------------------------- S32 Platform::compareFileTimes(const FileTime &a, const FileTime &b) { - if(a > b) - return 1; - if(a < b) - return -1; - return 0; + if(a > b) + return 1; + if(a < b) + return -1; + return 0; } @@ -501,100 +501,100 @@ S32 Platform::compareFileTimes(const FileTime &a, const FileTime &b) //----------------------------------------------------------------------------- bool Platform::getFileTimes(const char *path, FileTime *createTime, FileTime *modifyTime) { - // MacOSX is NOT guaranteed to be running off a HFS volume, - // and UNIX does not keep a record of a file's creation time anywhere. - // So instead of creation time we return changed time, - // just like the Linux platform impl does. - - if (!path || !*path) - return false; - - struct stat statData; - - if (stat(path, &statData) == -1) - return false; - - if(createTime) - *createTime = statData.st_ctime; - - if(modifyTime) - *modifyTime = statData.st_mtime; - - return true; + // MacOSX is NOT guaranteed to be running off a HFS volume, + // and UNIX does not keep a record of a file's creation time anywhere. + // So instead of creation time we return changed time, + // just like the Linux platform impl does. + + if (!path || !*path) + return false; + + struct stat statData; + + if (stat(path, &statData) == -1) + return false; + + if(createTime) + *createTime = statData.st_ctime; + + if(modifyTime) + *modifyTime = statData.st_mtime; + + return true; } //----------------------------------------------------------------------------- bool Platform::createPath(const char *file) { - // if the path exists, we're done. - struct stat statData; - if( stat(file, &statData) == 0 ) - { - return true; // exists, rejoice. - } - - Con::warnf( "creating path %s", file ); - - // get the parent path. - // we're not using basename because it's not thread safe. - U32 len = dStrlen(file); - char parent[len]; - bool isDirPath = false; - - dStrncpy(parent,file,len); - parent[len] = '\0'; - if(parent[len - 1] == '/') - { - parent[len - 1] = '\0'; // cut off the trailing slash, if there is one - isDirPath = true; // we got a trailing slash, so file is a directory. - } - - // recusively create the parent path. - // only recurse if newpath has a slash that isn't a leading slash. - char *slash = dStrrchr(parent,'/'); - if( slash && slash != parent) - { - // snip the path just after the last slash. - slash[1] = '\0'; - // recusively create the parent path. fail if parent path creation failed. - if(!Platform::createPath(parent)) - return false; - } - - // create *file if it is a directory path. - if(isDirPath) - { - // try to create the directory - if( mkdir(file, 0777) != 0) // app may reside in global apps dir, and so must be writable to all. - return false; - } - - return true; + // if the path exists, we're done. + struct stat statData; + if( stat(file, &statData) == 0 ) + { + return true; // exists, rejoice. + } + + Con::warnf( "creating path %s", file ); + + // get the parent path. + // we're not using basename because it's not thread safe. + U32 len = dStrlen(file); + char parent[len]; + bool isDirPath = false; + + dStrncpy(parent,file,len); + parent[len] = '\0'; + if(parent[len - 1] == '/') + { + parent[len - 1] = '\0'; // cut off the trailing slash, if there is one + isDirPath = true; // we got a trailing slash, so file is a directory. + } + + // recusively create the parent path. + // only recurse if newpath has a slash that isn't a leading slash. + char *slash = dStrrchr(parent,'/'); + if( slash && slash != parent) + { + // snip the path just after the last slash. + slash[1] = '\0'; + // recusively create the parent path. fail if parent path creation failed. + if(!Platform::createPath(parent)) + return false; + } + + // create *file if it is a directory path. + if(isDirPath) + { + // try to create the directory + if( mkdir(file, 0777) != 0) // app may reside in global apps dir, and so must be writable to all. + return false; + } + + return true; } //----------------------------------------------------------------------------- bool Platform::cdFileExists(const char *filePath, const char *volumeName, S32 serialNum) { - return true; + return true; } #pragma mark ---- Directories ---- //----------------------------------------------------------------------------- StringTableEntry Platform::getCurrentDirectory() { - // get the current directory, the one that would be opened if we did a fopen(".") - char* cwd = getcwd(NULL, 0); - StringTableEntry ret = StringTable->insert(cwd); - free(cwd); - return ret; + // get the current directory, the one that would be opened if we did a fopen(".") + char* cwd = getcwd(NULL, 0); + StringTableEntry ret = StringTable->insert(cwd); + free(cwd); + return ret; } //----------------------------------------------------------------------------- bool Platform::setCurrentDirectory(StringTableEntry newDir) { - return (chdir(newDir) == 0); + return (chdir(newDir) == 0); } //----------------------------------------------------------------------------- @@ -602,7 +602,7 @@ bool Platform::setCurrentDirectory(StringTableEntry newDir) // helper func for getWorkingDirectory bool isMainDotCsPresent(NSString* dir) { - return [[NSFileManager defaultManager] fileExistsAtPath:[dir stringByAppendingPathComponent:@"main.cs"]] == YES; + return [[NSFileManager defaultManager] fileExistsAtPath:[dir stringByAppendingPathComponent:@"main.cs"]] == YES; } //----------------------------------------------------------------------------- @@ -619,119 +619,119 @@ bool isMainDotCsPresent(NSString* dir) /// experience when you distribute your app. StringTableEntry Platform::getExecutablePath() { - static const char* cwd = NULL; - - // this isn't actually being used due to some static constructors at bundle load time - // calling this method (before there is a chance to set it) - // for instance, FMOD sound provider (this should be fixed in FMOD as it is with windows) - if (!cwd && torque_getexecutablepath()) - { - // we're in a plugin using the cinterface - cwd = torque_getexecutablepath(); - chdir(cwd); - } - else if(!cwd) - { - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - - //first check the cwd for main.cs - static char buf[4096]; - NSString* currentDir = [[NSString alloc ] initWithUTF8String:getcwd(buf,(4096 * sizeof(char))) ]; - - if (isMainDotCsPresent(currentDir)) - { - cwd = buf; - [pool release]; - [currentDir release]; - return cwd; - } - - NSString* string = [[NSBundle mainBundle] pathForResource:@"main" ofType:@"cs"]; - if(!string) - string = [[NSBundle mainBundle] bundlePath]; - - string = [string stringByDeletingLastPathComponent]; - AssertISV(isMainDotCsPresent(string), "Platform::getExecutablePath - Failed to find main.cs!"); - cwd = dStrdup([string UTF8String]); - chdir(cwd); - [pool release]; - [currentDir release]; - } - - return cwd; + static const char* cwd = NULL; + + // this isn't actually being used due to some static constructors at bundle load time + // calling this method (before there is a chance to set it) + // for instance, FMOD sound provider (this should be fixed in FMOD as it is with windows) + if (!cwd && torque_getexecutablepath()) + { + // we're in a plugin using the cinterface + cwd = torque_getexecutablepath(); + chdir(cwd); + } + else if(!cwd) + { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + + //first check the cwd for main.cs + static char buf[4096]; + NSString* currentDir = [[NSString alloc ] initWithUTF8String:getcwd(buf,(4096 * sizeof(char))) ]; + + if (isMainDotCsPresent(currentDir)) + { + cwd = buf; + [pool release]; + [currentDir release]; + return cwd; + } + + NSString* string = [[NSBundle mainBundle] pathForResource:@"main" ofType:@"cs"]; + if(!string) + string = [[NSBundle mainBundle] bundlePath]; + + string = [string stringByDeletingLastPathComponent]; + AssertISV(isMainDotCsPresent(string), "Platform::getExecutablePath - Failed to find main.cs!"); + cwd = dStrdup([string UTF8String]); + chdir(cwd); + [pool release]; + [currentDir release]; + } + + return cwd; } //----------------------------------------------------------------------------- StringTableEntry Platform::getExecutableName() { - static const char* name = NULL; - if(!name) - name = [[[[NSBundle mainBundle] bundlePath] lastPathComponent] UTF8String]; - - return name; + static const char* name = NULL; + if(!name) + name = [[[[NSBundle mainBundle] bundlePath] lastPathComponent] UTF8String]; + + return name; } //----------------------------------------------------------------------------- bool Platform::isFile(const char *path) { - if (!path || !*path) - return false; - - // make sure we can stat the file - struct stat statData; - if( stat(path, &statData) < 0 ) - { - // Since file does not exist on disk see if it exists in a zip file loaded - return Torque::FS::IsFile(path); - } - - // now see if it's a regular file - if( (statData.st_mode & S_IFMT) == S_IFREG) - return true; - - return false; + if (!path || !*path) + return false; + + // make sure we can stat the file + struct stat statData; + if( stat(path, &statData) < 0 ) + { + // Since file does not exist on disk see if it exists in a zip file loaded + return Torque::FS::IsFile(path); + } + + // now see if it's a regular file + if( (statData.st_mode & S_IFMT) == S_IFREG) + return true; + + return false; } //----------------------------------------------------------------------------- bool Platform::isDirectory(const char *path) { - if (!path || !*path) - return false; - - // make sure we can stat the file - struct stat statData; - if( stat(path, &statData) < 0 ) - return false; - - // now see if it's a directory - if( (statData.st_mode & S_IFMT) == S_IFDIR) - return true; - - return false; + if (!path || !*path) + return false; + + // make sure we can stat the file + struct stat statData; + if( stat(path, &statData) < 0 ) + return false; + + // now see if it's a directory + if( (statData.st_mode & S_IFMT) == S_IFDIR) + return true; + + return false; } S32 Platform::getFileSize(const char* pFilePath) { - if (!pFilePath || !*pFilePath) - return 0; - - struct stat statData; - if( stat(pFilePath, &statData) < 0 ) - return 0; - - // and return it's size in bytes - return (S32)statData.st_size; + if (!pFilePath || !*pFilePath) + return 0; + + struct stat statData; + if( stat(pFilePath, &statData) < 0 ) + return 0; + + // and return it's size in bytes + return (S32)statData.st_size; } //----------------------------------------------------------------------------- bool Platform::isSubDirectory(const char *pathParent, const char *pathSub) { - char fullpath[MAX_MAC_PATH_LONG]; - dStrcpyl(fullpath, MAX_MAC_PATH_LONG, pathParent, "/", pathSub, NULL); - return isDirectory((const char *)fullpath); + char fullpath[MAX_MAC_PATH_LONG]; + dStrcpyl(fullpath, MAX_MAC_PATH_LONG, pathParent, "/", pathSub, NULL); + return isDirectory((const char *)fullpath); } //----------------------------------------------------------------------------- @@ -739,250 +739,250 @@ bool Platform::isSubDirectory(const char *pathParent, const char *pathSub) // ensures that the entry is a directory, and isnt on the ignore lists. inline bool isGoodDirectory(dirent* entry) { - return (entry->d_type == DT_DIR // is a dir - && dStrcmp(entry->d_name,".") != 0 // not here - && dStrcmp(entry->d_name,"..") != 0 // not parent - && !Platform::isExcludedDirectory(entry->d_name)); // not excluded + return (entry->d_type == DT_DIR // is a dir + && dStrcmp(entry->d_name,".") != 0 // not here + && dStrcmp(entry->d_name,"..") != 0 // not parent + && !Platform::isExcludedDirectory(entry->d_name)); // not excluded } //----------------------------------------------------------------------------- bool Platform::hasSubDirectory(const char *path) { - DIR *dir; - dirent *entry; - - dir = opendir(path); - if(!dir) - return false; // we got a bad path, so no, it has no subdirectory. - - while( (entry = readdir(dir)) ) - { - if(isGoodDirectory(entry) ) - { - closedir(dir); - return true; // we have a subdirectory, that isnt on the exclude list. - } - } - - closedir(dir); - return false; // either this dir had no subdirectories, or they were all on the exclude list. + DIR *dir; + dirent *entry; + + dir = opendir(path); + if(!dir) + return false; // we got a bad path, so no, it has no subdirectory. + + while( (entry = readdir(dir)) ) + { + if(isGoodDirectory(entry) ) + { + closedir(dir); + return true; // we have a subdirectory, that isnt on the exclude list. + } + } + + closedir(dir); + return false; // either this dir had no subdirectories, or they were all on the exclude list. } bool Platform::fileDelete(const char * name) { - return dFileDelete(name); + return dFileDelete(name); } static bool recurseDumpDirectories(const char *basePath, const char *subPath, Vector &directoryVector, S32 currentDepth, S32 recurseDepth, bool noBasePath) { - char Path[1024]; - DIR *dip; - struct dirent *d; - - dsize_t trLen = basePath ? dStrlen(basePath) : 0; - dsize_t subtrLen = subPath ? dStrlen(subPath) : 0; - char trail = trLen > 0 ? basePath[trLen - 1] : '\0'; - char subTrail = subtrLen > 0 ? subPath[subtrLen - 1] : '\0'; - - if (trail == '/') - { - if (subPath && (dStrncmp(subPath, "", 1) != 0)) - { - if (subTrail == '/') - dSprintf(Path, 1024, "%s%s", basePath, subPath); - else - dSprintf(Path, 1024, "%s%s/", basePath, subPath); - } - else - dSprintf(Path, 1024, "%s", basePath); - } - else - { - if (subPath && (dStrncmp(subPath, "", 1) != 0)) - { - if (subTrail == '/') - dSprintf(Path, 1024, "%s%s", basePath, subPath); - else - dSprintf(Path, 1024, "%s%s/", basePath, subPath); - } - else - dSprintf(Path, 1024, "%s/", basePath); - } - - dip = opendir(Path); - if (dip == NULL) - return false; - - ////////////////////////////////////////////////////////////////////////// - // add path to our return list ( provided it is valid ) - ////////////////////////////////////////////////////////////////////////// - if (!Platform::isExcludedDirectory(subPath)) - { - if (noBasePath) - { - // We have a path and it's not an empty string or an excluded directory - if ( (subPath && (dStrncmp (subPath, "", 1) != 0)) ) - directoryVector.push_back(StringTable->insert(subPath)); - } - else - { - if ( (subPath && (dStrncmp(subPath, "", 1) != 0)) ) - { - char szPath[1024]; - dMemset(szPath, 0, 1024); - if (trail == '/') - { - if ((basePath[dStrlen(basePath) - 1]) != '/') - dSprintf(szPath, 1024, "%s%s", basePath, &subPath[1]); - else - dSprintf(szPath, 1024, "%s%s", basePath, subPath); - } - else - { - if ((basePath[dStrlen(basePath) - 1]) != '/') - dSprintf(szPath, 1024, "%s%s", basePath, subPath); - else - dSprintf(szPath, 1024, "%s/%s", basePath, subPath); - } - - directoryVector.push_back(StringTable->insert(szPath)); - } - else - directoryVector.push_back(StringTable->insert(basePath)); - } - } - ////////////////////////////////////////////////////////////////////////// - // Iterate through and grab valid directories - ////////////////////////////////////////////////////////////////////////// - - while (d = readdir(dip)) - { - bool isDir; - isDir = false; - if (d->d_type == DT_UNKNOWN) - { - char child [1024]; - if ((Path[dStrlen(Path) - 1] == '/')) - dSprintf(child, 1024, "%s%s", Path, d->d_name); - else - dSprintf(child, 1024, "%s/%s", Path, d->d_name); - isDir = Platform::isDirectory (child); - } - else if (d->d_type & DT_DIR) - isDir = true; - - if ( isDir ) - { - if (dStrcmp(d->d_name, ".") == 0 || - dStrcmp(d->d_name, "..") == 0) - continue; - if (Platform::isExcludedDirectory(d->d_name)) - continue; - if ( (subPath && (dStrncmp(subPath, "", 1) != 0)) ) - { - char child[1024]; - if ((subPath[dStrlen(subPath) - 1] == '/')) - dSprintf(child, 1024, "%s%s", subPath, d->d_name); - else - dSprintf(child, 1024, "%s/%s", subPath, d->d_name); - if (currentDepth < recurseDepth || recurseDepth == -1 ) - recurseDumpDirectories(basePath, child, directoryVector, - currentDepth + 1, recurseDepth, - noBasePath); - } - else - { - char child[1024]; - if ( (basePath[dStrlen(basePath) - 1]) == '/') - dStrcpy (child, d->d_name); - else - dSprintf(child, 1024, "/%s", d->d_name); - if (currentDepth < recurseDepth || recurseDepth == -1) - recurseDumpDirectories(basePath, child, directoryVector, - currentDepth + 1, recurseDepth, - noBasePath); - } - } - } - closedir(dip); - return true; + char Path[1024]; + DIR *dip; + struct dirent *d; + + dsize_t trLen = basePath ? dStrlen(basePath) : 0; + dsize_t subtrLen = subPath ? dStrlen(subPath) : 0; + char trail = trLen > 0 ? basePath[trLen - 1] : '\0'; + char subTrail = subtrLen > 0 ? subPath[subtrLen - 1] : '\0'; + + if (trail == '/') + { + if (subPath && (dStrncmp(subPath, "", 1) != 0)) + { + if (subTrail == '/') + dSprintf(Path, 1024, "%s%s", basePath, subPath); + else + dSprintf(Path, 1024, "%s%s/", basePath, subPath); + } + else + dSprintf(Path, 1024, "%s", basePath); + } + else + { + if (subPath && (dStrncmp(subPath, "", 1) != 0)) + { + if (subTrail == '/') + dSprintf(Path, 1024, "%s%s", basePath, subPath); + else + dSprintf(Path, 1024, "%s%s/", basePath, subPath); + } + else + dSprintf(Path, 1024, "%s/", basePath); + } + + dip = opendir(Path); + if (dip == NULL) + return false; + + ////////////////////////////////////////////////////////////////////////// + // add path to our return list ( provided it is valid ) + ////////////////////////////////////////////////////////////////////////// + if (!Platform::isExcludedDirectory(subPath)) + { + if (noBasePath) + { + // We have a path and it's not an empty string or an excluded directory + if ( (subPath && (dStrncmp (subPath, "", 1) != 0)) ) + directoryVector.push_back(StringTable->insert(subPath)); + } + else + { + if ( (subPath && (dStrncmp(subPath, "", 1) != 0)) ) + { + char szPath[1024]; + dMemset(szPath, 0, 1024); + if (trail == '/') + { + if ((basePath[dStrlen(basePath) - 1]) != '/') + dSprintf(szPath, 1024, "%s%s", basePath, &subPath[1]); + else + dSprintf(szPath, 1024, "%s%s", basePath, subPath); + } + else + { + if ((basePath[dStrlen(basePath) - 1]) != '/') + dSprintf(szPath, 1024, "%s%s", basePath, subPath); + else + dSprintf(szPath, 1024, "%s/%s", basePath, subPath); + } + + directoryVector.push_back(StringTable->insert(szPath)); + } + else + directoryVector.push_back(StringTable->insert(basePath)); + } + } + ////////////////////////////////////////////////////////////////////////// + // Iterate through and grab valid directories + ////////////////////////////////////////////////////////////////////////// + + while (d = readdir(dip)) + { + bool isDir; + isDir = false; + if (d->d_type == DT_UNKNOWN) + { + char child [1024]; + if ((Path[dStrlen(Path) - 1] == '/')) + dSprintf(child, 1024, "%s%s", Path, d->d_name); + else + dSprintf(child, 1024, "%s/%s", Path, d->d_name); + isDir = Platform::isDirectory (child); + } + else if (d->d_type & DT_DIR) + isDir = true; + + if ( isDir ) + { + if (dStrcmp(d->d_name, ".") == 0 || + dStrcmp(d->d_name, "..") == 0) + continue; + if (Platform::isExcludedDirectory(d->d_name)) + continue; + if ( (subPath && (dStrncmp(subPath, "", 1) != 0)) ) + { + char child[1024]; + if ((subPath[dStrlen(subPath) - 1] == '/')) + dSprintf(child, 1024, "%s%s", subPath, d->d_name); + else + dSprintf(child, 1024, "%s/%s", subPath, d->d_name); + if (currentDepth < recurseDepth || recurseDepth == -1 ) + recurseDumpDirectories(basePath, child, directoryVector, + currentDepth + 1, recurseDepth, + noBasePath); + } + else + { + char child[1024]; + if ( (basePath[dStrlen(basePath) - 1]) == '/') + dStrcpy (child, d->d_name); + else + dSprintf(child, 1024, "/%s", d->d_name); + if (currentDepth < recurseDepth || recurseDepth == -1) + recurseDumpDirectories(basePath, child, directoryVector, + currentDepth + 1, recurseDepth, + noBasePath); + } + } + } + closedir(dip); + return true; } //----------------------------------------------------------------------------- bool Platform::dumpDirectories(const char *path, Vector &directoryVector, S32 depth, bool noBasePath) { - bool retVal = recurseDumpDirectories(path, "", directoryVector, 0, depth, noBasePath); - clearExcludedDirectories(); - return retVal; + bool retVal = recurseDumpDirectories(path, "", directoryVector, 0, depth, noBasePath); + clearExcludedDirectories(); + return retVal; } //----------------------------------------------------------------------------- static bool recurseDumpPath(const char* curPath, Vector& fileVector, U32 depth) { - DIR *dir; - dirent *entry; - - // be sure it opens. - dir = opendir(curPath); - if(!dir) - return false; - - // look inside the current directory - while( (entry = readdir(dir)) ) - { - // construct the full file path. we need this to get the file size and to recurse - U32 len = dStrlen(curPath) + entry->d_namlen + 2; - char pathbuf[len]; - dSprintf( pathbuf, len, "%s/%s", curPath, entry->d_name); - pathbuf[len] = '\0'; - - // ok, deal with directories and files seperately. - if( entry->d_type == DT_DIR ) - { - if( depth == 0) - continue; - - // filter out dirs we dont want. - if( !isGoodDirectory(entry) ) - continue; - - // recurse into the dir - recurseDumpPath( pathbuf, fileVector, depth-1); - } - else - { - //add the file entry to the list - // unlike recurseDumpDirectories(), we need to return more complex info here. - U32 fileSize = Platform::getFileSize(pathbuf); - fileVector.increment(); - Platform::FileInfo& rInfo = fileVector.last(); - rInfo.pFullPath = StringTable->insert(curPath); - rInfo.pFileName = StringTable->insert(entry->d_name); - rInfo.fileSize = fileSize; - } - } - closedir(dir); - return true; - + DIR *dir; + dirent *entry; + + // be sure it opens. + dir = opendir(curPath); + if(!dir) + return false; + + // look inside the current directory + while( (entry = readdir(dir)) ) + { + // construct the full file path. we need this to get the file size and to recurse + U32 len = dStrlen(curPath) + entry->d_namlen + 2; + char pathbuf[len]; + dSprintf( pathbuf, len, "%s/%s", curPath, entry->d_name); + pathbuf[len] = '\0'; + + // ok, deal with directories and files seperately. + if( entry->d_type == DT_DIR ) + { + if( depth == 0) + continue; + + // filter out dirs we dont want. + if( !isGoodDirectory(entry) ) + continue; + + // recurse into the dir + recurseDumpPath( pathbuf, fileVector, depth-1); + } + else + { + //add the file entry to the list + // unlike recurseDumpDirectories(), we need to return more complex info here. + U32 fileSize = Platform::getFileSize(pathbuf); + fileVector.increment(); + Platform::FileInfo& rInfo = fileVector.last(); + rInfo.pFullPath = StringTable->insert(curPath); + rInfo.pFileName = StringTable->insert(entry->d_name); + rInfo.fileSize = fileSize; + } + } + closedir(dir); + return true; + } //----------------------------------------------------------------------------- bool Platform::dumpPath(const char *path, Vector& fileVector, S32 depth) { - PROFILE_START(dumpPath); - int len = dStrlen(path); - char newpath[len+1]; - - dStrncpy(newpath,path,len); - newpath[len] = '\0'; // null terminate - if(newpath[len - 1] == '/') - newpath[len - 1] = '\0'; // cut off the trailing slash, if there is one - - bool ret = recurseDumpPath( newpath, fileVector, depth); - PROFILE_END(); - - return ret; + PROFILE_START(dumpPath); + int len = dStrlen(path); + char newpath[len+1]; + + dStrncpy(newpath,path,len); + newpath[len] = '\0'; // null terminate + if(newpath[len - 1] == '/') + newpath[len - 1] = '\0'; // cut off the trailing slash, if there is one + + bool ret = recurseDumpPath( newpath, fileVector, depth); + PROFILE_END(); + + return ret; } // TODO: implement stringToFileTime() @@ -993,57 +993,57 @@ bool Platform::fileTimeToString(FileTime * time, char * string, U32 strLen) { re //----------------------------------------------------------------------------- #if defined(TORQUE_DEBUG) ConsoleFunction(testHasSubdir,void,2,2,"tests platform::hasSubDirectory") { - Con::printf("testing %s",(const char*)argv[1]); - Platform::addExcludedDirectory(".svn"); - if(Platform::hasSubDirectory(argv[1])) - Con::printf(" has subdir"); - else - Con::printf(" does not have subdir"); + Con::printf("testing %s",(const char*)argv[1]); + Platform::addExcludedDirectory(".svn"); + if(Platform::hasSubDirectory(argv[1])) + Con::printf(" has subdir"); + else + Con::printf(" does not have subdir"); } ConsoleFunction(testDumpDirectories,void,4,4,"testDumpDirectories('path', int depth, bool noBasePath)") { - Vector paths; - const S32 depth = dAtoi(argv[2]); - const bool noBasePath = dAtob(argv[3]); - - Platform::addExcludedDirectory(".svn"); - - Platform::dumpDirectories(argv[1], paths, depth, noBasePath); - - Con::printf("Dumping directories starting from %s with depth %i", (const char*)argv[1],depth); - - for(Vector::iterator itr = paths.begin(); itr != paths.end(); itr++) { - Con::printf(*itr); - } - + Vector paths; + const S32 depth = dAtoi(argv[2]); + const bool noBasePath = dAtob(argv[3]); + + Platform::addExcludedDirectory(".svn"); + + Platform::dumpDirectories(argv[1], paths, depth, noBasePath); + + Con::printf("Dumping directories starting from %s with depth %i", (const char*)argv[1],depth); + + for(Vector::iterator itr = paths.begin(); itr != paths.end(); itr++) { + Con::printf(*itr); + } + } ConsoleFunction(testDumpPaths, void, 3, 3, "testDumpPaths('path', int depth)") { - Vector files; - S32 depth = dAtoi(argv[2]); - - Platform::addExcludedDirectory(".svn"); - - Platform::dumpPath(argv[1], files, depth); - - for(Vector::iterator itr = files.begin(); itr != files.end(); itr++) { - Con::printf("%s/%s",itr->pFullPath, itr->pFileName); - } + Vector files; + S32 depth = dAtoi(argv[2]); + + Platform::addExcludedDirectory(".svn"); + + Platform::dumpPath(argv[1], files, depth); + + for(Vector::iterator itr = files.begin(); itr != files.end(); itr++) { + Con::printf("%s/%s",itr->pFullPath, itr->pFileName); + } } //----------------------------------------------------------------------------- ConsoleFunction(testFileTouch, bool , 2,2, "testFileTouch('path')") { - return dFileTouch(argv[1]); + return dFileTouch(argv[1]); } ConsoleFunction(testGetFileTimes, bool, 2,2, "testGetFileTimes('path')") { - FileTime create, modify; - bool ok = Platform::getFileTimes(argv[1], &create, &modify); - Con::printf("%s Platform::getFileTimes %i, %i", ok ? "+OK" : "-FAIL", create, modify); - return ok; + FileTime create, modify; + bool ok = Platform::getFileTimes(argv[1], &create, &modify); + Con::printf("%s Platform::getFileTimes %i, %i", ok ? "+OK" : "-FAIL", create, modify); + return ok; } #endif From 6a1048596e57a68661dda084f605870886200c14 Mon Sep 17 00:00:00 2001 From: "Thomas \"elfprince13\" Dickerson" Date: Fri, 6 Jan 2017 17:55:59 -0500 Subject: [PATCH 9/9] but now it works --- Engine/source/platformMac/macFileIO.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Engine/source/platformMac/macFileIO.mm b/Engine/source/platformMac/macFileIO.mm index 7c9b68eda..f11b5b052 100644 --- a/Engine/source/platformMac/macFileIO.mm +++ b/Engine/source/platformMac/macFileIO.mm @@ -994,7 +994,7 @@ bool Platform::fileTimeToString(FileTime * time, char * string, U32 strLen) { re #if defined(TORQUE_DEBUG) ConsoleFunction(testHasSubdir,void,2,2,"tests platform::hasSubDirectory") { Con::printf("testing %s",(const char*)argv[1]); - Platform::addExcludedDirectory(".svn"); + Platform::addExcludedDirectory(".svn"); if(Platform::hasSubDirectory(argv[1])) Con::printf(" has subdir"); else