Exemple #1
0
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;
}
Exemple #2
0
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;
}
Exemple #3
0
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);
  }
Exemple #5
0
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!");
}
Exemple #6
0
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>();
    }
}
Exemple #7
0
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;
}
Exemple #8
0
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);
}
Exemple #9
0
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;
}
Exemple #10
0
  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);
  }
Exemple #11
0
 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;
   }
 }
Exemple #12
0
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;
}
Exemple #13
0
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();
}
Exemple #14
0
  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);
  }
Exemple #15
0
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;
}
Exemple #16
0
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>();
    }
}
Exemple #17
0
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);
}
Exemple #18
0
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.");
}
Exemple #19
0
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;
  }
}
Exemple #20
0
void
lcpp::LispFunction::name(Ptr<LispSymbol> pName)
{
    EZ_ASSERT(pName, "The passed symbol instance is invalid!");
    NameableBase::name(pName);
}
Exemple #21
0
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;
    }
Exemple #22
0
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);
    }