ezResult ezMemoryStreamWriter::WriteBytes(const void* pWriteBuffer, ezUInt64 uiBytesToWrite) { EZ_ASSERT_API(m_pStreamStorage != nullptr, "The memory stream writer needs a valid memory storage object!"); if (uiBytesToWrite == 0) return EZ_SUCCESS; EZ_ASSERT(pWriteBuffer != nullptr, "No valid buffer containing data given!"); ezUInt64 uiNewSizeInBytes = m_uiWritePosition + uiBytesToWrite; EZ_IGNORE_UNUSED(uiNewSizeInBytes); EZ_ASSERT(uiNewSizeInBytes < ezInvalidIndex, "Memory stream only supports up to 4GB of data"); const ezUInt32 uiBytesToWrite32 = static_cast<ezUInt32>(uiBytesToWrite); // Reserve the memory in the storage object m_pStreamStorage->m_Storage.SetCount(uiBytesToWrite32 + m_uiWritePosition); ezUInt8* pWritePointer = &m_pStreamStorage->m_Storage[m_uiWritePosition]; ezMemoryUtils::Copy(pWritePointer, static_cast<const ezUInt8*>(pWriteBuffer), uiBytesToWrite32); m_uiWritePosition += uiBytesToWrite32; return EZ_SUCCESS; }
lcpp::Ptr<lcpp::LispObject> lcpp::LispFunction_UserDefined::call(Ptr<LispObject> pArgList) { EZ_ASSERT(m_pBody, "The function body MUST be valid!"); RecursionCounter counter(LispRuntime::instance()); auto pEnv = LispEnvironment::create(m_pName, m_pParentEnv); // Process args ////////////////////////////////////////////////////////////////////////// processArguments(pEnv, pArgList); // Process body ////////////////////////////////////////////////////////////////////////// Ptr<LispObject> pCodePointer = m_pBody; Ptr<LispObject> pResult = LCPP_NIL; while(!isNil(pCodePointer)) { EZ_ASSERT(pCodePointer->is<LispCons>(), "Function body must be a cons."); auto pCons = pCodePointer.cast<LispCons>(); pResult = LispRuntime::instance()->evaluator()->evalulate(pEnv, pCons->car()); pCodePointer = pCons->cdr(); } return pResult; }
void lcpp::LispRuntimeState::shutdown() { EZ_ASSERT(m_stats.m_initializationCount > 0, "LCPP_pRuntime was never initialized."); EZ_ASSERT(m_stats.m_initializationCount > m_stats.m_shutdownCount, "The LCPP_pRuntime was not shut down often enough!"); ++m_stats.m_shutdownCount; m_pGC->removeRoot(m_pReaderState->m_pMacroEnv.get()); m_pGC->removeRoot(m_pGlobalEnvironment); m_pGC->removeRoot(m_pSyntaxEnvironment); m_pReaderState->m_pMacroEnv = nullptr; EZ_DELETE(defaultAllocator(), m_pReaderState); m_pPrinterState->m_pOutStream = nullptr; EZ_DELETE(defaultAllocator(), m_pPrinterState); m_pGlobalEnvironment = nullptr; m_pSyntaxEnvironment = nullptr; // TODO Once we have a per-runtime garbage collector system running, uncomment the following line. //m_pGC->clear(); m_pGC->collect(0); }
void FolderType::RemoveDataDirectory() { for (ezUInt32 i = 0; i < m_Readers.GetCount(); ++i) { EZ_ASSERT(!m_Readers[i]->m_bIsInUse, "Cannot remove a data directory while there are still files open in it."); } for (ezUInt32 i = 0; i < m_Writers.GetCount(); ++i) { EZ_ASSERT(!m_Writers[i]->m_bIsInUse, "Cannot remove a data directory while there are still files open in it."); } FolderType* pThis = this; EZ_DEFAULT_DELETE(pThis); }
lcpp::LispFunction_BuiltIn::LispFunction_BuiltIn(Ptr<LispEnvironment> pParentEnv, ExecutorPtr_t pExec) : LispFunction(pParentEnv), m_pExec(pExec) { EZ_ASSERT(pExec, "The function executor must be valid!"); }
lcpp::LispFunction_UserDefined::LispFunction_UserDefined(Ptr<LispEnvironment> pParentEnv, Ptr<LispObject> pArgNameList, Ptr<LispCons> pBody) : LispFunction(pParentEnv), m_pArgNameList(pArgNameList), m_numArgs(0), m_pBody(pBody) #ifdef _DEBUG , m_dump(LispRuntime::instance()->allocator().get()) #endif // _DEBUG { EZ_ASSERT(m_pArgNameList, "The function body MUST be valid argNameList!"); EZ_ASSERT(m_pBody, "The function body MUST be valid!"); #ifdef _DEBUG { ezStringBuilder builder; m_pBody->toStringHelper(builder); m_dump = builder; } #endif // _DEBUG if(isNil(m_pArgNameList)) { return; } EZ_ASSERT(m_pArgNameList->is<LispCons>(), "Invalid arg name list."); auto pArgNamePtr = m_pArgNameList.cast<LispCons>(); while(true) { EZ_ASSERT(pArgNamePtr->car()->is<LispSymbol>(), "All arg names must be symbols!"); auto pArgName = pArgNamePtr->car().cast<LispSymbol>(); m_pParentEnv->add(pArgName, LCPP_NIL); ++m_numArgs; if(isNil(pArgNamePtr->cdr())) { break; } EZ_ASSERT(pArgNamePtr->cdr()->is<LispCons>(), "Invalid arg name list."); pArgNamePtr = pArgNamePtr->cdr().cast<LispCons>(); } }
lcpp::String lcpp::LispFunction_BuiltIn::toString() const { EZ_ASSERT(m_pName, "A built-in function needs to have a name!"); ezStringBuilder builder; builder.AppendFormat("<procedure (built-in):%s>", m_pName->value().GetData()); return builder; }
lcpp::Ptr<lcpp::LispObject> lcpp::LispFunction_BuiltIn::call(Ptr<LispObject> pArgList) { EZ_ASSERT(m_pExec, "The executor MUST be valid!"); RecursionCounter counter(LispRuntime::instance()); auto pEnv = LispEnvironment::create(m_pName, m_pParentEnv); return (*m_pExec)(pEnv, pArgList); }
ezResult ezTaskSystem::CancelTask(ezTask* pTask, ezOnTaskRunning::Enum OnTaskRunning) { if (pTask->IsTaskFinished()) return EZ_SUCCESS; EZ_PROFILE(s_ProfileCancelTask); EZ_ASSERT(pTask->m_BelongsToGroup.m_pTaskGroup->m_uiGroupCounter == pTask->m_BelongsToGroup.m_uiGroupCounter, "The task to be removed is in an invalid group."); // we set the cancel flag, to make sure that tasks that support canceling will terminate asap pTask->m_bCancelExecution = true; { EZ_LOCK(s_TaskSystemMutex); // if the task is still in the queue of its group, it had not yet been scheduled if (!pTask->m_bTaskIsScheduled && pTask->m_BelongsToGroup.m_pTaskGroup->m_Tasks.RemoveSwap(pTask)) { // we set the task to finished, even though it was not executed pTask->m_bIsFinished = true; return EZ_SUCCESS; } // check if the task has already been scheduled for execution // if so, remove it from the work queue { for (ezUInt32 i = 0; i < ezTaskPriority::ENUM_COUNT; ++i) { auto it = s_Tasks[i].GetIterator(); while (it.IsValid()) { if (it->m_pTask == pTask) { s_Tasks[i].Erase(it); // we set the task to finished, even though it was not executed pTask->m_bIsFinished = true; // tell the system that one task of that group is 'finished', to ensure its dependencies will get scheduled TaskHasFinished(it->m_pTask, it->m_pBelongsToGroup); return EZ_SUCCESS; } ++it; } } } } // if we made it here, the task was already running // thus we just wait for it to finish if (OnTaskRunning == ezOnTaskRunning::WaitTillFinished) WaitForTask(pTask); return EZ_FAILURE; }
void TextureCube::SetData(CubemapFace face, ezUInt32 uiMipLevel, const ezColor8UNorm* pData) { EZ_ASSERT(uiMipLevel < m_numMipLevels, "MipLevel %i does not exist, texture has only %i MipMapLevels", uiMipLevel, m_numMipLevels); Bind(0); glTexSubImage2D(static_cast<GLenum>(face), uiMipLevel, 0, 0, m_width, m_height, GL_RGBA, GL_UNSIGNED_BYTE, pData); }
void Texture::Bind(GLuint slotIndex) { EZ_ASSERT(slotIndex < sizeof(s_pBoundTextures) / sizeof(Texture*), "Can't bind texture to slot %i. Maximum number of slots is %i", slotIndex, sizeof(s_pBoundTextures) / sizeof(Texture*)); if(s_pBoundTextures[slotIndex] != this) { glActiveTexture(GL_TEXTURE0 + slotIndex); glBindTexture(GetOpenGLTextureType(), m_TextureHandle); gl::Utils::CheckError("glBindTexture"); s_pBoundTextures[slotIndex] = this; } }
bool lcpp::LispFunction_UserDefined::checkArgumentCount(Ptr<LispObject> pArgs) { if(isNil(pArgs)) { // No args are given, but 1 or more are expected. if(m_numArgs > 0) { ezStringBuilder message; message.AppendFormat("Invalid number of arguments: expected %u, got none.", m_numArgs); throw exceptions::InvalidInput(message.GetData()); } return false; } // From here on out we know that pArgs MUST be a cons. EZ_ASSERT(pArgs->is<LispCons>(), "pArgs must be a cons if it is not nil!"); auto pArgList = pArgs.cast<LispCons>(); // pArgs is not nil, which means it's a cons, so we count the args ezUInt32 numElements = 0; auto res = count(pArgList, numElements); EZ_ASSERT(res.Succeeded(), "pArgList is not a regular list!"); // pArgs is not nil but we don't expect any arguments if(m_numArgs == 0) { ezStringBuilder message; message.AppendFormat("Invalid number of arguments: expected no arguments, got %u", numElements); throw exceptions::InvalidInput(message.GetData()); } if(numElements != m_numArgs) { ezStringBuilder message; message.AppendFormat("Invalid number of arguments: Expected %u arguments, got %u", m_numArgs, numElements); throw exceptions::InvalidInput(message.GetData()); } return true; }
void lcpp::LispRuntimeState::initialize(ezAllocatorBase* pAllocator) { EZ_ASSERT(m_stats.m_shutdownCount <= m_stats.m_initializationCount, "LCPP_pRuntime was shut down more often than it was initialized!"); if (m_stats.m_shutdownCount < m_stats.m_initializationCount) { shutdown(); } EZ_ASSERT(m_stats.m_initializationCount == m_stats.m_shutdownCount, "LCPP_pRuntime initialization and shutdown count must be balanced!"); ++m_stats.m_initializationCount; m_pAllocator = pAllocator ? pAllocator : defaultAllocator(); m_pGC = lcpp::getGarbageCollector(); #if EZ_ENABLED(EZ_COMPILE_FOR_DEBUG) g_pGC = m_pGC.get(); #endif m_pSyntaxEnvironment = env::createTopLevel(symbol::create("syntax")).get(); m_pGC->addRoot(m_pSyntaxEnvironment); m_pGlobalEnvironment = env::create(getSyntaxEnvironment(), symbol::create("global")).get(); m_pGC->addRoot(m_pGlobalEnvironment); ////////////////////////////////////////////////////////////////////////// m_pReaderState = EZ_NEW(defaultAllocator(), reader::State); m_pReaderState->m_pMacroEnv = env::createTopLevel(symbol::create("reader-macros")); m_pGC->addRoot(m_pReaderState->m_pMacroEnv.get()); m_pPrinterState = EZ_NEW(defaultAllocator(), printer::State); ////////////////////////////////////////////////////////////////////////// registerBuiltIns(); }
Texture::Texture(ezUInt32 width, ezUInt32 height, ezUInt32 depth, GLuint format, ezInt32 numMipLevels, ezUInt32 numMSAASamples) : m_width(width), m_height(height), m_depth(depth), m_format(format), m_numMipLevels(ConvertMipMapSettingToActualCount(numMipLevels, width, height, depth)), m_numMSAASamples(numMSAASamples) { EZ_ASSERT(m_numMipLevels == 1 || numMSAASamples == 0, "Texture must have either zero MSAA samples or only one miplevel!"); glGenTextures(1, &m_TextureHandle); }
void ezTask::Run() { // actually this should not be possible to happen if (m_bIsFinished || m_bCancelExecution) { m_bIsFinished = true; return; } { EZ_ASSERT(m_bProfilingIDGenerated, "Profiling id must be valid at this point."); EZ_PROFILE(m_ProfilingID); Execute(); } m_bIsFinished = true; }
void lcpp::LispFunction_UserDefined::processArguments(Ptr<LispEnvironment> pEnv, Ptr<LispObject> pArgs) { if(!checkArgumentCount(pArgs)) { return; } // Update environment with argument values ////////////////////////////////////////////////////////////////////////// EZ_ASSERT(pArgs->is<LispCons>(), "pArgs must be a cons if it is not nil!"); auto pCurrentArgName = m_pArgNameList.cast<LispCons>(); auto pCurrentArg = pArgs.cast<LispCons>(); for(auto i = m_numArgs; i > 0; --i) { pEnv->add(pCurrentArgName->car().cast<LispSymbol>(), pCurrentArg->car()); pCurrentArgName = pCurrentArgName->cdr().cast<LispCons>(); pCurrentArg = pCurrentArg->cdr().cast<LispCons>(); } }
void ezClock::Load(ezIBinaryStreamReader& Stream) { ezUInt8 uiVersion = 0; Stream >> uiVersion; EZ_ASSERT(uiVersion == 1, "Wrong version for ezClock: %i", uiVersion); Stream >> m_AccumulatedTime; Stream >> m_LastTimeDiff; Stream >> m_FixedTimeStep; Stream >> m_MinTimeStep; Stream >> m_MaxTimeStep; Stream >> m_Speed; Stream >> m_bPaused; // make sure we continue properly m_LastTimeUpdate = ezTime::Now() - m_MinTimeStep; if (m_pTimeStepSmoother) m_pTimeStepSmoother->Reset(this); }
void ezCamera::CameraSettingsChanged() { EZ_ASSERT(m_Mode != None, "Wrong Camera Mode"); EZ_ASSERT(m_fNearPlane < m_fFarPlane, "Near and Far Plane are invalid."); EZ_ASSERT(m_fFovOrDim > 0.0f, "FOV or Camera Dimension is invalid."); }
ezTaskSystem::TaskData ezTaskSystem::GetNextTask(ezTaskPriority::Enum FirstPriority, ezTaskPriority::Enum LastPriority, ezTask* pPrioritizeThis) { // this is the central function that selects tasks for the worker threads to work on // do a quick and dirty check, whether we would find any work (without a lock) // if nothing is found, the thread can go to sleep, without entering the mutex // note: There is NO race condition here. Even if this loop would miss a work item, because it is added after it looked at the corresponding // queue, it will not be a problem. The function will return with 'no work' for the thread, the thread will try to go to sleep, but the // thread-signal will be signaled already and thus the thread will loop again, call 'GetNextTask' a second time and THEN detect the new work item EZ_ASSERT(FirstPriority >= ezTaskPriority::EarlyThisFrame && LastPriority < ezTaskPriority::ENUM_COUNT, "Priority Range is invalid: %i to %i", FirstPriority, LastPriority); for (ezUInt32 i = FirstPriority; i <= (ezUInt32) LastPriority; ++i) { if (!s_Tasks[i].IsEmpty()) goto foundany; } { TaskData td; td.m_pTask = nullptr; td.m_pBelongsToGroup = nullptr; return td; } foundany: // we have detected that there MIGHT be work EZ_LOCK(s_TaskSystemMutex); // if there is a task that should be prioritized, check if it exists in any of the task lists if (pPrioritizeThis != nullptr) { // only search for the task in the lists that this thread is willing to work on // otherwise we might execute a main-thread task in a thread that is not the main thread for (ezUInt32 i = FirstPriority; i <= (ezUInt32) LastPriority; ++i) { auto it = s_Tasks[i].GetIterator(); // just blindly search the entire list while (it.IsValid()) { // if we find that task, return it // otherwise this whole search will do nothing and the default priority based // system will take over if (it->m_pTask == pPrioritizeThis) { TaskData td = *it; s_Tasks[i].Erase(it); return td; } ++it; } } } // go through all the task lists that this thread is willing to work on for (ezUInt32 i = FirstPriority; i <= (ezUInt32) LastPriority; ++i) { // if the list is not empty, just take the first task and execute that if (!s_Tasks[i].IsEmpty()) { TaskData td = *s_Tasks[i].GetIterator(); s_Tasks[i].Erase(s_Tasks[i].GetIterator()); return td; } } { TaskData td; td.m_pTask = nullptr; td.m_pBelongsToGroup = nullptr; return td; } }
void lcpp::LispFunction::name(Ptr<LispSymbol> pName) { EZ_ASSERT(pName, "The passed symbol instance is invalid!"); NameableBase::name(pName); }
int ezStringUtils::vsnprintf(char* szOutputBuffer, unsigned int uiBufferSize, const char* szFormat, va_list args0) { va_list args; va_copy(args, args0); EZ_ASSERT(ezUnicodeUtils::IsValidUtf8(szFormat), "The sprintf format string must be valid Utf8."); // make sure the last character is a \0 if ((szOutputBuffer) && (uiBufferSize > 0)) szOutputBuffer[uiBufferSize - 1] = '\0'; unsigned int uiReadPos = 0; unsigned int uiWritePos = 0; bool bError = false; while (szFormat[uiReadPos] != '\0') { const char c = szFormat[uiReadPos]; ++uiReadPos; // if c is not %, just print it out and be done with it if (c != '%') { OutputChar (szOutputBuffer, uiBufferSize, uiWritePos, c); continue; } // otherwise parse the formatting string to find out what has to be done char cNext = szFormat[uiReadPos]; // *** parse the format string *** // first read the flags (as many as there are) unsigned int Flags = ReadFlags (szFormat, uiReadPos, cNext); // read the width of the field int iWidth = ReadWidth (szFormat, uiReadPos, cNext); // read the precision specifier int iPrecision = ReadPrecision (szFormat, uiReadPos, cNext); // read the input data 'length' (short / int / long it, float / double) const sprintfLength::Enum Length = ReadLength (szFormat, uiReadPos, cNext); // read the 'specifier' type const char cSpecifier = ReadSpecifier (szFormat, uiReadPos, cNext, bError); if (bError) { snprintf (szOutputBuffer, uiBufferSize, "Error in formatting string at position %u ('%c').", uiReadPos, cSpecifier); va_end(args); return -1; } // if 'width' was specified as '*', read it from an extra parameter if (iWidth < 0) iWidth = va_arg (args, int); // if 'precision' was specified as '*', read it from an extra parameter if (iPrecision == -2) iPrecision = va_arg (args, int); // % Sign if (cSpecifier == '%') { OutputChar (szOutputBuffer, uiBufferSize, uiWritePos, '%'); continue; } // Nothing: Writes the current write position back to an int pointer if (cSpecifier == 'n') { int* p = va_arg (args, int*); if (p) *p = (int) uiWritePos; continue; } // String if (cSpecifier == 's') { const char* s = va_arg (args, const char*); OutputString (szOutputBuffer, uiBufferSize, uiWritePos, s, Flags, iWidth, iPrecision); continue; } // Character if (cSpecifier == 'c') { char c2 = va_arg (args, int); char s[2] = {c2, 0}; OutputString (szOutputBuffer, uiBufferSize, uiWritePos, s, Flags, iWidth, iPrecision); continue; }
lcpp::Ptr<lcpp::LispObject> lcpp::Reader::parseAtom(ezStringIterator& input) { // Special case for + and - characters, since the ezEngine parses (+ 1) as +1... auto ch = input.GetCharacter(); if (ch == '+' || ch == '-') { auto copy = input; ezStringBuilder symbol; symbol.Append(ch); ++copy; ch = copy.GetCharacter(); while(true) { if(isSeparator(ch) || contains("()", char(ch)) || !copy.IsValid()) { // The + or - characters stand alone, which means they're meant to be a symbol. while(input.GetData() != copy.GetData()) { advance(input); } return create<LispSymbol>(symbol); } if (isDigit(ch)) { // The +'s or -'s are sign changers of the digit we just encountered. // Abort reading as symbol. break; } symbol.Append(ch); ++copy; if(copy.IsValid()) { ch = copy.GetCharacter(); } } } // Try parsing for an integer first, then a number, then a symbol const char* lastPos = nullptr; LispInteger::Number_t integer; auto result = to(input, integer, &lastPos); // The string contains a number, but it is a floating point number; reparse. if (result.Succeeded()) { LCPP_SCOPE_EXIT{ while(input.GetData() != lastPos) { advance(input); } }; if(lastPos[0] == '.') { LispNumber::Number_t number; auto result = to(input, number, &lastPos); EZ_ASSERT(result.Succeeded(), "An integer of the form '123.' should be parsed as float!"); return create<LispNumber>(number); } return create<LispInteger>(integer); }