<commit_before>/*
 * SessionThemes.cpp
 *
 * Copyright (C) 2018 by RStudio, Inc.
 *
 * Unless you have received this program directly from RStudio pursuant
 * to the terms of a commercial license agreement with RStudio, then
 * this program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

#include "SessionThemes.hpp"

#include <boost/bind.hpp>

#include <core/Error.hpp>
#include <core/Exec.hpp>
#include <core/FilePath.hpp>
#include <core/json/JsonRpc.hpp>
#include <core/system/System.hpp>

#include <core/http/Request.hpp>
#include <core/http/Response.hpp>

#include <session/SessionModuleContext.hpp>

#include <r/RRoutines.hpp>
#include <r/RSexp.hpp>

#include <fstream>
#include <map>
#include <regex>
#include <string>

using namespace rstudio::core;

namespace rstudio {
namespace session {
namespace modules {
namespace themes {

namespace {

const std::string kDefaultThemeLocation = "/theme/default/";
const std::string kGlobalCustomThemeLocation = "/theme/custom/global/";
const std::string kLocalCustomThemeLocation = "/theme/custom/local/";

// A map from the name of the theme to the location of the file and a boolean representing
// whether or not the theme is dark.
typedef std::map<std::string, std::tuple<std::string, std::string, bool> > ThemeMap;

/// @brief Determines whether a string can be evaluated to logical "true". A return value of false
///        does not indicate that the string can be evaluted to logical "false".
///
/// @param toConvert    The string to convert to boolean.
///
/// @return True if the string matches 1, TRUE, true, or any case variant of true; false otherwise.
bool strIsTrue(const std::string& toConvert)
{
   return std::regex_match(
            std::string(toConvert),
            std::regex("(?:1|t(?:rue)?)", std::regex_constants::icase));
}

/// @brief Determines whether a string can be evaluated to logical "false". A return value of true
///        does not indicate that the string can be evaluted to logical "true".
///
/// @param toConvert    The string to convert to boolean.
///
/// @return True if the string matches 0, FALSE, false, or any case variant of false; true
///         otherwise.
bool strIsFalse(const std::string& toConvert)
{
   return std::regex_match(
            std::string(toConvert),
            std::regex("(?:0|f(?:alse)?)", std::regex_constants::icase));
}

/**
 * @brief Gets themes in the specified location.
 *
 * @param location         The location in which to look for themes.
 * @param themeMap         The map which will contain all found themes after the call.
 * @param urlPrefix        The URL prefix for the theme. Must end with "/"
 */
void getThemesInLocation(
      const rstudio::core::FilePath& location,
      ThemeMap& themeMap,
      const std::string& urlPrefix = "")
{
   using rstudio::core::FilePath;
   if (location.isDirectory())
   {
      std::vector<FilePath> locationChildren;
      location.children(&locationChildren);
      for (const FilePath& themeFile: locationChildren)
      {
         if (themeFile.hasExtensionLowerCase(".rstheme"))
         {
            const std::string k_themeFileStr = themeFile.canonicalPath();
            std::ifstream themeIFStream(k_themeFileStr);
            std::string themeContents(
               (std::istreambuf_iterator<char>(themeIFStream)),
               (std::istreambuf_iterator<char>()));
            themeIFStream.close();

            std::smatch matches;
            std::regex_search(
               themeContents,
               matches,
               std::regex("rs-theme-name\\s*:\\s*([^\\*]+?)\\s*(?:\\*|$)"));

            // If there's no name specified,use the name of the file
            std::string name;
            if (matches.size() < 2)
            {
               name = themeFile.stem();
            }
            else
            {
               // If there's at least one name specified, get the first one.
               name = matches[1];
            }

            // Find out if the theme is dark or not.
            std::regex_search(
                     themeContents,
                     matches,
                     std::regex("rs-theme-is-dark\\s*:\\s*([^\\*]+?)\\s*(?:\\*|$)"));

            bool isDark = false;
            if (matches.size() >= 2)
            {
               isDark = strIsTrue(matches[1]);
            }
            if ((matches.size() < 2) ||
                (!isDark &&
                !strIsFalse(matches[1])))
            {
               // TODO: warning / logging about using default isDark value.
            }

            themeMap[boost::algorithm::to_lower_copy(name)] = std::make_tuple(
               name,
               urlPrefix + themeFile.filename(),
               isDark);
         }
      }
   }
}

/**
 * @brief Gets the location of themes that are installed with RStudio.
 *
 * @return The location of themes that are installed with RStudio.
 */
FilePath getDefaultThemePath()
{
   return session::options().rResourcesPath().childPath("themes");
}

/**
 * @brief Gets the location of custom themes that are installed for all users.
 *
 * @return The location of custom themes that are installed for all users.
 */
FilePath getGlobalCustomThemePath()
{
   using rstudio::core::FilePath;

   const char* kGlobalPathAlt = std::getenv("RS_THEME_GLOBAL_HOME");
   if (kGlobalPathAlt)
   {
      return FilePath(kGlobalPathAlt);
   }

#ifdef _WIN32
   return core::system::systemSettingsPath("RStudio\\themes", false);
#else
   return FilePath("/etc/rstudio/themes/");
#endif
}

/**
 * @brief Gets the location of custom themes that are installed for the current user.
 *
 * @return The location of custom themes that are installed for the current user.
 */
FilePath getLocalCustomThemePath()
{
   using rstudio::core::FilePath;
   const char* kLocalPathAlt = std::getenv("RS_THEME_LOCAL_HOME");
   if (kLocalPathAlt)
   {
      return FilePath(kLocalPathAlt);
   }

#ifdef _WIN32
   return core::system::userHomePath().childPath(".R\\rstudio\\themes");
#else
   return core::system::userHomePath().childPath(".R/rstudio/themes/");
#endif
}

/**
 * @brief Gets a map of all available themes, keyed by the unique name of the theme. If a theme is
 *        found in multiple locations, the theme in the most specific folder will be given
 *        precedence.
 *
 * @return The map of all available themes.
 */
ThemeMap getAllThemes()
{
   // Intentionally get global themes before getting user specific themes so that user specific
   // themes will override global ones.
   ThemeMap themeMap;
   getThemesInLocation(getDefaultThemePath(), themeMap, kDefaultThemeLocation);
   getThemesInLocation(getGlobalCustomThemePath(), themeMap, kGlobalCustomThemeLocation);
   getThemesInLocation(getLocalCustomThemePath(), themeMap, kLocalCustomThemeLocation);

   return themeMap;
}

/**
 * @brief Gets the list of all RStudio editor themes.
 *
 * @return The list of all RStudio editor themes.
 */
SEXP rs_getThemes()
{
   ThemeMap themeMap = getAllThemes();

   // Convert to an R list.
   rstudio::r::sexp::Protect protect;
   rstudio::r::sexp::ListBuilder themeListBuilder(&protect);

   for (auto theme: themeMap)
   {
      rstudio::r::sexp::ListBuilder themeDetailsListBuilder(&protect);
      themeDetailsListBuilder.add("name", std::get<0>(theme.second));
      themeDetailsListBuilder.add("url", std::get<1>(theme.second));
      themeDetailsListBuilder.add("isDark", std::get<2>(theme.second));

      themeListBuilder.add(theme.first, themeDetailsListBuilder);
   }

   return rstudio::r::sexp::create(themeListBuilder, &protect);
}

/**
 * @brief Gets the default theme based on the request from the client.
 *
 * @param request    The request from the client.
 *
 * @return The default theme. "Tomorrow Night" if the request is for a dark theme; "Textmate" if
 *         the request is for a light theme.
 */
FilePath getDefaultTheme(const http::Request& request)
{
   std::string isDarkStr = request.queryParamValue("dark");
   bool isDark = strIsTrue(isDarkStr);
   if (!isDark && !strIsFalse(isDarkStr))
   {
      // TODO: Error/warning/logging
      // Note that this should be considered an internal error, since the request is generated
      // by the client and without user input.
   }

   if (isDark)
   {
      return getDefaultThemePath().childPath("tomorrow_night.rstheme");
   }
   else
   {
      return getDefaultThemePath().childPath("textmate.rstheme");
   }
}

/**
 * @brief Gets a theme that is installed with RStudio.
 *
 * @param request       The HTTP request from the client.
 * @param pResponse     The HTTP response, which will contain the theme CSS.
 */
void handleDefaultThemeRequest(const http::Request& request,
                                     http::Response* pResponse)
{
   std::string fileName = http::util::pathAfterPrefix(request, kDefaultThemeLocation);
   pResponse->setCacheableFile(getDefaultThemePath().childPath(fileName), request);
   pResponse->setContentType("text/css");
}

/**
 * @brief Gets a custom theme that is installed for all users.
 *
 * @param request       The HTTP request from the client.
 * @param pResponse     The HTTP response, which will contain the theme CSS.
 */
void handleGlobalCustomThemeRequest(const http::Request& request,
                                          http::Response* pResponse)
{
   // Note: we probably want to return a warning code instead of success so the client has the
   // ability to pop up a warning dialog or something to the user.
   std::string fileName = http::util::pathAfterPrefix(request, kGlobalCustomThemeLocation);
   FilePath requestedTheme = getGlobalCustomThemePath().childPath(fileName);
   pResponse->setCacheableFile(
      requestedTheme.exists() ? requestedTheme : getDefaultTheme(request),
      request);
   pResponse->setContentType("text/css");
}

/**
 * @brief Gets a custom theme that is installed for all users.
 *
 * @param request       The HTTP request from the client.
 * @param pResponse     The HTTP response, which will contain the theme CSS.
 */
void handleLocalCustomThemeRequest(const http::Request& request,
                                         http::Response* pResponse)
{
   // Note: we probably want to return a warning code instead of success so the client has the
   // ability to pop up a warning dialog or something to the user.
   std::string fileName = http::util::pathAfterPrefix(request, kLocalCustomThemeLocation);
   FilePath requestedTheme = getLocalCustomThemePath().childPath(fileName);
   pResponse->setCacheableFile(
      requestedTheme.exists() ? requestedTheme : getDefaultTheme(request),
      request);
   pResponse->setContentType("text/css");
}

/**
 * @brief Gets the list of all the avialble themes for the client.
 *
 * @param request       The JSON request from the client.
 * @param pResponse     The JSON response, which will contain the list of themes.
 *
 * @return The error that occurred, if any; otherwise Success().
 */
Error getThemes(const json::JsonRpcRequest& request,
                      json::JsonRpcResponse* pResponse)
{
   ThemeMap themes = getAllThemes();

   // Convert the theme to a json array.
   json::Array jsonThemeArray;
   for (auto theme: themes)
   {
      json::Object jsonTheme;
      jsonTheme["name"] = std::get<0>(theme.second);
      jsonTheme["url"] = std::get<1>(theme.second);
      jsonTheme["isDark"] = std::get<2>(theme.second);
      jsonThemeArray.push_back(jsonTheme);
   }

   pResponse->setResult(jsonThemeArray);
   return Success();
}

} // anonymous namespace

Error initialize()
{
   using boost::bind;
   using namespace module_context;

   RS_REGISTER_CALL_METHOD(rs_getThemes, 0);

   ExecBlock initBlock;
   initBlock.addFunctions()
      (bind(sourceModuleRFile, "SessionThemes.R"))
      (bind(registerRpcMethod, "get_themes", getThemes))
      (bind(registerUriHandler, kDefaultThemeLocation, handleDefaultThemeRequest))
      (bind(registerUriHandler, kGlobalCustomThemeLocation, handleGlobalCustomThemeRequest))
      (bind(registerUriHandler, kLocalCustomThemeLocation, handleLocalCustomThemeRequest));

   return initBlock.execute();
}

} // namespace themes
} // namespace modules
} // namespace session
} // namespace rstudio
<commit_msg>switch from std::regex functions to boost::regex functions because gcc 4.8 doesn't support std::regex.<commit_after>/*
 * SessionThemes.cpp
 *
 * Copyright (C) 2018 by RStudio, Inc.
 *
 * Unless you have received this program directly from RStudio pursuant
 * to the terms of a commercial license agreement with RStudio, then
 * this program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

#include "SessionThemes.hpp"

#include <boost/algorithm/algorithm.hpp>
#include <boost/bind.hpp>
#include <boost/regex.hpp>

#include <core/Error.hpp>
#include <core/Exec.hpp>
#include <core/FilePath.hpp>
#include <core/json/JsonRpc.hpp>
#include <core/system/System.hpp>

#include <core/http/Request.hpp>
#include <core/http/Response.hpp>

#include <session/SessionModuleContext.hpp>

#include <r/RRoutines.hpp>
#include <r/RSexp.hpp>

#include <fstream>
#include <map>
#include <string>

using namespace rstudio::core;

namespace rstudio {
namespace session {
namespace modules {
namespace themes {

namespace {

const std::string kDefaultThemeLocation = "/theme/default/";
const std::string kGlobalCustomThemeLocation = "/theme/custom/global/";
const std::string kLocalCustomThemeLocation = "/theme/custom/local/";

// A map from the name of the theme to the location of the file and a boolean representing
// whether or not the theme is dark.
typedef std::map<std::string, std::tuple<std::string, std::string, bool> > ThemeMap;

/// @brief Determines whether a string can be evaluated to logical "true". A return value of false
///        does not indicate that the string can be evaluted to logical "false".
///
/// @param toConvert    The string to convert to boolean.
///
/// @return True if the string matches 1, TRUE, true, or any case variant of true; false otherwise.
bool strIsTrue(const std::string& toConvert)
{
   return boost::regex_match(
            toConvert,
            boost::regex("(?:1|t(?:rue)?)", boost::regex::icase));
}

/// @brief Determines whether a string can be evaluated to logical "false". A return value of true
///        does not indicate that the string can be evaluted to logical "true".
///
/// @param toConvert    The string to convert to boolean.
///
/// @return True if the string matches 0, FALSE, false, or any case variant of false; true
///         otherwise.
bool strIsFalse(const std::string& toConvert)
{
   return boost::regex_match(
            toConvert,
            boost::regex("(?:0|f(?:alse)?)", boost::regex::icase));
}

/**
 * @brief Gets themes in the specified location.
 *
 * @param location         The location in which to look for themes.
 * @param themeMap         The map which will contain all found themes after the call.
 * @param urlPrefix        The URL prefix for the theme. Must end with "/"
 */
void getThemesInLocation(
      const rstudio::core::FilePath& location,
      ThemeMap& themeMap,
      const std::string& urlPrefix = "")
{
   using rstudio::core::FilePath;
   if (location.isDirectory())
   {
      std::vector<FilePath> locationChildren;
      location.children(&locationChildren);
      for (const FilePath& themeFile: locationChildren)
      {
         if (themeFile.hasExtensionLowerCase(".rstheme"))
         {
            const std::string k_themeFileStr = themeFile.canonicalPath();
            std::ifstream themeIFStream(k_themeFileStr);
            std::string themeContents(
               (std::istreambuf_iterator<char>(themeIFStream)),
               (std::istreambuf_iterator<char>()));
            themeIFStream.close();

            boost::smatch matches;
            boost::regex_search(
               themeContents,
               matches,
               boost::regex("rs-theme-name\\s*:\\s*([^\\*]+?)\\s*(?:\\*|$)"));

            // If there's no name specified,use the name of the file
            std::string name;
            if (matches.size() < 2)
            {
               name = themeFile.stem();
            }
            else
            {
               // If there's at least one name specified, get the first one.
               name = matches[1];
            }

            // Find out if the theme is dark or not.
            boost::regex_search(
                     themeContents,
                     matches,
                     boost::regex("rs-theme-is-dark\\s*:\\s*([^\\*]+?)\\s*(?:\\*|$)"));

            bool isDark = false;
            if (matches.size() >= 2)
            {
               isDark = strIsTrue(matches[1]);
            }
            if ((matches.size() < 2) ||
                (!isDark &&
                !strIsFalse(matches[1])))
            {
               LOG_WARNING_MESSAGE("rs-theme-is-dark is not set or not convertable to boolean for theme \"" + name + "\".");
            }

            themeMap[boost::algorithm::to_lower_copy(name)] = std::make_tuple(
               name,
               urlPrefix + themeFile.filename(),
               isDark);
         }
      }
   }
}

/**
 * @brief Gets the location of themes that are installed with RStudio.
 *
 * @return The location of themes that are installed with RStudio.
 */
FilePath getDefaultThemePath()
{
   return session::options().rResourcesPath().childPath("themes");
}

/**
 * @brief Gets the location of custom themes that are installed for all users.
 *
 * @return The location of custom themes that are installed for all users.
 */
FilePath getGlobalCustomThemePath()
{
   using rstudio::core::FilePath;

   const char* kGlobalPathAlt = std::getenv("RS_THEME_GLOBAL_HOME");
   if (kGlobalPathAlt)
   {
      return FilePath(kGlobalPathAlt);
   }

#ifdef _WIN32
   return core::system::systemSettingsPath("RStudio\\themes", false);
#else
   return FilePath("/etc/rstudio/themes/");
#endif
}

/**
 * @brief Gets the location of custom themes that are installed for the current user.
 *
 * @return The location of custom themes that are installed for the current user.
 */
FilePath getLocalCustomThemePath()
{
   using rstudio::core::FilePath;
   const char* kLocalPathAlt = std::getenv("RS_THEME_LOCAL_HOME");
   if (kLocalPathAlt)
   {
      return FilePath(kLocalPathAlt);
   }

#ifdef _WIN32
   return core::system::userHomePath().childPath(".R\\rstudio\\themes");
#else
   return core::system::userHomePath().childPath(".R/rstudio/themes/");
#endif
}

/**
 * @brief Gets a map of all available themes, keyed by the unique name of the theme. If a theme is
 *        found in multiple locations, the theme in the most specific folder will be given
 *        precedence.
 *
 * @return The map of all available themes.
 */
ThemeMap getAllThemes()
{
   // Intentionally get global themes before getting user specific themes so that user specific
   // themes will override global ones.
   ThemeMap themeMap;
   getThemesInLocation(getDefaultThemePath(), themeMap, kDefaultThemeLocation);
   getThemesInLocation(getGlobalCustomThemePath(), themeMap, kGlobalCustomThemeLocation);
   getThemesInLocation(getLocalCustomThemePath(), themeMap, kLocalCustomThemeLocation);

   return themeMap;
}

/**
 * @brief Gets the list of all RStudio editor themes.
 *
 * @return The list of all RStudio editor themes.
 */
SEXP rs_getThemes()
{
   ThemeMap themeMap = getAllThemes();

   // Convert to an R list.
   rstudio::r::sexp::Protect protect;
   rstudio::r::sexp::ListBuilder themeListBuilder(&protect);

   for (auto theme: themeMap)
   {
      rstudio::r::sexp::ListBuilder themeDetailsListBuilder(&protect);
      themeDetailsListBuilder.add("name", std::get<0>(theme.second));
      themeDetailsListBuilder.add("url", std::get<1>(theme.second));
      themeDetailsListBuilder.add("isDark", std::get<2>(theme.second));

      themeListBuilder.add(theme.first, themeDetailsListBuilder);
   }

   return rstudio::r::sexp::create(themeListBuilder, &protect);
}

/**
 * @brief Gets the default theme based on the request from the client.
 *
 * @param request    The request from the client.
 *
 * @return The default theme. "Tomorrow Night" if the request is for a dark theme; "Textmate" if
 *         the request is for a light theme.
 */
FilePath getDefaultTheme(const http::Request& request)
{
   std::string isDarkStr = request.queryParamValue("dark");
   bool isDark = strIsTrue(isDarkStr);
   if (!isDark && !strIsFalse(isDarkStr))
   {
      LOG_WARNING_MESSAGE("\"dark\" parameter for request is missing or not a true or false value: " + isDarkStr);
   }

   if (isDark)
   {
      return getDefaultThemePath().childPath("tomorrow_night.rstheme");
   }
   else
   {
      return getDefaultThemePath().childPath("textmate.rstheme");
   }
}

/**
 * @brief Gets a theme that is installed with RStudio.
 *
 * @param request       The HTTP request from the client.
 * @param pResponse     The HTTP response, which will contain the theme CSS.
 */
void handleDefaultThemeRequest(const http::Request& request,
                                     http::Response* pResponse)
{
   std::string fileName = http::util::pathAfterPrefix(request, kDefaultThemeLocation);
   pResponse->setCacheableFile(getDefaultThemePath().childPath(fileName), request);
   pResponse->setContentType("text/css");
}

/**
 * @brief Gets a custom theme that is installed for all users.
 *
 * @param request       The HTTP request from the client.
 * @param pResponse     The HTTP response, which will contain the theme CSS.
 */
void handleGlobalCustomThemeRequest(const http::Request& request,
                                          http::Response* pResponse)
{
   // Note: we probably want to return a warning code instead of success so the client has the
   // ability to pop up a warning dialog or something to the user.
   std::string fileName = http::util::pathAfterPrefix(request, kGlobalCustomThemeLocation);
   FilePath requestedTheme = getGlobalCustomThemePath().childPath(fileName);
   pResponse->setCacheableFile(
      requestedTheme.exists() ? requestedTheme : getDefaultTheme(request),
      request);
   pResponse->setContentType("text/css");
}

/**
 * @brief Gets a custom theme that is installed for all users.
 *
 * @param request       The HTTP request from the client.
 * @param pResponse     The HTTP response, which will contain the theme CSS.
 */
void handleLocalCustomThemeRequest(const http::Request& request,
                                         http::Response* pResponse)
{
   // Note: we probably want to return a warning code instead of success so the client has the
   // ability to pop up a warning dialog or something to the user.
   std::string fileName = http::util::pathAfterPrefix(request, kLocalCustomThemeLocation);
   FilePath requestedTheme = getLocalCustomThemePath().childPath(fileName);
   pResponse->setCacheableFile(
      requestedTheme.exists() ? requestedTheme : getDefaultTheme(request),
      request);
   pResponse->setContentType("text/css");
}

/**
 * @brief Gets the list of all the avialble themes for the client.
 *
 * @param request       The JSON request from the client.
 * @param pResponse     The JSON response, which will contain the list of themes.
 *
 * @return The error that occurred, if any; otherwise Success().
 */
Error getThemes(const json::JsonRpcRequest& request,
                      json::JsonRpcResponse* pResponse)
{
   ThemeMap themes = getAllThemes();

   // Convert the theme to a json array.
   json::Array jsonThemeArray;
   for (auto theme: themes)
   {
      json::Object jsonTheme;
      jsonTheme["name"] = std::get<0>(theme.second);
      jsonTheme["url"] = std::get<1>(theme.second);
      jsonTheme["isDark"] = std::get<2>(theme.second);
      jsonThemeArray.push_back(jsonTheme);
   }

   pResponse->setResult(jsonThemeArray);
   return Success();
}

} // anonymous namespace

Error initialize()
{
   using boost::bind;
   using namespace module_context;

   RS_REGISTER_CALL_METHOD(rs_getThemes, 0);

   ExecBlock initBlock;
   initBlock.addFunctions()
      (bind(sourceModuleRFile, "SessionThemes.R"))
      (bind(registerRpcMethod, "get_themes", getThemes))
      (bind(registerUriHandler, kDefaultThemeLocation, handleDefaultThemeRequest))
      (bind(registerUriHandler, kGlobalCustomThemeLocation, handleGlobalCustomThemeRequest))
      (bind(registerUriHandler, kLocalCustomThemeLocation, handleLocalCustomThemeRequest));

   return initBlock.execute();
}

} // namespace themes
} // namespace modules
} // namespace session
} // namespace rstudio
<|endoftext|>


<commit_before><commit_msg>Removed the hand-selection logic that re-picked a previous winning hand if it was still above threshold and it now always picks the best 'left' or 'right' hand at a given moment.<commit_after><|endoftext|>


<commit_before>#include <stdio.h>
#include <stdlib.h>

#include "App.h"
#include <Directory.h>
#include <NodeMonitor.h>
#include <Entry.h>
#include <Path.h>
#include <String.h>

App::App(void)
  : BApplication("application/x-vnd.lh-MyDropboxClient")
{
  //start watching ~/Dropbox folder
  BDirectory dir("/boot/home/Dropbox");
  node_ref nref;
  status_t err;
  if(dir.InitCheck() == B_OK){
    dir.GetNodeRef(&nref);
    err = watch_node(&nref, B_WATCH_DIRECTORY, BMessenger(this));
    if(err != B_OK)
      printf("Watch Node: Not OK\n");
  }

  // track each file in the folder for edits

  // record each file in the folder so that we know the name on deletion
  BEntry entry;
  err = dir.GetNextEntry(&entry);
  while(err == B_OK){
    err = dir.GetNextEntry(&entry);
    this->tracked_files.AddItem((void*)&entry);
  }
}

int
run_script(const char *cmd)
{
  char buf[BUFSIZ];
  FILE *ptr;

  if ((ptr = popen(cmd, "r")) != NULL)
    while (fgets(buf, BUFSIZ, ptr) != NULL)
      (void) printf("RAWR%s", buf);
  (void) pclose(ptr);
  return 0;
}

void
delete_file_on_dropbox(char * filepath)
{
  BString s, dbfp;
  s = BString(filepath);
  s.RemoveFirst("/boot/home/Dropbox");
  dbfp << "python db_rm.py " << s;
  run_script(dbfp);
}

BString local_to_db_filepath(const char * local_path)
{
  BString s;
  s = BString(local_path);
  s.RemoveFirst("/boot/home/Dropbox/");
  return s;
}

void
add_file_to_dropbox(const char * filepath)
{
  BString s, dbfp;
  dbfp = local_to_db_filepath(filepath);
  s << "python db_put.py " << BString(filepath) << " " << dbfp;
  printf("local filepath:%s\n",filepath);
  printf("dropbox filepath:%s\n",dbfp.String());
  run_script(s.String());
}

void
add_folder_to_dropbox(const char * filepath)
{
  BString s;
  s << "python db_mkdir.py " << local_to_db_filepath(filepath);
  printf("local filepath: %s\n", filepath);
  printf("db filepath: %s\n", local_to_db_filepath(filepath).String());
  run_script(s.String());
}

void
moved_file(BMessage *msg)
{
  //is this file being move into or out of ~/Dropbox?
  run_script("python db_ls.py");
}

void
App::MessageReceived(BMessage *msg)
{
  switch(msg->what)
  {
    case B_NODE_MONITOR:
    {
      printf("Received Node Monitor Alert\n");
      status_t err;
      int32 opcode;
      err = msg->FindInt32("opcode",&opcode);
      if(err == B_OK)
      {
        printf("what:%d\topcode:%d\n",msg->what, opcode);
        switch(opcode)
        {
          case B_ENTRY_CREATED:
          {
            printf("NEW FILE\n");
            entry_ref ref;
            BPath path;
            const char * name;
            msg->FindInt32("device",&ref.device);
            msg->FindInt64("directory",&ref.directory);
            msg->FindString("name",&name);
            printf("name:%s\n",name);
            ref.set_name(name);
            BEntry new_file = BEntry(&ref);
            new_file.GetPath(&path);
            add_file_to_dropbox(path.Path());
            break;
          }
          case B_ENTRY_MOVED:
          {
            printf("MOVED FILE\n");
            moved_file(msg);
            break;
          }
          case B_ENTRY_REMOVED:
          {
            printf("DELETED FILE\n");
            //node_ref nref;
            //msg->FindInt32("device",&nref.device);
            //msg->FindInt64("node",&nref.node);
            //BNode node = BNode(&nref);
            delete_file_on_dropbox("hi");
            break;
          }
          default:
          {
            printf("default case opcode...\n");
          }
        }
      }
      break;
    }
    default:
    {
      printf("default msg\n");
      BApplication::MessageReceived(msg);
      break;
    }
  }
}

int
main(void)
{
  //Haiku make window code
  App *app = new App();

  app->Run();
  delete app;
  return 0;
}
<commit_msg>added tracking of all the file initially in the folder. Remove doesn't work and Edit isn't tested at all. It compiles.<commit_after>#include <stdio.h>
#include <stdlib.h>

#include "App.h"
#include <Directory.h>
#include <NodeMonitor.h>
#include <Entry.h>
#include <Path.h>
#include <String.h>

App::App(void)
  : BApplication("application/x-vnd.lh-MyDropboxClient")
{
  //start watching ~/Dropbox folder
  BDirectory dir("/boot/home/Dropbox");
  node_ref nref;
  status_t err;
  if(dir.InitCheck() == B_OK){
    dir.GetNodeRef(&nref);
    err = watch_node(&nref, B_WATCH_DIRECTORY, BMessenger(this));
    if(err != B_OK)
      printf("Watch Node: Not OK\n");
  }

  // track each file in the folder for edits

  // record each file in the folder so that we know the name on deletion
  BEntry entry;
  status_t err2;
  err = dir.GetNextEntry(&entry);
  while(err == B_OK)
  {
    err = dir.GetNextEntry(&entry);
    this->tracked_files.AddItem((void*)&entry);
    err2 = entry.GetNodeRef(&nref);
    if(err2 == B_OK)
    {
      err2 = watch_node(&nref, B_WATCH_STAT, be_app_messenger);
      if(err2 != B_OK)
        printf("Watch file Node: Not OK\n");
    }
  }

  //watch each file for edits

}

int
run_script(const char *cmd)
{
  char buf[BUFSIZ];
  FILE *ptr;

  if ((ptr = popen(cmd, "r")) != NULL)
    while (fgets(buf, BUFSIZ, ptr) != NULL)
      (void) printf("RAWR%s", buf);
  (void) pclose(ptr);
  return 0;
}

void
delete_file_on_dropbox(const char * filepath)
{
  BString s, dbfp;
  s = BString(filepath);
  s.RemoveFirst("/boot/home/Dropbox");
  dbfp << "python db_rm.py " << s;
  run_script(dbfp);
}

BString local_to_db_filepath(const char * local_path)
{
  BString s;
  s = BString(local_path);
  s.RemoveFirst("/boot/home/Dropbox/");
  return s;
}

void
add_file_to_dropbox(const char * filepath)
{
  BString s, dbfp;
  dbfp = local_to_db_filepath(filepath);
  s << "python db_put.py " << BString(filepath) << " " << dbfp;
  printf("local filepath:%s\n",filepath);
  printf("dropbox filepath:%s\n",dbfp.String());
  run_script(s.String());
}

void
add_folder_to_dropbox(const char * filepath)
{
  BString s;
  s << "python db_mkdir.py " << local_to_db_filepath(filepath);
  printf("local filepath: %s\n", filepath);
  printf("db filepath: %s\n", local_to_db_filepath(filepath).String());
  run_script(s.String());
}

void
moved_file(BMessage *msg)
{
  //is this file being move into or out of ~/Dropbox?
  run_script("python db_ls.py");
}

void
update_file_in_dropbox(const char * filepath)
{
  add_file_to_dropbox(filepath); //just put it?
}

void
App::MessageReceived(BMessage *msg)
{
  switch(msg->what)
  {
    case B_NODE_MONITOR:
    {
      printf("Received Node Monitor Alert\n");
      status_t err;
      int32 opcode;
      err = msg->FindInt32("opcode",&opcode);
      if(err == B_OK)
      {
        printf("what:%d\topcode:%d\n",msg->what, opcode);
        switch(opcode)
        {
          case B_ENTRY_CREATED:
          {
            printf("NEW FILE\n");
            entry_ref ref;
            BPath path;
            const char * name;
            msg->FindInt32("device",&ref.device);
            msg->FindInt64("directory",&ref.directory);
            msg->FindString("name",&name);
            printf("name:%s\n",name);
            ref.set_name(name);
            BEntry new_file = BEntry(&ref);
            new_file.GetPath(&path);
            add_file_to_dropbox(path.Path());
            break;
          }
          case B_ENTRY_MOVED:
          {
            printf("MOVED FILE\n");
            moved_file(msg);
            break;
          }
          case B_ENTRY_REMOVED:
          {
            printf("DELETED FILE\n");
            node_ref nref, cref;
            msg->FindInt32("device",&nref.device);
            msg->FindInt64("node",&nref.node);
            BEntry *entryPtr;
            int32 ktr = 0;
            int32 limit = this->tracked_files.CountItems();
            while((entryPtr = (BEntry *)this->tracked_files.ItemAt(ktr++))&&(ktr<limit))
            {
              if(entryPtr->InitCheck() == B_OK)
              {
                entryPtr->GetNodeRef(&cref);
              }
              else
              {
                printf("OH NO!\t%d\n",entryPtr->InitCheck());
                printf("OK = %d\n", B_OK);
                printf("Entry Not Found = %d\n",B_ENTRY_NOT_FOUND);
                printf("Bad Value = %d\n",B_BAD_VALUE);
                printf("No Init = %d\n", B_NO_INIT);
                return;
              }

              if(nref == cref)
              {
                BPath path;
                entryPtr->GetPath(&path);
                delete_file_on_dropbox(path.Path());
                break; //break out of loop
              }
            }
            break;
          }
          case B_STAT_CHANGED:
          {
            printf("EDITED FILE\n");
            node_ref nref1,nref2;
            msg->FindInt32("device",&nref1.device);
            msg->FindInt64("node",&nref1.node);
            BEntry * entryPtr;
            int32 ktr = 0;
            while((entryPtr = (BEntry *)this->tracked_files.ItemAt(ktr++)))

            {
              entryPtr->GetNodeRef(&nref2);
              if(nref1 == nref2)
              {
                BPath path;
                entryPtr->GetPath(&path);
                update_file_in_dropbox(path.Path());
                break;
              }
            }
            break;
          }
          default:
          {
            printf("default case opcode...\n");
          }
        }
      }
      break;
    }
    default:
    {
      printf("default msg\n");
      BApplication::MessageReceived(msg);
      break;
    }
  }
}

int
main(void)
{
  //Haiku make window code
  App *app = new App();

  app->Run();
  delete app;
  return 0;
}
<|endoftext|>


<commit_before>#include "HexagonAlignLoads.h"
#include "IRMutator.h"
#include "IROperator.h"
#include "Scope.h"
#include "Bounds.h"
#include "ModulusRemainder.h"
#include "Simplify.h"
namespace Halide {
namespace Internal {
using std::vector;

class HexagonAlignLoads : public IRMutator {
public:
    HexagonAlignLoads(Target t) : target(t) {}
private:
    Target target;
    enum AlignCheck { Aligned, Unaligned, NoResult };

    /** Alignment info for Int(32) variables in scope. */
    Scope<ModulusRemainder> alignment_info;
    using IRMutator::visit;
    ModulusRemainder get_alignment_info(Expr e) {
        return modulus_remainder(e, alignment_info);
    }

    Expr concat_and_shuffle(Expr vec_a, Expr vec_b, int start, int size) {
        Type dbl_t = vec_a.type().with_lanes(vec_a.type().lanes() * 2);
        Expr dbl_vec = Call::make(dbl_t, Call::concat_vectors, { vec_a, vec_b }, Call::PureIntrinsic);
        std::vector<Expr> args;
        args.push_back(dbl_vec);
        for (int i = start; i < start+size; i++) {
            args.push_back(i);
        }
        return Call::make(vec_a.type(), Call::shuffle_vector, args, Call::PureIntrinsic);
    }

    Expr concat_and_shuffle(Expr vec_a, Expr vec_b, std::vector<Expr> &indices) {
        Type dbl_t = vec_a.type().with_lanes(vec_a.type().lanes() * 2);
        Expr dbl_vec = Call::make(dbl_t, Call::concat_vectors, { vec_a, vec_b }, Call::PureIntrinsic);
        std::vector<Expr> args;
        args.push_back(dbl_vec);
        for (int i = 0; i < (int) indices.size(); i++) {
            args.push_back(indices[i]);
        }
        return Call::make(vec_a.type(), Call::shuffle_vector, args, Call::PureIntrinsic);
    }

    AlignCheck get_alignment_check(const Ramp *ramp, int host_alignment, int *lanes_off) {
        // We reason only in terms of lanes. Each lane is a vector element.
        // We want to know the following.
        //    1. if the base of buffer + ramp->base (i.e. the index) are aligned.
        //    2. if not, then how many lanes off an aligned address are they (returned in base_mod).
        //    3. if 2, then we create two loads and slice_vector them.
        //    4. rem_mod is used if the ramp base is 64*x + 65 and lanes is 64, then we are not
        //       modulus_remainder.remainder lanes off, but we are only 1 lane off.
        int lanes = ramp->lanes;
        Expr base = ramp->base;
        // We know the base itself puts us off an aligned address by base_lanes_off
        // number of lanes.
        int base_lanes_off = mod_imp(host_alignment, lanes);
        ModulusRemainder mod_rem = get_alignment_info(base);
        if (mod_rem.modulus == 1 && mod_rem.remainder == 0) {
            // We can't reason about alignment.
            return AlignCheck::NoResult;
        }
        else {
            int base_mod = base_lanes_off + mod_imp(mod_rem.modulus, lanes);
            int rem_mod = mod_imp(mod_rem.remainder, lanes);
            if (!(base_mod + rem_mod)) return AlignCheck::Aligned;
            else {
                if (lanes_off) *lanes_off = base_mod + rem_mod;
                return AlignCheck::Unaligned;
            }
        }
    }
    void visit(const Load *op) {
        debug(4) << "HexagonAlignLoads: Working on " << (Expr) op << "..\n";
        Expr index = mutate(op->index);
        if (op->type.is_vector()) {
            bool external = op->image.defined();
            if (external) {
                debug(4) << "HexagonAlignLoads: Not dealing with an external image\n";
                debug(4) << (Expr) op << "\n";
                expr = op;
                return;
            }
            else {
                const Ramp *ramp = index.as<Ramp>();
                const IntImm *stride = ramp ? ramp->stride.as<IntImm>() : NULL;
                // We will work only on natural vectors supported by the target.
                if (ramp->lanes != target.natural_vector_size(op->type)) {
                    expr = op;
                    return;
                }
                if (ramp && stride && stride->value == 1) {
                    int lanes = ramp->lanes;
                    int vec_size = target.natural_vector_size(Int(8));
                    // If this is a parameter, the base_alignment should be host_alignment.
                    // This cannot be an external image because we have already checked for
                    // it. Otherwise, this is an internal buffers that is always aligned
                    // to the natural vector width.
                    int base_alignment = op->param.defined() ?
                        op->param.host_alignment() : vec_size;
                    int lanes_off;
                    AlignCheck ac = get_alignment_check(ramp, base_alignment, &lanes_off);
                    if (ac == AlignCheck::NoResult) {
                        // We know nothing about alignment. Give up.
                        // TODO: Fix this.
                        debug(4) << "HexagonAlignLoads: Cannot reason about alignment.\n";
                        debug(4) << "HexagonAlignLoads: Type: " << op->type << "\n";
                        debug(4) << "HexagonAlignLoads: Index: " << index << "\n";
                        expr = op;
                        return;
                    }
                    if (ac == AlignCheck::Aligned) {
                        expr = op;
                        debug(4) << "HexagonAlignLoads: Encountered a perfectly aligned load.\n";
                        debug(4) << "HexagonAlignLoads: Type: " << op->type << "\n";
                        debug(4) << "HexagonAlignLoads: Index: " << index << "\n";
                        return;
                    } else {
                        Expr base = ramp->base;
                        const Add *add = base.as<Add>();
                        const IntImm *b = add->b.as<IntImm>();
                        if (!b) {
                            // Should we be expecting the index to be in simplified
                            // canonical form, i.e. expression + IntImm?
                            debug(4) << "HexagonAlignLoads: add->b is not a constant\n";
                            debug(4) << "HexagonAlignLoads: Type: " << op->type << "\n";
                            debug(4) << "HexagonAlignLoads: Index: " << index << "\n";
                            expr = op;
                            return;
                        }
                        Expr base_low = base - (lanes_off);
                        Expr ramp_low = Ramp::make(simplify(base_low), 1, lanes);
                        Expr ramp_high = Ramp::make(simplify(base_low + lanes), 1, lanes);
                        Expr load_low = Load::make(op->type, op->name, ramp_low, op->image, op->param);
                        Expr load_high = Load::make(op->type, op->name, ramp_high, op->image, op->param);
                        // slice_vector considers the vectors in it to be concatenated and the result
                        // is a vector containing as many lanes as the last argument and the vector
                        // begins at lane number specified by the penultimate arg.
                        // So, slice_vector(2, a, b, 126, 128) gives a vector of 128 lanes starting
                        // from lanes 126 through 253 of the concatenated vector a.b.
                        debug(4) << "HexagonAlignLoads: Unaligned Load: Converting " << (Expr) op << " into ...\n";
                        expr = concat_and_shuffle(load_low, load_high, lanes_off, lanes);
                        debug(4) <<  "... " << expr << "\n";
                        return;
                    }
                } else if (ramp && stride && stride->value == 2) {
                    // We'll try to break this into two dense loads followed by a shuffle.
                    Expr base_a = ramp->base, base_b = ramp->base + ramp->lanes;
                    int b_shift = 0;
                    int lanes = ramp->lanes;

                    if (op->param.defined()) {
                        // We need to be able to figure out if buffer_base + base_a is aligned. If not,
                        // we may have to shift base_b left by one so as to not read beyond the end
                        // of an external buffer.
                        AlignCheck ac = get_alignment_check(ramp, op->param.host_alignment(), nullptr);

                        if (ac == AlignCheck::Unaligned) {
                            debug(4) << "HexagonAlignLoads: base_a is unaligned: shifting base_b\n";
                            debug(4) << "HexagonAlignLoads: Type: " << op->type << "\n";
                            debug(4) << "HexagonAlignLoads: Index: " << index << "\n";
                            base_b -= 1;
                            b_shift = 1;
                        }
                    }

                    Expr ramp_a = Ramp::make(base_a, 1, lanes);
                    Expr ramp_b = Ramp::make(base_b, 1, lanes);
                    Expr vec_a = mutate(Load::make(op->type, op->name, ramp_a, op->image, op->param));
                    Expr vec_b = mutate(Load::make(op->type, op->name, ramp_b, op->image, op->param));

                    std::vector<Expr> indices;
                    for (int i = 0; i < lanes/2; ++i) {
                        indices.push_back(i*2);
                    }
                    for (int i = lanes/2; i < lanes; ++i) {
                        indices.push_back(i*2 + b_shift);
                    }

                    debug(4) << "HexagonAlignLoads: Unaligned Load: Converting " << (Expr) op << " into ...\n";

                    expr = concat_and_shuffle(vec_a, vec_b, indices);

                    debug(4) <<  "... " << expr << "\n";
                    return;
                }else {
                    expr = op;
                    return;
                }
            }
        } else {
            expr = op;
            return;
        }
    }

    template<typename NodeType, typename LetType>
    void visit_let(NodeType &result, const LetType *op) {
        Expr value;
        if (op->value.type() == Int(32)) {
            alignment_info.push(op->name, modulus_remainder(op->value, alignment_info));
            value = op->value;
        } else {
            const Load *ld = op->value.template as<Load>();
            if (ld) value = mutate(op->value);
            else value = op->value;
        }

        NodeType body = mutate(op->body);
        if (op->value.type() == Int(32)) {
            alignment_info.pop(op->name);
        }
        result = LetType::make(op->name, value, body);
    }

    void visit(const Let *op) { visit_let(expr, op); }
    void visit(const LetStmt *op) { visit_let(stmt, op); }
};

Stmt hexagon_align_loads(Stmt s, const Target &t) {
    return HexagonAlignLoads(t).mutate(s);
  }
}
}
<commit_msg>Fix use of target.natural_vector_size for hexagon only and hexagon offload usage.<commit_after>#include "HexagonAlignLoads.h"
#include "IRMutator.h"
#include "IROperator.h"
#include "Scope.h"
#include "Bounds.h"
#include "ModulusRemainder.h"
#include "Simplify.h"
namespace Halide {
namespace Internal {
using std::vector;

class HexagonAlignLoads : public IRMutator {
public:
    HexagonAlignLoads(Target t, int vs) : target(t), vector_size(vs) {}
private:
    Target target;
    enum AlignCheck { Aligned, Unaligned, NoResult };
    // size of a vector in bytes.
    int vector_size;
    /** Alignment info for Int(32) variables in scope. */
    Scope<ModulusRemainder> alignment_info;
    using IRMutator::visit;
    ModulusRemainder get_alignment_info(Expr e) {
        return modulus_remainder(e, alignment_info);
    }
    int natural_vector_lanes(Type t) {
        return vector_size / t.bytes();
    }
    Expr concat_and_shuffle(Expr vec_a, Expr vec_b, int start, int size) {
        Type dbl_t = vec_a.type().with_lanes(vec_a.type().lanes() * 2);
        Expr dbl_vec = Call::make(dbl_t, Call::concat_vectors, { vec_a, vec_b }, Call::PureIntrinsic);
        std::vector<Expr> args;
        args.push_back(dbl_vec);
        for (int i = start; i < start+size; i++) {
            args.push_back(i);
        }
        return Call::make(vec_a.type(), Call::shuffle_vector, args, Call::PureIntrinsic);
    }

    Expr concat_and_shuffle(Expr vec_a, Expr vec_b, std::vector<Expr> &indices) {
        Type dbl_t = vec_a.type().with_lanes(vec_a.type().lanes() * 2);
        Expr dbl_vec = Call::make(dbl_t, Call::concat_vectors, { vec_a, vec_b }, Call::PureIntrinsic);
        std::vector<Expr> args;
        args.push_back(dbl_vec);
        for (int i = 0; i < (int) indices.size(); i++) {
            args.push_back(indices[i]);
        }
        return Call::make(vec_a.type(), Call::shuffle_vector, args, Call::PureIntrinsic);
    }

    AlignCheck get_alignment_check(const Ramp *ramp, int host_alignment, int *lanes_off) {
        // We reason only in terms of lanes. Each lane is a vector element.
        // We want to know the following.
        //    1. if the base of buffer + ramp->base (i.e. the index) are aligned.
        //    2. if not, then how many lanes off an aligned address are they (returned in base_mod).
        //    3. if 2, then we create two loads and slice_vector them.
        //    4. rem_mod is used if the ramp base is 64*x + 65 and lanes is 64, then we are not
        //       modulus_remainder.remainder lanes off, but we are only 1 lane off.
        int lanes = ramp->lanes;
        Expr base = ramp->base;
        // We know the base itself puts us off an aligned address by base_lanes_off
        // number of lanes.
        int base_lanes_off = mod_imp(host_alignment, lanes);
        ModulusRemainder mod_rem = get_alignment_info(base);
        if (mod_rem.modulus == 1 && mod_rem.remainder == 0) {
            // We can't reason about alignment.
            return AlignCheck::NoResult;
        }
        else {
            int base_mod = base_lanes_off + mod_imp(mod_rem.modulus, lanes);
            int rem_mod = mod_imp(mod_rem.remainder, lanes);
            if (!(base_mod + rem_mod)) return AlignCheck::Aligned;
            else {
                if (lanes_off) *lanes_off = base_mod + rem_mod;
                return AlignCheck::Unaligned;
            }
        }
    }
    void visit(const Load *op) {
        debug(4) << "HexagonAlignLoads: Working on " << (Expr) op << "..\n";
        Expr index = mutate(op->index);
        if (op->type.is_vector()) {
            bool external = op->image.defined();
            if (external) {
                debug(4) << "HexagonAlignLoads: Not dealing with an external image\n";
                debug(4) << (Expr) op << "\n";
                expr = op;
                return;
            }
            else {
                const Ramp *ramp = index.as<Ramp>();
                const IntImm *stride = ramp ? ramp->stride.as<IntImm>() : NULL;
                // We will work only on natural vectors supported by the target.
                if (ramp->lanes != natural_vector_lanes(op->type)) {
                    expr = op;
                    return;
                }
                if (ramp && stride && stride->value == 1) {
                    int lanes = ramp->lanes;
                    // If this is a parameter, the base_alignment should be host_alignment.
                    // This cannot be an external image because we have already checked for
                    // it. Otherwise, this is an internal buffers that is always aligned
                    // to the natural vector width.
                    int base_alignment = op->param.defined() ?
                        op->param.host_alignment() : vector_size;
                    int lanes_off;
                    AlignCheck ac = get_alignment_check(ramp, base_alignment, &lanes_off);
                    if (ac == AlignCheck::NoResult) {
                        // We know nothing about alignment. Give up.
                        // TODO: Fix this.
                        debug(4) << "HexagonAlignLoads: Cannot reason about alignment.\n";
                        debug(4) << "HexagonAlignLoads: Type: " << op->type << "\n";
                        debug(4) << "HexagonAlignLoads: Index: " << index << "\n";
                        expr = op;
                        return;
                    }
                    if (ac == AlignCheck::Aligned) {
                        expr = op;
                        debug(4) << "HexagonAlignLoads: Encountered a perfectly aligned load.\n";
                        debug(4) << "HexagonAlignLoads: Type: " << op->type << "\n";
                        debug(4) << "HexagonAlignLoads: Index: " << index << "\n";
                        return;
                    } else {
                        Expr base = ramp->base;
                        const Add *add = base.as<Add>();
                        const IntImm *b = add->b.as<IntImm>();
                        if (!b) {
                            // Should we be expecting the index to be in simplified
                            // canonical form, i.e. expression + IntImm?
                            debug(4) << "HexagonAlignLoads: add->b is not a constant\n";
                            debug(4) << "HexagonAlignLoads: Type: " << op->type << "\n";
                            debug(4) << "HexagonAlignLoads: Index: " << index << "\n";
                            expr = op;
                            return;
                        }
                        Expr base_low = base - (lanes_off);
                        Expr ramp_low = Ramp::make(simplify(base_low), 1, lanes);
                        Expr ramp_high = Ramp::make(simplify(base_low + lanes), 1, lanes);
                        Expr load_low = Load::make(op->type, op->name, ramp_low, op->image, op->param);
                        Expr load_high = Load::make(op->type, op->name, ramp_high, op->image, op->param);
                        // slice_vector considers the vectors in it to be concatenated and the result
                        // is a vector containing as many lanes as the last argument and the vector
                        // begins at lane number specified by the penultimate arg.
                        // So, slice_vector(2, a, b, 126, 128) gives a vector of 128 lanes starting
                        // from lanes 126 through 253 of the concatenated vector a.b.
                        debug(4) << "HexagonAlignLoads: Unaligned Load: Converting " << (Expr) op << " into ...\n";
                        expr = concat_and_shuffle(load_low, load_high, lanes_off, lanes);
                        debug(4) <<  "... " << expr << "\n";
                        return;
                    }
                } else if (ramp && stride && stride->value == 2) {
                    // We'll try to break this into two dense loads followed by a shuffle.
                    Expr base_a = ramp->base, base_b = ramp->base + ramp->lanes;
                    int b_shift = 0;
                    int lanes = ramp->lanes;

                    if (op->param.defined()) {
                        // We need to be able to figure out if buffer_base + base_a is aligned. If not,
                        // we may have to shift base_b left by one so as to not read beyond the end
                        // of an external buffer.
                        AlignCheck ac = get_alignment_check(ramp, op->param.host_alignment(), nullptr);

                        if (ac == AlignCheck::Unaligned) {
                            debug(4) << "HexagonAlignLoads: base_a is unaligned: shifting base_b\n";
                            debug(4) << "HexagonAlignLoads: Type: " << op->type << "\n";
                            debug(4) << "HexagonAlignLoads: Index: " << index << "\n";
                            base_b -= 1;
                            b_shift = 1;
                        }
                    }

                    Expr ramp_a = Ramp::make(base_a, 1, lanes);
                    Expr ramp_b = Ramp::make(base_b, 1, lanes);
                    Expr vec_a = mutate(Load::make(op->type, op->name, ramp_a, op->image, op->param));
                    Expr vec_b = mutate(Load::make(op->type, op->name, ramp_b, op->image, op->param));

                    std::vector<Expr> indices;
                    for (int i = 0; i < lanes/2; ++i) {
                        indices.push_back(i*2);
                    }
                    for (int i = lanes/2; i < lanes; ++i) {
                        indices.push_back(i*2 + b_shift);
                    }

                    debug(4) << "HexagonAlignLoads: Unaligned Load: Converting " << (Expr) op << " into ...\n";

                    expr = concat_and_shuffle(vec_a, vec_b, indices);

                    debug(4) <<  "... " << expr << "\n";
                    return;
                }else {
                    expr = op;
                    return;
                }
            }
        } else {
            expr = op;
            return;
        }
    }

    template<typename NodeType, typename LetType>
    void visit_let(NodeType &result, const LetType *op) {
        Expr value;
        if (op->value.type() == Int(32)) {
            alignment_info.push(op->name, modulus_remainder(op->value, alignment_info));
            value = op->value;
        } else {
            const Load *ld = op->value.template as<Load>();
            if (ld) value = mutate(op->value);
            else value = op->value;
        }

        NodeType body = mutate(op->body);
        if (op->value.type() == Int(32)) {
            alignment_info.pop(op->name);
        }
        result = LetType::make(op->name, value, body);
    }

    void visit(const Let *op) { visit_let(expr, op); }
    void visit(const LetStmt *op) { visit_let(stmt, op); }
    void visit(const For *op) {
        if (op->device_api == DeviceAPI::Hexagon) {
            if (target.has_feature(Target::HVX_128)) {
                vector_size = 128;
            }
            else if (target.has_feature(Target::HVX_64)) {
                vector_size = 64;
            } else {
                internal_error << "Unknown HVX mode";
            }
        }
        IRMutator::visit(op);
        return;
    }
};

Stmt hexagon_align_loads(Stmt s, const Target &t) {
    return HexagonAlignLoads(t, t.natural_vector_size(Int(8))).mutate(s);
  }
}
}
<|endoftext|>


<commit_before>// This file is part of BlueSky
//
// BlueSky 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 3
// of the License, or (at your option) any later version.
//
// BlueSky 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with BlueSky; if not, see <http://www.gnu.org/licenses/>.

#include "bs_kernel.h"
#include "bs_kernel_tools.h"
#include "bs_tree.h"
#include "py_bs_exports.h"
#include "py_smart_ptr.h"

#include <boost/python/overloads.hpp>
#include <iostream>

namespace {
using namespace blue_sky;
using namespace std;

struct kernel_handle {
	kernel_handle() : k_(&give_kernel::Instance()) {}
	kernel_handle(kernel*) : k_(&give_kernel::Instance()) {}

	kernel* k_;
};

kernel* get_pointer(const kernel_handle& kf) {
	return kf.k_;
}

struct py_kernel_tools {
	static void print_loaded_types() {
		cout << kernel_tools::print_loaded_types();
	}

	static void walk_tree() {
		cout << kernel_tools::walk_tree();
	}

	static void print_registered_instances() {
		cout << kernel_tools::print_registered_instances();
	}
};

}

namespace boost { namespace python {

template< >
struct pointee< kernel_handle > {
	typedef blue_sky::kernel type;
};

}}

namespace blue_sky { namespace python {

BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(create_object_overl, create_object, 1, 3);
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(load_plugin_overl, load_plugin, 2, 3);
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(load_plugins_overl, LoadPlugins, 0, 1);

void py_bind_kernel() {
	// plugin_types overloads
	kernel::types_enum (kernel::*plugin_types1)(const plugin_descriptor&) const = &kernel::plugin_types;
	kernel::types_enum (kernel::*plugin_types2)(const std::string&) const = &kernel::plugin_types;
	// create_object overloads
	sp_obj (kernel::*create_object1)(const type_descriptor&, bool, bs_type_ctor_param) const = &kernel::create_object;
	sp_obj (kernel::*create_object2)(const std::string&, bool, bs_type_ctor_param) const = &kernel::create_object;

	{
		// main kernel binding
		scope k_scope = class_<
			kernel,
			kernel_handle,
			boost::noncopyable
			>
		("kernel_iface", no_init)
			.def("loaded_plugins", &kernel::loaded_plugins)
			.def("plugin_types", plugin_types1)
			.def("plugin_types", plugin_types2)
			.def("find_type", &kernel::find_type)
			.def("registeres_types", &kernel::registered_types)
			.def("register_type", &kernel::register_type)
			.def("create_type", create_object1, create_object_overl())
			.def("create_type", create_object2, create_object_overl())
			.def("create_object_copy", &kernel::create_object_copy)
			.def("register_instance", &kernel::register_instance)
			.def("free_instance", &kernel::free_instance)
			.def("tree_gc", &kernel::tree_gc)
			.def("objinst_cnt", &kernel::objinst_cnt)
			.def("create_storage", &kernel::create_storage)
			.def("close_storage", &kernel::close_storage)
			.def("load_plugin", &kernel::load_plugin, load_plugin_overl())
			.def("unload_lugin", &kernel::unload_plugin)
			.def("load_plugins", &kernel::LoadPlugins, load_plugins_overl())
			.def("unload_plugins", &kernel::UnloadPlugins)
			.def("pert_str_dt", &kernel::pert_str_dt)
			.def("pert_idx_dt", &kernel::pert_idx_dt)
			.def("get_last_error", &kernel::get_last_error)
			.def("add_task", &kernel::add_task)
			.def("is_tq_empty", &kernel::is_tq_empty)
			.def("wait_tq_empty", &kernel::wait_tq_empty)
			.add_property("tree_root_link", &kernel::bs_root)
			.def("reg_signal", &kernel::reg_signal)
			.def("rem_signal", &kernel::rem_signal)
			//.def("get_memory_manager", &kernel::get_memory_manager)
			//.def("get_log", &kernel::get_log)
			//.def("get_tlog", &kernel::get_tlog)
			.def("register_disconnector", &kernel::register_disconnector)
			.def("unregister_disconnector", &kernel::unregister_disconnector)
		;

		// quick access to root node
		k_scope.attr("tree_root") = BS_KERNEL.bs_root()->node();

		// kernel_tools binding
		class_< py_kernel_tools >("tools", no_init)
			.def("print_loaded_types", &py_kernel_tools::print_loaded_types)
			.def("walk_tree", &py_kernel_tools::walk_tree)
			.def("print_registered_instances", &py_kernel_tools::print_registered_instances)
			.staticmethod("print_loaded_types")
			.staticmethod("walk_tree")
			.staticmethod("print_registered_instances")
		;
	}

	// shortcat to access kernel
	// function form - like in C++
	def("give_kernel", &give_kernel::Instance, return_value_policy< reference_existing_object >());
	// like global attribute - no need to write '()'
	scope().attr("kernel") = kernel_handle();
}

}} 	// eof namespace blue_sky::python

<commit_msg>python: rename create_type -> create_object in Python<commit_after>// This file is part of BlueSky
//
// BlueSky 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 3
// of the License, or (at your option) any later version.
//
// BlueSky 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with BlueSky; if not, see <http://www.gnu.org/licenses/>.

#include "bs_kernel.h"
#include "bs_kernel_tools.h"
#include "bs_tree.h"
#include "py_bs_exports.h"
#include "py_smart_ptr.h"

#include <boost/python/overloads.hpp>
#include <iostream>

namespace {
using namespace blue_sky;
using namespace std;

struct kernel_handle {
	kernel_handle() : k_(&give_kernel::Instance()) {}
	kernel_handle(kernel*) : k_(&give_kernel::Instance()) {}

	kernel* k_;
};

kernel* get_pointer(const kernel_handle& kf) {
	return kf.k_;
}

struct py_kernel_tools {
	static void print_loaded_types() {
		cout << kernel_tools::print_loaded_types();
	}

	static void walk_tree() {
		cout << kernel_tools::walk_tree();
	}

	static void print_registered_instances() {
		cout << kernel_tools::print_registered_instances();
	}
};

}

namespace boost { namespace python {

template< >
struct pointee< kernel_handle > {
	typedef blue_sky::kernel type;
};

}}

namespace blue_sky { namespace python {

BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(create_object_overl, create_object, 1, 3);
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(load_plugin_overl, load_plugin, 2, 3);
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(load_plugins_overl, LoadPlugins, 0, 1);

void py_bind_kernel() {
	// plugin_types overloads
	kernel::types_enum (kernel::*plugin_types1)(const plugin_descriptor&) const = &kernel::plugin_types;
	kernel::types_enum (kernel::*plugin_types2)(const std::string&) const = &kernel::plugin_types;
	// create_object overloads
	sp_obj (kernel::*create_object1)(const type_descriptor&, bool, bs_type_ctor_param) const = &kernel::create_object;
	sp_obj (kernel::*create_object2)(const std::string&, bool, bs_type_ctor_param) const = &kernel::create_object;

	{
		// main kernel binding
		scope k_scope = class_<
			kernel,
			kernel_handle,
			boost::noncopyable
			>
		("kernel_iface", no_init)
			.def("loaded_plugins", &kernel::loaded_plugins)
			.def("plugin_types", plugin_types1)
			.def("plugin_types", plugin_types2)
			.def("find_type", &kernel::find_type)
			.def("registeres_types", &kernel::registered_types)
			.def("register_type", &kernel::register_type)
			.def("create_object", create_object1, create_object_overl())
			.def("create_object", create_object2, create_object_overl())
			.def("create_object_copy", &kernel::create_object_copy)
			.def("register_instance", &kernel::register_instance)
			.def("free_instance", &kernel::free_instance)
			.def("tree_gc", &kernel::tree_gc)
			.def("objinst_cnt", &kernel::objinst_cnt)
			.def("create_storage", &kernel::create_storage)
			.def("close_storage", &kernel::close_storage)
			.def("load_plugin", &kernel::load_plugin, load_plugin_overl())
			.def("unload_lugin", &kernel::unload_plugin)
			.def("load_plugins", &kernel::LoadPlugins, load_plugins_overl())
			.def("unload_plugins", &kernel::UnloadPlugins)
			.def("pert_str_dt", &kernel::pert_str_dt)
			.def("pert_idx_dt", &kernel::pert_idx_dt)
			.def("get_last_error", &kernel::get_last_error)
			.def("add_task", &kernel::add_task)
			.def("is_tq_empty", &kernel::is_tq_empty)
			.def("wait_tq_empty", &kernel::wait_tq_empty)
			.add_property("tree_root_link", &kernel::bs_root)
			.def("reg_signal", &kernel::reg_signal)
			.def("rem_signal", &kernel::rem_signal)
			//.def("get_memory_manager", &kernel::get_memory_manager)
			//.def("get_log", &kernel::get_log)
			//.def("get_tlog", &kernel::get_tlog)
			.def("register_disconnector", &kernel::register_disconnector)
			.def("unregister_disconnector", &kernel::unregister_disconnector)
		;

		// quick access to root node
		k_scope.attr("tree_root") = BS_KERNEL.bs_root()->node();

		// kernel_tools binding
		class_< py_kernel_tools >("tools", no_init)
			.def("print_loaded_types", &py_kernel_tools::print_loaded_types)
			.def("walk_tree", &py_kernel_tools::walk_tree)
			.def("print_registered_instances", &py_kernel_tools::print_registered_instances)
			.staticmethod("print_loaded_types")
			.staticmethod("walk_tree")
			.staticmethod("print_registered_instances")
		;
	}

	// shortcat to access kernel
	// function form - like in C++
	def("give_kernel", &give_kernel::Instance, return_value_policy< reference_existing_object >());
	// like global attribute - no need to write '()'
	scope().attr("kernel") = kernel_handle();
}

}} 	// eof namespace blue_sky::python

<|endoftext|>


<commit_before>/*
Copyright 2016-2017 Nia Catlin

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.
*/

/*
The targets combo box at the top of the interface.
Also handles creating new targets.
*/

#include "stdafx.h"
#include "targetcombo.h"
#include "maintabbox.h"
#include <boost\filesystem.hpp>
#include "ui_rgat.h"

targetCombo::targetCombo(QWidget *parent)
	: QComboBox(parent)
{

}

targetCombo::~targetCombo()
{
}

void targetCombo::setActiveTarget(binaryTarget * target)
{
	if (!targets->exists(target) || (target == clientState->activeBinary)) return;

	clientState->activeBinary = target;
	clientState->clearActiveGraph();
	clientState->activeTrace = NULL;
	mainTabs->changeTarget(target, eVisualiseTab);

	Ui::rgatClass *ui = (Ui::rgatClass *)clientState->ui;

	ui->traceGatherTab->fillAnalyseTab(target);
}

void targetCombo::setActiveTarget(int index)
{
	if (index == -1 || paths.size() <= index) return;

	boost::filesystem::path activePath = paths.at(index);
	if (activePath.size() == 0) return;

	binaryTarget * target;

	targets->getTargetByPath(activePath, &target);
	if (target)
		setActiveTarget(target);
}

void targetCombo::addTargetToInterface(binaryTarget *target, bool newBinary)
{
	Ui::rgatClass *ui = (Ui::rgatClass *)clientState->ui;
	boost::filesystem::path filepath = target->path();
	if (newBinary)
	{

		if (paths.empty())
		{
			//get rid of the [hey you should add a target] text
			removeItem(0);
		}

		paths.push_back(target->path());

		stringstream targetSS;
		targetSS << "[" << paths.size()-1 << "]" << "   " << filepath.string();
		QString targetDisplayString = QString::fromStdString(targetSS.str());

		addItem(targetDisplayString);
		setCurrentIndex(count() - 1);

		ui->staticDynamicStack->setCurrentIndex(eDynamicTabs);

		ui->dynamicAnalysisContentsTab->setCurrentIndex(eStartTraceTab);
	}
	else
	{
		auto vecpos = std::find(paths.begin(), paths.end(), filepath);
		assert(vecpos != paths.end());
		setCurrentIndex(vecpos - paths.begin());
		ui->dynamicAnalysisContentsTab->setCurrentIndex(eStartTraceTab);
	}

	ui->traceGatherTab->fillAnalyseTab(target);

}

void targetCombo::addNewTarget()
{
	//crash when right click in this dialog https://bugreports.qt.io/browse/QTBUG-33119?page=com.atlassian.jira.plugin.system.issuetabpanels%3Aall-tabpanel
	QString fileName = QFileDialog::getOpenFileName(this,
		tr("Select new target"), clientState->config.getLastPathString(),
		tr("Executable (*.exe);;Library (*.dll);;All Files (*.*)"));

	boost::filesystem::path filepath(fileName.toStdString());
	if (!boost::filesystem::exists(filepath))
		return;

	binaryTarget *target;

	bool newBinary = targets->getTargetByPath(filepath, &target);

	addTargetToInterface(target, newBinary);

	clientState->config.updateLastPath(filepath);

}<commit_msg>main part of ui disabled until a target is selected because a lot of it is uninitialised without a binary<commit_after>/*
Copyright 2016-2017 Nia Catlin

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.
*/

/*
The targets combo box at the top of the interface.
Also handles creating new targets.
*/

#include "stdafx.h"
#include "targetcombo.h"
#include "maintabbox.h"
#include <boost\filesystem.hpp>
#include "ui_rgat.h"

targetCombo::targetCombo(QWidget *parent)
	: QComboBox(parent)
{

}

targetCombo::~targetCombo()
{
}

void targetCombo::setActiveTarget(binaryTarget * target)
{
	if (!targets->exists(target) || (target == clientState->activeBinary)) return;

	clientState->activeBinary = target;
	clientState->clearActiveGraph();
	clientState->activeTrace = NULL;
	mainTabs->changeTarget(target, eVisualiseTab);

	Ui::rgatClass *ui = (Ui::rgatClass *)clientState->ui;

	ui->traceGatherTab->fillAnalyseTab(target);
}

void targetCombo::setActiveTarget(int index)
{
	if (index == -1 || paths.size() <= index) return;

	boost::filesystem::path activePath = paths.at(index);
	if (activePath.size() == 0) return;

	binaryTarget * target;

	targets->getTargetByPath(activePath, &target);
	if (target)
		setActiveTarget(target);
}

void targetCombo::addTargetToInterface(binaryTarget *target, bool newBinary)
{
	Ui::rgatClass *ui = (Ui::rgatClass *)clientState->ui;

	if (!ui->staticDynamicStack->isEnabled())
		ui->staticDynamicStack->setEnabled(true);

	boost::filesystem::path filepath = target->path();
	if (newBinary)
	{

		if (paths.empty())
		{
			//get rid of the [hey you should add a target] text
			removeItem(0);
		}

		paths.push_back(target->path());

		stringstream targetSS;
		targetSS << "[" << paths.size()-1 << "]" << "   " << filepath.string();
		QString targetDisplayString = QString::fromStdString(targetSS.str());

		addItem(targetDisplayString);
		setCurrentIndex(count() - 1);

		ui->staticDynamicStack->setCurrentIndex(eDynamicTabs);

		ui->dynamicAnalysisContentsTab->setCurrentIndex(eStartTraceTab);
	}
	else
	{
		auto vecpos = std::find(paths.begin(), paths.end(), filepath);
		assert(vecpos != paths.end());
		setCurrentIndex(vecpos - paths.begin());
		ui->dynamicAnalysisContentsTab->setCurrentIndex(eStartTraceTab);
	}

	ui->traceGatherTab->fillAnalyseTab(target);

}

void targetCombo::addNewTarget()
{
	//crash when right click in this dialog https://bugreports.qt.io/browse/QTBUG-33119?page=com.atlassian.jira.plugin.system.issuetabpanels%3Aall-tabpanel
	QString fileName = QFileDialog::getOpenFileName(this,
		tr("Select new target"), clientState->config.getLastPathString(),
		tr("Executable (*.exe);;Library (*.dll);;All Files (*.*)"));

	boost::filesystem::path filepath(fileName.toStdString());
	if (!boost::filesystem::exists(filepath))
		return;

	binaryTarget *target;

	bool newBinary = targets->getTargetByPath(filepath, &target);

	addTargetToInterface(target, newBinary);

	clientState->config.updateLastPath(filepath);

}<|endoftext|>


<commit_before>#include "Fraction.h"
#include "../Data.h"
#include "../Ensemble.h"
#include "../Variables/Variable.h"

MeasureFraction::MeasureFraction(const Options& iOptions, const Data& iData) :
      Measure(iOptions, iData),
      mX(Global::MV),
      mUseMin(false),
      mUseMax(false) {
   //! Use this threshold
   iOptions.getValue("x", mX);
   //! Set the threshold to the forecast variable's minimum value (e.g. 0 mm for preciptation)
   iOptions.getValue("useMin", mUseMin);
   //! Set the threshold to the forecast variable's maximum value (e.g. 100 % for RH)
   iOptions.getValue("useMax", mUseMax);
   if(!Global::isValid(mX) + !mUseMin + !mUseMax != 1) {
      std::stringstream ss;
      ss << "At least (and at most) one of 'x', 'useMin', and 'useMax', must be specified";
      Global::logger->write(ss.str(), Logger::error);
   }
}

float MeasureFraction::measureCore(const Ensemble& iEnsemble) const {
   int counter = 0;
   int total   = 0;

   // Determine where on the variable-axis the discrete point is
   float point = mX;
   if(mUseMin)
      point = Variable::get(iEnsemble.getVariable())->getMin();
   else if(mUseMax)
      point = Variable::get(iEnsemble.getVariable())->getMax();
   assert(Global::isValid(point));

   for(int i = 0; i < iEnsemble.size(); i++) {
      if(Global::isValid(iEnsemble[i])) {
         if(iEnsemble[i] == point) {
            counter++;
         }
         total++;
      }
   }
   float frac = Global::MV;
   if(total > 0)
      frac = (float) counter / total;
   return frac;
}
<commit_msg>Fixes the checking of options to MeasureFraction<commit_after>#include "Fraction.h"
#include "../Data.h"
#include "../Ensemble.h"
#include "../Variables/Variable.h"

MeasureFraction::MeasureFraction(const Options& iOptions, const Data& iData) :
      Measure(iOptions, iData),
      mX(Global::MV),
      mUseMin(false),
      mUseMax(false) {
   //! Use this threshold
   iOptions.getValue("x", mX);
   //! Set the threshold to the forecast variable's minimum value (e.g. 0 mm for preciptation)
   iOptions.getValue("useMin", mUseMin);
   //! Set the threshold to the forecast variable's maximum value (e.g. 100 % for RH)
   iOptions.getValue("useMax", mUseMax);
   if(Global::isValid(mX) + mUseMin + mUseMax != 1) {
      std::stringstream ss;
      ss << "At least (and at most) one of 'x', 'useMin', and 'useMax', must be specified";
      Global::logger->write(ss.str(), Logger::error);
   }
}

float MeasureFraction::measureCore(const Ensemble& iEnsemble) const {
   int counter = 0;
   int total   = 0;

   // Determine where on the variable-axis the discrete point is
   float point = mX;
   if(mUseMin)
      point = Variable::get(iEnsemble.getVariable())->getMin();
   else if(mUseMax)
      point = Variable::get(iEnsemble.getVariable())->getMax();
   assert(Global::isValid(point));

   for(int i = 0; i < iEnsemble.size(); i++) {
      if(Global::isValid(iEnsemble[i])) {
         if(iEnsemble[i] == point) {
            counter++;
         }
         total++;
      }
   }
   float frac = Global::MV;
   if(total > 0)
      frac = (float) counter / total;
   return frac;
}
<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2011 Artem Pavlenko
 *
 * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

// mapnik
#include <mapnik/debug.hpp>
#include <mapnik/graphics.hpp>
#include <mapnik/image_util.hpp>
#include <mapnik/global.hpp>
#include <mapnik/color.hpp>

// agg
#include "agg_rendering_buffer.h"
#include "agg_pixfmt_rgba.h"

// boost
#include <boost/scoped_array.hpp>

// cairo
#ifdef HAVE_CAIRO
#include <mapnik/cairo_context.hpp>
#endif

namespace mapnik
{
image_32::image_32(int width,int height)
    :width_(width),
     height_(height),
     data_(width,height),
     painted_(false),
     premultiplied_(false) {}

image_32::image_32(const image_32& rhs)
    :width_(rhs.width_),
     height_(rhs.height_),
     data_(rhs.data_),
     painted_(rhs.painted_),
     premultiplied_(rhs.premultiplied_) {}

#ifdef HAVE_CAIRO
image_32::image_32(cairo_surface_ptr const& surface)
    :width_(cairo_image_surface_get_width(&*surface)),
     height_(cairo_image_surface_get_height(&*surface)),
     data_(width_, height_),
     premultiplied_(false)
{
    painted_ = true;
    if ( cairo_image_surface_get_format(&*surface) != CAIRO_FORMAT_ARGB32)
    {
        MAPNIK_LOG_WARN(graphics) << "Unable to convert this Cairo format";
        throw;
    }

    int stride = cairo_image_surface_get_stride(&*surface) / 4;

    boost::scoped_array<unsigned int> out_row(new unsigned int[width_]);
    const unsigned int *in_row = (const unsigned int *)cairo_image_surface_get_data(&*surface);

    for (unsigned int row = 0; row < height_; row++, in_row += stride)
    {
        for (unsigned int column = 0; column < width_; column++)
        {
            unsigned int in = in_row[column];
            unsigned int a = (in >> 24) & 0xff;
            unsigned int r = (in >> 16) & 0xff;
            unsigned int g = (in >> 8) & 0xff;
            unsigned int b = (in >> 0) & 0xff;

#define DE_ALPHA(x) do {                        \
                if (a == 0) x = 0;              \
                else x = x * 255 / a;           \
                if (x > 255) x = 255;           \
            } while(0)

            DE_ALPHA(r);
            DE_ALPHA(g);
            DE_ALPHA(b);

            out_row[column] = color(r, g, b, a).rgba();
        }
        data_.setRow(row, out_row.get(), width_);
    }
}
#endif

image_32::~image_32() {}

void image_32::set_grayscale_to_alpha()
{
    for (unsigned int y = 0; y < height_; ++y)
    {
        unsigned int* row_from = data_.getRow(y);
        for (unsigned int x = 0; x < width_; ++x)
        {
            unsigned rgba = row_from[x];
            // TODO - big endian support
            unsigned r = rgba & 0xff;
            unsigned g = (rgba >> 8 ) & 0xff;
            unsigned b = (rgba >> 16) & 0xff;

            // magic numbers for grayscale
            unsigned a = static_cast<unsigned>(std::ceil((r * .3) + (g * .59) + (b * .11)));

            row_from[x] = (a << 24)| (255 << 16) |  (255 << 8) | (255) ;
        }
    }
}

void image_32::set_color_to_alpha(const color& c)
{
    for (unsigned y = 0; y < height_; ++y)
    {
        unsigned int* row_from = data_.getRow(y);
        for (unsigned x = 0; x < width_; ++x)
        {
            unsigned rgba = row_from[x];
            unsigned r = rgba & 0xff;
            unsigned g = (rgba >> 8 ) & 0xff;
            unsigned b = (rgba >> 16) & 0xff;
            if (r == c.red() && g == c.green() && b == c.blue())
            {
                row_from[x] = 0;
            }
        }
    }
}

void image_32::set_alpha(float opacity)
{
    for (unsigned int y = 0; y < height_; ++y)
    {
        unsigned int* row_to =  data_.getRow(y);
        for (unsigned int x = 0; x < width_; ++x)
        {
            unsigned rgba = row_to[x];

#ifdef MAPNIK_BIG_ENDIAN
            unsigned a0 = (rgba & 0xff);
            unsigned a1 = int( (rgba & 0xff) * opacity );

            if (a0 == a1) continue;

            unsigned r = (rgba >> 24) & 0xff;
            unsigned g = (rgba >> 16 ) & 0xff;
            unsigned b = (rgba >> 8) & 0xff;

            row_to[x] = (a1) | (b << 8) |  (g << 16) | (r << 24) ;

#else
            unsigned a0 = (rgba >> 24) & 0xff;
            unsigned a1 = int( ((rgba >> 24) & 0xff) * opacity );
            //unsigned a1 = opacity;
            if (a0 == a1) continue;

            unsigned r = rgba & 0xff;
            unsigned g = (rgba >> 8 ) & 0xff;
            unsigned b = (rgba >> 16) & 0xff;

            row_to[x] = (a1 << 24)| (b << 16) |  (g << 8) | (r) ;
#endif
        }
    }
}

void image_32::set_background(const color& c)
{
    background_=c;
    data_.set(background_->rgba());
}

boost::optional<color> const& image_32::get_background() const
{
    return background_;
}

void image_32::premultiply()
{
    agg::rendering_buffer buffer(data_.getBytes(),width_,height_,width_ * 4);
    agg::pixfmt_rgba32 pixf(buffer);
    pixf.premultiply();
    premultiplied_ = true;
}

void image_32::demultiply()
{
    agg::rendering_buffer buffer(data_.getBytes(),width_,height_,width_ * 4);
    agg::pixfmt_rgba32 pixf(buffer);
    pixf.demultiply();
    premultiplied_ = false;
}

void image_32::composite_pixel(unsigned op, int x,int y, unsigned c, unsigned cover, double opacity)
{
    typedef agg::rgba8 color_type;
    typedef color_type::value_type value_type;
    typedef agg::order_rgba order_type;
    typedef agg::comp_op_adaptor_rgba<color_type,order_type> blender_type;

    if (checkBounds(x,y))
    {
        unsigned rgba = data_(x,y);
        unsigned ca = (unsigned)(((c >> 24) & 0xff) * opacity);
        unsigned cb = (c >> 16 ) & 0xff;
        unsigned cg = (c >> 8) & 0xff;
        unsigned cr = (c & 0xff);
        blender_type::blend_pix(op, (value_type*)&rgba, cr, cg, cb, ca, cover);
        data_(x,y) = rgba;
    }
}

}
<commit_msg>use pixfmt pre for the sake of clarity<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2011 Artem Pavlenko
 *
 * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

// mapnik
#include <mapnik/debug.hpp>
#include <mapnik/graphics.hpp>
#include <mapnik/image_util.hpp>
#include <mapnik/global.hpp>
#include <mapnik/color.hpp>

// agg
#include "agg_rendering_buffer.h"
#include "agg_pixfmt_rgba.h"
#include "agg_color_rgba.h"

// boost
#include <boost/scoped_array.hpp>

// cairo
#ifdef HAVE_CAIRO
#include <mapnik/cairo_context.hpp>
#endif

namespace mapnik
{
image_32::image_32(int width,int height)
    :width_(width),
     height_(height),
     data_(width,height),
     painted_(false),
     premultiplied_(false) {}

image_32::image_32(const image_32& rhs)
    :width_(rhs.width_),
     height_(rhs.height_),
     data_(rhs.data_),
     painted_(rhs.painted_),
     premultiplied_(rhs.premultiplied_) {}

#ifdef HAVE_CAIRO
image_32::image_32(cairo_surface_ptr const& surface)
    :width_(cairo_image_surface_get_width(&*surface)),
     height_(cairo_image_surface_get_height(&*surface)),
     data_(width_, height_),
     premultiplied_(false)
{
    painted_ = true;
    if ( cairo_image_surface_get_format(&*surface) != CAIRO_FORMAT_ARGB32)
    {
        MAPNIK_LOG_WARN(graphics) << "Unable to convert this Cairo format";
        throw;
    }

    int stride = cairo_image_surface_get_stride(&*surface) / 4;

    boost::scoped_array<unsigned int> out_row(new unsigned int[width_]);
    const unsigned int *in_row = (const unsigned int *)cairo_image_surface_get_data(&*surface);

    for (unsigned int row = 0; row < height_; row++, in_row += stride)
    {
        for (unsigned int column = 0; column < width_; column++)
        {
            unsigned int in = in_row[column];
            unsigned int a = (in >> 24) & 0xff;
            unsigned int r = (in >> 16) & 0xff;
            unsigned int g = (in >> 8) & 0xff;
            unsigned int b = (in >> 0) & 0xff;

#define DE_ALPHA(x) do {                        \
                if (a == 0) x = 0;              \
                else x = x * 255 / a;           \
                if (x > 255) x = 255;           \
            } while(0)

            DE_ALPHA(r);
            DE_ALPHA(g);
            DE_ALPHA(b);

            out_row[column] = color(r, g, b, a).rgba();
        }
        data_.setRow(row, out_row.get(), width_);
    }
}
#endif

image_32::~image_32() {}

void image_32::set_grayscale_to_alpha()
{
    for (unsigned int y = 0; y < height_; ++y)
    {
        unsigned int* row_from = data_.getRow(y);
        for (unsigned int x = 0; x < width_; ++x)
        {
            unsigned rgba = row_from[x];
            // TODO - big endian support
            unsigned r = rgba & 0xff;
            unsigned g = (rgba >> 8 ) & 0xff;
            unsigned b = (rgba >> 16) & 0xff;

            // magic numbers for grayscale
            unsigned a = static_cast<unsigned>(std::ceil((r * .3) + (g * .59) + (b * .11)));

            row_from[x] = (a << 24)| (255 << 16) |  (255 << 8) | (255) ;
        }
    }
}

void image_32::set_color_to_alpha(const color& c)
{
    for (unsigned y = 0; y < height_; ++y)
    {
        unsigned int* row_from = data_.getRow(y);
        for (unsigned x = 0; x < width_; ++x)
        {
            unsigned rgba = row_from[x];
            unsigned r = rgba & 0xff;
            unsigned g = (rgba >> 8 ) & 0xff;
            unsigned b = (rgba >> 16) & 0xff;
            if (r == c.red() && g == c.green() && b == c.blue())
            {
                row_from[x] = 0;
            }
        }
    }
}

void image_32::set_alpha(float opacity)
{
    for (unsigned int y = 0; y < height_; ++y)
    {
        unsigned int* row_to =  data_.getRow(y);
        for (unsigned int x = 0; x < width_; ++x)
        {
            unsigned rgba = row_to[x];

#ifdef MAPNIK_BIG_ENDIAN
            unsigned a0 = (rgba & 0xff);
            unsigned a1 = int( (rgba & 0xff) * opacity );

            if (a0 == a1) continue;

            unsigned r = (rgba >> 24) & 0xff;
            unsigned g = (rgba >> 16 ) & 0xff;
            unsigned b = (rgba >> 8) & 0xff;

            row_to[x] = (a1) | (b << 8) |  (g << 16) | (r << 24) ;

#else
            unsigned a0 = (rgba >> 24) & 0xff;
            unsigned a1 = int( ((rgba >> 24) & 0xff) * opacity );
            //unsigned a1 = opacity;
            if (a0 == a1) continue;

            unsigned r = rgba & 0xff;
            unsigned g = (rgba >> 8 ) & 0xff;
            unsigned b = (rgba >> 16) & 0xff;

            row_to[x] = (a1 << 24)| (b << 16) |  (g << 8) | (r) ;
#endif
        }
    }
}

void image_32::set_background(const color& c)
{
    background_=c;
    data_.set(background_->rgba());
}

boost::optional<color> const& image_32::get_background() const
{
    return background_;
}

void image_32::premultiply()
{
    agg::rendering_buffer buffer(data_.getBytes(),width_,height_,width_ * 4);
    agg::pixfmt_rgba32 pixf(buffer);
    pixf.premultiply();
    premultiplied_ = true;
}

void image_32::demultiply()
{
    agg::rendering_buffer buffer(data_.getBytes(),width_,height_,width_ * 4);
    agg::pixfmt_rgba32_pre pixf(buffer);
    pixf.demultiply();
    premultiplied_ = false;
}

void image_32::composite_pixel(unsigned op, int x,int y, unsigned c, unsigned cover, double opacity)
{
    typedef agg::rgba8 color_type;
    typedef color_type::value_type value_type;
    typedef agg::order_rgba order_type;
    typedef agg::comp_op_adaptor_rgba<color_type,order_type> blender_type;

    if (checkBounds(x,y))
    {
        unsigned rgba = data_(x,y);
        unsigned ca = (unsigned)(((c >> 24) & 0xff) * opacity);
        unsigned cb = (c >> 16 ) & 0xff;
        unsigned cg = (c >> 8) & 0xff;
        unsigned cr = (c & 0xff);
        blender_type::blend_pix(op, (value_type*)&rgba, cr, cg, cb, ca, cover);
        data_(x,y) = rgba;
    }
}

}
<|endoftext|>