<commit_before>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// author:  Vassil Vassilev <vasil.georgiev.vasilev@cern.ch>
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
//------------------------------------------------------------------------------

#include "cling/Interpreter/DynamicLibraryManager.h"
#include "cling/Interpreter/InvocationOptions.h"

#include "llvm/Support/DynamicLibrary.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"

#include <algorithm>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>

#ifdef WIN32
#include <Windows.h>
#include <shlobj.h>
#else
#include <limits.h> /* PATH_MAX */
#include <dlfcn.h>
#endif

namespace {
#if defined(LLVM_ON_UNIX)
  static void GetSystemLibraryPaths(llvm::SmallVectorImpl<std::string>& Paths) {
    char* env_var = getenv("LD_LIBRARY_PATH");
#if __APPLE__
    if (!env_var)
      env_var = getenv("DYLD_LIBRARY_PATH");
    if (!env_var)
      env_var = getenv("DYLD_FALLBACK_LIBRARY_PATH");
#endif
    if (env_var != 0) {
      static const char PathSeparator = ':';
      const char* at = env_var;
      const char* delim = strchr(at, PathSeparator);
      while (delim != 0) {
        std::string tmp(at, size_t(delim-at));
        if (llvm::sys::fs::is_directory(tmp.c_str()))
          Paths.push_back(tmp);
        at = delim + 1;
        delim = strchr(at, PathSeparator);
      }

      if (*at != 0)
        if (llvm::sys::fs::is_directory(llvm::StringRef(at)))
          Paths.push_back(at);
    }
#if defined(__APPLE__) || defined(__CYGWIN__)
    Paths.push_back("/usr/local/lib/");
    Paths.push_back("/usr/X11R6/lib/");
    Paths.push_back("/usr/lib/");
    Paths.push_back("/lib/");

    Paths.push_back("/lib/x86_64-linux-gnu/");
    Paths.push_back("/usr/local/lib64/");
    Paths.push_back("/usr/lib64/");
    Paths.push_back("/lib64/");
#else
    static bool initialized = false;
    static std::vector<std::string> SysPaths;
    if (!initialized) {
      // trick to get the system search path
      std::string cmd("LD_DEBUG=libs LD_PRELOAD=DOESNOTEXIST ls 2>&1");
      FILE *pf = popen(cmd.c_str (), "r");
      std::string result = "";
      std::string sys_path = "";
      char buffer[128];
      while (!feof(pf)) {
        if (fgets(buffer, 128, pf) != NULL)
          result += buffer;
      }
      pclose(pf);
      std::size_t from
        = result.find("search path=", result.find("(LD_LIBRARY_PATH)"));
      std::size_t to = result.find("(system search path)");
      if (from != std::string::npos && to != std::string::npos) {
        from += 12;
        sys_path = result.substr(from, to-from);
        sys_path.erase(std::remove_if(sys_path.begin(), sys_path.end(), isspace),
                       sys_path.end());
        sys_path += ':';
      }
      static const char PathSeparator = ':';
      const char* at = sys_path.c_str();
      const char* delim = strchr(at, PathSeparator);
      while (delim != 0) {
        std::string tmp(at, size_t(delim-at));
        if (llvm::sys::fs::is_directory(tmp.c_str()))
          SysPaths.push_back(tmp);
        at = delim + 1;
        delim = strchr(at, PathSeparator);
      }
      initialized = true;
    }

    for (std::vector<std::string>::const_iterator I = SysPaths.begin(),
           E = SysPaths.end(); I != E; ++I)
      Paths.push_back((*I).c_str());
#endif
  }
#elif defined(LLVM_ON_WIN32)
  static void GetSystemLibraryPaths(llvm::SmallVectorImpl<std::string>& Paths) {
    char buff[MAX_PATH];
    // Generic form of C:\Windows\System32
    HRESULT res =  SHGetFolderPathA(NULL,
                                    CSIDL_FLAG_CREATE | CSIDL_SYSTEM,
                                    NULL,
                                    SHGFP_TYPE_CURRENT,
                                    buff);
    if (res != S_OK) {
      assert(0 && "Failed to get system directory");
      return;
    }
    Paths.push_back(buff);

    // Reset buff.
    buff[0] = 0;
    // Generic form of C:\Windows
    res =  SHGetFolderPathA(NULL,
                            CSIDL_FLAG_CREATE | CSIDL_WINDOWS,
                            NULL,
                            SHGFP_TYPE_CURRENT,
                            buff);
    if (res != S_OK) {
      assert(0 && "Failed to get windows directory");
      return;
    }
    Paths.push_back(buff);
  }
#else
# error "Unsupported platform."
#endif

}

namespace cling {
  DynamicLibraryManager::DynamicLibraryManager(const InvocationOptions& Opts)
    : m_Opts(Opts) {
    GetSystemLibraryPaths(m_SystemSearchPaths);
    m_SystemSearchPaths.push_back(".");
  }

  DynamicLibraryManager::~DynamicLibraryManager() {}

  static bool isSharedLib(llvm::StringRef LibName, bool* exists = 0) {
    using namespace llvm::sys::fs;
    file_magic Magic;
    llvm::error_code Error = identify_magic(LibName, Magic);
    bool onDisk = (Error == llvm::errc::success);
    if (exists)
      *exists = onDisk;

    return onDisk &&
#ifdef __APPLE__
      (Magic == file_magic::macho_fixed_virtual_memory_shared_lib
       || Magic == file_magic::macho_dynamically_linked_shared_lib
       || Magic == file_magic::macho_dynamically_linked_shared_lib_stub)
#elif defined(LLVM_ON_UNIX)
#ifdef __CYGWIN__
      (Magic == file_magic::pecoff_executable)
#else
      (Magic == file_magic::elf_shared_object)
#endif
#elif defined(LLVM_ON_WIN32)
      (Magic == file_magic::pecoff_executable)
#else
# error "Unsupported platform."
#endif
      ;
  }

  std::string
  DynamicLibraryManager::lookupLibInPaths(llvm::StringRef libStem) const {
    llvm::SmallVector<std::string, 128>
      Paths(m_Opts.LibSearchPath.begin(), m_Opts.LibSearchPath.end());
    Paths.append(m_SystemSearchPaths.begin(), m_SystemSearchPaths.end());

    for (llvm::SmallVectorImpl<std::string>::const_iterator
           IPath = Paths.begin(), E = Paths.end();IPath != E; ++IPath) {
      llvm::SmallString<512> ThisPath(*IPath); // FIXME: move alloc outside loop
      llvm::sys::path::append(ThisPath, libStem);
      bool exists;
      if (isSharedLib(ThisPath.str(), &exists))
        return ThisPath.str();
      if (exists)
        return "";
    }
    return "";
  }

  std::string
  DynamicLibraryManager::lookupLibMaybeAddExt(llvm::StringRef libStem) const {
    using namespace llvm::sys;

    std::string foundDyLib = lookupLibInPaths(libStem);

    if (foundDyLib.empty()) {
      // Add DyLib extension:
      llvm::SmallString<512> filenameWithExt(libStem);
#if defined(LLVM_ON_UNIX)
#ifdef __APPLE__
      llvm::SmallString<512>::iterator IStemEnd = filenameWithExt.end() - 1;
#endif
      static const char* DyLibExt = ".so";
#elif defined(LLVM_ON_WIN32)
      static const char* DyLibExt = ".dll";
#else
# error "Unsupported platform."
#endif
      filenameWithExt += DyLibExt;
      foundDyLib = lookupLibInPaths(filenameWithExt);
#ifdef __APPLE__
      if (foundDyLib.empty()) {
        filenameWithExt.erase(IStemEnd + 1, filenameWithExt.end());
        filenameWithExt += ".dylib";
        foundDyLib = lookupLibInPaths(filenameWithExt);
      }
#endif
    }

    if (foundDyLib.empty())
      return "";

    // get canonical path name and check if already loaded
#if defined(LLVM_ON_WIN32)
    llvm::SmallString<_MAX_PATH> FullPath("");
    char *res = _fullpath((char *)FullPath.data(), foundDyLib.c_str(), _MAX_PATH);
#else
    llvm::SmallString<PATH_MAX+1> FullPath("");
    char *res = realpath(foundDyLib.c_str(), (char *)FullPath.data());
#endif
    if (res == 0) {
      llvm::errs() << "cling::DyLibMan::lookupLibMaybeAddExt(): error getting "
        "real (canonical) path of library " << foundDyLib << '\n';
      return foundDyLib;
    }
    FullPath.set_size(strlen(res));
    return FullPath.str();
  }

  static std::string normalizePath(llvm::StringRef path) {
    // Make the path canonical if the file exists.
    struct stat buffer;
    if (stat(path.data(), &buffer) != 0)
      return "";
#if defined(LLVM_ON_WIN32)
    char buf[_MAX_PATH];
    char *res = _fullpath(buf, path.data(), _MAX_PATH);
#else
    char buf[PATH_MAX+1];
    char *res = realpath(path.data(), buf);
#endif
    if (res == 0) {
      assert(0 && "Cannot normalize!?");
      return "";
    }
    return res;
  }

  std::string
  DynamicLibraryManager::lookupLibrary(llvm::StringRef libStem) const {
    llvm::SmallString<128> Absolute(libStem);
    llvm::sys::fs::make_absolute(Absolute);
    bool isAbsolute = libStem == Absolute;

    // If it is an absolute path, don't try iterate over the paths.
    if (isAbsolute) {
      if (isSharedLib(libStem))
        return normalizePath(libStem);
      else
        return "";
    }

    std::string foundName = lookupLibMaybeAddExt(libStem);
    if (foundName.empty() && !libStem.startswith("lib")) {
      // try with "lib" prefix:
      foundName = lookupLibMaybeAddExt("lib" + libStem.str());
    }

    if (isSharedLib(foundName))
      return normalizePath(foundName);
    return "";
  }

  DynamicLibraryManager::LoadLibResult
  DynamicLibraryManager::loadLibrary(const std::string& libStem,
                                     bool permanent) {
    std::string canonicalLoadedLib = lookupLibrary(libStem);
    if (canonicalLoadedLib.empty())
      return kLoadLibNotFound;

    if (m_LoadedLibraries.find(canonicalLoadedLib) != m_LoadedLibraries.end())
      return kLoadLibAlreadyLoaded;

    std::string errMsg;
    // TODO: !permanent case
#if defined(LLVM_ON_WIN32)
    HMODULE dyLibHandle = LoadLibraryEx(canonicalLoadedLib.c_str(), NULL,
                                        DONT_RESOLVE_DLL_REFERENCES);
    errMsg = "LoadLibraryEx: GetLastError() returned ";
    errMsg += GetLastError();
#else
    const void* dyLibHandle = dlopen(canonicalLoadedLib.c_str(),
                                     RTLD_LAZY|RTLD_GLOBAL);
    if (const char* DyLibError = dlerror()) {
      errMsg = DyLibError;
    }
#endif
    if (!dyLibHandle) {
      llvm::errs() << "cling::DyLibMan::loadLibrary(): " << errMsg << '\n';
      return kLoadLibLoadError;
    }
    std::pair<DyLibs::iterator, bool> insRes
      = m_DyLibs.insert(std::pair<DyLibHandle, std::string>(dyLibHandle,
                                                            canonicalLoadedLib));
    if (!insRes.second)
      return kLoadLibAlreadyLoaded;
    m_LoadedLibraries.insert(canonicalLoadedLib);
    return kLoadLibSuccess;
  }

  void DynamicLibraryManager::unloadLibrary(llvm::StringRef libStem) {
    std::string canonicalLoadedLib = lookupLibrary(libStem);
    if (!isLibraryLoaded(canonicalLoadedLib))
      return;

    DyLibHandle dyLibHandle = 0;
    for (DyLibs::const_iterator I = m_DyLibs.begin(), E = m_DyLibs.end();
         I != E; ++I) {
      if (I->second == canonicalLoadedLib)
        dyLibHandle = I->first;
    }

    std::string errMsg;
    // TODO: !permanent case
#if defined(LLVM_ON_WIN32)
    FreeLibrary(dyLibHandle);
    errMsg = "UnoadLibraryEx: GetLastError() returned ";
    errMsg += GetLastError();
#else
    dlclose(const_cast<void*>(dyLibHandle));
    if (const char* DyLibError = dlerror()) {
      errMsg = DyLibError;
    }
#endif
    if (InterpreterCallbacks* C = m_Interpreter.getCallbacks())
      C->LibraryUnloaded(dyLibHandle, canonicalLoadedLib);

    m_DyLibs.erase(dyLibHandle);
    m_LoadedLibraries.erase(canonicalLoadedLib);
  }

  bool DynamicLibraryManager::isLibraryLoaded(llvm::StringRef fullPath) const {
    std::string canonPath = normalizePath(fullPath);
    if (m_LoadedLibraries.find(canonPath) != m_LoadedLibraries.end())
      return true;
    return false;
  }

  void DynamicLibraryManager::ExposeHiddenSharedLibrarySymbols(void* handle) {
    llvm::sys::DynamicLibrary::addPermanentLibrary(const_cast<void*>(handle));
  }
} // end namespace cling
<commit_msg>Revert unintentionally checked in code.<commit_after>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// author:  Vassil Vassilev <vasil.georgiev.vasilev@cern.ch>
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
//------------------------------------------------------------------------------

#include "cling/Interpreter/DynamicLibraryManager.h"
#include "cling/Interpreter/InvocationOptions.h"

#include "llvm/Support/DynamicLibrary.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"

#include <algorithm>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>

#ifdef WIN32
#include <Windows.h>
#include <shlobj.h>
#else
#include <limits.h> /* PATH_MAX */
#include <dlfcn.h>
#endif

namespace {
#if defined(LLVM_ON_UNIX)
  static void GetSystemLibraryPaths(llvm::SmallVectorImpl<std::string>& Paths) {
    char* env_var = getenv("LD_LIBRARY_PATH");
#if __APPLE__
    if (!env_var)
      env_var = getenv("DYLD_LIBRARY_PATH");
    if (!env_var)
      env_var = getenv("DYLD_FALLBACK_LIBRARY_PATH");
#endif
    if (env_var != 0) {
      static const char PathSeparator = ':';
      const char* at = env_var;
      const char* delim = strchr(at, PathSeparator);
      while (delim != 0) {
        std::string tmp(at, size_t(delim-at));
        if (llvm::sys::fs::is_directory(tmp.c_str()))
          Paths.push_back(tmp);
        at = delim + 1;
        delim = strchr(at, PathSeparator);
      }

      if (*at != 0)
        if (llvm::sys::fs::is_directory(llvm::StringRef(at)))
          Paths.push_back(at);
    }
#if defined(__APPLE__) || defined(__CYGWIN__)
    Paths.push_back("/usr/local/lib/");
    Paths.push_back("/usr/X11R6/lib/");
    Paths.push_back("/usr/lib/");
    Paths.push_back("/lib/");

    Paths.push_back("/lib/x86_64-linux-gnu/");
    Paths.push_back("/usr/local/lib64/");
    Paths.push_back("/usr/lib64/");
    Paths.push_back("/lib64/");
#else
    static bool initialized = false;
    static std::vector<std::string> SysPaths;
    if (!initialized) {
      // trick to get the system search path
      std::string cmd("LD_DEBUG=libs LD_PRELOAD=DOESNOTEXIST ls 2>&1");
      FILE *pf = popen(cmd.c_str (), "r");
      std::string result = "";
      std::string sys_path = "";
      char buffer[128];
      while (!feof(pf)) {
        if (fgets(buffer, 128, pf) != NULL)
          result += buffer;
      }
      pclose(pf);
      std::size_t from
        = result.find("search path=", result.find("(LD_LIBRARY_PATH)"));
      std::size_t to = result.find("(system search path)");
      if (from != std::string::npos && to != std::string::npos) {
        from += 12;
        sys_path = result.substr(from, to-from);
        sys_path.erase(std::remove_if(sys_path.begin(), sys_path.end(), isspace),
                       sys_path.end());
        sys_path += ':';
      }
      static const char PathSeparator = ':';
      const char* at = sys_path.c_str();
      const char* delim = strchr(at, PathSeparator);
      while (delim != 0) {
        std::string tmp(at, size_t(delim-at));
        if (llvm::sys::fs::is_directory(tmp.c_str()))
          SysPaths.push_back(tmp);
        at = delim + 1;
        delim = strchr(at, PathSeparator);
      }
      initialized = true;
    }

    for (std::vector<std::string>::const_iterator I = SysPaths.begin(),
           E = SysPaths.end(); I != E; ++I)
      Paths.push_back((*I).c_str());
#endif
  }
#elif defined(LLVM_ON_WIN32)
  static void GetSystemLibraryPaths(llvm::SmallVectorImpl<std::string>& Paths) {
    char buff[MAX_PATH];
    // Generic form of C:\Windows\System32
    HRESULT res =  SHGetFolderPathA(NULL,
                                    CSIDL_FLAG_CREATE | CSIDL_SYSTEM,
                                    NULL,
                                    SHGFP_TYPE_CURRENT,
                                    buff);
    if (res != S_OK) {
      assert(0 && "Failed to get system directory");
      return;
    }
    Paths.push_back(buff);

    // Reset buff.
    buff[0] = 0;
    // Generic form of C:\Windows
    res =  SHGetFolderPathA(NULL,
                            CSIDL_FLAG_CREATE | CSIDL_WINDOWS,
                            NULL,
                            SHGFP_TYPE_CURRENT,
                            buff);
    if (res != S_OK) {
      assert(0 && "Failed to get windows directory");
      return;
    }
    Paths.push_back(buff);
  }
#else
# error "Unsupported platform."
#endif

}

namespace cling {
  DynamicLibraryManager::DynamicLibraryManager(const InvocationOptions& Opts)
    : m_Opts(Opts) {
    GetSystemLibraryPaths(m_SystemSearchPaths);
    m_SystemSearchPaths.push_back(".");
  }

  DynamicLibraryManager::~DynamicLibraryManager() {}

  static bool isSharedLib(llvm::StringRef LibName, bool* exists = 0) {
    using namespace llvm::sys::fs;
    file_magic Magic;
    llvm::error_code Error = identify_magic(LibName, Magic);
    bool onDisk = (Error == llvm::errc::success);
    if (exists)
      *exists = onDisk;

    return onDisk &&
#ifdef __APPLE__
      (Magic == file_magic::macho_fixed_virtual_memory_shared_lib
       || Magic == file_magic::macho_dynamically_linked_shared_lib
       || Magic == file_magic::macho_dynamically_linked_shared_lib_stub)
#elif defined(LLVM_ON_UNIX)
#ifdef __CYGWIN__
      (Magic == file_magic::pecoff_executable)
#else
      (Magic == file_magic::elf_shared_object)
#endif
#elif defined(LLVM_ON_WIN32)
      (Magic == file_magic::pecoff_executable)
#else
# error "Unsupported platform."
#endif
      ;
  }

  std::string
  DynamicLibraryManager::lookupLibInPaths(llvm::StringRef libStem) const {
    llvm::SmallVector<std::string, 128>
      Paths(m_Opts.LibSearchPath.begin(), m_Opts.LibSearchPath.end());
    Paths.append(m_SystemSearchPaths.begin(), m_SystemSearchPaths.end());

    for (llvm::SmallVectorImpl<std::string>::const_iterator
           IPath = Paths.begin(), E = Paths.end();IPath != E; ++IPath) {
      llvm::SmallString<512> ThisPath(*IPath); // FIXME: move alloc outside loop
      llvm::sys::path::append(ThisPath, libStem);
      bool exists;
      if (isSharedLib(ThisPath.str(), &exists))
        return ThisPath.str();
      if (exists)
        return "";
    }
    return "";
  }

  std::string
  DynamicLibraryManager::lookupLibMaybeAddExt(llvm::StringRef libStem) const {
    using namespace llvm::sys;

    std::string foundDyLib = lookupLibInPaths(libStem);

    if (foundDyLib.empty()) {
      // Add DyLib extension:
      llvm::SmallString<512> filenameWithExt(libStem);
#if defined(LLVM_ON_UNIX)
#ifdef __APPLE__
      llvm::SmallString<512>::iterator IStemEnd = filenameWithExt.end() - 1;
#endif
      static const char* DyLibExt = ".so";
#elif defined(LLVM_ON_WIN32)
      static const char* DyLibExt = ".dll";
#else
# error "Unsupported platform."
#endif
      filenameWithExt += DyLibExt;
      foundDyLib = lookupLibInPaths(filenameWithExt);
#ifdef __APPLE__
      if (foundDyLib.empty()) {
        filenameWithExt.erase(IStemEnd + 1, filenameWithExt.end());
        filenameWithExt += ".dylib";
        foundDyLib = lookupLibInPaths(filenameWithExt);
      }
#endif
    }

    if (foundDyLib.empty())
      return "";

    // get canonical path name and check if already loaded
#if defined(LLVM_ON_WIN32)
    llvm::SmallString<_MAX_PATH> FullPath("");
    char *res = _fullpath((char *)FullPath.data(), foundDyLib.c_str(), _MAX_PATH);
#else
    llvm::SmallString<PATH_MAX+1> FullPath("");
    char *res = realpath(foundDyLib.c_str(), (char *)FullPath.data());
#endif
    if (res == 0) {
      llvm::errs() << "cling::DyLibMan::lookupLibMaybeAddExt(): error getting "
        "real (canonical) path of library " << foundDyLib << '\n';
      return foundDyLib;
    }
    FullPath.set_size(strlen(res));
    return FullPath.str();
  }

  static std::string normalizePath(llvm::StringRef path) {
    // Make the path canonical if the file exists.
    struct stat buffer;
    if (stat(path.data(), &buffer) != 0)
      return "";
#if defined(LLVM_ON_WIN32)
    char buf[_MAX_PATH];
    char *res = _fullpath(buf, path.data(), _MAX_PATH);
#else
    char buf[PATH_MAX+1];
    char *res = realpath(path.data(), buf);
#endif
    if (res == 0) {
      assert(0 && "Cannot normalize!?");
      return "";
    }
    return res;
  }

  std::string
  DynamicLibraryManager::lookupLibrary(llvm::StringRef libStem) const {
    llvm::SmallString<128> Absolute(libStem);
    llvm::sys::fs::make_absolute(Absolute);
    bool isAbsolute = libStem == Absolute;

    // If it is an absolute path, don't try iterate over the paths.
    if (isAbsolute) {
      if (isSharedLib(libStem))
        return normalizePath(libStem);
      else
        return "";
    }

    std::string foundName = lookupLibMaybeAddExt(libStem);
    if (foundName.empty() && !libStem.startswith("lib")) {
      // try with "lib" prefix:
      foundName = lookupLibMaybeAddExt("lib" + libStem.str());
    }

    if (isSharedLib(foundName))
      return normalizePath(foundName);
    return "";
  }

  DynamicLibraryManager::LoadLibResult
  DynamicLibraryManager::loadLibrary(const std::string& libStem,
                                     bool permanent) {
    std::string canonicalLoadedLib = lookupLibrary(libStem);
    if (canonicalLoadedLib.empty())
      return kLoadLibNotFound;

    if (m_LoadedLibraries.find(canonicalLoadedLib) != m_LoadedLibraries.end())
      return kLoadLibAlreadyLoaded;

    std::string errMsg;
    // TODO: !permanent case
#if defined(LLVM_ON_WIN32)
    HMODULE dyLibHandle = LoadLibraryEx(canonicalLoadedLib.c_str(), NULL,
                                        DONT_RESOLVE_DLL_REFERENCES);
    errMsg = "LoadLibraryEx: GetLastError() returned ";
    errMsg += GetLastError();
#else
    const void* dyLibHandle = dlopen(canonicalLoadedLib.c_str(),
                                     RTLD_LAZY|RTLD_GLOBAL);
    if (const char* DyLibError = dlerror()) {
      errMsg = DyLibError;
    }
#endif
    if (!dyLibHandle) {
      llvm::errs() << "cling::DyLibMan::loadLibrary(): " << errMsg << '\n';
      return kLoadLibLoadError;
    }
    std::pair<DyLibs::iterator, bool> insRes
      = m_DyLibs.insert(std::pair<DyLibHandle, std::string>(dyLibHandle,
                                                            canonicalLoadedLib));
    if (!insRes.second)
      return kLoadLibAlreadyLoaded;
    m_LoadedLibraries.insert(canonicalLoadedLib);
    return kLoadLibSuccess;
  }

  void DynamicLibraryManager::unloadLibrary(llvm::StringRef libStem) {
    std::string canonicalLoadedLib = lookupLibrary(libStem);
    if (!isLibraryLoaded(canonicalLoadedLib))
      return;

    DyLibHandle dyLibHandle = 0;
    for (DyLibs::const_iterator I = m_DyLibs.begin(), E = m_DyLibs.end();
         I != E; ++I) {
      if (I->second == canonicalLoadedLib)
        dyLibHandle = I->first;
    }

    std::string errMsg;
    // TODO: !permanent case
#if defined(LLVM_ON_WIN32)
    FreeLibrary(dyLibHandle);
    errMsg = "UnoadLibraryEx: GetLastError() returned ";
    errMsg += GetLastError();
#else
    dlclose(const_cast<void*>(dyLibHandle));
    if (const char* DyLibError = dlerror()) {
      errMsg = DyLibError;
    }
#endif
    m_DyLibs.erase(dyLibHandle);
    m_LoadedLibraries.erase(canonicalLoadedLib);
  }

  bool DynamicLibraryManager::isLibraryLoaded(llvm::StringRef fullPath) const {
    std::string canonPath = normalizePath(fullPath);
    if (m_LoadedLibraries.find(canonPath) != m_LoadedLibraries.end())
      return true;
    return false;
  }

  void DynamicLibraryManager::ExposeHiddenSharedLibrarySymbols(void* handle) {
    llvm::sys::DynamicLibrary::addPermanentLibrary(const_cast<void*>(handle));
  }
} // end namespace cling
<|endoftext|>


<commit_before>// Copyright (c) 2016 ASMlover. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
//  * Redistributions of source code must retain the above copyright
//    notice, this list ofconditions and the following disclaimer.
//
//  * Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in
//    the documentation and/or other materialsprovided 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 HOLDER 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 <exception>
#include <iostream>
#include <string>
#include "co/co_unittest.h"
#include "tpp_types.h"
#include "tpp_thread.h"
#include "tpp_backtrace.h"
#include "tpp_corotine.h"
#include "tpp_intrusive_ptr.h"

#define __TPP_LITTLE_ENDIAN (0x41424344UL)
#define __TPP_BIG_ENDIAN    (0x44434241UL)
#define __TPP_PDP_ENDIAN    (0x42414443UL)
#define __TPP_BYTE_ORDER    ('ABCD')

enum {
  TPP_LITTLE_ENDIAN = 0x03020100ul,
  TPP_BIG_ENDIAN = 0x00010203ul,
  TPP_PDP_ENDIAN = 0x01000302ul,
};
static const union { unsigned char bytes[4]; uint32_t value; } tpp_byte_order = {{0, 1, 2, 3}};
#define TPP_BYTE_ORDER (tpp_byte_order.value)

void thread_closure(void* arg) {
  std::cout << "**************** thread_closure ************* " << arg << std::endl;
}

void corotine_closure(void* arg) {
  tpp::Corotine* co = (tpp::Corotine*)arg;
  auto c = co->running();
  for (auto i = 0; i < 5; ++i) {
    std::cout << "**************** corotine_closure ************* " << c << std::endl;
    co->yield();
  }
}

class Integer : public tpp::IntrusiveRefCounter<Integer, tpp::ThreadUnsafeCounter> {
public:
  Integer(void) {
    std::cout << "********** Integer::Integer **********" << std::endl;
  }

  ~Integer(void) {
    std::cout << "********** Integer::~Integer **********" << std::endl;
  }
};

int main(int argc, char* argv[]) {
  TPP_UNUSED(argc);
  TPP_UNUSED(argv);

  std::cout << "Hello, `tpp` !" << std::endl;

  {
    // byte order checking
    // if (__TPP_BYTE_ORDER == __TPP_LITTLE_ENDIAN)
    if (TPP_BYTE_ORDER == TPP_LITTLE_ENDIAN)
      std::cout << "little endian" << std::endl;
    else if (BYTE_ORDER == BIG_ENDIAN)
      std::cout << "big endian" << std::endl;
    else if (BYTE_ORDER == PDP_ENDIAN)
      std::cout << "pdp endian" << std::endl;
    else
      std::cout << "error endian" << std::endl;
  }

  {
    // thread sample
    tpp::Thread t(thread_closure, nullptr);
    t.join();
  }
  {
    // backtrace sample
    std::string bt;
    tpp::__libtpp_backtrace(bt);
    std::cout << bt << std::endl;
  }
  {
    // intrusive pointer sample
    tpp::IntrusivePtr<Integer> p(new Integer());
  }
  co::test::run_all_unittests();

  {
    // corotine sample
    tpp::Corotine co;
    auto c1 = co.create(corotine_closure, &co);
    auto c2 = co.create(corotine_closure, &co);

    while (tpp::CoStatus::DEAD != co.status(c1)
        && tpp::CoStatus::DEAD != co.status(c2)) {
      std::cout << "================ main corotine - corotines status >> " << (int)co.status(c1) << " : " << (int)co.status(c2) << std::endl;
      co.resume(c1);
      co.resume(c2);
    }
    std::cout << "================ return main thread ================" << std::endl;
  }

  return 0;
}
<commit_msg>fix(tpp): fixed bug of get byte order<commit_after>// Copyright (c) 2016 ASMlover. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
//  * Redistributions of source code must retain the above copyright
//    notice, this list ofconditions and the following disclaimer.
//
//  * Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in
//    the documentation and/or other materialsprovided 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 HOLDER 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 <exception>
#include <iostream>
#include <string>
#include "co/co_unittest.h"
#include "tpp_types.h"
#include "tpp_thread.h"
#include "tpp_backtrace.h"
#include "tpp_corotine.h"
#include "tpp_intrusive_ptr.h"

#define __TPP_LITTLE_ENDIAN (0x41424344UL)
#define __TPP_BIG_ENDIAN    (0x44434241UL)
#define __TPP_PDP_ENDIAN    (0x42414443UL)
#define __TPP_BYTE_ORDER    ('ABCD')

enum {
  TPP_LITTLE_ENDIAN = 0x03020100ul,
  TPP_BIG_ENDIAN = 0x00010203ul,
  TPP_PDP_ENDIAN = 0x01000302ul,
};
static const union { unsigned char bytes[4]; uint32_t value; } tpp_byte_order = {{0, 1, 2, 3}};
#define TPP_BYTE_ORDER (tpp_byte_order.value)

void thread_closure(void* arg) {
  std::cout << "**************** thread_closure ************* " << arg << std::endl;
}

void corotine_closure(void* arg) {
  tpp::Corotine* co = (tpp::Corotine*)arg;
  auto c = co->running();
  for (auto i = 0; i < 5; ++i) {
    std::cout << "**************** corotine_closure ************* " << c << std::endl;
    co->yield();
  }
}

class Integer : public tpp::IntrusiveRefCounter<Integer, tpp::ThreadUnsafeCounter> {
public:
  Integer(void) {
    std::cout << "********** Integer::Integer **********" << std::endl;
  }

  ~Integer(void) {
    std::cout << "********** Integer::~Integer **********" << std::endl;
  }
};

int main(int argc, char* argv[]) {
  TPP_UNUSED(argc);
  TPP_UNUSED(argv);

  std::cout << "Hello, `tpp` !" << std::endl;

  {
    // byte order checking
    // if (__TPP_BYTE_ORDER == __TPP_LITTLE_ENDIAN)
    if (TPP_BYTE_ORDER == TPP_LITTLE_ENDIAN)
      std::cout << "little endian" << std::endl;
    else if (TPP_BYTE_ORDER == TPP_BIG_ENDIAN)
      std::cout << "big endian" << std::endl;
    else if (TPP_BYTE_ORDER == TPP_PDP_ENDIAN)
      std::cout << "pdp endian" << std::endl;
    else
      std::cout << "error endian" << std::endl;
  }

  {
    // thread sample
    tpp::Thread t(thread_closure, nullptr);
    t.join();
  }
  {
    // backtrace sample
    std::string bt;
    tpp::__libtpp_backtrace(bt);
    std::cout << bt << std::endl;
  }
  {
    // intrusive pointer sample
    tpp::IntrusivePtr<Integer> p(new Integer());
  }
  co::test::run_all_unittests();

  {
    // corotine sample
    tpp::Corotine co;
    auto c1 = co.create(corotine_closure, &co);
    auto c2 = co.create(corotine_closure, &co);

    while (tpp::CoStatus::DEAD != co.status(c1)
        && tpp::CoStatus::DEAD != co.status(c2)) {
      std::cout << "================ main corotine - corotines status >> " << (int)co.status(c1) << " : " << (int)co.status(c2) << std::endl;
      co.resume(c1);
      co.resume(c2);
    }
    std::cout << "================ return main thread ================" << std::endl;
  }

  return 0;
}
<|endoftext|>


<commit_before>//*********************************************************
//
// Copyright (c) Microsoft. All rights reserved.
// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//*********************************************************
#include "pch.h"
#if !TV_API && defined(_WIN32)
#include <Pathcch.h>
#endif
#include "xsapi/system.h"
#include "local_config.h"
#include "xbox_system_factory.h"
#include "Utils.h"
#if XSAPI_A
#include "a/user_impl_a.h"
#include "a/java_interop.h"
#endif

using namespace std;
NAMESPACE_MICROSOFT_XBOX_SERVICES_CPP_BEGIN

std::shared_ptr<local_config> local_config::get_local_config_singleton()
{
    auto xsapiSingleton = get_xsapi_singleton();
    std::lock_guard<std::mutex> guard(xsapiSingleton->s_singletonLock);
    if (xsapiSingleton->s_localConfigSingleton == nullptr)
    {
        xsapiSingleton->s_localConfigSingleton = std::make_shared<local_config>();

#if !TV_API
        xbox_live_result<void> configResult = xsapiSingleton->s_localConfigSingleton->read();
        if (configResult.err())
        {
            LOGS_ERROR << "Loading local config file error: " << configResult.err() << ", msg:" << configResult.err_message();
            XSAPI_ASSERT(!configResult.err());
        }
#endif
    }
    return xsapiSingleton->s_localConfigSingleton;
}

local_config::local_config()
{
}

#if !TV_API
uint64_t local_config::get_uint64_from_config(
    _In_ const string_t& name,
    _In_ bool required,
    _In_ uint64_t defaultValue
    )
{
    std::lock_guard<std::mutex> guard(m_jsonConfigLock);
    return utils::extract_json_uint52(m_jsonConfig, name.c_str(), required, defaultValue);
}

string_t local_config::get_value_from_config(
    _In_ const string_t& name,
    _In_ bool required,
    _In_ const string_t& defaultValue
    )
{
    std::lock_guard<std::mutex> guard(m_jsonConfigLock);
    return utils::extract_json_string(m_jsonConfig, name.c_str(), required, defaultValue);
}

bool local_config::get_bool_from_config(
    _In_ const string_t& name,
    _In_ bool required,
    _In_ bool defaultValue
    )
{
    std::lock_guard<std::mutex> guard(m_jsonConfigLock);

    std::error_code err;
    auto value = utils::extract_json_field(m_jsonConfig, name.c_str(), err, required);

    // the value could be "0", "1", or true false
    if (value.is_boolean())
    {
        return value.as_bool();
    }
    else if (value.is_string())
    {
        return value.as_string() == _T("1");
    }
    else
    {
        return defaultValue;
    }
}

uint32_t local_config::title_id()
{
    uint64_t titleId = get_uint64_from_config(_T("TitleId"), false, 0);

    // Also support title id in string from
    if (titleId == 0)
    {
        string_t titleIdString = get_value_from_config(_T("TitleId"), false, _T(""));
        if (!titleIdString.empty())
        {
            titleId = utils::string_t_to_uint64(titleIdString);
        }
    }

    return static_cast<uint32_t>(titleId);
}

string_t local_config::scid()
{
    return get_value_from_config(_T("PrimaryServiceConfigId"), false, _T(""));
}

uint32_t local_config::override_title_id()
{
    uint64_t titleId = get_uint64_from_config(_T("OverrideTitleId"), false, 0);
    return static_cast<uint32_t>(titleId);
}

string_t local_config::override_scid()
{
    return get_value_from_config(_T("OverrideServiceConfigId"), false, _T(""));
}

string_t local_config::environment_prefix()
{
    return get_value_from_config(_T("EnvironmentPrefix"), false, _T(""));
}

string_t local_config::environment()
{
    string_t environment = get_value_from_config(_T("Environment"), false, _T(""));
    if (!environment.empty())
    {
        if (environment[0] != _T('.'))
        {
            environment = _T(".") + environment;
        }
    }

    return environment;
}

string_t local_config::sandbox()
{
    return get_value_from_config(_T("Sandbox"), false, _T("RETAIL"));
}

string_t local_config::client_secret()
{
    return get_value_from_config(_T("ClientSecret"), false, _T(""));
}

bool local_config::use_first_party_token()
{
    return get_bool_from_config(_T("FirstParty"), false, false);
}

#if XSAPI_I
string_t local_config::apns_environment()
{
    return get_value_from_config(_T("ApnsEnvironment"), false, _T("apnsProduction"));
}
#endif

#endif
NAMESPACE_MICROSOFT_XBOX_SERVICES_CPP_END

<commit_msg>Adding support for titleId in hex (#59)<commit_after>//*********************************************************
//
// Copyright (c) Microsoft. All rights reserved.
// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//*********************************************************
#include "pch.h"
#if !TV_API && defined(_WIN32)
#include <Pathcch.h>
#endif
#include "xsapi/system.h"
#include "local_config.h"
#include "xbox_system_factory.h"
#include "Utils.h"
#if XSAPI_A
#include "a/user_impl_a.h"
#include "a/java_interop.h"
#endif

using namespace std;
NAMESPACE_MICROSOFT_XBOX_SERVICES_CPP_BEGIN

std::shared_ptr<local_config> local_config::get_local_config_singleton()
{
    auto xsapiSingleton = get_xsapi_singleton();
    std::lock_guard<std::mutex> guard(xsapiSingleton->s_singletonLock);
    if (xsapiSingleton->s_localConfigSingleton == nullptr)
    {
        xsapiSingleton->s_localConfigSingleton = std::make_shared<local_config>();

#if !TV_API
        xbox_live_result<void> configResult = xsapiSingleton->s_localConfigSingleton->read();
        if (configResult.err())
        {
            LOGS_ERROR << "Loading local config file error: " << configResult.err() << ", msg:" << configResult.err_message();
            XSAPI_ASSERT(!configResult.err());
        }
#endif
    }
    return xsapiSingleton->s_localConfigSingleton;
}

local_config::local_config()
{
}

#if !TV_API
uint64_t local_config::get_uint64_from_config(
    _In_ const string_t& name,
    _In_ bool required,
    _In_ uint64_t defaultValue
    )
{
    std::lock_guard<std::mutex> guard(m_jsonConfigLock);
    return utils::extract_json_uint52(m_jsonConfig, name.c_str(), required, defaultValue);
}

string_t local_config::get_value_from_config(
    _In_ const string_t& name,
    _In_ bool required,
    _In_ const string_t& defaultValue
    )
{
    std::lock_guard<std::mutex> guard(m_jsonConfigLock);
    return utils::extract_json_string(m_jsonConfig, name.c_str(), required, defaultValue);
}

bool local_config::get_bool_from_config(
    _In_ const string_t& name,
    _In_ bool required,
    _In_ bool defaultValue
    )
{
    std::lock_guard<std::mutex> guard(m_jsonConfigLock);

    std::error_code err;
    auto value = utils::extract_json_field(m_jsonConfig, name.c_str(), err, required);

    // the value could be "0", "1", or true false
    if (value.is_boolean())
    {
        return value.as_bool();
    }
    else if (value.is_string())
    {
        return value.as_string() == _T("1");
    }
    else
    {
        return defaultValue;
    }
}

uint32_t local_config::title_id()
{
    uint64_t titleId = get_uint64_from_config(_T("TitleId"), false, 0);

    // Also support title id in string dec form or string hex form
    if (titleId == 0)
    {
        string_t titleIdString = get_value_from_config(_T("TitleId"), false, _T(""));
        if (!titleIdString.empty())
        {
            titleId = utils::string_t_to_uint64(titleIdString);
            if (titleId == 0)
            {
                stringstream_t ss;
                ss << std::hex << titleIdString;
                ss >> titleId;
            }
        }
    }

    return static_cast<uint32_t>(titleId);
}

string_t local_config::scid()
{
    return get_value_from_config(_T("PrimaryServiceConfigId"), false, _T(""));
}

uint32_t local_config::override_title_id()
{
    uint64_t titleId = get_uint64_from_config(_T("OverrideTitleId"), false, 0);
    return static_cast<uint32_t>(titleId);
}

string_t local_config::override_scid()
{
    return get_value_from_config(_T("OverrideServiceConfigId"), false, _T(""));
}

string_t local_config::environment_prefix()
{
    return get_value_from_config(_T("EnvironmentPrefix"), false, _T(""));
}

string_t local_config::environment()
{
    string_t environment = get_value_from_config(_T("Environment"), false, _T(""));
    if (!environment.empty())
    {
        if (environment[0] != _T('.'))
        {
            environment = _T(".") + environment;
        }
    }

    return environment;
}

string_t local_config::sandbox()
{
    return get_value_from_config(_T("Sandbox"), false, _T("RETAIL"));
}

string_t local_config::client_secret()
{
    return get_value_from_config(_T("ClientSecret"), false, _T(""));
}

bool local_config::use_first_party_token()
{
    return get_bool_from_config(_T("FirstParty"), false, false);
}

#if XSAPI_I
string_t local_config::apns_environment()
{
    return get_value_from_config(_T("ApnsEnvironment"), false, _T("apnsProduction"));
}
#endif

#endif
NAMESPACE_MICROSOFT_XBOX_SERVICES_CPP_END

<|endoftext|>


<commit_before>#include <cilantro/connected_component_segmentation.hpp>
#include <stack>

#include <iostream>

ConnectedComponentSegmentation::ConnectedComponentSegmentation(const std::vector<Eigen::Vector3f> &points, const std::vector<Eigen::Vector3f> &normals, const std::vector<Eigen::Vector3f> &colors)
        : points_(&points),
          normals_((normals.size() == points.size()) ? &normals : NULL),
          colors_((colors.size() == points.size()) ? &colors : NULL),
          kd_tree_(new KDTree(points)),
          kd_tree_owned_(true)
{}

ConnectedComponentSegmentation::ConnectedComponentSegmentation(const std::vector<Eigen::Vector3f> &points, const std::vector<Eigen::Vector3f> &normals, const std::vector<Eigen::Vector3f> &colors, const KDTree &kd_tree)
        : points_(&points),
          normals_((normals.size() == points.size()) ? &normals : NULL),
          colors_((colors.size() == points.size()) ? &colors : NULL),
          kd_tree_((KDTree*)&kd_tree),
          kd_tree_owned_(false)
{}

ConnectedComponentSegmentation::ConnectedComponentSegmentation(const PointCloud &cloud)
        : points_(&cloud.points),
          normals_((cloud.normals.size() == cloud.points.size()) ? &cloud.normals : NULL),
          colors_((cloud.colors.size() == cloud.points.size()) ? &cloud.colors : NULL),
          kd_tree_(new KDTree(cloud.points)),
          kd_tree_owned_(true)
{}

ConnectedComponentSegmentation::ConnectedComponentSegmentation(const PointCloud &cloud, const KDTree &kd_tree)
        : points_(&cloud.points),
          normals_((cloud.normals.size() == cloud.points.size()) ? &cloud.normals : NULL),
          colors_((cloud.colors.size() == cloud.points.size()) ? &cloud.colors : NULL),
          kd_tree_((KDTree*)&kd_tree),
          kd_tree_owned_(false)
{}

ConnectedComponentSegmentation::~ConnectedComponentSegmentation() {
    if (kd_tree_owned_) delete kd_tree_;
}

ConnectedComponentSegmentation& ConnectedComponentSegmentation::segment(std::vector<size_t> seeds_ind,
                                                                        float dist_thresh,
                                                                        float normal_angle_thresh,
                                                                        float color_diff_thresh,
                                                                        size_t min_segment_size,
                                                                        size_t max_segment_size)
{
    dist_thresh_ = dist_thresh;
    normal_angle_thresh_ = normal_angle_thresh;
    color_diff_thresh_ = color_diff_thresh;
    min_segment_size_ = min_segment_size;
    max_segment_size_ = max_segment_size;

    std::vector<bool> has_been_assigned(points_->size(), false);

    std::vector<size_t> neighbors;
    std::vector<float> distances;

    component_indices_.clear();
    for (size_t i = 0; i < seeds_ind.size(); i++) {
        if (has_been_assigned[seeds_ind[i]]) continue;

        std::vector<size_t> curr_cc_ind;
        std::vector<bool> is_in_stack(points_->size(), 0);

        std::stack<size_t> seeds_stack;
        seeds_stack.push(seeds_ind[i]);
        is_in_stack[seeds_ind[i]] = 1;
        while (!seeds_stack.empty()) {
            size_t curr_seed = seeds_stack.top();
            seeds_stack.pop();

            has_been_assigned[curr_seed] = 1;
            curr_cc_ind.emplace_back(curr_seed);

            kd_tree_->radiusSearch((*points_)[curr_seed], dist_thresh_, neighbors, distances);

            for (size_t j = 0; j < neighbors.size(); j++) {
                if (is_similar_(curr_seed,neighbors[j]) && !is_in_stack[neighbors[j]]) {
                    seeds_stack.push(neighbors[j]);
                    is_in_stack[neighbors[j]] = 1;
                }
            }

        }

        if (curr_cc_ind.size() >= min_segment_size_ && curr_cc_ind.size() <= max_segment_size_) {
            component_indices_.emplace_back(curr_cc_ind);
        }
    }

    std::sort(component_indices_.begin(), component_indices_.end(), vector_size_comparator_);

    label_map_ = std::vector<size_t>(points_->size(), component_indices_.size());
    for (size_t i = 0; i < component_indices_.size(); i++) {
        for (size_t j = 0; j < component_indices_[i].size(); j++) {
            label_map_[component_indices_[i][j]] = i;
        }
    }

    return *this;
}

ConnectedComponentSegmentation& ConnectedComponentSegmentation::segment(float dist_thresh,
                                                                        float normal_angle_thresh,
                                                                        float color_diff_thresh,
                                                                        size_t min_segment_size,
                                                                        size_t max_segment_size)
{
    std::vector<size_t> seeds_ind(points_->size());
    for (size_t i = 0; i < seeds_ind.size(); i++) {
        seeds_ind[i] = i;
    }
    return segment(seeds_ind, dist_thresh, normal_angle_thresh, color_diff_thresh, min_segment_size, max_segment_size);
}
<commit_msg>Connected component segmentation improvements<commit_after>#include <cilantro/connected_component_segmentation.hpp>
#include <stack>

#include <iostream>

ConnectedComponentSegmentation::ConnectedComponentSegmentation(const std::vector<Eigen::Vector3f> &points, const std::vector<Eigen::Vector3f> &normals, const std::vector<Eigen::Vector3f> &colors)
        : points_(&points),
          normals_((normals.size() == points.size()) ? &normals : NULL),
          colors_((colors.size() == points.size()) ? &colors : NULL),
          kd_tree_(new KDTree(points)),
          kd_tree_owned_(true)
{}

ConnectedComponentSegmentation::ConnectedComponentSegmentation(const std::vector<Eigen::Vector3f> &points, const std::vector<Eigen::Vector3f> &normals, const std::vector<Eigen::Vector3f> &colors, const KDTree &kd_tree)
        : points_(&points),
          normals_((normals.size() == points.size()) ? &normals : NULL),
          colors_((colors.size() == points.size()) ? &colors : NULL),
          kd_tree_((KDTree*)&kd_tree),
          kd_tree_owned_(false)
{}

ConnectedComponentSegmentation::ConnectedComponentSegmentation(const PointCloud &cloud)
        : points_(&cloud.points),
          normals_((cloud.normals.size() == cloud.points.size()) ? &cloud.normals : NULL),
          colors_((cloud.colors.size() == cloud.points.size()) ? &cloud.colors : NULL),
          kd_tree_(new KDTree(cloud.points)),
          kd_tree_owned_(true)
{}

ConnectedComponentSegmentation::ConnectedComponentSegmentation(const PointCloud &cloud, const KDTree &kd_tree)
        : points_(&cloud.points),
          normals_((cloud.normals.size() == cloud.points.size()) ? &cloud.normals : NULL),
          colors_((cloud.colors.size() == cloud.points.size()) ? &cloud.colors : NULL),
          kd_tree_((KDTree*)&kd_tree),
          kd_tree_owned_(false)
{}

ConnectedComponentSegmentation::~ConnectedComponentSegmentation() {
    if (kd_tree_owned_) delete kd_tree_;
}

ConnectedComponentSegmentation& ConnectedComponentSegmentation::segment(std::vector<size_t> seeds_ind,
                                                                        float dist_thresh,
                                                                        float normal_angle_thresh,
                                                                        float color_diff_thresh,
                                                                        size_t min_segment_size,
                                                                        size_t max_segment_size)
{
    dist_thresh_ = dist_thresh;
    normal_angle_thresh_ = normal_angle_thresh;
    color_diff_thresh_ = color_diff_thresh;
    min_segment_size_ = min_segment_size;
    max_segment_size_ = max_segment_size;

    std::vector<bool> has_been_assigned(points_->size(), false);

    std::vector<size_t> neighbors;
    std::vector<float> distances;

    component_indices_.clear();
    for (size_t i = 0; i < seeds_ind.size(); i++) {
        if (has_been_assigned[seeds_ind[i]]) continue;

        std::stack<size_t> seeds_stack;
        seeds_stack.push(seeds_ind[i]);
        has_been_assigned[seeds_ind[i]] = true;

        std::vector<size_t> curr_cc_ind;
        while (!seeds_stack.empty()) {
            size_t curr_seed = seeds_stack.top();
            seeds_stack.pop();
            curr_cc_ind.emplace_back(curr_seed);

            kd_tree_->radiusSearch((*points_)[curr_seed], dist_thresh_, neighbors, distances);
            for (size_t j = 1; j < neighbors.size(); j++) {
                if (!has_been_assigned[neighbors[j]] && is_similar_(curr_seed,neighbors[j])) {
                    seeds_stack.push(neighbors[j]);
                    has_been_assigned[neighbors[j]] = true;
                }
            }

        }

        if (curr_cc_ind.size() >= min_segment_size_ && curr_cc_ind.size() <= max_segment_size_) {
            component_indices_.emplace_back(curr_cc_ind);
        }
    }

    std::sort(component_indices_.begin(), component_indices_.end(), vector_size_comparator_);

    label_map_ = std::vector<size_t>(points_->size(), component_indices_.size());
    for (size_t i = 0; i < component_indices_.size(); i++) {
        for (size_t j = 0; j < component_indices_[i].size(); j++) {
            label_map_[component_indices_[i][j]] = i;
        }
    }

    return *this;
}

ConnectedComponentSegmentation& ConnectedComponentSegmentation::segment(float dist_thresh,
                                                                        float normal_angle_thresh,
                                                                        float color_diff_thresh,
                                                                        size_t min_segment_size,
                                                                        size_t max_segment_size)
{
    std::vector<size_t> seeds_ind(points_->size());
    for (size_t i = 0; i < seeds_ind.size(); i++) {
        seeds_ind[i] = i;
    }
    return segment(seeds_ind, dist_thresh, normal_angle_thresh, color_diff_thresh, min_segment_size, max_segment_size);
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: ScaleAutomatism.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: hr $ $Date: 2004-05-11 14:11:16 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  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
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2003 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
#include "ScaleAutomatism.hxx"
#include "macros.hxx"
#include "TickmarkHelper.hxx"

#ifndef _COM_SUN_STAR_LANG_XSERVICENAME_HPP_
#include <com/sun/star/lang/XServiceName.hpp>
#endif

#ifndef INCLUDED_RTL_MATH_HXX
#include <rtl/math.hxx>
#endif

#ifndef _TOOLS_DEBUG_HXX
#include <tools/debug.hxx>
#endif

//.............................................................................
namespace chart
{
//.............................................................................
using namespace ::com::sun::star;
using namespace ::com::sun::star::chart2;

ScaleAutomatism::ScaleAutomatism( const ScaleData& rSourceScale )
                    : m_fValueMinimum( 0.0 )
                    , m_fValueMaximum( 0.0 )
                    , m_nMaximumAutomaticMainIncrementCount(10)
                    , m_aSourceScale( rSourceScale )
                    , m_aSourceIncrement()
                    , m_aSourceSubIncrementList()
{
    ::rtl::math::setNan( &m_fValueMinimum );
    ::rtl::math::setNan( &m_fValueMaximum );
}

ScaleAutomatism::ScaleAutomatism( const ScaleData& rSourceScale
                    , const IncrementData& rSourceIncrement
                    , const uno::Sequence< SubIncrement >& rSourceSubIncrementList )
                    : m_fValueMinimum( 0.0 )
                    , m_fValueMaximum( 0.0 )
                    , m_nMaximumAutomaticMainIncrementCount(9)
                    , m_aSourceScale( rSourceScale )
                    , m_aSourceIncrement( rSourceIncrement )
                    , m_aSourceSubIncrementList( rSourceSubIncrementList )
{
    ::rtl::math::setNan( &m_fValueMinimum );
    ::rtl::math::setNan( &m_fValueMaximum );
}

ScaleAutomatism::~ScaleAutomatism()
{
}

//@todo these method should become part of the scaling interface and implementation somehow
//@todo problem with outparamters at api
ExplicitIncrementData getExplicitIncrementAndScaleForLogarithm(
        bool bChangeMinimumToIncrementRythm, bool bChangeMaximumToIncrementRythm
        , sal_Int32 nMaximumAutomaticMainIncrementCount
        , ExplicitScaleData& rExplicitScale
        , const IncrementData& rSourceIncrement
        , const uno::Sequence< SubIncrement >& rSourceSubIncrementList )
{
    //minimum and maximum of the ExplicitScaleData may be changed
    //to suiteable values if allowed
    //but they will definitly be changed if they are out of allowed borders

    if( nMaximumAutomaticMainIncrementCount <= 0 )
        nMaximumAutomaticMainIncrementCount = 5;

    //make sure that minimum and maximum are not out of allowed range
    {
        if( rExplicitScale.Maximum<=0.0 )
            rExplicitScale.Maximum = 100.0;
        if( rExplicitScale.Minimum<=0.0 )
        {
            rExplicitScale.Minimum = 0.1;
            if( rExplicitScale.Minimum >= rExplicitScale.Maximum )
                rExplicitScale.Minimum =  log(rExplicitScale.Maximum)/10.0;
        }
        if( rExplicitScale.Maximum<= rExplicitScale.Minimum )
            rExplicitScale.Maximum = rExplicitScale.Minimum + 10;
    }

    ExplicitIncrementData aRet;
    if(!(rSourceIncrement.PostEquidistant>>=aRet.PostEquidistant))
    {
        //maybe scaling dependent
        aRet.PostEquidistant = sal_True;
    }
    if(!(rSourceIncrement.Distance>>=aRet.Distance))
    {
        //autocalculate the distance
        if(aRet.PostEquidistant && rExplicitScale.Scaling.is() )
        {
            double fRange = rExplicitScale.Scaling->doScaling( rExplicitScale.Maximum )
                          - rExplicitScale.Scaling->doScaling( rExplicitScale.Minimum );
            double fSlice = fRange/nMaximumAutomaticMainIncrementCount;
            //make a fine value out of fSlice now:
            //only integers are reasonable as distance values
            sal_Int32 nDistance = static_cast<sal_Int32>(fSlice);
            if(nDistance<=0)
                nDistance=1;
            aRet.Distance = nDistance;
        }
        else
        {
            //@todo this was not tested
            double fRange = rExplicitScale.Maximum - rExplicitScale.Minimum;
            double fSlice = fRange/nMaximumAutomaticMainIncrementCount;
            //make a fine value out of fSlice now:
            double fSliceMagnitude = pow ( (double)10, floor (log10 (fSlice)));
            aRet.Distance = static_cast<sal_Int32>(fSlice/fSliceMagnitude)*fSliceMagnitude;
        }
    }

    if(!(rSourceIncrement.BaseValue>>=aRet.BaseValue))
    {
        //scaling dependent
        //@maybe todo is this default also plotter dependent ??
        aRet.BaseValue = 1.0;
    }
    else if( aRet.BaseValue<=0.0 ) //make sure that BaseValue is not out of allowed ranges
        aRet.BaseValue = 1.0;

    if(bChangeMinimumToIncrementRythm)
    {
        double fMin = rExplicitScale.Minimum;
        if( aRet.PostEquidistant && rExplicitScale.Scaling.is() )
            fMin = rExplicitScale.Scaling->doScaling(fMin);

        fMin = TickmarkHelper::getMinimumAtIncrement( fMin, aRet );
        if( aRet.PostEquidistant && rExplicitScale.Scaling.is() )
            fMin = rExplicitScale.Scaling->getInverseScaling()->doScaling(fMin);
        rExplicitScale.Minimum = fMin;

        if( rExplicitScale.Minimum<=0.0 )
        {
            rExplicitScale.Minimum = 0.1;
            if( rExplicitScale.Minimum >= rExplicitScale.Maximum )
                rExplicitScale.Minimum =  log(rExplicitScale.Maximum)/10.0;
        }
    }
    if(bChangeMaximumToIncrementRythm)
    {
        double fMax = rExplicitScale.Maximum;
        if( aRet.PostEquidistant && rExplicitScale.Scaling.is() )
            fMax = rExplicitScale.Scaling->doScaling(fMax);
        fMax = TickmarkHelper::getMaximumAtIncrement( fMax, aRet );
        if( aRet.PostEquidistant && rExplicitScale.Scaling.is() )
            fMax = rExplicitScale.Scaling->getInverseScaling()->doScaling(fMax);
        rExplicitScale.Maximum = fMax;
    }
    //---------------------------------------------------------------
    //fill explicit sub increment
    sal_Int32 nSubCount = rSourceSubIncrementList.getLength();
    aRet.SubIncrements.realloc(nSubCount);
    for( sal_Int32 nN=0; nN<nSubCount; nN++ )
    {
        const SubIncrement&     rSubIncrement         = rSourceSubIncrementList[nN];
        ExplicitSubIncrement&   rExplicitSubIncrement = aRet.SubIncrements[nN];

        if(!(rSubIncrement.IntervalCount>>=rExplicitSubIncrement.IntervalCount))
        {
            //scaling dependent
            //@todo autocalculate IntervalCount dependent on MainIncrement and scaling
            rExplicitSubIncrement.IntervalCount = 5;
        }
        if(!(rSubIncrement.PostEquidistant>>=rExplicitSubIncrement.PostEquidistant))
        {
            //scaling dependent
            rExplicitSubIncrement.PostEquidistant = sal_False;
        }
    }
    return aRet;
}

ExplicitIncrementData getExplicitIncrementAndScaleForLinear(
        bool bChangeMinimumToIncrementRythm, bool bChangeMaximumToIncrementRythm
        , sal_Int32 nMaximumAutomaticMainIncrementCount
        , ExplicitScaleData& rExplicitScale
        , const IncrementData& rSourceIncrement
        , const uno::Sequence< SubIncrement >& rSourceSubIncrementList )
{
    //minimum and maximum of the ExplicitScaleData may be changed
    //to suiteable values if allowed
    //but they will definitly be changed if they are out of allowed borders

    if( nMaximumAutomaticMainIncrementCount <= 0 )
        nMaximumAutomaticMainIncrementCount = 5;

    //make sure that minimum and maximum have allowed values
    {
        if( rExplicitScale.Maximum<= rExplicitScale.Minimum )
            rExplicitScale.Maximum = rExplicitScale.Minimum + 10;
    }

    ExplicitIncrementData aRet;
    if(!(rSourceIncrement.PostEquidistant>>=aRet.PostEquidistant))
    {
        //maybe scaling dependent
        aRet.PostEquidistant = sal_True;
    }
    if(!(rSourceIncrement.Distance>>=aRet.Distance))
    {
        //autocalculate the distance
        double fRange = rExplicitScale.Maximum - rExplicitScale.Minimum;
        double fSlice = fRange/nMaximumAutomaticMainIncrementCount;

        //make a fine value out of fSlice now:
        double fSliceMagnitude = pow ( (double)10, floor (log10 (fSlice)));
        fSlice /= fSliceMagnitude;
        if(fSlice<=1.0)
            fSlice=1.0;
        else if( fSlice<= 2.0 )
            fSlice=2.0;
        else if( fSlice<= 2.5 )
            fSlice=2.5;
        else if( fSlice<= 5.0)
            fSlice=5.0;
        else
            fSlice=10.0;

        aRet.Distance = fSlice*fSliceMagnitude;
    }
    if(!(rSourceIncrement.BaseValue>>=aRet.BaseValue))
    {
        //@maybe todo is this default also plotter dependent ??
        aRet.BaseValue = 0.0;
    }
    if(bChangeMinimumToIncrementRythm)
    {
        rExplicitScale.Minimum = TickmarkHelper::getMinimumAtIncrement( rExplicitScale.Minimum, aRet );
    }
    if(bChangeMaximumToIncrementRythm)
    {
        rExplicitScale.Maximum = TickmarkHelper::getMaximumAtIncrement( rExplicitScale.Maximum, aRet );
    }
    //---------------------------------------------------------------
    //fill explicit sub increment
    sal_Int32 nSubCount = rSourceSubIncrementList.getLength();
    aRet.SubIncrements.realloc(nSubCount);
    for( sal_Int32 nN=0; nN<nSubCount; nN++ )
    {
        const SubIncrement&     rSubIncrement         = rSourceSubIncrementList[nN];
        ExplicitSubIncrement&   rExplicitSubIncrement = aRet.SubIncrements[nN];

        if(!(rSubIncrement.IntervalCount>>=rExplicitSubIncrement.IntervalCount))
        {
            //scaling dependent
            //@todo autocalculate IntervalCount dependent on MainIncrement and scaling
            rExplicitSubIncrement.IntervalCount = 2;
        }
        if(!(rSubIncrement.PostEquidistant>>=rExplicitSubIncrement.PostEquidistant))
        {
            //scaling dependent
            rExplicitSubIncrement.PostEquidistant = sal_False;
        }
    }
    return aRet;
}

void ScaleAutomatism::calculateExplicitScaleAndIncrement(
            ExplicitScaleData& rExplicitScale
            , ExplicitIncrementData& rExplicitIncrement )
{
    //---------------------------------------------------------------
    //fill explicit scale
    bool bChangeMinimumToIncrementRythm=false, bChangeMaximumToIncrementRythm=false;
    if(!(m_aSourceScale.Minimum>>=rExplicitScale.Minimum))
    {
        //autocalculate the minimum in first iteration
        //the increment is considered below
        if( !::rtl::math::isNan(m_fValueMinimum) )
            rExplicitScale.Minimum = m_fValueMinimum;
        else
            rExplicitScale.Minimum = 0.0;//@todo get Minimum from scsaling or from plotter????
        bChangeMinimumToIncrementRythm = true;
    }
    if(!(m_aSourceScale.Maximum>>=rExplicitScale.Maximum))
    {
        //autocalculate the maximum in first iteration
        //the increment is considered below
        if( !::rtl::math::isNan(m_fValueMaximum) )
            rExplicitScale.Maximum = m_fValueMaximum;
        else
            rExplicitScale.Maximum = 10.0;//@todo get Maximum from scaling or from plotter????
        bChangeMaximumToIncrementRythm=true;
    }
    rExplicitScale.Orientation = m_aSourceScale.Orientation;//AxisOrientation_MATHEMATICAL;
    rExplicitScale.Scaling = m_aSourceScale.Scaling;
    rExplicitScale.Breaks = m_aSourceScale.Breaks;
    //---------------------------------------------------------------
    //fill explicit increment
    //minimum and maximum of the ExplicitScaleData may be changed if allowed
    uno::Reference< lang::XServiceName > xServiceName( rExplicitScale.Scaling, uno::UNO_QUERY );
    bool bIsLogarithm = ( xServiceName.is() && (xServiceName->getServiceName()).equals(
                      C2U( "com.sun.star.chart2.LogarithmicScaling" )));
    if(bIsLogarithm)
        rExplicitIncrement = getExplicitIncrementAndScaleForLogarithm( bChangeMinimumToIncrementRythm, bChangeMaximumToIncrementRythm, m_nMaximumAutomaticMainIncrementCount
                            , rExplicitScale, m_aSourceIncrement, m_aSourceSubIncrementList );
    else
        rExplicitIncrement = getExplicitIncrementAndScaleForLinear( bChangeMinimumToIncrementRythm, bChangeMaximumToIncrementRythm, m_nMaximumAutomaticMainIncrementCount
                            , rExplicitScale, m_aSourceIncrement, m_aSourceSubIncrementList );
}

//.............................................................................
} //namespace chart
//.............................................................................
<commit_msg>INTEGRATION: CWS ooo19126 (1.4.88); FILE MERGED 2005/09/05 18:43:37 rt 1.4.88.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: ScaleAutomatism.cxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 01:36:11 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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 "ScaleAutomatism.hxx"
#include "macros.hxx"
#include "TickmarkHelper.hxx"

#ifndef _COM_SUN_STAR_LANG_XSERVICENAME_HPP_
#include <com/sun/star/lang/XServiceName.hpp>
#endif

#ifndef INCLUDED_RTL_MATH_HXX
#include <rtl/math.hxx>
#endif

#ifndef _TOOLS_DEBUG_HXX
#include <tools/debug.hxx>
#endif

//.............................................................................
namespace chart
{
//.............................................................................
using namespace ::com::sun::star;
using namespace ::com::sun::star::chart2;

ScaleAutomatism::ScaleAutomatism( const ScaleData& rSourceScale )
                    : m_fValueMinimum( 0.0 )
                    , m_fValueMaximum( 0.0 )
                    , m_nMaximumAutomaticMainIncrementCount(10)
                    , m_aSourceScale( rSourceScale )
                    , m_aSourceIncrement()
                    , m_aSourceSubIncrementList()
{
    ::rtl::math::setNan( &m_fValueMinimum );
    ::rtl::math::setNan( &m_fValueMaximum );
}

ScaleAutomatism::ScaleAutomatism( const ScaleData& rSourceScale
                    , const IncrementData& rSourceIncrement
                    , const uno::Sequence< SubIncrement >& rSourceSubIncrementList )
                    : m_fValueMinimum( 0.0 )
                    , m_fValueMaximum( 0.0 )
                    , m_nMaximumAutomaticMainIncrementCount(9)
                    , m_aSourceScale( rSourceScale )
                    , m_aSourceIncrement( rSourceIncrement )
                    , m_aSourceSubIncrementList( rSourceSubIncrementList )
{
    ::rtl::math::setNan( &m_fValueMinimum );
    ::rtl::math::setNan( &m_fValueMaximum );
}

ScaleAutomatism::~ScaleAutomatism()
{
}

//@todo these method should become part of the scaling interface and implementation somehow
//@todo problem with outparamters at api
ExplicitIncrementData getExplicitIncrementAndScaleForLogarithm(
        bool bChangeMinimumToIncrementRythm, bool bChangeMaximumToIncrementRythm
        , sal_Int32 nMaximumAutomaticMainIncrementCount
        , ExplicitScaleData& rExplicitScale
        , const IncrementData& rSourceIncrement
        , const uno::Sequence< SubIncrement >& rSourceSubIncrementList )
{
    //minimum and maximum of the ExplicitScaleData may be changed
    //to suiteable values if allowed
    //but they will definitly be changed if they are out of allowed borders

    if( nMaximumAutomaticMainIncrementCount <= 0 )
        nMaximumAutomaticMainIncrementCount = 5;

    //make sure that minimum and maximum are not out of allowed range
    {
        if( rExplicitScale.Maximum<=0.0 )
            rExplicitScale.Maximum = 100.0;
        if( rExplicitScale.Minimum<=0.0 )
        {
            rExplicitScale.Minimum = 0.1;
            if( rExplicitScale.Minimum >= rExplicitScale.Maximum )
                rExplicitScale.Minimum =  log(rExplicitScale.Maximum)/10.0;
        }
        if( rExplicitScale.Maximum<= rExplicitScale.Minimum )
            rExplicitScale.Maximum = rExplicitScale.Minimum + 10;
    }

    ExplicitIncrementData aRet;
    if(!(rSourceIncrement.PostEquidistant>>=aRet.PostEquidistant))
    {
        //maybe scaling dependent
        aRet.PostEquidistant = sal_True;
    }
    if(!(rSourceIncrement.Distance>>=aRet.Distance))
    {
        //autocalculate the distance
        if(aRet.PostEquidistant && rExplicitScale.Scaling.is() )
        {
            double fRange = rExplicitScale.Scaling->doScaling( rExplicitScale.Maximum )
                          - rExplicitScale.Scaling->doScaling( rExplicitScale.Minimum );
            double fSlice = fRange/nMaximumAutomaticMainIncrementCount;
            //make a fine value out of fSlice now:
            //only integers are reasonable as distance values
            sal_Int32 nDistance = static_cast<sal_Int32>(fSlice);
            if(nDistance<=0)
                nDistance=1;
            aRet.Distance = nDistance;
        }
        else
        {
            //@todo this was not tested
            double fRange = rExplicitScale.Maximum - rExplicitScale.Minimum;
            double fSlice = fRange/nMaximumAutomaticMainIncrementCount;
            //make a fine value out of fSlice now:
            double fSliceMagnitude = pow ( (double)10, floor (log10 (fSlice)));
            aRet.Distance = static_cast<sal_Int32>(fSlice/fSliceMagnitude)*fSliceMagnitude;
        }
    }

    if(!(rSourceIncrement.BaseValue>>=aRet.BaseValue))
    {
        //scaling dependent
        //@maybe todo is this default also plotter dependent ??
        aRet.BaseValue = 1.0;
    }
    else if( aRet.BaseValue<=0.0 ) //make sure that BaseValue is not out of allowed ranges
        aRet.BaseValue = 1.0;

    if(bChangeMinimumToIncrementRythm)
    {
        double fMin = rExplicitScale.Minimum;
        if( aRet.PostEquidistant && rExplicitScale.Scaling.is() )
            fMin = rExplicitScale.Scaling->doScaling(fMin);

        fMin = TickmarkHelper::getMinimumAtIncrement( fMin, aRet );
        if( aRet.PostEquidistant && rExplicitScale.Scaling.is() )
            fMin = rExplicitScale.Scaling->getInverseScaling()->doScaling(fMin);
        rExplicitScale.Minimum = fMin;

        if( rExplicitScale.Minimum<=0.0 )
        {
            rExplicitScale.Minimum = 0.1;
            if( rExplicitScale.Minimum >= rExplicitScale.Maximum )
                rExplicitScale.Minimum =  log(rExplicitScale.Maximum)/10.0;
        }
    }
    if(bChangeMaximumToIncrementRythm)
    {
        double fMax = rExplicitScale.Maximum;
        if( aRet.PostEquidistant && rExplicitScale.Scaling.is() )
            fMax = rExplicitScale.Scaling->doScaling(fMax);
        fMax = TickmarkHelper::getMaximumAtIncrement( fMax, aRet );
        if( aRet.PostEquidistant && rExplicitScale.Scaling.is() )
            fMax = rExplicitScale.Scaling->getInverseScaling()->doScaling(fMax);
        rExplicitScale.Maximum = fMax;
    }
    //---------------------------------------------------------------
    //fill explicit sub increment
    sal_Int32 nSubCount = rSourceSubIncrementList.getLength();
    aRet.SubIncrements.realloc(nSubCount);
    for( sal_Int32 nN=0; nN<nSubCount; nN++ )
    {
        const SubIncrement&     rSubIncrement         = rSourceSubIncrementList[nN];
        ExplicitSubIncrement&   rExplicitSubIncrement = aRet.SubIncrements[nN];

        if(!(rSubIncrement.IntervalCount>>=rExplicitSubIncrement.IntervalCount))
        {
            //scaling dependent
            //@todo autocalculate IntervalCount dependent on MainIncrement and scaling
            rExplicitSubIncrement.IntervalCount = 5;
        }
        if(!(rSubIncrement.PostEquidistant>>=rExplicitSubIncrement.PostEquidistant))
        {
            //scaling dependent
            rExplicitSubIncrement.PostEquidistant = sal_False;
        }
    }
    return aRet;
}

ExplicitIncrementData getExplicitIncrementAndScaleForLinear(
        bool bChangeMinimumToIncrementRythm, bool bChangeMaximumToIncrementRythm
        , sal_Int32 nMaximumAutomaticMainIncrementCount
        , ExplicitScaleData& rExplicitScale
        , const IncrementData& rSourceIncrement
        , const uno::Sequence< SubIncrement >& rSourceSubIncrementList )
{
    //minimum and maximum of the ExplicitScaleData may be changed
    //to suiteable values if allowed
    //but they will definitly be changed if they are out of allowed borders

    if( nMaximumAutomaticMainIncrementCount <= 0 )
        nMaximumAutomaticMainIncrementCount = 5;

    //make sure that minimum and maximum have allowed values
    {
        if( rExplicitScale.Maximum<= rExplicitScale.Minimum )
            rExplicitScale.Maximum = rExplicitScale.Minimum + 10;
    }

    ExplicitIncrementData aRet;
    if(!(rSourceIncrement.PostEquidistant>>=aRet.PostEquidistant))
    {
        //maybe scaling dependent
        aRet.PostEquidistant = sal_True;
    }
    if(!(rSourceIncrement.Distance>>=aRet.Distance))
    {
        //autocalculate the distance
        double fRange = rExplicitScale.Maximum - rExplicitScale.Minimum;
        double fSlice = fRange/nMaximumAutomaticMainIncrementCount;

        //make a fine value out of fSlice now:
        double fSliceMagnitude = pow ( (double)10, floor (log10 (fSlice)));
        fSlice /= fSliceMagnitude;
        if(fSlice<=1.0)
            fSlice=1.0;
        else if( fSlice<= 2.0 )
            fSlice=2.0;
        else if( fSlice<= 2.5 )
            fSlice=2.5;
        else if( fSlice<= 5.0)
            fSlice=5.0;
        else
            fSlice=10.0;

        aRet.Distance = fSlice*fSliceMagnitude;
    }
    if(!(rSourceIncrement.BaseValue>>=aRet.BaseValue))
    {
        //@maybe todo is this default also plotter dependent ??
        aRet.BaseValue = 0.0;
    }
    if(bChangeMinimumToIncrementRythm)
    {
        rExplicitScale.Minimum = TickmarkHelper::getMinimumAtIncrement( rExplicitScale.Minimum, aRet );
    }
    if(bChangeMaximumToIncrementRythm)
    {
        rExplicitScale.Maximum = TickmarkHelper::getMaximumAtIncrement( rExplicitScale.Maximum, aRet );
    }
    //---------------------------------------------------------------
    //fill explicit sub increment
    sal_Int32 nSubCount = rSourceSubIncrementList.getLength();
    aRet.SubIncrements.realloc(nSubCount);
    for( sal_Int32 nN=0; nN<nSubCount; nN++ )
    {
        const SubIncrement&     rSubIncrement         = rSourceSubIncrementList[nN];
        ExplicitSubIncrement&   rExplicitSubIncrement = aRet.SubIncrements[nN];

        if(!(rSubIncrement.IntervalCount>>=rExplicitSubIncrement.IntervalCount))
        {
            //scaling dependent
            //@todo autocalculate IntervalCount dependent on MainIncrement and scaling
            rExplicitSubIncrement.IntervalCount = 2;
        }
        if(!(rSubIncrement.PostEquidistant>>=rExplicitSubIncrement.PostEquidistant))
        {
            //scaling dependent
            rExplicitSubIncrement.PostEquidistant = sal_False;
        }
    }
    return aRet;
}

void ScaleAutomatism::calculateExplicitScaleAndIncrement(
            ExplicitScaleData& rExplicitScale
            , ExplicitIncrementData& rExplicitIncrement )
{
    //---------------------------------------------------------------
    //fill explicit scale
    bool bChangeMinimumToIncrementRythm=false, bChangeMaximumToIncrementRythm=false;
    if(!(m_aSourceScale.Minimum>>=rExplicitScale.Minimum))
    {
        //autocalculate the minimum in first iteration
        //the increment is considered below
        if( !::rtl::math::isNan(m_fValueMinimum) )
            rExplicitScale.Minimum = m_fValueMinimum;
        else
            rExplicitScale.Minimum = 0.0;//@todo get Minimum from scsaling or from plotter????
        bChangeMinimumToIncrementRythm = true;
    }
    if(!(m_aSourceScale.Maximum>>=rExplicitScale.Maximum))
    {
        //autocalculate the maximum in first iteration
        //the increment is considered below
        if( !::rtl::math::isNan(m_fValueMaximum) )
            rExplicitScale.Maximum = m_fValueMaximum;
        else
            rExplicitScale.Maximum = 10.0;//@todo get Maximum from scaling or from plotter????
        bChangeMaximumToIncrementRythm=true;
    }
    rExplicitScale.Orientation = m_aSourceScale.Orientation;//AxisOrientation_MATHEMATICAL;
    rExplicitScale.Scaling = m_aSourceScale.Scaling;
    rExplicitScale.Breaks = m_aSourceScale.Breaks;
    //---------------------------------------------------------------
    //fill explicit increment
    //minimum and maximum of the ExplicitScaleData may be changed if allowed
    uno::Reference< lang::XServiceName > xServiceName( rExplicitScale.Scaling, uno::UNO_QUERY );
    bool bIsLogarithm = ( xServiceName.is() && (xServiceName->getServiceName()).equals(
                      C2U( "com.sun.star.chart2.LogarithmicScaling" )));
    if(bIsLogarithm)
        rExplicitIncrement = getExplicitIncrementAndScaleForLogarithm( bChangeMinimumToIncrementRythm, bChangeMaximumToIncrementRythm, m_nMaximumAutomaticMainIncrementCount
                            , rExplicitScale, m_aSourceIncrement, m_aSourceSubIncrementList );
    else
        rExplicitIncrement = getExplicitIncrementAndScaleForLinear( bChangeMinimumToIncrementRythm, bChangeMaximumToIncrementRythm, m_nMaximumAutomaticMainIncrementCount
                            , rExplicitScale, m_aSourceIncrement, m_aSourceSubIncrementList );
}

//.............................................................................
} //namespace chart
//.............................................................................
<|endoftext|>