<commit_before>#include "LargeRAWFile.h"
#include <sstream>

using namespace std;

LargeRAWFile::LargeRAWFile(const std::string& strFilename, UINT64 iHeaderSize):
  m_strFilename(strFilename),
  m_bIsOpen(false),
  m_bWritable(false),
  m_iHeaderSize(iHeaderSize)
{
}

LargeRAWFile::LargeRAWFile(const std::wstring& wstrFilename, UINT64 iHeaderSize):
  m_bIsOpen(false),
  m_bWritable(false),
  m_iHeaderSize(iHeaderSize)
{
  string strFilename(wstrFilename.begin(), wstrFilename.end());
  m_strFilename = strFilename;
}

LargeRAWFile::LargeRAWFile(LargeRAWFile &other) :
  m_strFilename(other.m_strFilename),
  m_bIsOpen(other.m_bIsOpen),
  m_bWritable(other.m_bWritable),
  m_iHeaderSize(other.m_iHeaderSize)
{
  /// @todo !?!? need a better fix, a copy constructor shouldn't be expensive.
  if (m_bIsOpen && m_bWritable) {
    m_strFilename += "~";
    UINT64 iDataSize = other.GetCurrentSize();
    Create(iDataSize);

    other.SeekStart();

    unsigned char* pData = new unsigned char[size_t(min(iDataSize,
                                                        BLOCK_COPY_SIZE))];
    for (UINT64 i = 0;i<iDataSize;i+=BLOCK_COPY_SIZE) {
      UINT64 iCopySize = min(BLOCK_COPY_SIZE, iDataSize-i);

      other.ReadRAW(pData, iCopySize);
      WriteRAW(pData, iCopySize);
    }
    delete [] pData;
  }
}

bool LargeRAWFile::Open(bool bReadWrite) {
  #ifdef _WIN32
  m_StreamFile = CreateFileA(m_strFilename.c_str(),
                             (bReadWrite) ? GENERIC_READ | GENERIC_WRITE
                                          : GENERIC_READ,
                             FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
    m_bIsOpen = m_StreamFile != INVALID_HANDLE_VALUE;
  #else
    m_StreamFile = fopen(m_strFilename.c_str(), (bReadWrite) ? "r+b" : "rb");
    if(m_StreamFile == NULL) {
      perror("fopen");
    }
    m_bIsOpen = m_StreamFile != NULL;
  #endif

  if (m_bIsOpen && m_iHeaderSize != 0) SeekStart();

  m_bWritable = (m_bIsOpen) ? bReadWrite : false;

  return m_bIsOpen;
}

bool LargeRAWFile::Create(UINT64 iInitialSize) {
#ifdef _WIN32
  m_StreamFile = CreateFileA(m_strFilename.c_str(),
                             GENERIC_READ | GENERIC_WRITE, 0, NULL,
                             CREATE_ALWAYS, 0, NULL);
  m_bIsOpen = m_StreamFile != INVALID_HANDLE_VALUE;
#else
  m_StreamFile = fopen(m_strFilename.c_str(), "w+b");
  m_bIsOpen = m_StreamFile != NULL;
#endif

  if (m_bIsOpen && iInitialSize>0) {
    SeekPos(iInitialSize-1);
    WriteData<unsigned char>(0,false);
    SeekStart();
  }

  return m_bIsOpen;
}

bool LargeRAWFile::Append() {
#ifdef _WIN32
  m_StreamFile = CreateFileA(m_strFilename.c_str(),
                             GENERIC_READ | GENERIC_WRITE, 0, NULL,
                             OPEN_ALWAYS, 0, NULL);
  m_bIsOpen = m_StreamFile != INVALID_HANDLE_VALUE;
#else
  m_StreamFile = fopen(m_strFilename.c_str(), "a+b");
  m_bIsOpen = m_StreamFile != NULL;
#endif

  if (m_bIsOpen) SeekEnd();

  return m_bIsOpen;
}

void LargeRAWFile::Close() {
  if (m_bIsOpen) {
    #ifdef _WIN32
        CloseHandle(m_StreamFile);
    #else
      fclose(m_StreamFile);
    #endif
    m_bIsOpen =false;
  }
}

UINT64 LargeRAWFile::GetCurrentSize() {
  UINT64 iPrevPos = GetPos();

  SeekStart();
  UINT64 ulStart = GetPos();
  UINT64 ulEnd   = SeekEnd();
  UINT64 ulFileLength = ulEnd - ulStart;

  SeekPos(iPrevPos);

  return ulFileLength;
}

void LargeRAWFile::SeekStart() {
  SeekPos(0);
}

UINT64 LargeRAWFile::SeekEnd() {
  #ifdef _WIN32
    LARGE_INTEGER liTarget, liRealTarget; liTarget.QuadPart = 0;
    SetFilePointerEx(m_StreamFile, liTarget, &liRealTarget, FILE_END);
    return UINT64(liRealTarget.QuadPart)-m_iHeaderSize;
  #else
    // get current position=file size!
    if(fseeko(m_StreamFile, 0, SEEK_END)==0)
      return ftello(m_StreamFile)-m_iHeaderSize;
    else
      return 0;
  #endif
}

UINT64 LargeRAWFile::GetPos() {
  #ifdef _WIN32
    LARGE_INTEGER liTarget, liRealTarget; liTarget.QuadPart = 0;
    SetFilePointerEx(m_StreamFile, liTarget, &liRealTarget, FILE_CURRENT);
    return UINT64(liRealTarget.QuadPart)-m_iHeaderSize;
  #else
    //get current position=file size!
    return ftello(m_StreamFile)-m_iHeaderSize;
  #endif
}

void LargeRAWFile::SeekPos(UINT64 iPos) {
  #ifdef _WIN32
    LARGE_INTEGER liTarget; liTarget.QuadPart = LONGLONG(iPos+m_iHeaderSize);
    SetFilePointerEx(m_StreamFile, liTarget, NULL, FILE_BEGIN);
  #else
    fseeko(m_StreamFile, off_t(iPos+m_iHeaderSize), SEEK_SET);
  #endif
}

size_t LargeRAWFile::ReadRAW(unsigned char* pData, UINT64 iCount) {
  #ifdef _WIN32
    DWORD dwReadBytes;
    ReadFile(m_StreamFile, pData, DWORD(iCount), &dwReadBytes, NULL);
    return dwReadBytes;
  #else
    return fread(pData,1,iCount,m_StreamFile);
  #endif
}

size_t LargeRAWFile::WriteRAW(const unsigned char* pData, UINT64 iCount) {
  #ifdef _WIN32
    DWORD dwWrittenBytes;
    WriteFile(m_StreamFile, pData, DWORD(iCount), &dwWrittenBytes, NULL);
    return dwWrittenBytes;
  #else
    return fwrite(pData,1,iCount,m_StreamFile);
  #endif
}

void LargeRAWFile::Delete() {
  if (m_bIsOpen) Close();
  remove(m_strFilename.c_str());
}

bool LargeRAWFile::Copy(const std::string& strSource,
                        const std::string& strTarget, UINT64 iSourceHeaderSkip,
                        std::string* strMessage) {
  std::wstring wstrSource(strSource.begin(), strSource.end());
  std::wstring wstrTarget(strTarget.begin(), strTarget.end());
  if (!strMessage)
    return Copy(wstrSource, wstrTarget, iSourceHeaderSkip, NULL);
  else {
    std::wstring wstrMessage;
    bool bResult = Copy(wstrSource, wstrTarget, iSourceHeaderSkip,
                        &wstrMessage);
    (*strMessage) = string(wstrMessage.begin(), wstrMessage.end());
    return bResult;
  }
}

bool LargeRAWFile::Copy(const std::wstring& wstrSource,
                        const std::wstring& wstrTarget,
                        UINT64 iSourceHeaderSkip, std::wstring* wstrMessage) {
  LargeRAWFile source(wstrSource, iSourceHeaderSkip);
  LargeRAWFile target(wstrTarget);

  source.Open(false);
  if (!source.IsOpen()) {
    if (wstrMessage) (*wstrMessage) = L"Unable to open source file " +
                                      wstrSource;
    return false;
  }

  target.Create();
  if (!target.IsOpen()) {
    if (wstrMessage) (*wstrMessage) = L"Unable to open target file " +
                                      wstrTarget;
    source.Close();
    return false;
  }

  UINT64 iFileSize = source.GetCurrentSize();
  UINT64 iCopySize = min(iFileSize,BLOCK_COPY_SIZE);
  unsigned char* pBuffer = new unsigned char[size_t(iCopySize)];

  do {
    iCopySize = source.ReadRAW(pBuffer, iCopySize);
    target.WriteRAW(pBuffer, iCopySize);
  } while (iCopySize>0);

  target.Close();
  source.Close();
  return true;
}

bool LargeRAWFile::Compare(const std::string& strFirstFile,
                           const std::string& strSecondFile,
                           std::string* strMessage) {
  std::wstring wstrFirstFile(strFirstFile.begin(), strFirstFile.end());
  std::wstring wstrSecondFile(strSecondFile.begin(), strSecondFile.end());
  if (!strMessage)
    return Compare(wstrFirstFile, wstrSecondFile, NULL);
  else {
    std::wstring wstrMessage;
    bool bResult = Compare(wstrFirstFile, wstrSecondFile, &wstrMessage);
    (*strMessage) = string(wstrMessage.begin(), wstrMessage.end());
    return bResult;
  }
}

bool LargeRAWFile::Compare(const std::wstring& wstrFirstFile,
                           const std::wstring& wstrSecondFile,
                           std::wstring* wstrMessage) {
  LargeRAWFile first(wstrFirstFile);
  LargeRAWFile second(wstrSecondFile);

  first.Open(false);
  if (!first.IsOpen()) {
    if (wstrMessage) (*wstrMessage) = L"Unable to open input file " +
                                      wstrFirstFile;
    return false;
  }
  second.Open(false);
  if (!second.IsOpen()) {
    if (wstrMessage) (*wstrMessage) = L"Unable to open input file " +
                                      wstrSecondFile;
    first.Close();
    return false;
  }

  if (first.GetCurrentSize() != second.GetCurrentSize()) {
    first.Close();
    second.Close();
    if (wstrMessage) (*wstrMessage) = L"Files differ in size";
    return false;
  }

  UINT64 iFileSize = first.GetCurrentSize();
  UINT64 iCopySize = min(iFileSize,BLOCK_COPY_SIZE/2);
  unsigned char* pBuffer1 = new unsigned char[size_t(iCopySize)];
  unsigned char* pBuffer2 = new unsigned char[size_t(iCopySize)];
  UINT64 iCopiedSize = 0;
  UINT64 iDiffCount = 0;

  if (wstrMessage) (*wstrMessage) = L"";

  do {
    iCopySize = first.ReadRAW(pBuffer1, iCopySize);
    second.ReadRAW(pBuffer2, iCopySize);

    for (UINT64 i = 0;i<iCopySize;i++) {
      if (pBuffer1[i] != pBuffer2[i]) {
        if (wstrMessage) {
          wstringstream ss;
          if (iDiffCount == 0) {
            ss << L"Files differ at address " << i+iCopiedSize;
            iDiffCount = 1;
          } else {
            // don't report more than 10 differences.
            if (++iDiffCount == 10) {
              (*wstrMessage) += L" and more";
              delete [] pBuffer1;
              delete [] pBuffer2;
              first.Close();
              second.Close();
              return false;
            } else {
              ss << L", " << i+iCopiedSize;
            }
          }
          (*wstrMessage) +=ss.str();
        }
      }

    }
    iCopiedSize += iCopySize;
  } while (iCopySize > 0);

  first.Close();
  second.Close();
  delete [] pBuffer1;
  delete [] pBuffer2;
  return iDiffCount == 0;
}
<commit_msg>Indentation.<commit_after>#include "LargeRAWFile.h"
#include <sstream>

using namespace std;

LargeRAWFile::LargeRAWFile(const std::string& strFilename, UINT64 iHeaderSize):
  m_strFilename(strFilename),
  m_bIsOpen(false),
  m_bWritable(false),
  m_iHeaderSize(iHeaderSize)
{
}

LargeRAWFile::LargeRAWFile(const std::wstring& wstrFilename, UINT64 iHeaderSize):
  m_bIsOpen(false),
  m_bWritable(false),
  m_iHeaderSize(iHeaderSize)
{
  string strFilename(wstrFilename.begin(), wstrFilename.end());
  m_strFilename = strFilename;
}

LargeRAWFile::LargeRAWFile(LargeRAWFile &other) :
  m_strFilename(other.m_strFilename),
  m_bIsOpen(other.m_bIsOpen),
  m_bWritable(other.m_bWritable),
  m_iHeaderSize(other.m_iHeaderSize)
{
  /// @todo !?!? need a better fix, a copy constructor shouldn't be expensive.
  if (m_bIsOpen && m_bWritable) {
    m_strFilename += "~";
    UINT64 iDataSize = other.GetCurrentSize();
    Create(iDataSize);

    other.SeekStart();

    unsigned char* pData = new unsigned char[size_t(min(iDataSize,
                                                        BLOCK_COPY_SIZE))];
    for (UINT64 i = 0;i<iDataSize;i+=BLOCK_COPY_SIZE) {
      UINT64 iCopySize = min(BLOCK_COPY_SIZE, iDataSize-i);

      other.ReadRAW(pData, iCopySize);
      WriteRAW(pData, iCopySize);
    }
    delete [] pData;
  }
}

bool LargeRAWFile::Open(bool bReadWrite) {
  #ifdef _WIN32
  m_StreamFile = CreateFileA(m_strFilename.c_str(),
                             (bReadWrite) ? GENERIC_READ | GENERIC_WRITE
                                          : GENERIC_READ,
                             FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
    m_bIsOpen = m_StreamFile != INVALID_HANDLE_VALUE;
  #else
    m_StreamFile = fopen(m_strFilename.c_str(), (bReadWrite) ? "r+b" : "rb");
    if(m_StreamFile == NULL) {
      perror("fopen");
    }
    m_bIsOpen = m_StreamFile != NULL;
  #endif

  if (m_bIsOpen && m_iHeaderSize != 0) SeekStart();

  m_bWritable = (m_bIsOpen) ? bReadWrite : false;

  return m_bIsOpen;
}

bool LargeRAWFile::Create(UINT64 iInitialSize) {
#ifdef _WIN32
  m_StreamFile = CreateFileA(m_strFilename.c_str(),
                             GENERIC_READ | GENERIC_WRITE, 0, NULL,
                             CREATE_ALWAYS, 0, NULL);
  m_bIsOpen = m_StreamFile != INVALID_HANDLE_VALUE;
#else
  m_StreamFile = fopen(m_strFilename.c_str(), "w+b");
  m_bIsOpen = m_StreamFile != NULL;
#endif

  if (m_bIsOpen && iInitialSize>0) {
    SeekPos(iInitialSize-1);
    WriteData<unsigned char>(0,false);
    SeekStart();
  }

  return m_bIsOpen;
}

bool LargeRAWFile::Append() {
#ifdef _WIN32
  m_StreamFile = CreateFileA(m_strFilename.c_str(),
                             GENERIC_READ | GENERIC_WRITE, 0, NULL,
                             OPEN_ALWAYS, 0, NULL);
  m_bIsOpen = m_StreamFile != INVALID_HANDLE_VALUE;
#else
  m_StreamFile = fopen(m_strFilename.c_str(), "a+b");
  m_bIsOpen = m_StreamFile != NULL;
#endif

  if (m_bIsOpen) SeekEnd();

  return m_bIsOpen;
}

void LargeRAWFile::Close() {
  if (m_bIsOpen) {
#ifdef _WIN32
    CloseHandle(m_StreamFile);
#else
    fclose(m_StreamFile);
#endif
    m_bIsOpen =false;
  }
}

UINT64 LargeRAWFile::GetCurrentSize() {
  UINT64 iPrevPos = GetPos();

  SeekStart();
  UINT64 ulStart = GetPos();
  UINT64 ulEnd   = SeekEnd();
  UINT64 ulFileLength = ulEnd - ulStart;

  SeekPos(iPrevPos);

  return ulFileLength;
}

void LargeRAWFile::SeekStart() {
  SeekPos(0);
}

UINT64 LargeRAWFile::SeekEnd() {
  #ifdef _WIN32
    LARGE_INTEGER liTarget, liRealTarget; liTarget.QuadPart = 0;
    SetFilePointerEx(m_StreamFile, liTarget, &liRealTarget, FILE_END);
    return UINT64(liRealTarget.QuadPart)-m_iHeaderSize;
  #else
    // get current position=file size!
    if(fseeko(m_StreamFile, 0, SEEK_END)==0)
      return ftello(m_StreamFile)-m_iHeaderSize;
    else
      return 0;
  #endif
}

UINT64 LargeRAWFile::GetPos() {
  #ifdef _WIN32
    LARGE_INTEGER liTarget, liRealTarget; liTarget.QuadPart = 0;
    SetFilePointerEx(m_StreamFile, liTarget, &liRealTarget, FILE_CURRENT);
    return UINT64(liRealTarget.QuadPart)-m_iHeaderSize;
  #else
    //get current position=file size!
    return ftello(m_StreamFile)-m_iHeaderSize;
  #endif
}

void LargeRAWFile::SeekPos(UINT64 iPos) {
  #ifdef _WIN32
    LARGE_INTEGER liTarget; liTarget.QuadPart = LONGLONG(iPos+m_iHeaderSize);
    SetFilePointerEx(m_StreamFile, liTarget, NULL, FILE_BEGIN);
  #else
    fseeko(m_StreamFile, off_t(iPos+m_iHeaderSize), SEEK_SET);
  #endif
}

size_t LargeRAWFile::ReadRAW(unsigned char* pData, UINT64 iCount) {
  #ifdef _WIN32
    DWORD dwReadBytes;
    ReadFile(m_StreamFile, pData, DWORD(iCount), &dwReadBytes, NULL);
    return dwReadBytes;
  #else
    return fread(pData,1,iCount,m_StreamFile);
  #endif
}

size_t LargeRAWFile::WriteRAW(const unsigned char* pData, UINT64 iCount) {
  #ifdef _WIN32
    DWORD dwWrittenBytes;
    WriteFile(m_StreamFile, pData, DWORD(iCount), &dwWrittenBytes, NULL);
    return dwWrittenBytes;
  #else
    return fwrite(pData,1,iCount,m_StreamFile);
  #endif
}

void LargeRAWFile::Delete() {
  if (m_bIsOpen) Close();
  remove(m_strFilename.c_str());
}

bool LargeRAWFile::Copy(const std::string& strSource,
                        const std::string& strTarget, UINT64 iSourceHeaderSkip,
                        std::string* strMessage) {
  std::wstring wstrSource(strSource.begin(), strSource.end());
  std::wstring wstrTarget(strTarget.begin(), strTarget.end());
  if (!strMessage)
    return Copy(wstrSource, wstrTarget, iSourceHeaderSkip, NULL);
  else {
    std::wstring wstrMessage;
    bool bResult = Copy(wstrSource, wstrTarget, iSourceHeaderSkip,
                        &wstrMessage);
    (*strMessage) = string(wstrMessage.begin(), wstrMessage.end());
    return bResult;
  }
}

bool LargeRAWFile::Copy(const std::wstring& wstrSource,
                        const std::wstring& wstrTarget,
                        UINT64 iSourceHeaderSkip, std::wstring* wstrMessage) {
  LargeRAWFile source(wstrSource, iSourceHeaderSkip);
  LargeRAWFile target(wstrTarget);

  source.Open(false);
  if (!source.IsOpen()) {
    if (wstrMessage) (*wstrMessage) = L"Unable to open source file " +
                                      wstrSource;
    return false;
  }

  target.Create();
  if (!target.IsOpen()) {
    if (wstrMessage) (*wstrMessage) = L"Unable to open target file " +
                                      wstrTarget;
    source.Close();
    return false;
  }

  UINT64 iFileSize = source.GetCurrentSize();
  UINT64 iCopySize = min(iFileSize,BLOCK_COPY_SIZE);
  unsigned char* pBuffer = new unsigned char[size_t(iCopySize)];

  do {
    iCopySize = source.ReadRAW(pBuffer, iCopySize);
    target.WriteRAW(pBuffer, iCopySize);
  } while (iCopySize>0);

  target.Close();
  source.Close();
  return true;
}

bool LargeRAWFile::Compare(const std::string& strFirstFile,
                           const std::string& strSecondFile,
                           std::string* strMessage) {
  std::wstring wstrFirstFile(strFirstFile.begin(), strFirstFile.end());
  std::wstring wstrSecondFile(strSecondFile.begin(), strSecondFile.end());
  if (!strMessage)
    return Compare(wstrFirstFile, wstrSecondFile, NULL);
  else {
    std::wstring wstrMessage;
    bool bResult = Compare(wstrFirstFile, wstrSecondFile, &wstrMessage);
    (*strMessage) = string(wstrMessage.begin(), wstrMessage.end());
    return bResult;
  }
}

bool LargeRAWFile::Compare(const std::wstring& wstrFirstFile,
                           const std::wstring& wstrSecondFile,
                           std::wstring* wstrMessage) {
  LargeRAWFile first(wstrFirstFile);
  LargeRAWFile second(wstrSecondFile);

  first.Open(false);
  if (!first.IsOpen()) {
    if (wstrMessage) (*wstrMessage) = L"Unable to open input file " +
                                      wstrFirstFile;
    return false;
  }
  second.Open(false);
  if (!second.IsOpen()) {
    if (wstrMessage) (*wstrMessage) = L"Unable to open input file " +
                                      wstrSecondFile;
    first.Close();
    return false;
  }

  if (first.GetCurrentSize() != second.GetCurrentSize()) {
    first.Close();
    second.Close();
    if (wstrMessage) (*wstrMessage) = L"Files differ in size";
    return false;
  }

  UINT64 iFileSize = first.GetCurrentSize();
  UINT64 iCopySize = min(iFileSize,BLOCK_COPY_SIZE/2);
  unsigned char* pBuffer1 = new unsigned char[size_t(iCopySize)];
  unsigned char* pBuffer2 = new unsigned char[size_t(iCopySize)];
  UINT64 iCopiedSize = 0;
  UINT64 iDiffCount = 0;

  if (wstrMessage) (*wstrMessage) = L"";

  do {
    iCopySize = first.ReadRAW(pBuffer1, iCopySize);
    second.ReadRAW(pBuffer2, iCopySize);

    for (UINT64 i = 0;i<iCopySize;i++) {
      if (pBuffer1[i] != pBuffer2[i]) {
        if (wstrMessage) {
          wstringstream ss;
          if (iDiffCount == 0) {
            ss << L"Files differ at address " << i+iCopiedSize;
            iDiffCount = 1;
          } else {
            // don't report more than 10 differences.
            if (++iDiffCount == 10) {
              (*wstrMessage) += L" and more";
              delete [] pBuffer1;
              delete [] pBuffer2;
              first.Close();
              second.Close();
              return false;
            } else {
              ss << L", " << i+iCopiedSize;
            }
          }
          (*wstrMessage) +=ss.str();
        }
      }

    }
    iCopiedSize += iCopySize;
  } while (iCopySize > 0);

  first.Close();
  second.Close();
  delete [] pBuffer1;
  delete [] pBuffer2;
  return iDiffCount == 0;
}
<|endoftext|>


<commit_before>//===-- sanitizer_flags.cc ------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file is a part of ThreadSanitizer/AddressSanitizer runtime.
//
//===----------------------------------------------------------------------===//

#include "sanitizer_flags.h"

#include "sanitizer_common.h"
#include "sanitizer_libc.h"

namespace __sanitizer {

void ParseCommonFlagsFromString(const char *str) {
  CommonFlags *f = common_flags();
  ParseFlag(str, &f->malloc_context_size, "malloc_context_size");
  ParseFlag(str, &f->strip_path_prefix, "strip_path_prefix");
  ParseFlag(str, &f->fast_unwind_on_fatal, "fast_unwind_on_fatal");
  ParseFlag(str, &f->fast_unwind_on_malloc, "fast_unwind_on_malloc");
  ParseFlag(str, &f->symbolize, "symbolize");
  ParseFlag(str, &f->handle_ioctl, "handle_ioctl");
  ParseFlag(str, &f->log_path, "log_path");
  ParseFlag(str, &f->verbosity, "verbosity");
  ParseFlag(str, &f->detect_leaks, "detect_leaks");
  ParseFlag(str, &f->leak_check_at_exit, "leak_check_at_exit");
  ParseFlag(str, &f->allocator_may_return_null, "allocator_may_return_null");

  // Do a sanity check for certain flags.
  if (f->malloc_context_size < 1)
    f->malloc_context_size = 1;
}

static bool GetFlagValue(const char *env, const char *name,
                         const char **value, int *value_length) {
  if (env == 0)
    return false;
  const char *pos = 0;
  for (;;) {
    pos = internal_strstr(env, name);
    if (pos == 0)
      return false;
    if (pos != env && ((pos[-1] >= 'a' && pos[-1] <= 'z') || pos[-1] == '_')) {
      // Seems to be middle of another flag name or value.
      env = pos + 1;
      continue;
    }
    break;
  }
  pos += internal_strlen(name);
  const char *end;
  if (pos[0] != '=') {
    end = pos;
  } else {
    pos += 1;
    if (pos[0] == '"') {
      pos += 1;
      end = internal_strchr(pos, '"');
    } else if (pos[0] == '\'') {
      pos += 1;
      end = internal_strchr(pos, '\'');
    } else {
      // Read until the next space or colon.
      end = pos + internal_strcspn(pos, " :");
    }
    if (end == 0)
      end = pos + internal_strlen(pos);
  }
  *value = pos;
  *value_length = end - pos;
  return true;
}

static bool StartsWith(const char *flag, int flag_length, const char *value) {
  if (!flag || !value)
    return false;
  int value_length = internal_strlen(value);
  return (flag_length >= value_length) &&
         (0 == internal_strncmp(flag, value, value_length));
}

void ParseFlag(const char *env, bool *flag, const char *name) {
  const char *value;
  int value_length;
  if (!GetFlagValue(env, name, &value, &value_length))
    return;
  if (StartsWith(value, value_length, "0") ||
      StartsWith(value, value_length, "no") ||
      StartsWith(value, value_length, "false"))
    *flag = false;
  if (StartsWith(value, value_length, "1") ||
      StartsWith(value, value_length, "yes") ||
      StartsWith(value, value_length, "true"))
    *flag = true;
}

void ParseFlag(const char *env, int *flag, const char *name) {
  const char *value;
  int value_length;
  if (!GetFlagValue(env, name, &value, &value_length))
    return;
  *flag = static_cast<int>(internal_atoll(value));
}

static LowLevelAllocator allocator_for_flags;

void ParseFlag(const char *env, const char **flag, const char *name) {
  const char *value;
  int value_length;
  if (!GetFlagValue(env, name, &value, &value_length))
    return;
  // Copy the flag value. Don't use locks here, as flags are parsed at
  // tool startup.
  char *value_copy = (char*)(allocator_for_flags.Allocate(value_length + 1));
  internal_memcpy(value_copy, value, value_length);
  value_copy[value_length] = '\0';
  *flag = value_copy;
}

}  // namespace __sanitizer
<commit_msg>tsan: parse symbolize/external_symbolizer_path common flags<commit_after>//===-- sanitizer_flags.cc ------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file is a part of ThreadSanitizer/AddressSanitizer runtime.
//
//===----------------------------------------------------------------------===//

#include "sanitizer_flags.h"

#include "sanitizer_common.h"
#include "sanitizer_libc.h"

namespace __sanitizer {

void ParseCommonFlagsFromString(const char *str) {
  CommonFlags *f = common_flags();
  ParseFlag(str, &f->symbolize, "symbolize");
  ParseFlag(str, &f->external_symbolizer_path, "external_symbolizer_path");
  ParseFlag(str, &f->malloc_context_size, "malloc_context_size");
  ParseFlag(str, &f->strip_path_prefix, "strip_path_prefix");
  ParseFlag(str, &f->fast_unwind_on_fatal, "fast_unwind_on_fatal");
  ParseFlag(str, &f->fast_unwind_on_malloc, "fast_unwind_on_malloc");
  ParseFlag(str, &f->symbolize, "symbolize");
  ParseFlag(str, &f->handle_ioctl, "handle_ioctl");
  ParseFlag(str, &f->log_path, "log_path");
  ParseFlag(str, &f->verbosity, "verbosity");
  ParseFlag(str, &f->detect_leaks, "detect_leaks");
  ParseFlag(str, &f->leak_check_at_exit, "leak_check_at_exit");
  ParseFlag(str, &f->allocator_may_return_null, "allocator_may_return_null");

  // Do a sanity check for certain flags.
  if (f->malloc_context_size < 1)
    f->malloc_context_size = 1;
}

static bool GetFlagValue(const char *env, const char *name,
                         const char **value, int *value_length) {
  if (env == 0)
    return false;
  const char *pos = 0;
  for (;;) {
    pos = internal_strstr(env, name);
    if (pos == 0)
      return false;
    if (pos != env && ((pos[-1] >= 'a' && pos[-1] <= 'z') || pos[-1] == '_')) {
      // Seems to be middle of another flag name or value.
      env = pos + 1;
      continue;
    }
    break;
  }
  pos += internal_strlen(name);
  const char *end;
  if (pos[0] != '=') {
    end = pos;
  } else {
    pos += 1;
    if (pos[0] == '"') {
      pos += 1;
      end = internal_strchr(pos, '"');
    } else if (pos[0] == '\'') {
      pos += 1;
      end = internal_strchr(pos, '\'');
    } else {
      // Read until the next space or colon.
      end = pos + internal_strcspn(pos, " :");
    }
    if (end == 0)
      end = pos + internal_strlen(pos);
  }
  *value = pos;
  *value_length = end - pos;
  return true;
}

static bool StartsWith(const char *flag, int flag_length, const char *value) {
  if (!flag || !value)
    return false;
  int value_length = internal_strlen(value);
  return (flag_length >= value_length) &&
         (0 == internal_strncmp(flag, value, value_length));
}

void ParseFlag(const char *env, bool *flag, const char *name) {
  const char *value;
  int value_length;
  if (!GetFlagValue(env, name, &value, &value_length))
    return;
  if (StartsWith(value, value_length, "0") ||
      StartsWith(value, value_length, "no") ||
      StartsWith(value, value_length, "false"))
    *flag = false;
  if (StartsWith(value, value_length, "1") ||
      StartsWith(value, value_length, "yes") ||
      StartsWith(value, value_length, "true"))
    *flag = true;
}

void ParseFlag(const char *env, int *flag, const char *name) {
  const char *value;
  int value_length;
  if (!GetFlagValue(env, name, &value, &value_length))
    return;
  *flag = static_cast<int>(internal_atoll(value));
}

static LowLevelAllocator allocator_for_flags;

void ParseFlag(const char *env, const char **flag, const char *name) {
  const char *value;
  int value_length;
  if (!GetFlagValue(env, name, &value, &value_length))
    return;
  // Copy the flag value. Don't use locks here, as flags are parsed at
  // tool startup.
  char *value_copy = (char*)(allocator_for_flags.Allocate(value_length + 1));
  internal_memcpy(value_copy, value, value_length);
  value_copy[value_length] = '\0';
  *flag = value_copy;
}

}  // namespace __sanitizer
<|endoftext|>


<commit_before>/*
  Copyright (c) 1999 - 2007 Simon Peter <dn.tlp@gmx.net>
  Copyright (c) 2002 Nikita V. Kalaganov <riven@ok.ru>

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#include "plugin.h"

#ifdef DEBUG
#	include "debug.h"
#endif

HINSTANCE		myInstance;
HWND			*myWindow;

extern In_Module	mod;

Config			config;
FileTypes		filetypes;
MyPlayer		my_player;
GuiDlgAbout		dlg_about;
GuiDlgConfig		dlg_config;
GuiDlgInfo		dlg_info;

void wa2_Init()
{
  myInstance = mod.hDllInstance;
  myWindow = &mod.hMainWindow;
}

void wa2_Quit()
{
  free(mod.FileExtensions);
  config.set_ignored(filetypes.get_ignore_list());
  config.save();
}

int wa2_IsOurFile(char *fn)
{
  // ignored ?
  if (filetypes.grata(fn))
    {
      CSilentopl silent;

      // try to make adplug player
      CPlayer *p = CAdPlug::factory(fn,&silent);

      if (p)
	{
	  delete p;
	  return 1;
	}
    }

  return 0;
}

void wa2_GetFileInfo(char *file, char *title, int *length_in_ms)
{
  const char *my_file;

  // current file ?
  if ((!file) || (!(*file)))
    my_file = my_player.get_file();
  else
    {
      // our file ?
      if (!wa2_IsOurFile(file))
	return;

      my_file = file;
    }

  // set default info
  if (title)
    strcpy(title,strrchr(my_file,'\\')+1);

  if (length_in_ms)
    *length_in_ms = 0;

  // try to get real info
  CSilentopl silent;

  CPlayer *p = CAdPlug::factory(my_file,&silent);

  if (p)
    {
      if (title)
	if (!p->gettitle().empty())
	  strcpy(title,p->gettitle().c_str());

      if (length_in_ms)
	if (file)
	  *length_in_ms = my_player.get_length(my_file,my_player.get_subsong());
	else
	  *length_in_ms = my_player.get_length(my_file,DFL_SUBSONG);

      delete p;
    }
}

int wa2_Play(char *fn)
{
  return my_player.play(fn);
}

void wa2_Pause()
{
  my_player.pause();
}

void wa2_UnPause()
{
  my_player.unpause();
}

int wa2_IsPaused()
{
  return my_player.is_paused();
}

void wa2_Stop()
{
  my_player.stop();
}

int wa2_GetLength()
{
  return my_player.get_length();
}

int wa2_GetOutputTime()
{
  return my_player.get_position();
}

void wa2_SetOutputTime(int time_in_ms)
{
  my_player.seek(time_in_ms);
}

void wa2_SetVolume(int volume)
{
  my_player.set_volume(volume);
}

void wa2_SetPan(int pan)
{
  my_player.set_panning(pan);
}

void wa2_EqSet(int on, char data[10], int preamp)
{
  return;
}

void wa2_DlgAbout(HWND hwndParent)
{
  dlg_about.open(hwndParent);
}

void wa2_DlgConfig(HWND hwndParent)
{
  dlg_config.open(hwndParent);
}

int wa2_DlgInfo(char *file, HWND hwndParent)
{
  return dlg_info.open(file,hwndParent);
}

extern "C" __declspec(dllexport) bool winampGetExtendedFileInfo(char *file, char *meta, char *ret, int retlen)
{
  if (ret == NULL || !retlen) return false;

  const char *my_file;

  // current file ?
  if ((!file) || (!(*file)))
    my_file = my_player.get_file();
  else
  {
    // our file ?
    if (!wa2_IsOurFile(file))
      return false;

    my_file = file;
  }

  CSilentopl silent;

  CPlayer *p = CAdPlug::factory(my_file, &silent);
  if (!p) return false;

  // default to a blank string
  *ret = L'\0';
  bool result = false;

  if (!stricmp(meta, "title"))
  {
    result = !p->gettitle().empty() && ((int)p->gettitle().length() < retlen);
    if (result)
      strcpy(ret, p->gettitle().c_str());
  }
  else if (!stricmp(meta, "artist"))
  {
    result = !p->getauthor().empty() && ((int)p->getauthor().length() < retlen);
    if (result)
      strcpy(ret, p->getauthor().c_str());
  }
  else if (!stricmp(meta, "comment"))
  {
    result = !p->getdesc().empty() && ((int)p->getdesc().length() < retlen);
    if (result)
      strcpy(ret, p->getdesc().c_str());
  }
  else if (!stricmp(meta, "family") || !stricmp(meta, "genre"))
  {
    result = !p->gettype().empty() && ((int)p->gettype().length() < retlen);
    if (result)
      strcpy(ret, p->gettype().c_str());
  }
  else if (!stricmp(meta, "length"))
  {
    int length_in_ms;
    if (file)
      length_in_ms = my_player.get_length(my_file, my_player.get_subsong());
    else
      length_in_ms = my_player.get_length(my_file, DFL_SUBSONG);
    sprintf(ret, "%d", length_in_ms);
    result = true;
  }
  else if (!stricmp(meta, "type"))
  {
    ret[0] = '0'; // Audio
    ret[1] = 0;
    result = true;
  }

  delete p;
  return result;
}

In_Module mod =
  {
    IN_VER,
    PLUGIN_VER,
    0,
    0,
    0,
    1,
    1,
    wa2_DlgConfig,
    wa2_DlgAbout,
    wa2_Init,
    wa2_Quit,
    wa2_GetFileInfo,
    wa2_DlgInfo,
    wa2_IsOurFile,
    wa2_Play,
    wa2_Pause,
    wa2_UnPause,
    wa2_IsPaused,
    wa2_Stop,
    wa2_GetLength,
    wa2_GetOutputTime,
    wa2_SetOutputTime,
    wa2_SetVolume,
    wa2_SetPan,
    0,0,0,0,0,0,0,0,0,
    0,0,
    wa2_EqSet,
    0,
    0
  };

extern "C" __declspec(dllexport) In_Module *winampGetInModule2()
{
  t_config_data	cfg;

#ifdef DEBUG
  debug_init();
#endif
  config.load();
  config.get(&cfg);

  mod.UsesOutputPlug = config.useoutputplug;

  filetypes.add("a2m", "Adlib Tracker 2 Modules (*.A2M)");
  filetypes.add("adl", "Westwood ADL Files (*.ADL)");
  filetypes.add("amd", "AMUSIC Modules (*.AMD)");
  filetypes.add("bam", "Bob's Adlib Music Files (*.BAM)");
  filetypes.add("cff", "BoomTracker 4 Modules (*.CFF)");
  filetypes.add("cmf", "Creative Adlib Music Files (*.CMF)");
  filetypes.add("cmf", "SoundFX Macs Opera (*.CMF)");
  filetypes.add("d00", "Packed EdLib Modules (*.D00)");
  filetypes.add("dfm", "Digital-FM Modules (*.DFM)");
  filetypes.add("dmo", "TwinTeam Modules (*.DMO)");
  filetypes.add("dro", "DOSBox Raw OPL v1.0 and v2.0 Files (*.DRO)");
  filetypes.add("dtm", "DeFy Adlib Tracker Modules (*.DTM)");
  filetypes.add("got", "God of Thunder Music (*.GOT)");
  filetypes.add("hsc", "HSC-Tracker Modules (*.HSC)");
  filetypes.add("hsp", "Packed HSC-Tracker Modules (*.HSP)");
  filetypes.add("imf;wlf;adlib", "Apogee IMF Files (*.IMF;*.WLF;*.ADLIB)");
  filetypes.add("ims", "IMPlay Song Files (*.IMS)");
  filetypes.add("jbm", "JBM Adlib Music Files (*.JBM)");
  filetypes.add("ksm", "Ken Silverman's Music Files (*.KSM)");
  filetypes.add("laa", "LucasArts Adlib Audio Files (*.LAA)");
  filetypes.add("lds", "LOUDNESS Sound System Files (*.LDS)");
  filetypes.add("m", "Ultima 6 Music Files (*.M)");
  filetypes.add("mad", "Mlat Adlib Tracker Modules (*.MAD)");
  filetypes.add("mdi", "AdLib MIDIPlay Files (*.MDI)");
  filetypes.add("mid;kar", "MIDI Audio Files (*.MID;*.KAR)");
  filetypes.add("mkj", "MKJamz Audio Files (*.MKJ)");
  filetypes.add("msc", "AdLib MSCplay (*.MSC)");
  filetypes.add("mtk", "MPU-401 Trakker Modules (*.MTK)");
  filetypes.add("mus", "AdLib MIDI Music Files (*.MUS)");
  filetypes.add("rad", "Reality Adlib Tracker Modules (*.RAD)");
  filetypes.add("raw", "Rdos RAW Files (*.RAW)");
  filetypes.add("rix", "Softstar RIX OPL Music Files (*.RIX)");
  filetypes.add("rol", "Adlib Visual Composer Modules (*.ROL)");
  if(!cfg.s3m_workaround) {
    filetypes.add("s3m", "Scream Tracker 3 Modules (*.S3M)");
  }
  filetypes.add("sa2", "Surprise! Adlib Tracker 2 Modules (*.SA2)");
  filetypes.add("sat", "Surprise! Adlib Tracker Modules (*.SAT)");
  filetypes.add("sci", "Sierra Adlib Audio Files (*.SCI)");
  filetypes.add("sng", "Adlib Tracker 1.0 Modules (*.SNG)");
  filetypes.add("sng", "Faust Music Creator Modules (*.SNG)");
  filetypes.add("sng", "SNGPlay Files (*.SNG)");
  filetypes.add("xad", "eXotic Adlib Files (*.XAD)");
  filetypes.add("xms", "XMS-Tracker Modules (*.XMS)");
  filetypes.add("xsm", "eXtra Simple Music Files (*.XSM)");

  filetypes.set_ignore_list(config.get_ignored());

  mod.FileExtensions = filetypes.export_filetypes((char *)malloc(4096));

  return &mod;
}
<commit_msg>Add *.VGM extension<commit_after>/*
  Copyright (c) 1999 - 2007 Simon Peter <dn.tlp@gmx.net>
  Copyright (c) 2002 Nikita V. Kalaganov <riven@ok.ru>

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#include "plugin.h"

#ifdef DEBUG
#	include "debug.h"
#endif

HINSTANCE		myInstance;
HWND			*myWindow;

extern In_Module	mod;

Config			config;
FileTypes		filetypes;
MyPlayer		my_player;
GuiDlgAbout		dlg_about;
GuiDlgConfig		dlg_config;
GuiDlgInfo		dlg_info;

void wa2_Init()
{
  myInstance = mod.hDllInstance;
  myWindow = &mod.hMainWindow;
}

void wa2_Quit()
{
  free(mod.FileExtensions);
  config.set_ignored(filetypes.get_ignore_list());
  config.save();
}

int wa2_IsOurFile(char *fn)
{
  // ignored ?
  if (filetypes.grata(fn))
    {
      CSilentopl silent;

      // try to make adplug player
      CPlayer *p = CAdPlug::factory(fn,&silent);

      if (p)
	{
	  delete p;
	  return 1;
	}
    }

  return 0;
}

void wa2_GetFileInfo(char *file, char *title, int *length_in_ms)
{
  const char *my_file;

  // current file ?
  if ((!file) || (!(*file)))
    my_file = my_player.get_file();
  else
    {
      // our file ?
      if (!wa2_IsOurFile(file))
	return;

      my_file = file;
    }

  // set default info
  if (title)
    strcpy(title,strrchr(my_file,'\\')+1);

  if (length_in_ms)
    *length_in_ms = 0;

  // try to get real info
  CSilentopl silent;

  CPlayer *p = CAdPlug::factory(my_file,&silent);

  if (p)
    {
      if (title)
	if (!p->gettitle().empty())
	  strcpy(title,p->gettitle().c_str());

      if (length_in_ms)
	if (file)
	  *length_in_ms = my_player.get_length(my_file,my_player.get_subsong());
	else
	  *length_in_ms = my_player.get_length(my_file,DFL_SUBSONG);

      delete p;
    }
}

int wa2_Play(char *fn)
{
  return my_player.play(fn);
}

void wa2_Pause()
{
  my_player.pause();
}

void wa2_UnPause()
{
  my_player.unpause();
}

int wa2_IsPaused()
{
  return my_player.is_paused();
}

void wa2_Stop()
{
  my_player.stop();
}

int wa2_GetLength()
{
  return my_player.get_length();
}

int wa2_GetOutputTime()
{
  return my_player.get_position();
}

void wa2_SetOutputTime(int time_in_ms)
{
  my_player.seek(time_in_ms);
}

void wa2_SetVolume(int volume)
{
  my_player.set_volume(volume);
}

void wa2_SetPan(int pan)
{
  my_player.set_panning(pan);
}

void wa2_EqSet(int on, char data[10], int preamp)
{
  return;
}

void wa2_DlgAbout(HWND hwndParent)
{
  dlg_about.open(hwndParent);
}

void wa2_DlgConfig(HWND hwndParent)
{
  dlg_config.open(hwndParent);
}

int wa2_DlgInfo(char *file, HWND hwndParent)
{
  return dlg_info.open(file,hwndParent);
}

extern "C" __declspec(dllexport) bool winampGetExtendedFileInfo(char *file, char *meta, char *ret, int retlen)
{
  if (ret == NULL || !retlen) return false;

  const char *my_file;

  // current file ?
  if ((!file) || (!(*file)))
    my_file = my_player.get_file();
  else
  {
    // our file ?
    if (!wa2_IsOurFile(file))
      return false;

    my_file = file;
  }

  CSilentopl silent;

  CPlayer *p = CAdPlug::factory(my_file, &silent);
  if (!p) return false;

  // default to a blank string
  *ret = L'\0';
  bool result = false;

  if (!stricmp(meta, "title"))
  {
    result = !p->gettitle().empty() && ((int)p->gettitle().length() < retlen);
    if (result)
      strcpy(ret, p->gettitle().c_str());
  }
  else if (!stricmp(meta, "artist"))
  {
    result = !p->getauthor().empty() && ((int)p->getauthor().length() < retlen);
    if (result)
      strcpy(ret, p->getauthor().c_str());
  }
  else if (!stricmp(meta, "comment"))
  {
    result = !p->getdesc().empty() && ((int)p->getdesc().length() < retlen);
    if (result)
      strcpy(ret, p->getdesc().c_str());
  }
  else if (!stricmp(meta, "family") || !stricmp(meta, "genre"))
  {
    result = !p->gettype().empty() && ((int)p->gettype().length() < retlen);
    if (result)
      strcpy(ret, p->gettype().c_str());
  }
  else if (!stricmp(meta, "length"))
  {
    int length_in_ms;
    if (file)
      length_in_ms = my_player.get_length(my_file, my_player.get_subsong());
    else
      length_in_ms = my_player.get_length(my_file, DFL_SUBSONG);
    sprintf(ret, "%d", length_in_ms);
    result = true;
  }
  else if (!stricmp(meta, "type"))
  {
    ret[0] = '0'; // Audio
    ret[1] = 0;
    result = true;
  }

  delete p;
  return result;
}

In_Module mod =
  {
    IN_VER,
    PLUGIN_VER,
    0,
    0,
    0,
    1,
    1,
    wa2_DlgConfig,
    wa2_DlgAbout,
    wa2_Init,
    wa2_Quit,
    wa2_GetFileInfo,
    wa2_DlgInfo,
    wa2_IsOurFile,
    wa2_Play,
    wa2_Pause,
    wa2_UnPause,
    wa2_IsPaused,
    wa2_Stop,
    wa2_GetLength,
    wa2_GetOutputTime,
    wa2_SetOutputTime,
    wa2_SetVolume,
    wa2_SetPan,
    0,0,0,0,0,0,0,0,0,
    0,0,
    wa2_EqSet,
    0,
    0
  };

extern "C" __declspec(dllexport) In_Module *winampGetInModule2()
{
  t_config_data	cfg;

#ifdef DEBUG
  debug_init();
#endif
  config.load();
  config.get(&cfg);

  mod.UsesOutputPlug = config.useoutputplug;

  filetypes.add("a2m", "Adlib Tracker 2 Modules (*.A2M)");
  filetypes.add("adl", "Westwood ADL Files (*.ADL)");
  filetypes.add("amd", "AMUSIC Modules (*.AMD)");
  filetypes.add("bam", "Bob's Adlib Music Files (*.BAM)");
  filetypes.add("cff", "BoomTracker 4 Modules (*.CFF)");
  filetypes.add("cmf", "Creative Adlib Music Files (*.CMF)");
  filetypes.add("cmf", "SoundFX Macs Opera (*.CMF)");
  filetypes.add("d00", "Packed EdLib Modules (*.D00)");
  filetypes.add("dfm", "Digital-FM Modules (*.DFM)");
  filetypes.add("dmo", "TwinTeam Modules (*.DMO)");
  filetypes.add("dro", "DOSBox Raw OPL v1.0 and v2.0 Files (*.DRO)");
  filetypes.add("dtm", "DeFy Adlib Tracker Modules (*.DTM)");
  filetypes.add("got", "God of Thunder Music (*.GOT)");
  filetypes.add("hsc", "HSC-Tracker Modules (*.HSC)");
  filetypes.add("hsp", "Packed HSC-Tracker Modules (*.HSP)");
  filetypes.add("imf;wlf;adlib", "Apogee IMF Files (*.IMF;*.WLF;*.ADLIB)");
  filetypes.add("ims", "IMPlay Song Files (*.IMS)");
  filetypes.add("jbm", "JBM Adlib Music Files (*.JBM)");
  filetypes.add("ksm", "Ken Silverman's Music Files (*.KSM)");
  filetypes.add("laa", "LucasArts Adlib Audio Files (*.LAA)");
  filetypes.add("lds", "LOUDNESS Sound System Files (*.LDS)");
  filetypes.add("m", "Ultima 6 Music Files (*.M)");
  filetypes.add("mad", "Mlat Adlib Tracker Modules (*.MAD)");
  filetypes.add("mdi", "AdLib MIDIPlay Files (*.MDI)");
  filetypes.add("mid;kar", "MIDI Audio Files (*.MID;*.KAR)");
  filetypes.add("mkj", "MKJamz Audio Files (*.MKJ)");
  filetypes.add("msc", "AdLib MSCplay (*.MSC)");
  filetypes.add("mtk", "MPU-401 Trakker Modules (*.MTK)");
  filetypes.add("mus", "AdLib MIDI Music Files (*.MUS)");
  filetypes.add("rad", "Reality Adlib Tracker Modules (*.RAD)");
  filetypes.add("raw", "Rdos RAW Files (*.RAW)");
  filetypes.add("rix", "Softstar RIX OPL Music Files (*.RIX)");
  filetypes.add("rol", "Adlib Visual Composer Modules (*.ROL)");
  if(!cfg.s3m_workaround) {
    filetypes.add("s3m", "Scream Tracker 3 Modules (*.S3M)");
  }
  filetypes.add("sa2", "Surprise! Adlib Tracker 2 Modules (*.SA2)");
  filetypes.add("sat", "Surprise! Adlib Tracker Modules (*.SAT)");
  filetypes.add("sci", "Sierra Adlib Audio Files (*.SCI)");
  filetypes.add("sng", "Adlib Tracker 1.0 Modules (*.SNG)");
  filetypes.add("sng", "Faust Music Creator Modules (*.SNG)");
  filetypes.add("sng", "SNGPlay Files (*.SNG)");
  filetypes.add("vgm", "Video Game Music (*.VGM)");
  filetypes.add("xad", "eXotic Adlib Files (*.XAD)");
  filetypes.add("xms", "XMS-Tracker Modules (*.XMS)");
  filetypes.add("xsm", "eXtra Simple Music Files (*.XSM)");

  filetypes.set_ignore_list(config.get_ignored());

  mod.FileExtensions = filetypes.export_filetypes((char *)malloc(4096));

  return &mod;
}
<|endoftext|>


<commit_before>// Copyright (c) 2019 by Robert Bosch GmbH. All rights reserved.
// Copyright (c) 2021 - 2022 by Apex.AI Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// SPDX-License-Identifier: Apache-2.0
#ifndef IOX_HOOFS_CXX_OPTIONAL_HPP
#define IOX_HOOFS_CXX_OPTIONAL_HPP

#include "iceoryx_hoofs/cxx/functional_interface.hpp"
#include "iceoryx_hoofs/cxx/requires.hpp"
#include "iceoryx_hoofs/iceoryx_hoofs_types.hpp"

#include <new> // needed for placement new in the construct_value member function
#include <utility>

namespace iox
{
namespace cxx
{
/// @brief Helper struct which is used to signal an empty optional.
///         It is equivalent to no value.
struct nullopt_t
{
};
// AXIVION Next Construct AutosarC++19_03-M17.0.2 : nullopt is defined within iox::cxx namespace which prevents easy
// misuse
constexpr nullopt_t nullopt{nullopt_t()};

/// @brief helper struct which is used to call the in-place-construction constructor
struct in_place_t
{
};

// AXIVION Next Construct AutosarC++19_03-M17.0.2 : in_place is defined within iox::cxx namespace which prevents easy
// misuse
constexpr in_place_t in_place{};

/// @brief Optional implementation from the C++17 standard with C++11. The
///         interface is analog to the C++17 standard and it can be used in
///         factory functions which can fail.
///
/// @code
///     #include "iceoryx_hoofs/cxx/optional.hpp"
///
///     cxx::optional<void*> SomeFactory() {
///         void *memory = malloc(1234);
///         if ( memory == nullptr )
///             return cxx::nullopt_t();
///         else
///             return cxx::make_optional<void*>(memory);
///     }
///
///     int main() {
///         auto var = SomeFactory();
///         // never forget the has_value call before working with an optional
///         if ( var.has_value() ) {
///             // do stuff with var
///         }
///     }
/// @endcode
template <typename T>
class optional final : public FunctionalInterface<optional<T>, T, void>
{
  public:
    using type = T;

    /// @brief Creates an optional which has no value. If you access such an
    ///         optional via .value() or the arrow operator the application
    ///         terminates.
    optional() noexcept;

    /// @brief Creates an optional which has no value. If you access such an
    ///         optional via .value() or the arrow operator the application
    ///         terminates.
    // NOLINTNEXTLINE(hicpp-explicit-conversions) for justification see doxygen
    optional(const nullopt_t) noexcept;

    /// @brief Creates an optional by forwarding value to the constructor of
    ///         T. This optional has a value.
    /// @param[in] value rvalue of type T which will be moved into the optional
    // NOLINTNEXTLINE(hicpp-explicit-conversions) for justification see doxygen
    optional(T&& value) noexcept;

    /// @brief Creates an optional by using the copy constructor of T.
    /// @param[in] value lvalue of type T which will be copy constructed into the optional
    // NOLINTNEXTLINE(hicpp-explicit-conversions) for justification see doxygen
    optional(const T& value) noexcept;

    /// @brief Creates an optional and an object inside the optional on construction by perfectly forwarding args to the
    /// constructor of T. Could be used e.g. when T is not copyable/movable.
    /// @tparam Targs is the template parameter pack for the perfectly forwarded arguments
    /// @param[in] in_place_t compile time variable to distinguish between constructors with certain behavior
    template <typename... Targs>
    // in_place_t is a compile time variable to call the in-place-construction
    // NOLINTNEXTLINE(hicpp-named-parameter, readability-named-parameter)
    explicit optional(in_place_t, Targs&&... args) noexcept;

    /// @brief The destructor will call the destructor of T if a value is set.
    ~optional() noexcept;

    /// @brief Constructs a value with the copy constructor if rhs has a value.
    ///         Otherwise it contains no value.
    /// @param[in] rhs source of the copy
    optional(const optional& rhs) noexcept;

    /// @brief Constructs a value with the move constructor if rhs has a value.
    ///         Otherwise it contains no value.
    /// @param[in] rhs source of the move
    optional(optional&& rhs) noexcept;

    /// @brief Copies an optional. If the optional has a value then the copy
    ///         assignment of that value is called. If the optional has no
    ///         value a new value is constructed with the copy constructor.
    /// @param[in] rhs source of the copy
    /// @return reference to the current optional
    optional& operator=(const optional& rhs) noexcept;

    /// @brief Moves an optional. If the optional has a value then the move
    ///         assignment of that value is called. If the optional has no
    ///         value a new value is constructed with the move constructor.
    /// @param[in] rhs source of the move
    /// @return reference to the current optional
    optional& operator=(optional&& rhs) noexcept;

    /// @brief Direct assignment of the underlying value. If the optional has no
    ///         value then a new T is constructed by forwarding the assignment to
    ///         T's constructor.
    ///        If the optional has a value the assignment operator of T is called.
    /// @param[in] value value to assign to the underlying optional value
    /// @return reference to the current optional
    template <typename U = T>
    // NOLINTNEXTLINE(cppcoreguidelines-c-copy-assignment-signature) return type is optional&
    typename std::enable_if<!std::is_same<U, optional<T>&>::value, optional>::type& operator=(U&& newValue) noexcept;

    /// @brief Returns a pointer to the underlying value. If the optional has no
    ///         value the application terminates. You need to verify that the
    ///         optional has a value by calling has_value() before using it.
    /// @return pointer of type const T to the underlying type
    const T* operator->() const noexcept;

    /// @brief Returns a reference to the underlying value. If the optional has no
    ///         value the application terminates. You need to verify that the
    ///         optional has a value by calling has_value() before using it.
    /// @return reference of type const T to the underlying type
    const T& operator*() const noexcept;

    /// @brief Returns a pointer to the underlying value. If the optional has no
    ///         value the application terminates. You need to verify that the
    ///         optional has a value by calling has_value() before using it.
    /// @return pointer of type T to the underlying type
    T* operator->() noexcept;

    /// @brief Returns a reference to the underlying value. If the optional has no
    ///         value the application terminates. You need to verify that the
    ///         optional has a value by calling has_value() before using it.
    /// @return reference of type T to the underlying type
    T& operator*() noexcept;

    /// @brief Will return true if the optional contains a value, otherwise false.
    /// @return true if optional contains a value, otherwise false
    // AXIVION Next Construct AutosarC++19_03-A13.5.3: designed implementation shall be as close
    // as std::optional and it requires operator bool
    constexpr explicit operator bool() const noexcept;

    /// @brief Will return true if the optional contains a value, otherwise false.
    /// @return true if optional contains a value, otherwise false
    constexpr bool has_value() const noexcept;

    /// @brief A new element is constructed by forwarding the arguments to the
    ///         constructor of T.
    ///         If the optional has a value then the destructor of T is called.
    /// @param[in] perfectly forwards args to the constructor of T to perform a placement
    ///             new
    /// @return reference to the underlying type
    template <typename... Targs>
    T& emplace(Targs&&... args) noexcept;

    /// @brief Calls the destructor of T if the optional has a value.
    ///         If the optional has no value, nothing happens. After that call
    ///         the optional has no more value.
    void reset() noexcept;

    /// @brief Returns a reference to the underlying value. If the optional has no
    ///         value the application terminates. You need to verify that the
    ///         optional has a value by calling has_value() before using it.
    /// @return reference to the underlying type
    T& value() & noexcept;

    /// @brief Returns a const reference to the underlying value. If the optional has no
    ///         value the application terminates. You need to verify that the
    ///         optional has a value by calling has_value() before using it.
    /// @return const reference to the underlying type
    const T& value() const& noexcept;

    /// @brief Returns a rvalue reference to the underlying value. If the optional has no
    ///         value the application terminates. You need to verify that the
    ///         optional has a value by calling has_value() before using it.
    /// @return rvalue reference to the underlying type
    T&& value() && noexcept;

    /// @brief Returns a const rvalue reference to the underlying value. If the optional has no
    ///         value the application terminates. You need to verify that the
    ///         optional has a value by calling has_value() before using it.
    /// @return const rvalue reference to the underlying type
    const T&& value() const&& noexcept;

  private:
    // the hasValue member should be first member in the memory layout to reveal casting
    // bugs early.
    //
    // See the following problem:
    //   void initHandle(void * ptr) {
    //     Handle * handle = static_cast<Handle>(ptr);
    //   }
    //   void doStuff(cxx::optional<Handle> & handle) {
    //     // uses optional<Handle> instead of handle, if the bool is the second parameter such
    //     // mistakes can be introduced quickly in low level c abstraction classes
    //     initHandle(&handle);
    //   }
    bool m_hasValue{false};

  private:
    // AXIVION Next Construct AutosarC++19_03-A18.1.1 : safe access is guaranteed since the array
    // is wrapped inside the optional
    // NOLINTNEXTLINE(hicpp-avoid-c-arrays, cppcoreguidelines-avoid-c-arrays)
    alignas(T) byte_t m_data[sizeof(T)];

  private:
    template <typename... Targs>
    void construct_value(Targs&&... args) noexcept;
    void destruct_value() noexcept;
};

// AXIVION Next Construct AutosarC++19_03-M17.0.3 : make_optional is defined within iox::cxx which prevents easy misuse
/// @brief Creates an optional which contains a value by forwarding the arguments
///         to the constructor of T.
/// @param[in] args arguments which will be perfectly forwarded to the constructor
///             of T
/// @return optional which contains T constructed with args
template <typename OptionalBaseType, typename... Targs>
optional<OptionalBaseType> make_optional(Targs&&... args) noexcept;

/// @brief Compare two optionals for equality.
/// @param[in] lhs cxx::optional
/// @param[in] rhs optional to which lhs should be compared to
/// @return true if the contained values are equal or both have no value, otherwise false
template <typename T>
bool operator==(const optional<T>& lhs, const optional<T>& rhs) noexcept;

/// @brief Compare two optionals for inequality.
/// @param[in] lhs cxx::optional
/// @param[in] rhs optional to which lhs should be compared to
/// @return true if the contained values are not equal, otherwise false
template <typename T>
bool operator!=(const optional<T>& lhs, const optional<T>& rhs) noexcept;

// AXIVION DISABLE STYLE AutosarC++19_03-A13.5.5: Comparison with nullopt_t is required
/// @brief Comparison for equality with nullopt_t for easier unset optional comparison
/// @param[in] lhs empty optional, cxx::nullopt_t
/// @param[in] rhs optional to which lhs should be compared to
/// @return true if the rhs is not set, otherwise false
template <typename T>
bool operator==(const nullopt_t, const optional<T>& rhs) noexcept;

/// @brief Comparison for equality with nullopt_t for easier unset optional comparison
/// @param[in] lhs optional which should be compared to cxx::nullopt_t
/// @param[in] rhs empty optional
/// @return true if the lhs is not set, otherwise false
template <typename T>
bool operator==(const optional<T>& lhs, const nullopt_t) noexcept;

/// @brief Comparison for inequality with nullopt_t for easier unset optional comparison
/// @param[in] lhs empty optional, cxx::nullopt_t
/// @param[in] rhs optional to which lhs should be compared to
/// @return true if the optional is set, otherwise false
template <typename T>
bool operator!=(const nullopt_t, const optional<T>& rhs) noexcept;

/// @brief Comparison for inequality with nullopt_t for easier unset optional comparison
/// @param[in] lhs optional which should be compared to cxx::nullopt_t
/// @param[in] rhs empty optional
/// @return true if the optional is set, otherwise false
template <typename T>
bool operator!=(const optional<T>& lhs, const nullopt_t) noexcept;
// AXIVION ENABLE STYLE AutosarC++19_03-A13.5.5
} // namespace cxx
} // namespace iox

#include "iceoryx_hoofs/internal/cxx/optional.inl"

#endif // IOX_HOOFS_CXX_OPTIONAL_HPP
<commit_msg>iox-#1394 Update axivion rule suppression justification<commit_after>// Copyright (c) 2019 by Robert Bosch GmbH. All rights reserved.
// Copyright (c) 2021 - 2022 by Apex.AI Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// SPDX-License-Identifier: Apache-2.0
#ifndef IOX_HOOFS_CXX_OPTIONAL_HPP
#define IOX_HOOFS_CXX_OPTIONAL_HPP

#include "iceoryx_hoofs/cxx/functional_interface.hpp"
#include "iceoryx_hoofs/cxx/requires.hpp"
#include "iceoryx_hoofs/iceoryx_hoofs_types.hpp"

#include <new> // needed for placement new in the construct_value member function
#include <utility>

namespace iox
{
namespace cxx
{
/// @brief Helper struct which is used to signal an empty optional.
///         It is equivalent to no value.
struct nullopt_t
{
};
// AXIVION Next Construct AutosarC++19_03-M17.0.2 : nullopt is defined within iox::cxx namespace which prevents easy
// misuse
constexpr nullopt_t nullopt{nullopt_t()};

/// @brief helper struct which is used to call the in-place-construction constructor
struct in_place_t
{
};

// AXIVION Next Construct AutosarC++19_03-M17.0.2 : in_place is defined within iox::cxx namespace which prevents easy
// misuse
constexpr in_place_t in_place{};

/// @brief Optional implementation from the C++17 standard with C++11. The
///         interface is analog to the C++17 standard and it can be used in
///         factory functions which can fail.
///
/// @code
///     #include "iceoryx_hoofs/cxx/optional.hpp"
///
///     cxx::optional<void*> SomeFactory() {
///         void *memory = malloc(1234);
///         if ( memory == nullptr )
///             return cxx::nullopt_t();
///         else
///             return cxx::make_optional<void*>(memory);
///     }
///
///     int main() {
///         auto var = SomeFactory();
///         // never forget the has_value call before working with an optional
///         if ( var.has_value() ) {
///             // do stuff with var
///         }
///     }
/// @endcode
template <typename T>
class optional final : public FunctionalInterface<optional<T>, T, void>
{
  public:
    using type = T;

    /// @brief Creates an optional which has no value. If you access such an
    ///         optional via .value() or the arrow operator the application
    ///         terminates.
    optional() noexcept;

    /// @brief Creates an optional which has no value. If you access such an
    ///         optional via .value() or the arrow operator the application
    ///         terminates.
    // NOLINTNEXTLINE(hicpp-explicit-conversions) for justification see doxygen
    optional(const nullopt_t) noexcept;

    /// @brief Creates an optional by forwarding value to the constructor of
    ///         T. This optional has a value.
    /// @param[in] value rvalue of type T which will be moved into the optional
    // NOLINTNEXTLINE(hicpp-explicit-conversions) for justification see doxygen
    optional(T&& value) noexcept;

    /// @brief Creates an optional by using the copy constructor of T.
    /// @param[in] value lvalue of type T which will be copy constructed into the optional
    // NOLINTNEXTLINE(hicpp-explicit-conversions) for justification see doxygen
    optional(const T& value) noexcept;

    /// @brief Creates an optional and an object inside the optional on construction by perfectly forwarding args to the
    /// constructor of T. Could be used e.g. when T is not copyable/movable.
    /// @tparam Targs is the template parameter pack for the perfectly forwarded arguments
    /// @param[in] in_place_t compile time variable to distinguish between constructors with certain behavior
    template <typename... Targs>
    // in_place_t is a compile time variable to call the in-place-construction
    // NOLINTNEXTLINE(hicpp-named-parameter, readability-named-parameter)
    explicit optional(in_place_t, Targs&&... args) noexcept;

    /// @brief The destructor will call the destructor of T if a value is set.
    ~optional() noexcept;

    /// @brief Constructs a value with the copy constructor if rhs has a value.
    ///         Otherwise it contains no value.
    /// @param[in] rhs source of the copy
    optional(const optional& rhs) noexcept;

    /// @brief Constructs a value with the move constructor if rhs has a value.
    ///         Otherwise it contains no value.
    /// @param[in] rhs source of the move
    optional(optional&& rhs) noexcept;

    /// @brief Copies an optional. If the optional has a value then the copy
    ///         assignment of that value is called. If the optional has no
    ///         value a new value is constructed with the copy constructor.
    /// @param[in] rhs source of the copy
    /// @return reference to the current optional
    optional& operator=(const optional& rhs) noexcept;

    /// @brief Moves an optional. If the optional has a value then the move
    ///         assignment of that value is called. If the optional has no
    ///         value a new value is constructed with the move constructor.
    /// @param[in] rhs source of the move
    /// @return reference to the current optional
    optional& operator=(optional&& rhs) noexcept;

    /// @brief Direct assignment of the underlying value. If the optional has no
    ///         value then a new T is constructed by forwarding the assignment to
    ///         T's constructor.
    ///        If the optional has a value the assignment operator of T is called.
    /// @param[in] value value to assign to the underlying optional value
    /// @return reference to the current optional
    template <typename U = T>
    // NOLINTNEXTLINE(cppcoreguidelines-c-copy-assignment-signature) return type is optional&
    typename std::enable_if<!std::is_same<U, optional<T>&>::value, optional>::type& operator=(U&& newValue) noexcept;

    /// @brief Returns a pointer to the underlying value. If the optional has no
    ///         value the application terminates. You need to verify that the
    ///         optional has a value by calling has_value() before using it.
    /// @return pointer of type const T to the underlying type
    const T* operator->() const noexcept;

    /// @brief Returns a reference to the underlying value. If the optional has no
    ///         value the application terminates. You need to verify that the
    ///         optional has a value by calling has_value() before using it.
    /// @return reference of type const T to the underlying type
    const T& operator*() const noexcept;

    /// @brief Returns a pointer to the underlying value. If the optional has no
    ///         value the application terminates. You need to verify that the
    ///         optional has a value by calling has_value() before using it.
    /// @return pointer of type T to the underlying type
    T* operator->() noexcept;

    /// @brief Returns a reference to the underlying value. If the optional has no
    ///         value the application terminates. You need to verify that the
    ///         optional has a value by calling has_value() before using it.
    /// @return reference of type T to the underlying type
    T& operator*() noexcept;

    // AXIVION Next Construct AutosarC++19_03-A13.5.3: Implemented to be as close to the STL interface as possible.
    // In combination with the keyword explicit accidental casts can be excluded and the usage is well known in the
    // C++ community.
    /// @brief Will return true if the optional contains a value, otherwise false.
    /// @return true if optional contains a value, otherwise false
    constexpr explicit operator bool() const noexcept;

    /// @brief Will return true if the optional contains a value, otherwise false.
    /// @return true if optional contains a value, otherwise false
    constexpr bool has_value() const noexcept;

    /// @brief A new element is constructed by forwarding the arguments to the
    ///         constructor of T.
    ///         If the optional has a value then the destructor of T is called.
    /// @param[in] perfectly forwards args to the constructor of T to perform a placement
    ///             new
    /// @return reference to the underlying type
    template <typename... Targs>
    T& emplace(Targs&&... args) noexcept;

    /// @brief Calls the destructor of T if the optional has a value.
    ///         If the optional has no value, nothing happens. After that call
    ///         the optional has no more value.
    void reset() noexcept;

    /// @brief Returns a reference to the underlying value. If the optional has no
    ///         value the application terminates. You need to verify that the
    ///         optional has a value by calling has_value() before using it.
    /// @return reference to the underlying type
    T& value() & noexcept;

    /// @brief Returns a const reference to the underlying value. If the optional has no
    ///         value the application terminates. You need to verify that the
    ///         optional has a value by calling has_value() before using it.
    /// @return const reference to the underlying type
    const T& value() const& noexcept;

    /// @brief Returns a rvalue reference to the underlying value. If the optional has no
    ///         value the application terminates. You need to verify that the
    ///         optional has a value by calling has_value() before using it.
    /// @return rvalue reference to the underlying type
    T&& value() && noexcept;

    /// @brief Returns a const rvalue reference to the underlying value. If the optional has no
    ///         value the application terminates. You need to verify that the
    ///         optional has a value by calling has_value() before using it.
    /// @return const rvalue reference to the underlying type
    const T&& value() const&& noexcept;

  private:
    // the hasValue member should be first member in the memory layout to reveal casting
    // bugs early.
    //
    // See the following problem:
    //   void initHandle(void * ptr) {
    //     Handle * handle = static_cast<Handle>(ptr);
    //   }
    //   void doStuff(cxx::optional<Handle> & handle) {
    //     // uses optional<Handle> instead of handle, if the bool is the second parameter such
    //     // mistakes can be introduced quickly in low level c abstraction classes
    //     initHandle(&handle);
    //   }
    bool m_hasValue{false};

  private:
    // AXIVION Next Construct AutosarC++19_03-A18.1.1 : safe access is guaranteed since the array
    // is wrapped inside the optional
    // NOLINTNEXTLINE(hicpp-avoid-c-arrays, cppcoreguidelines-avoid-c-arrays)
    alignas(T) byte_t m_data[sizeof(T)];

  private:
    template <typename... Targs>
    void construct_value(Targs&&... args) noexcept;
    void destruct_value() noexcept;
};

// AXIVION Next Construct AutosarC++19_03-M17.0.3 : make_optional is defined within iox::cxx which prevents easy misuse
/// @brief Creates an optional which contains a value by forwarding the arguments
///         to the constructor of T.
/// @param[in] args arguments which will be perfectly forwarded to the constructor
///             of T
/// @return optional which contains T constructed with args
template <typename OptionalBaseType, typename... Targs>
optional<OptionalBaseType> make_optional(Targs&&... args) noexcept;

/// @brief Compare two optionals for equality.
/// @param[in] lhs cxx::optional
/// @param[in] rhs optional to which lhs should be compared to
/// @return true if the contained values are equal or both have no value, otherwise false
template <typename T>
bool operator==(const optional<T>& lhs, const optional<T>& rhs) noexcept;

/// @brief Compare two optionals for inequality.
/// @param[in] lhs cxx::optional
/// @param[in] rhs optional to which lhs should be compared to
/// @return true if the contained values are not equal, otherwise false
template <typename T>
bool operator!=(const optional<T>& lhs, const optional<T>& rhs) noexcept;

// AXIVION DISABLE STYLE AutosarC++19_03-A13.5.5: Comparison with nullopt_t is required
/// @brief Comparison for equality with nullopt_t for easier unset optional comparison
/// @param[in] lhs empty optional, cxx::nullopt_t
/// @param[in] rhs optional to which lhs should be compared to
/// @return true if the rhs is not set, otherwise false
template <typename T>
bool operator==(const nullopt_t, const optional<T>& rhs) noexcept;

/// @brief Comparison for equality with nullopt_t for easier unset optional comparison
/// @param[in] lhs optional which should be compared to cxx::nullopt_t
/// @param[in] rhs empty optional
/// @return true if the lhs is not set, otherwise false
template <typename T>
bool operator==(const optional<T>& lhs, const nullopt_t) noexcept;

/// @brief Comparison for inequality with nullopt_t for easier unset optional comparison
/// @param[in] lhs empty optional, cxx::nullopt_t
/// @param[in] rhs optional to which lhs should be compared to
/// @return true if the optional is set, otherwise false
template <typename T>
bool operator!=(const nullopt_t, const optional<T>& rhs) noexcept;

/// @brief Comparison for inequality with nullopt_t for easier unset optional comparison
/// @param[in] lhs optional which should be compared to cxx::nullopt_t
/// @param[in] rhs empty optional
/// @return true if the optional is set, otherwise false
template <typename T>
bool operator!=(const optional<T>& lhs, const nullopt_t) noexcept;
// AXIVION ENABLE STYLE AutosarC++19_03-A13.5.5
} // namespace cxx
} // namespace iox

#include "iceoryx_hoofs/internal/cxx/optional.inl"

#endif // IOX_HOOFS_CXX_OPTIONAL_HPP
<|endoftext|>


<commit_before>// Copyright (c) 2011-2013, Zeex
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
//    this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <exception>
#include <fstream>
#include <list>
#include <map>
#include <sstream>
#include <string>
#include <subhook.h>
#include <amx/amx.h>
#include <amxprof/call_graph_writer_dot.h>
#include <amxprof/debug_info.h>
#include <amxprof/statistics_writer_html.h>
#include <amxprof/statistics_writer_text.h>
#include <amxprof/statistics_writer_json.h>
#include <amxprof/profiler.h>
#include "amxpath.h"
#include "configreader.h"
#include "plugin.h"
#include "pluginversion.h"

typedef void (*logprintf_t)(const char *format, ...);

extern void *pAMXFunctions;

static logprintf_t logprintf;

typedef std::map<AMX*, AMX_DEBUG> AmxToAmxDebugMap;
static AmxToAmxDebugMap old_debug_hooks;

typedef std::map<AMX*, amxprof::Profiler*> AmxToProfilerMap;
static AmxToProfilerMap profilers;

typedef std::map<AMX*, amxprof::DebugInfo*> AmxToDebugInfoMap;
static AmxToDebugInfoMap debug_infos;

// Plugin settings and their defauls.
namespace cfg {
  bool          profile_gamemode      = false;
  std::string   profile_filterscripts = "";
  std::string   profile_format        = "html";
  bool          call_graph            = false;
  std::string   call_graph_format     = "dot";
}

static void PrintException(const std::exception &e) {
  logprintf("[profiler] Error: %s", e.what());
}

namespace hooks {

SubHook amx_Exec_hook;
SubHook amx_Callback_hook;

int AMXAPI amx_Debug(AMX *amx) {
  amxprof::Profiler *profiler = ::profilers[amx];
  if (profiler) {
    try {
      profiler->DebugHook();
    } catch (const std::exception &e) {
      PrintException(e);
    }
  }

  AmxToAmxDebugMap::const_iterator iterator = old_debug_hooks.find(amx);
  if (iterator != old_debug_hooks.end()) {
    if (iterator->second != 0) {
      return (iterator->second)(amx);
    }
  }

  return AMX_ERR_NONE;
}

int AMXAPI amx_Callback(AMX *amx, cell index, cell *result, cell *params) {
  SubHook::ScopedRemove r(&amx_Callback_hook);
  SubHook::ScopedInstall i(&amx_Exec_hook);

  amxprof::Profiler *profiler = ::profilers[amx];
  if (profiler != 0) {
    try {
      return profiler->CallbackHook(index, result, params);
    } catch (const std::exception &e) {
      PrintException(e);
    }
  }

  return ::amx_Callback(amx, index, result, params);
}

int AMXAPI amx_Exec(AMX *amx, cell *retval, int index) {
  SubHook::ScopedRemove r(&amx_Exec_hook);
  SubHook::ScopedInstall i(&amx_Callback_hook);

  amxprof::Profiler *profiler = ::profilers[amx];
  if (profiler != 0) {
    try {
      return profiler->ExecHook(retval, index);
    } catch (const std::exception &e) {
      PrintException(e);
    }
  }

  return ::amx_Exec(amx, retval, index);
}

} // namespace hooks

static void ToLower(std::string &s) {
  std::transform(s.begin(), s.end(), s.begin(), ::tolower);
}

static std::string GetAmxPath(AMX *amx) {
  // Has to be static to make caching work in AmxUnload().
  static AmxPathFinder finder;
  finder.AddSearchDirectory("gamemodes");
  finder.AddSearchDirectory("filterscripts");
  return finder.FindAmxPath(amx);
}

static std::string ToUnixPath(const std::string &path) {
  std::string fsPath = path;
  std::replace(fsPath.begin(), fsPath.end(), '\\', '/');
  return fsPath;
}

static bool IsGameMode(const std::string &amx_name) {
  return ToUnixPath(amx_name).find("gamemodes/") != std::string::npos;
}

static bool IsFilterScript(const std::string &amx_name) {
  return ToUnixPath(amx_name).find("filterscripts/") != std::string::npos;
}

static bool WantsProfiler(const std::string &amx_name) {
  std::string good_amx_name = ToUnixPath(amx_name);

  if (IsGameMode(good_amx_name)) {
    if (cfg::profile_gamemode) {
      return true;
    }
  } else if (IsFilterScript(good_amx_name)) {
    std::string fs_list = cfg::profile_filterscripts;
    std::stringstream fs_stream(fs_list);
    do {
      std::string fs_name;
      fs_stream >> fs_name;
      if (good_amx_name == "filterscripts/" + fs_name + ".amx"
          || good_amx_name == "filterscripts/" + fs_name) {
        return true;
      }
    } while (!fs_stream.eof());
  }

  return false;
}

template<typename Map, typename Key>
static void DeleteMapEntry(Map &map, const Key &key) {
  typename Map::iterator iterator = map.find(key);
  if (iterator != map.end()) {
    delete iterator->second;
    map.erase(iterator);
  }
}

template<typename Func>
static void *FunctionToVoidPtr(Func func) {
  return (void*)func;
}

static void *AMXAPI amx_Align_stub(void *v) {
  return v;
}

PLUGIN_EXPORT unsigned int PLUGIN_CALL Supports() {
  return SUPPORTS_VERSION | SUPPORTS_AMX_NATIVES;
}

PLUGIN_EXPORT bool PLUGIN_CALL Load(void **ppData) {
  try {
    pAMXFunctions = ppData[PLUGIN_DATA_AMX_EXPORTS];
    logprintf = (logprintf_t) ppData[PLUGIN_DATA_LOGPRINTF];

    void **exports = reinterpret_cast<void**>(pAMXFunctions);

    exports[PLUGIN_AMX_EXPORT_Align16] = FunctionToVoidPtr(amx_Align_stub);
    exports[PLUGIN_AMX_EXPORT_Align32] = FunctionToVoidPtr(amx_Align_stub);
    exports[PLUGIN_AMX_EXPORT_Align64] = FunctionToVoidPtr(amx_Align_stub);

    hooks::amx_Exec_hook.Install(exports[PLUGIN_AMX_EXPORT_Exec],
                                 FunctionToVoidPtr(hooks::amx_Exec));
    hooks::amx_Callback_hook.Install(exports[PLUGIN_AMX_EXPORT_Callback],
                                     FunctionToVoidPtr(hooks::amx_Callback));

    ConfigReader server_cfg("server.cfg");
    server_cfg.GetOption("profile_gamemode", cfg::profile_gamemode);
    server_cfg.GetOption("profile_filterscripts", cfg::profile_filterscripts);
    server_cfg.GetOption("profile_format", cfg::profile_format);
    server_cfg.GetOption("call_graph", cfg::call_graph);
    server_cfg.GetOption("call_graph_format", cfg::call_graph_format);

    logprintf("  Profiler v" PROJECT_VERSION_STRING " is OK.");
  }
  catch (std::exception &e) {
    PrintException(e);
  }

  return true;
}

PLUGIN_EXPORT int PLUGIN_CALL AmxLoad(AMX *amx) {
  try {
    std::string filename = GetAmxPath(amx);

    if (filename.empty()) {
      logprintf("[profiler] Failed to find corresponding .amx file");
      return AMX_ERR_NONE;
    }

    if (!WantsProfiler(filename)) {
      return AMX_ERR_NONE;
    }

    amxprof::DebugInfo *debug_info = 0;

    if (amxprof::HasDebugInfo(amx)) {
      debug_info = new amxprof::DebugInfo(filename);
      if (debug_info->is_loaded()) {
        ::debug_infos[amx] = debug_info;
      } else {
        logprintf("[profiler] Error loading debug info: %s",
                  aux_StrError(debug_info->last_error()));
        delete debug_info;
        debug_info = 0;
      }
    }

    amxprof::Profiler *profiler = new amxprof::Profiler(amx,
                                                                  debug_info);
    profiler->set_call_graph_enabled(cfg::call_graph);

    if (debug_info != 0) {
      logprintf("[profiler] Attached profiler to '%s'", filename.c_str());
    } else {
      logprintf("[profiler] Attached profiler to '%s' (no debug info)",
                filename.c_str());
    }

    ::old_debug_hooks[amx] = amx->debug;
    amx_SetDebugHook(amx, hooks::amx_Debug);

    ::profilers[amx] = profiler;
  }
  catch (const std::exception &e) {
    PrintException(e);
  }

  return AMX_ERR_NONE;
}

PLUGIN_EXPORT int PLUGIN_CALL AmxUnload(AMX *amx) {
  try {
    amxprof::Profiler *profiler = ::profilers[amx];

    if (profiler != 0) {
      std::string amx_path = GetAmxPath(amx);
      std::string amx_name = std::string(amx_path, 0,
                                         amx_path.find_last_of("."));

      ToLower(cfg::profile_format);
      std::string profile_filename = amx_name + "-profile." +
                                     cfg::profile_format;
      std::ofstream profile_stream(profile_filename.c_str());

      if (profile_stream.is_open()) {
        amxprof::StatisticsWriter *writer = 0;

        if (cfg::profile_format == "html") {
          writer = new amxprof::StatisticsWriterHtml;
        } else if (cfg::profile_format == "txt" ||
                   cfg::profile_format == "text") {
          writer = new amxprof::StatisticsWriterText;
        } else if (cfg::profile_format == "json") {
          writer = new amxprof::StatisticsWriterJson;
        } else {
          logprintf("[profiler] Unrecognized profile format '%s'",
                    cfg::profile_format.c_str());
        }

        if (writer != 0) {
          logprintf("[profiler] Writing profile to '%s'",
                    profile_filename.c_str());
          writer->set_stream(&profile_stream);
          writer->set_script_name(amx_path);
          writer->set_print_date(true);
          writer->set_print_run_time(true);
          writer->Write(profiler->stats());
          delete writer;
        }

        profile_stream.close();
      } else {
        logprintf("[profiler]: Error opening file '%s'",
                  profile_filename.c_str());
      }

      if (cfg::call_graph) {
        ToLower(cfg::call_graph_format);
        std::string call_graph_filename = amx_name + "-calls." +
                                          cfg::call_graph_format;
        std::ofstream call_graph_stream(call_graph_filename.c_str());

        if (call_graph_stream.is_open()) {
          amxprof::CallGraphWriterDot *writer = 0;

          if (cfg::call_graph_format == "dot") {
            writer = new amxprof::CallGraphWriterDot;
          } else {
            logprintf("[profiler] Unrecognized call graph format '%s'",
                      cfg::call_graph_format.c_str());
          }

          if (writer != 0) {
            logprintf("[profiler] Writing call graph to '%s'",
                      call_graph_filename.c_str());
            writer->set_stream(&call_graph_stream);
            writer->set_script_name(amx_path);
            writer->set_root_node_name("SA-MP Server");
            writer->Write(profiler->call_graph());
            delete writer;
          }

          call_graph_stream.close();
        } else {
          logprintf("[profiler]: Error opening file '%s'",
                    call_graph_filename.c_str());
        }
      }
    }

    DeleteMapEntry(::profilers, amx);
    DeleteMapEntry(::debug_infos, amx);
  }
  catch (const std::exception &e) {
    PrintException(e);
  }

  return AMX_ERR_NONE;
}
<commit_msg>Fix compatibility with GDK 4.0.1+<commit_after>// Copyright (c) 2011-2013, Zeex
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
//    this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <exception>
#include <fstream>
#include <list>
#include <map>
#include <sstream>
#include <string>
#include <subhook.h>
#include <amx/amx.h>
#include <amxprof/call_graph_writer_dot.h>
#include <amxprof/debug_info.h>
#include <amxprof/statistics_writer_html.h>
#include <amxprof/statistics_writer_text.h>
#include <amxprof/statistics_writer_json.h>
#include <amxprof/profiler.h>
#include "amxpath.h"
#include "configreader.h"
#include "plugin.h"
#include "pluginversion.h"

typedef void (*logprintf_t)(const char *format, ...);

extern void *pAMXFunctions;

static logprintf_t logprintf;

typedef std::map<AMX*, AMX_DEBUG> AmxToAmxDebugMap;
static AmxToAmxDebugMap old_debug_hooks;

typedef std::map<AMX*, amxprof::Profiler*> AmxToProfilerMap;
static AmxToProfilerMap profilers;

typedef std::map<AMX*, amxprof::DebugInfo*> AmxToDebugInfoMap;
static AmxToDebugInfoMap debug_infos;

// Plugin settings and their defauls.
namespace cfg {
  bool          profile_gamemode      = false;
  std::string   profile_filterscripts = "";
  std::string   profile_format        = "html";
  bool          call_graph            = false;
  std::string   call_graph_format     = "dot";
}

static void PrintException(const std::exception &e) {
  logprintf("[profiler] Error: %s", e.what());
}

namespace hooks {

SubHook amx_Exec_hook;
SubHook amx_Callback_hook;

int AMXAPI amx_Debug(AMX *amx) {
  amxprof::Profiler *profiler = ::profilers[amx];
  if (profiler) {
    try {
      profiler->DebugHook();
    } catch (const std::exception &e) {
      PrintException(e);
    }
  }

  AmxToAmxDebugMap::const_iterator iterator = old_debug_hooks.find(amx);
  if (iterator != old_debug_hooks.end()) {
    if (iterator->second != 0) {
      return (iterator->second)(amx);
    }
  }

  return AMX_ERR_NONE;
}

int AMXAPI amx_Callback(AMX *amx, cell index, cell *result, cell *params) {
  SubHook::ScopedRemove r(&amx_Callback_hook);
  SubHook::ScopedInstall i(&amx_Exec_hook);

  amxprof::Profiler *profiler = ::profilers[amx];
  if (profiler != 0) {
    try {
      return profiler->CallbackHook(index, result, params);
    } catch (const std::exception &e) {
      PrintException(e);
    }
  }

  return ::amx_Callback(amx, index, result, params);
}

int AMXAPI amx_Exec(AMX *amx, cell *retval, int index) {
  SubHook::ScopedRemove r(&amx_Exec_hook);
  SubHook::ScopedInstall i(&amx_Callback_hook);

  amxprof::Profiler *profiler = ::profilers[amx];
  if (profiler != 0) {
    try {
      return profiler->ExecHook(retval, index);
    } catch (const std::exception &e) {
      PrintException(e);
    }
  }

  return ::amx_Exec(amx, retval, index);
}

} // namespace hooks

static void ToLower(std::string &s) {
  std::transform(s.begin(), s.end(), s.begin(), ::tolower);
}

static std::string GetAmxPath(AMX *amx) {
  // Has to be static to make caching work in AmxUnload().
  static AmxPathFinder finder;
  finder.AddSearchDirectory("gamemodes");
  finder.AddSearchDirectory("filterscripts");
  return finder.FindAmxPath(amx);
}

static std::string ToUnixPath(const std::string &path) {
  std::string fsPath = path;
  std::replace(fsPath.begin(), fsPath.end(), '\\', '/');
  return fsPath;
}

static bool IsGameMode(const std::string &amx_name) {
  return ToUnixPath(amx_name).find("gamemodes/") != std::string::npos;
}

static bool IsFilterScript(const std::string &amx_name) {
  return ToUnixPath(amx_name).find("filterscripts/") != std::string::npos;
}

static bool WantsProfiler(const std::string &amx_name) {
  std::string good_amx_name = ToUnixPath(amx_name);

  if (IsGameMode(good_amx_name)) {
    if (cfg::profile_gamemode) {
      return true;
    }
  } else if (IsFilterScript(good_amx_name)) {
    std::string fs_list = cfg::profile_filterscripts;
    std::stringstream fs_stream(fs_list);
    do {
      std::string fs_name;
      fs_stream >> fs_name;
      if (good_amx_name == "filterscripts/" + fs_name + ".amx"
          || good_amx_name == "filterscripts/" + fs_name) {
        return true;
      }
    } while (!fs_stream.eof());
  }

  return false;
}

template<typename Map, typename Key>
static void DeleteMapEntry(Map &map, const Key &key) {
  typename Map::iterator iterator = map.find(key);
  if (iterator != map.end()) {
    delete iterator->second;
    map.erase(iterator);
  }
}

template<typename Func>
static void *FunctionToVoidPtr(Func func) {
  return (void*)func;
}

static void *AMXAPI amx_Align_stub(void *v) {
  return v;
}

PLUGIN_EXPORT unsigned int PLUGIN_CALL Supports() {
  return SUPPORTS_VERSION | SUPPORTS_AMX_NATIVES;
}

PLUGIN_EXPORT bool PLUGIN_CALL Load(void **ppData) {
  try {
    pAMXFunctions = ppData[PLUGIN_DATA_AMX_EXPORTS];
    logprintf = (logprintf_t) ppData[PLUGIN_DATA_LOGPRINTF];

    void **exports = reinterpret_cast<void**>(pAMXFunctions);

    exports[PLUGIN_AMX_EXPORT_Align16] = FunctionToVoidPtr(amx_Align_stub);
    exports[PLUGIN_AMX_EXPORT_Align32] = FunctionToVoidPtr(amx_Align_stub);
    exports[PLUGIN_AMX_EXPORT_Align64] = FunctionToVoidPtr(amx_Align_stub);

    hooks::amx_Exec_hook.SetSrc(exports[PLUGIN_AMX_EXPORT_Exec]);
    hooks::amx_Exec_hook.SetDst(FunctionToVoidPtr(hooks::amx_Exec));
    hooks::amx_Exec_hook.Install();

    hooks::amx_Callback_hook.SetSrc(exports[PLUGIN_AMX_EXPORT_Callback]);
    hooks::amx_Callback_hook.SetDst(FunctionToVoidPtr(hooks::amx_Callback));

    ConfigReader server_cfg("server.cfg");
    server_cfg.GetOption("profile_gamemode", cfg::profile_gamemode);
    server_cfg.GetOption("profile_filterscripts", cfg::profile_filterscripts);
    server_cfg.GetOption("profile_format", cfg::profile_format);
    server_cfg.GetOption("call_graph", cfg::call_graph);
    server_cfg.GetOption("call_graph_format", cfg::call_graph_format);

    logprintf("  Profiler v" PROJECT_VERSION_STRING " is OK.");
  }
  catch (std::exception &e) {
    PrintException(e);
  }

  return true;
}

PLUGIN_EXPORT int PLUGIN_CALL AmxLoad(AMX *amx) {
  try {
    std::string filename = GetAmxPath(amx);

    if (filename.empty()) {
      logprintf("[profiler] Failed to find corresponding .amx file");
      return AMX_ERR_NONE;
    }

    if (!WantsProfiler(filename)) {
      return AMX_ERR_NONE;
    }

    amxprof::DebugInfo *debug_info = 0;

    if (amxprof::HasDebugInfo(amx)) {
      debug_info = new amxprof::DebugInfo(filename);
      if (debug_info->is_loaded()) {
        ::debug_infos[amx] = debug_info;
      } else {
        logprintf("[profiler] Error loading debug info: %s",
                  aux_StrError(debug_info->last_error()));
        delete debug_info;
        debug_info = 0;
      }
    }

    amxprof::Profiler *profiler = new amxprof::Profiler(amx,
                                                                  debug_info);
    profiler->set_call_graph_enabled(cfg::call_graph);

    if (debug_info != 0) {
      logprintf("[profiler] Attached profiler to '%s'", filename.c_str());
    } else {
      logprintf("[profiler] Attached profiler to '%s' (no debug info)",
                filename.c_str());
    }

    ::old_debug_hooks[amx] = amx->debug;
    amx_SetDebugHook(amx, hooks::amx_Debug);

    ::profilers[amx] = profiler;
  }
  catch (const std::exception &e) {
    PrintException(e);
  }

  return AMX_ERR_NONE;
}

PLUGIN_EXPORT int PLUGIN_CALL AmxUnload(AMX *amx) {
  try {
    amxprof::Profiler *profiler = ::profilers[amx];

    if (profiler != 0) {
      std::string amx_path = GetAmxPath(amx);
      std::string amx_name = std::string(amx_path, 0,
                                         amx_path.find_last_of("."));

      ToLower(cfg::profile_format);
      std::string profile_filename = amx_name + "-profile." +
                                     cfg::profile_format;
      std::ofstream profile_stream(profile_filename.c_str());

      if (profile_stream.is_open()) {
        amxprof::StatisticsWriter *writer = 0;

        if (cfg::profile_format == "html") {
          writer = new amxprof::StatisticsWriterHtml;
        } else if (cfg::profile_format == "txt" ||
                   cfg::profile_format == "text") {
          writer = new amxprof::StatisticsWriterText;
        } else if (cfg::profile_format == "json") {
          writer = new amxprof::StatisticsWriterJson;
        } else {
          logprintf("[profiler] Unrecognized profile format '%s'",
                    cfg::profile_format.c_str());
        }

        if (writer != 0) {
          logprintf("[profiler] Writing profile to '%s'",
                    profile_filename.c_str());
          writer->set_stream(&profile_stream);
          writer->set_script_name(amx_path);
          writer->set_print_date(true);
          writer->set_print_run_time(true);
          writer->Write(profiler->stats());
          delete writer;
        }

        profile_stream.close();
      } else {
        logprintf("[profiler]: Error opening file '%s'",
                  profile_filename.c_str());
      }

      if (cfg::call_graph) {
        ToLower(cfg::call_graph_format);
        std::string call_graph_filename = amx_name + "-calls." +
                                          cfg::call_graph_format;
        std::ofstream call_graph_stream(call_graph_filename.c_str());

        if (call_graph_stream.is_open()) {
          amxprof::CallGraphWriterDot *writer = 0;

          if (cfg::call_graph_format == "dot") {
            writer = new amxprof::CallGraphWriterDot;
          } else {
            logprintf("[profiler] Unrecognized call graph format '%s'",
                      cfg::call_graph_format.c_str());
          }

          if (writer != 0) {
            logprintf("[profiler] Writing call graph to '%s'",
                      call_graph_filename.c_str());
            writer->set_stream(&call_graph_stream);
            writer->set_script_name(amx_path);
            writer->set_root_node_name("SA-MP Server");
            writer->Write(profiler->call_graph());
            delete writer;
          }

          call_graph_stream.close();
        } else {
          logprintf("[profiler]: Error opening file '%s'",
                    call_graph_filename.c_str());
        }
      }
    }

    DeleteMapEntry(::profilers, amx);
    DeleteMapEntry(::debug_infos, amx);
  }
  catch (const std::exception &e) {
    PrintException(e);
  }

  return AMX_ERR_NONE;
}
<|endoftext|>