//----------------------------------------------------------------------------- bool Platform::createPath(const char *file) { char pathbuf[MaxPath]; const char *dir; pathbuf[0] = 0; U32 pathLen = 0; // all paths should be created in home directory char prefPathName[MaxPath]; MungePath(prefPathName, MaxPath, file, GetPrefDir()); file = prefPathName; // does the directory exist already? if (DirExists(prefPathName, true)) // true means that the path is a filepath return true; while((dir = dStrchr(file, '/')) != NULL) { dStrncpy(pathbuf + pathLen, file, dir - file); pathbuf[pathLen + dir-file] = 0; bool ret = mkdir(pathbuf, 0700); pathLen += dir - file; pathbuf[pathLen++] = '/'; file = dir + 1; } return true; }
//-------------------------------------- bool Platform::createPath(const char *file) { TempAlloc< TCHAR > pathbuf( dStrlen( file ) + 1 ); #ifdef UNICODE TempAlloc< WCHAR > fileBuf( pathbuf.size ); convertUTF8toUTF16( file, fileBuf, fileBuf.size ); const WCHAR* fileName = fileBuf; const WCHAR* dir; #else const char* fileName = file; const char* dir; #endif pathbuf[ 0 ] = 0; U32 pathLen = 0; while((dir = dStrchr(fileName, '/')) != NULL) { TCHAR* pathptr = pathbuf; dMemcpy( pathptr + pathLen, fileName, ( dir - fileName ) * sizeof( TCHAR ) ); pathbuf[pathLen + dir-fileName] = 0; // ignore return value because we are fine with already existing directory CreateDirectory(pathbuf, NULL); pathLen += dir - fileName; pathbuf[pathLen++] = '\\'; fileName = dir + 1; } return true; }
void BanList::addBan(S32 uniqueId, const char *TA, S32 banTime) { S32 curTime = Platform::getTime(); if(banTime != 0 && banTime < curTime) return; // make sure this bastard isn't already banned on this server Vector<BanInfo>::iterator i; for(i = list.begin();i != list.end();i++) { if(uniqueId == i->uniqueId) { i->bannedUntil = banTime; return; } } BanInfo b; dStrcpy(b.transportAddress, TA); b.uniqueId = uniqueId; b.bannedUntil = banTime; if(!dStrnicmp(b.transportAddress, "ip:", 3)) { char *c = dStrchr(b.transportAddress+3, ':'); if(c) { *(c+1) = '*'; *(c+2) = 0; } } list.push_back(b); }
void GuiTextListCtrl::onRenderCell(Point2I offset, Point2I cell, bool selected, bool mouseOver) { if ( mList[cell.y].active ) { if (selected || (mProfile->mMouseOverSelected && mouseOver)) { RectI highlightRect = RectI(offset.x, offset.y, mCellSize.x, mCellSize.y); highlightRect.inset( 0, -1 ); renderFilledBorder( highlightRect, mProfile->mBorderColorHL, mProfile->mFillColorHL); GFX->getDrawUtil()->setBitmapModulation(mProfile->mFontColorHL); } else GFX->getDrawUtil()->setBitmapModulation(mouseOver ? mProfile->mFontColorHL : mProfile->mFontColor); } else GFX->getDrawUtil()->setBitmapModulation( mProfile->mFontColorNA ); const char *text = mList[cell.y].text; for(U32 index = 0; index < mColumnOffsets.size(); index++) { const char *nextCol = dStrchr(text, '\t'); if(mColumnOffsets[index] >= 0) { dsize_t slen; if(nextCol) slen = nextCol - text; else slen = dStrlen(text); Point2I pos(offset.x + 4 + mColumnOffsets[index], offset.y); RectI saveClipRect; bool clipped = false; if(mClipColumnText && (index != (mColumnOffsets.size() - 1))) { saveClipRect = GFX->getClipRect(); RectI clipRect(pos, Point2I(mColumnOffsets[index+1] - mColumnOffsets[index] - 4, mCellSize.y)); if(clipRect.intersect(saveClipRect)) { clipped = true; GFX->setClipRect( clipRect ); } } GFX->getDrawUtil()->drawTextN(mFont, pos, text, slen, mProfile->mFontColors); if(clipped) GFX->setClipRect( saveClipRect ); } if(!nextCol) break; text = nextCol+1; } }
StringTableEntry getModNameFromPath(const char *path) { if(path == NULL || *path == 0) return NULL; char buf[1024]; buf[0] = 0; if(path[0] == '/' || path[1] == ':') { // It's an absolute path const StringTableEntry exePath = Platform::getMainDotCsDir(); U32 len = dStrlen(exePath); if(dStrnicmp(exePath, path, len) == 0) { const char *ptr = path + len + 1; const char *slash = dStrchr(ptr, '/'); if(slash) { dStrncpy(buf, ptr, slash - ptr); buf[slash - ptr] = 0; } else return NULL; } else return NULL; } else { const char *slash = dStrchr(path, '/'); if(slash) { dStrncpy(buf, path, slash - path); buf[slash - path] = 0; } else return NULL; } return StringTable->insert(buf); }
static const char *getColumn(const char *text) { S32 ct = sortColumn; while(ct--) { text = dStrchr(text, '\t'); if(!text) return ""; text++; } return text; }
void GuiInspectorField::_setFieldDocs( StringTableEntry docs ) { mFieldDocs = String(); if( docs && docs[ 0 ] ) { // Only accept first line of docs for brevity. const char* newline = dStrchr( docs, '\n' ); if( newline ) mFieldDocs = String( docs, newline - docs ); else mFieldDocs = docs; } }
void RemoteCommandEvent::process(NetConnection *conn) { static char idBuf[10]; // de-tag the command name for(S32 i = mArgc - 1; i >= 0; i--) { char *arg = mArgv[i+1]; if(*arg == StringTagPrefixByte) { // it's a tag: U32 localTag = dAtoi(arg + 1); NetStringHandle tag = conn->translateRemoteStringId(localTag); NetStringTable::expandString( tag, mBuf, sizeof(mBuf), (mArgc - 1) - i, (const char**)(mArgv + i + 2) ); dFree(mArgv[i+1]); mArgv[i+1] = dStrdup(mBuf); } } const char *rmtCommandName = dStrchr(mArgv[1], ' ') + 1; if(conn->isConnectionToServer()) { dStrcpy(mBuf, "clientCmd"); dStrcat(mBuf, rmtCommandName); char *temp = mArgv[1]; mArgv[1] = mBuf; Con::execute(mArgc, (const char **) mArgv+1); mArgv[1] = temp; } else { dStrcpy(mBuf, "serverCmd"); dStrcat(mBuf, rmtCommandName); char *temp = mArgv[1]; dSprintf(idBuf, sizeof(idBuf), "%d", conn->getId()); mArgv[0] = mBuf; mArgv[1] = idBuf; Con::execute(mArgc+1, (const char **) mArgv); mArgv[1] = temp; } }
ColladaAppNode::ColladaAppNode(const domNode* node, ColladaAppNode* parent) : p_domNode(node), appParent(parent), nodeExt(new ColladaExtension_node(node)), lastTransformTime(TSShapeLoader::DefaultTime-1), defaultTransformValid(false), invertMeshes(false) { mName = dStrdup(_GetNameOrId(node)); mParentName = dStrdup(parent ? parent->getName() : "ROOT"); // Extract user properties from the <node> extension as whitespace separated // "name=value" pairs char* properties = dStrdup(nodeExt->user_properties); char* pos = properties; char* end = properties + dStrlen( properties ); while ( pos < end ) { // Find the '=' character to separate the name and value pair char* split = dStrchr( pos, '=' ); if ( !split ) break; // Get the name (whitespace trimmed string up to the '=') // and value (whitespace trimmed string after the '=') *split = '\0'; char* name = TrimFirstWord( pos ); char* value = TrimFirstWord( split + 1 ); mProps.insert(StringTable->insert(name), dAtof(value)); pos = value + dStrlen( value ) + 1; } dFree( properties ); // Create vector of transform elements for (S32 iChild = 0; iChild < node->getContents().getCount(); iChild++) { switch (node->getContents()[iChild]->getElementType()) { case COLLADA_TYPE::TRANSLATE: case COLLADA_TYPE::ROTATE: case COLLADA_TYPE::SCALE: case COLLADA_TYPE::SKEW: case COLLADA_TYPE::MATRIX: case COLLADA_TYPE::LOOKAT: nodeTransforms.increment(); nodeTransforms.last().element = node->getContents()[iChild]; break; } } }
const char* dStrichr( const char* str, char ch ) { AssertFatal( str != NULL, "dStrichr - NULL string" ); if( !ch ) return dStrchr( str, ch ); char c = dToupper( ch ); while( *str ) { if( dToupper( *str ) == c ) return str; ++ str; } return NULL; }
static void dumpDoc( Stream& stream, const char* text, bool checkUngrouped = true ) { // Extract brief. String brief; if( text ) { const char* briefTag = dStrstr( text, "@brief" ); if( !briefTag ) { const char* newline = dStrchr( text, '\n' ); if( newline ) { brief = String( text, newline - text ); text = newline + 1; } else { brief = text; text = NULL; } } } // Write doc comment. if( !brief.isEmpty() ) { stream.writeText( "@brief " ); stream.writeText( brief ); stream.writeText( "\r\n\r\n" ); } if( text ) stream.writeText( text ); #ifdef USE_UNDOCUMENTED_GROUP if( checkUngrouped && ( !text || !dStrstr( text, "@ingroup" ) ) ) { smDocGroups.insertUnique( "UNDOCUMENTED", 0 ); stream.writeText( "\r\n@ingroup UNDOCUMENTED\r\n" ); } #endif }
ZipArchive::ZipEntry *ZipArchive::findZipEntry(const char *filename) { char path[1024]; dStrncpy(path, filename, sizeof(path)); path[sizeof(path) - 1] = 0; for(S32 i = 0;i < dStrlen(path);++i) { if(path[i] == '\\') path[i] = '/'; } ZipEntry *root = mRoot; char *ptr = path, *slash = NULL; do { slash = dStrchr(ptr, '/'); if(slash) { // Find the directory *slash = 0; // check child dict for new root ZipEntry *newRoot = NULL; if (!root->mChildren.tryGetValue(ptr, newRoot)) return NULL; root = newRoot; ptr = slash + 1; } else { // Find the file ZipEntry* entry = NULL; if (root->mChildren.tryGetValue(ptr, entry)) return entry; } } while(slash); return NULL; }
void setVariable(const char *name, const char *value) { // get the field info from the object.. if(name[0] != '$' && dStrchr(name, '.') && !isFunction(name)) { S32 len = dStrlen(name); AssertFatal(len < sizeof(scratchBuffer)-1, "Sim::getVariable - name too long"); dMemcpy(scratchBuffer, name, len+1); char * token = dStrtok(scratchBuffer, "."); SimObject * obj = Sim::findObject(token); if(!obj) return; token = dStrtok(0, ".\0"); if(!token) return; while(token != NULL) { const char * val = obj->getDataField(StringTable->insert(token), 0); if(!val) return; char *fieldToken = token; token = dStrtok(0, ".\0"); if(token) { obj = Sim::findObject(token); if(!obj) return; } else { obj->setDataField(StringTable->insert(fieldToken), 0, value); } } } name = prependDollar(name); gEvalState.globalVars.setVariable(StringTable->insert(name), value); }
U32 GuiTextListCtrl::getRowWidth(Entry *row) { U32 width = 1; const char *text = row->text; for(U32 index = 0; index < mColumnOffsets.size(); index++) { const char *nextCol = dStrchr(text, '\t'); U32 textWidth; if(nextCol) textWidth = mFont->getStrNWidth((const UTF8*)text, nextCol - text); else textWidth = mFont->getStrWidth((const UTF8*)text); if(mColumnOffsets[index] >= 0) width = getMax(width, mColumnOffsets[index] + textWidth); if(!nextCol) break; text = nextCol+1; } return width; }
bool Net::stringToAddress(const char *addressString, NetAddress *address) { if(!dStrnicmp(addressString, "ipx:", 4)) // ipx support deprecated return false; if(!dStrnicmp(addressString, "ip:", 3)) addressString += 3; // eat off the ip: sockaddr_in ipAddr; char remoteAddr[256]; if(strlen(addressString) > 255) return false; dStrcpy(remoteAddr, addressString); char *portString = dStrchr(remoteAddr, ':'); if(portString) *portString++ = '\0'; if(!dStricmp(remoteAddr, "broadcast")) ipAddr.sin_addr.s_addr = htonl(INADDR_BROADCAST); else { ipAddr.sin_addr.s_addr = inet_addr(remoteAddr); if (ipAddr.sin_addr.s_addr == INADDR_NONE) // error { // On the Xbox, 'gethostbyname' does not exist so... #ifndef TORQUE_OS_XENON struct hostent *hp; if((hp = gethostbyname(remoteAddr)) == 0) return false; else memcpy(&ipAddr.sin_addr.s_addr, hp->h_addr, sizeof(in_addr)); #else // On the Xbox do XNetDnsLookup XNDNS *pxndns = NULL; HANDLE hEvent = CreateEvent(NULL, false, false, NULL); XNetDnsLookup(remoteAddr, hEvent, &pxndns); // Wait for event (passing NULL as a handle to XNetDnsLookup will NOT // cause it to behave synchronously, so do not remove the handle/wait while(pxndns->iStatus == WSAEINPROGRESS) WaitForSingleObject(hEvent, INFINITE); bool foundAddr = pxndns->iStatus == 0 && pxndns->cina > 0; if(foundAddr) { // Lets just grab the first address returned, for now memcpy(&ipAddr.sin_addr, pxndns->aina, sizeof(IN_ADDR)); } XNetDnsRelease(pxndns); CloseHandle(hEvent); // If we didn't successfully resolve the DNS lookup, bail after the // handles are released if(!foundAddr) return false; #endif } } if(portString) ipAddr.sin_port = htons(dAtoi(portString)); else ipAddr.sin_port = htons(defaultPort); ipAddr.sin_family = AF_INET; IPSocketToNetAddress(&ipAddr, address); return true; }
NetSocket Net::openConnectTo(const char *addressString) { if(!dStrnicmp(addressString, "ipx:", 4)) // ipx support deprecated return InvalidSocket; if(!dStrnicmp(addressString, "ip:", 3)) addressString += 3; // eat off the ip: char remoteAddr[256]; dStrcpy(remoteAddr, addressString); char *portString = dStrchr(remoteAddr, ':'); U16 port; if(portString) { *portString++ = 0; port = htons(dAtoi(portString)); } else port = htons(defaultPort); if(!dStricmp(remoteAddr, "broadcast")) return InvalidSocket; if(Journal::IsPlaying()) { U32 ret; Journal::Read(&ret); return NetSocket(ret); } NetSocket sock = openSocket(); setBlocking(sock, false); sockaddr_in ipAddr; dMemset(&ipAddr, 0, sizeof(ipAddr)); ipAddr.sin_addr.s_addr = inet_addr(remoteAddr); if(ipAddr.sin_addr.s_addr != INADDR_NONE) { ipAddr.sin_port = port; ipAddr.sin_family = AF_INET; if(::connect(sock, (struct sockaddr *)&ipAddr, sizeof(ipAddr)) == -1) { S32 err = getLastError(); if(err != Net::WouldBlock) { Con::errorf("Error connecting %s: %s", addressString, strerror(err)); ::closesocket(sock); sock = InvalidSocket; } } if(sock != InvalidSocket) { // add this socket to our list of polled sockets addPolledSocket(sock, ConnectionPending); } } else { // need to do an asynchronous name lookup. first, add the socket // to the polled list addPolledSocket(sock, NameLookupRequired, remoteAddr, port); // queue the lookup gNetAsync.queueLookup(remoteAddr, sock); } if(Journal::IsRecording()) Journal::Write(U32(sock)); return sock; }
bool Tokenizer::regressToken(const bool crossLine) { if (mTokenIsCurrent == true) { AssertFatal(mCurrTokenBuffer[0] != '\0', "No token, but marked as current?"); mTokenIsCurrent = false; return true; } U32 currPosition = 0; mCurrTokenBuffer[0] = '\0'; mTokenIsQuoted = false; // Store the beginning of the previous advance // and the beginning of the current advance mCurrPos = mStartPos; // Back up to the first character of the previous token mStartPos--; while (mStartPos > 0) { char c = mpBuffer[mStartPos]; bool cont = true; if (mSingleTokens && dStrchr(mSingleTokens, c)) { if (currPosition == 0) { mCurrTokenBuffer[currPosition++] = c; mStartPos--; cont = false; break; } else { // End of token cont = false; } } else { switch (c) { case ' ': case '\t': if (currPosition == 0) { // Token hasn't started yet... mStartPos--; } else { // End of token mStartPos--; cont = false; } break; case '\r': case '\n': if (crossLine == true && currPosition == 0) { // Windows line ending if (mStartPos > 0 && mpBuffer[mStartPos] == '\r' && mpBuffer[mStartPos - 1] == '\n') mStartPos -= 2; // Not sure if this ever happens but just in case else if (mStartPos > 0 && mpBuffer[mStartPos] == '\n' && mpBuffer[mStartPos - 1] == '\r') mStartPos -= 2; // Unix line endings should only have a single line break character else mStartPos--; } else { cont = false; break; } break; default: if (c == '\"' || c == '\'') { // Quoted token U32 endLine = getCurrentLine(); mStartPos--; while (mpBuffer[mStartPos] != c) { AssertISV(mStartPos < 0, avar("Beginning of file reached before finding begin quote. Quote ended: (%s: %d)", getFileName(), endLine)); mCurrTokenBuffer[currPosition++] = mpBuffer[mStartPos--]; } mTokenIsQuoted = true; mStartPos--; cont = false; } else if (c == '/' && mStartPos > 0 && mpBuffer[mStartPos - 1] == '/') { // Line quote... // Clear out anything saved already currPosition = 0; mStartPos -= 2; } else { mCurrTokenBuffer[currPosition++] = c; mStartPos--; } break; } } if (cont == false) break; } mCurrTokenBuffer[currPosition] = '\0'; // Reveres the token for (U32 i = 0; i < currPosition / 2; i++) { char c = mCurrTokenBuffer[i]; mCurrTokenBuffer[i] = mCurrTokenBuffer[currPosition - i - 1]; mCurrTokenBuffer[currPosition - i - 1] = c; } mStartPos++; if (mStartPos == mCurrPos) return false; return true; }
bool Tokenizer::advanceToken(const bool crossLine, const bool assertAvail) { if (mTokenIsCurrent == true) { AssertFatal(mCurrTokenBuffer[0] != '\0', "No token, but marked as current?"); mTokenIsCurrent = false; return true; } U32 currPosition = 0; mCurrTokenBuffer[0] = '\0'; mTokenIsQuoted = false; // Store the beginning of the previous advance // and the beginning of the current advance mStartPos = mCurrPos; while (mCurrPos < mBufferSize) { char c = mpBuffer[mCurrPos]; bool cont = true; if (mSingleTokens && dStrchr(mSingleTokens, c)) { if (currPosition == 0) { mCurrTokenBuffer[currPosition++] = c; mCurrPos++; cont = false; break; } else { // End of token cont = false; } } else { switch (c) { case ' ': case '\t': if (currPosition == 0) { // Token hasn't started yet... mCurrPos++; } else { // End of token mCurrPos++; cont = false; } break; case '\r': case '\n': if (crossLine == true) { // Windows line ending if (mpBuffer[mCurrPos] == '\r' && mpBuffer[mCurrPos + 1] == '\n') mCurrPos += 2; // Not sure if this ever happens but just in case else if (mpBuffer[mCurrPos] == '\n' && mpBuffer[mCurrPos + 1] == '\r') mCurrPos += 2; // Unix line endings should only have a single line break character else mCurrPos++; } else { cont = false; break; } break; default: if (c == '\"' || c == '\'') { // Quoted token U32 startLine = getCurrentLine(); mCurrPos++; // Store the beginning of the token mStartPos = mCurrPos; while (mpBuffer[mCurrPos] != c) { AssertISV(mCurrPos < mBufferSize, avar("End of file before quote closed. Quote started: (%s: %d)", getFileName(), startLine)); AssertISV((mpBuffer[mCurrPos] != '\n' && mpBuffer[mCurrPos] != '\r'), avar("End of line reached before end of quote. Quote started: (%s: %d)", getFileName(), startLine)); mCurrTokenBuffer[currPosition++] = mpBuffer[mCurrPos++]; } mTokenIsQuoted = true; mCurrPos++; cont = false; } else if (c == '/' && mpBuffer[mCurrPos+1] == '/') { // Line quote... if (currPosition == 0) { // continue to end of line, then let crossLine determine on the next pass while (mCurrPos < mBufferSize && (mpBuffer[mCurrPos] != '\n' && mpBuffer[mCurrPos] != '\r')) mCurrPos++; } else { // This is the end of the token. Continue to EOL while (mCurrPos < mBufferSize && (mpBuffer[mCurrPos] != '\n' && mpBuffer[mCurrPos] != '\r')) mCurrPos++; cont = false; } } else if (c == '/' && mpBuffer[mCurrPos+1] == '*') { // Block quote... if (currPosition == 0) { // continue to end of block, then let crossLine determine on the next pass while (mCurrPos < mBufferSize - 1 && (mpBuffer[mCurrPos] != '*' || mpBuffer[mCurrPos + 1] != '/')) mCurrPos++; if (mCurrPos < mBufferSize - 1) mCurrPos += 2; } else { // This is the end of the token. Continue to EOL while (mCurrPos < mBufferSize - 1 && (mpBuffer[mCurrPos] != '*' || mpBuffer[mCurrPos + 1] != '/')) mCurrPos++; if (mCurrPos < mBufferSize - 1) mCurrPos += 2; cont = false; } } else { // If this is the first non-token character then store the // beginning of the token if (currPosition == 0) mStartPos = mCurrPos; mCurrTokenBuffer[currPosition++] = c; mCurrPos++; } break; } } if (cont == false) break; } mCurrTokenBuffer[currPosition] = '\0'; if (assertAvail == true) AssertISV(currPosition != 0, avar("Error parsing: %s at or around line: %d", getFileName(), getCurrentLine())); if (mCurrPos == mBufferSize) return false; return true; }
void ZipArchive::insertEntry(ZipEntry *ze) { char path[1024]; dStrncpy(path, ze->mCD.mFilename.c_str(), sizeof(path)); path[sizeof(path) - 1] = 0; for(S32 i = 0;i < dStrlen(path);++i) { if(path[i] == '\\') path[i] = '/'; } ZipEntry *root = mRoot; char *ptr = path, *slash = NULL; do { slash = dStrchr(ptr, '/'); if(slash) { // Add the directory *slash = 0; // try to get root, create if not found ZipEntry *newEntry = NULL; if (!root->mChildren.tryGetValue(ptr, newEntry)) { newEntry = new ZipEntry; newEntry->mParent = root; newEntry->mName = String(ptr); newEntry->mIsDirectory = true; newEntry->mCD.setFilename(path); root->mChildren[ptr] = newEntry; } root = newEntry; *slash = '/'; ptr = slash + 1; } else { // Add the file. if(*ptr) { ze->mIsDirectory = false; ze->mName = ptr; ze->mParent = root; root->mChildren[ptr] = ze; mEntries.push_back(ze); } else { // [tom, 2/6/2007] If ptr is empty, this was a directory entry. Since // we created a new entry for it above, we need to delete the old // pointer otherwise it will leak as it won't have got inserted. delete ze; } } } while(slash); }
static void _printf(ConsoleLogEntry::Level level, ConsoleLogEntry::Type type, const char* fmt, va_list argptr) { if (!active) return; Con::active = false; char buffer[8192]; U32 offset = 0; if( gEvalState.traceOn && gEvalState.getStackDepth() > 0 ) { offset = gEvalState.getStackDepth() * 3; for(U32 i = 0; i < offset; i++) buffer[i] = ' '; } if (useTimestamp) { static U32 startTime = Platform::getRealMilliseconds(); U32 curTime = Platform::getRealMilliseconds() - startTime; offset += dSprintf(buffer + offset, sizeof(buffer) - offset, "[+%4d.%03d]", U32(curTime * 0.001), curTime % 1000); } dVsprintf(buffer + offset, sizeof(buffer) - offset, fmt, argptr); for(S32 i = 0; i < gConsumers.size(); i++) gConsumers[i](level, buffer); if(logBufferEnabled || consoleLogMode) { char *pos = buffer; while(*pos) { if(*pos == '\t') *pos = '^'; pos++; } pos = buffer; for(;;) { char *eofPos = dStrchr(pos, '\n'); if(eofPos) *eofPos = 0; log(pos); if(logBufferEnabled && !consoleLogLocked) { ConsoleLogEntry entry; entry.mLevel = level; entry.mType = type; #ifndef TORQUE_SHIPPING // this is equivalent to a memory leak, turn it off in ship build entry.mString = (const char *)consoleLogChunker.alloc(dStrlen(pos) + 1); dStrcpy(const_cast<char*>(entry.mString), pos); // This prevents infinite recursion if the console itself needs to // re-allocate memory to accommodate the new console log entry, and // LOG_PAGE_ALLOCS is defined. It is kind of a dirty hack, but the // uses for LOG_PAGE_ALLOCS are limited, and it is not worth writing // a lot of special case code to support this situation. -patw const bool save = Con::active; Con::active = false; consoleLog.push_back(entry); Con::active = save; #endif } if(!eofPos) break; pos = eofPos + 1; } } Con::active = true; }
SimObject *SimObjectMemento::restore() const { // Make sure we have data to restore. if ( !mState ) return NULL; // TODO: We could potentially make this faster by // caching the CodeBlock generated from the string SimObject* object; if( !mIsDatablock ) { // Set the redefine behavior to automatically giving // the new objects unique names. This will restore the // old names if they are still available or give reasonable // approximations if not. const char* oldRedefineBehavior = Con::getVariable( "$Con::redefineBehavior" ); Con::setVariable( "$Con::redefineBehavior", "renameNew" ); // Read the object. const UTF8* result = Con::evaluate( mState ); // Restore the redefine behavior. Con::setVariable( "$Con::redefineBehavior", oldRedefineBehavior ); if ( !result || !result[ 0 ] ) return NULL; // Look up the object. U32 objectId = dAtoi( result ); object = Sim::findObject( objectId ); } else { String objectName = mObjectName; // For datablocks, it's getting a little complicated. Datablock definitions cannot be used // as expressions and thus we can't get to the datablock object we create by using the // Con::evaluate() return value. Instead, we need to rely on the object name. However, if // the name is already taken and needs to be changed, we need to manually do that. To complicate // this further, we cannot rely on automatic renaming since then we don't know by what name // the newly created object actually goes. So what we do is we alter the source text snapshot // and substitute a name in case the old object name is actually taken now. char* tempBuffer; if( !Sim::findObject( objectName ) ) tempBuffer = mState; else { String uniqueName = Sim::getUniqueName( objectName ); U32 uniqueNameLen = uniqueName.length(); char* pLeftParen = dStrchr( mState, '(' ); if( pLeftParen == NULL ) return NULL; U32 numCharsToLeftParen = pLeftParen - mState; tempBuffer = ( char* ) dMalloc( dStrlen( mState ) + uniqueNameLen + 1 ); dMemcpy( tempBuffer, mState, numCharsToLeftParen ); dMemcpy( &tempBuffer[ numCharsToLeftParen ], uniqueName, uniqueNameLen ); dStrcpy( &tempBuffer[ numCharsToLeftParen + uniqueNameLen ], &mState[ numCharsToLeftParen ] ); } Con::evaluate( tempBuffer ); if( tempBuffer != mState ) dFree( tempBuffer ); if( objectName == String::EmptyString ) return NULL; object = Sim::findObject( objectName ); } return object; }
//----------------------------------------------------------------------------- // preload //----------------------------------------------------------------------------- bool ParticleData::preload(bool server, String &errorStr) { if (Parent::preload(server, errorStr) == false) return false; bool error = false; if(!server) { // Here we attempt to load the particle's texture if specified. An undefined // texture is *not* an error since the emitter may provide one. if (textureName && textureName[0]) { textureHandle = GFXTexHandle(textureName, &GFXDefaultStaticDiffuseProfile, avar("%s() - textureHandle (line %d)", __FUNCTION__, __LINE__)); if (!textureHandle) { errorStr = String::ToString("Missing particle texture: %s", textureName); error = true; } } if (animateTexture) { // Here we parse animTexFramesString into byte-size frame numbers in animTexFrames. // Each frame token must be separated by whitespace. // A frame token must be a positive integer frame number or a range of frame numbers // separated with a '-'. // The range separator, '-', cannot have any whitspace around it. // Ranges can be specified to move through the frames in reverse as well as forward. // Frame numbers exceeding the number of tiles will wrap. // example: // "0-16 20 19 18 17 31-21" S32 n_tiles = animTexTiling.x * animTexTiling.y; AssertFatal(n_tiles > 0 && n_tiles <= 256, "Error, bad animTexTiling setting." ); animTexFrames.clear(); char* tokCopy = new char[dStrlen(animTexFramesString) + 1]; dStrcpy(tokCopy, animTexFramesString); char* currTok = dStrtok(tokCopy, " \t"); while (currTok != NULL) { char* minus = dStrchr(currTok, '-'); if (minus) { // add a range of frames *minus = '\0'; S32 range_a = dAtoi(currTok); S32 range_b = dAtoi(minus+1); if (range_b < range_a) { // reverse frame range for (S32 i = range_a; i >= range_b; i--) animTexFrames.push_back((U8)(i % n_tiles)); } else { // forward frame range for (S32 i = range_a; i <= range_b; i++) animTexFrames.push_back((U8)(i % n_tiles)); } } else { // add one frame animTexFrames.push_back((U8)(dAtoi(currTok) % n_tiles)); } currTok = dStrtok(NULL, " \t"); } // Here we pre-calculate the UVs for each frame tile, which are // tiled inside the UV region specified by texCoords. Since the // UVs are calculated using bilinear interpolation, the texCoords // region does *not* have to be an axis-aligned rectangle. if (animTexUVs) delete [] animTexUVs; animTexUVs = new Point2F[(animTexTiling.x+1)*(animTexTiling.y+1)]; // interpolate points on the left and right edge of the uv quadrangle Point2F lf_pt = texCoords[0]; Point2F rt_pt = texCoords[3]; // per-row delta for left and right interpolated points Point2F lf_d = (texCoords[1] - texCoords[0])/(F32)animTexTiling.y; Point2F rt_d = (texCoords[2] - texCoords[3])/(F32)animTexTiling.y; S32 idx = 0; for (S32 yy = 0; yy <= animTexTiling.y; yy++) { Point2F p = lf_pt; Point2F dp = (rt_pt - lf_pt)/(F32)animTexTiling.x; for (S32 xx = 0; xx <= animTexTiling.x; xx++) { animTexUVs[idx++] = p; p += dp; } lf_pt += lf_d; rt_pt += rt_d; } // cleanup delete [] tokCopy; numFrames = animTexFrames.size(); } } return !error; }
//------------------------------------------------------------------------------ // munge the case of the specified pathName. This means try to find the actual // filename in with case-insensitive matching on the specified pathName, and // store the actual found name. static void MungeCase(char* pathName, S32 pathNameSize) { char tempBuf[MaxPath]; dStrncpy(tempBuf, pathName, pathNameSize); AssertFatal(pathName[0] == '/', "PATH must be absolute"); struct stat filestat; const int MaxPathEl = 200; char *currChar = pathName; char testPath[MaxPath]; char pathEl[MaxPathEl]; bool done = false; dStrncpy(tempBuf, "/", MaxPath); currChar++; while (!done) { char* termChar = dStrchr(currChar, '/'); if (termChar == NULL) termChar = dStrchr(currChar, '\0'); AssertFatal(termChar, "Can't find / or NULL terminator"); S32 pathElLen = (termChar - currChar); dStrncpy(pathEl, currChar, pathElLen); pathEl[pathElLen] = '\0'; dStrncpy(testPath, tempBuf, MaxPath); dStrcat(testPath, pathEl); if (stat(testPath, &filestat) != -1) { dStrncpy(tempBuf, testPath, MaxPath); } else { DIR *dir = opendir(tempBuf); struct dirent* ent; bool foundMatch = false; while (dir != NULL && (ent = readdir(dir)) != NULL) { if (dStricmp(pathEl, ent->d_name) == 0) { foundMatch = true; dStrcat(tempBuf, ent->d_name); break; } } if (!foundMatch) dStrncpy(tempBuf, testPath, MaxPath); if (dir) closedir(dir); } if (*termChar == '/') { dStrcat(tempBuf, "/"); termChar++; currChar = termChar; } else done = true; } dStrncpy(pathName, tempBuf, pathNameSize); }