<commit_before>/*************************************************************************
 *
 *  $RCSfile: viewcontactofe3dscene.hxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: rt $ $Date: 2003-11-24 16:26:11 $
 *
 *  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: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _SDR_CONTACT_VIEWCONTACTOFE3DSCENE_HXX
#define _SDR_CONTACT_VIEWCONTACTOFE3DSCENE_HXX

#ifndef _SDR_CONTACT_VIEWCONTACTOFSDROBJ_HXX
#include <svx/sdr/contact/viewcontactofsdrobj.hxx>
#endif

//////////////////////////////////////////////////////////////////////////////
// predeclarations

class E3dScene;

//////////////////////////////////////////////////////////////////////////////

namespace sdr
{
    namespace contact
    {
        class ViewContactOfE3dScene : public ViewContactOfSdrObj
        {
        protected:
            // internal access to SdrObject
            E3dScene& GetE3dScene() const
            {
                return (E3dScene&)GetSdrObject();
            }

            // method to recalculate the PaintRectangle if the validity flag shows that
            // it is invalid. The flag is set from GetPaintRectangle, thus the implementation
            // only needs to refresh maPaintRectangle itself.
            virtual void CalcPaintRectangle();

        public:
            // basic constructor, used from SdrObject.
            ViewContactOfE3dScene(E3dScene& rScene);

            // The destructor. When PrepareDelete() was not called before (see there)
            // warnings will be generated in debug version if there are still contacts
            // existing.
            virtual ~ViewContactOfE3dScene();

            // When ShouldPaintObject() returns sal_True, the object itself is painted and
            // PaintObject() is called.
            virtual sal_Bool ShouldPaintObject(DisplayInfo& rDisplayInfo, const ViewObjectContact& rAssociatedVOC);

            // These methods decide which parts of the objects will be painted:
            // When ShouldPaintDrawHierarchy() returns sal_True, the DrawHierarchy of the object is painted.
            // Else, the flags and rectangles of the VOCs of the sub-hierarchy are set to the values of the
            // object's VOC.
            virtual sal_Bool ShouldPaintDrawHierarchy(DisplayInfo& rDisplayInfo, const ViewObjectContact& rAssociatedVOC);

            // Paint this object. This is before evtl. SubObjects get painted. It needs to return
            // sal_True when something was pained and the paint output rectangle in rPaintRectangle.
            virtual sal_Bool PaintObject(DisplayInfo& rDisplayInfo, Rectangle& rPaintRectangle, const ViewObjectContact& rAssociatedVOC);
        };
    } // end of namespace contact
} // end of namespace sdr

//////////////////////////////////////////////////////////////////////////////

#endif //_SDR_CONTACT_VIEWCONTACTOFE3DSCENE_HXX

// eof
<commit_msg>INTEGRATION: CWS ooo19126 (1.2.1096); FILE MERGED 2005/09/05 14:18:23 rt 1.2.1096.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: viewcontactofe3dscene.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 19:58:16 $
 *
 *  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
 *
 ************************************************************************/

#ifndef _SDR_CONTACT_VIEWCONTACTOFE3DSCENE_HXX
#define _SDR_CONTACT_VIEWCONTACTOFE3DSCENE_HXX

#ifndef _SDR_CONTACT_VIEWCONTACTOFSDROBJ_HXX
#include <svx/sdr/contact/viewcontactofsdrobj.hxx>
#endif

//////////////////////////////////////////////////////////////////////////////
// predeclarations

class E3dScene;

//////////////////////////////////////////////////////////////////////////////

namespace sdr
{
    namespace contact
    {
        class ViewContactOfE3dScene : public ViewContactOfSdrObj
        {
        protected:
            // internal access to SdrObject
            E3dScene& GetE3dScene() const
            {
                return (E3dScene&)GetSdrObject();
            }

            // method to recalculate the PaintRectangle if the validity flag shows that
            // it is invalid. The flag is set from GetPaintRectangle, thus the implementation
            // only needs to refresh maPaintRectangle itself.
            virtual void CalcPaintRectangle();

        public:
            // basic constructor, used from SdrObject.
            ViewContactOfE3dScene(E3dScene& rScene);

            // The destructor. When PrepareDelete() was not called before (see there)
            // warnings will be generated in debug version if there are still contacts
            // existing.
            virtual ~ViewContactOfE3dScene();

            // When ShouldPaintObject() returns sal_True, the object itself is painted and
            // PaintObject() is called.
            virtual sal_Bool ShouldPaintObject(DisplayInfo& rDisplayInfo, const ViewObjectContact& rAssociatedVOC);

            // These methods decide which parts of the objects will be painted:
            // When ShouldPaintDrawHierarchy() returns sal_True, the DrawHierarchy of the object is painted.
            // Else, the flags and rectangles of the VOCs of the sub-hierarchy are set to the values of the
            // object's VOC.
            virtual sal_Bool ShouldPaintDrawHierarchy(DisplayInfo& rDisplayInfo, const ViewObjectContact& rAssociatedVOC);

            // Paint this object. This is before evtl. SubObjects get painted. It needs to return
            // sal_True when something was pained and the paint output rectangle in rPaintRectangle.
            virtual sal_Bool PaintObject(DisplayInfo& rDisplayInfo, Rectangle& rPaintRectangle, const ViewObjectContact& rAssociatedVOC);
        };
    } // end of namespace contact
} // end of namespace sdr

//////////////////////////////////////////////////////////////////////////////

#endif //_SDR_CONTACT_VIEWCONTACTOFE3DSCENE_HXX

// eof
<|endoftext|>


<commit_before>#include "singletons.h"
#include "config.h"
#include "logging.h"
#include <exception>
#include "files.h"
#include <iostream>

using namespace std; //TODO: remove

MainConfig::MainConfig() {
  auto search_envs = init_home_path();
  auto config_json = (home/"config"/"config.json").string(); // This causes some redundant copies, but assures windows support
  try {
    find_or_create_config_files();
    if(home.empty()) {
      std::string searched_envs = "[";
      for(auto &env : search_envs)
        searched_envs+=env+", ";
      searched_envs.erase(searched_envs.end()-2, searched_envs.end());
      searched_envs+="]";
      throw std::runtime_error("One of these environment variables needs to point to a writable directory to save configuration: " + searched_envs);
    }
    boost::property_tree::json_parser::read_json(config_json, cfg);
    update_config_file();
    retrieve_config();
  }
  catch(const std::exception &e) {
    std::stringstream ss;
    ss << configjson;
    boost::property_tree::read_json(ss, cfg);
    retrieve_config();
    JERROR("Error reading "+ config_json + ": "+e.what()+"\n"); // logs will print to cerr when init_log haven't been run yet
  }
}

void MainConfig::find_or_create_config_files() {
  auto config_dir = home/"config";
  auto config_json = config_dir/"config.json";
  auto plugins_py = config_dir/"plugins.py";

  boost::filesystem::create_directories(config_dir); // io exp captured by calling method

  if (!boost::filesystem::exists(config_json))
    filesystem::write(config_json, configjson); // vars configjson and pluginspy
  if (!boost::filesystem::exists(plugins_py))   // live in files.h
    filesystem::write(plugins_py, pluginspy);

  auto juci_style_path = home/"styles";
  boost::filesystem::create_directories(juci_style_path); // io exp captured by calling method

  juci_style_path/="juci-light.xml";
  if(!boost::filesystem::exists(juci_style_path))
    filesystem::write(juci_style_path, juci_light_style);
  juci_style_path=juci_style_path.parent_path();
  juci_style_path/="juci-dark.xml";
  if(!boost::filesystem::exists(juci_style_path))
    filesystem::write(juci_style_path, juci_dark_style);
  juci_style_path=juci_style_path.parent_path();
  juci_style_path/="juci-dark-blue.xml";
  if(!boost::filesystem::exists(juci_style_path))
    filesystem::write(juci_style_path, juci_dark_blue_style);
}

void MainConfig::retrieve_config() {
  Singleton::Config::window()->keybindings = cfg.get_child("keybindings");
  GenerateSource();
  GenerateDirectoryFilter();

  Singleton::Config::window()->theme_name=cfg.get<std::string>("gtk_theme.name");
  Singleton::Config::window()->theme_variant=cfg.get<std::string>("gtk_theme.variant");
  Singleton::Config::window()->version = cfg.get<std::string>("version");
  Singleton::Config::window()->default_size = {cfg.get<int>("default_window_size.width"), cfg.get<int>("default_window_size.height")};
  Singleton::Config::terminal()->make_command=cfg.get<std::string>("project.make_command");
  Singleton::Config::terminal()->cmake_command=cfg.get<std::string>("project.cmake_command");
  Singleton::Config::terminal()->history_size=cfg.get<int>("terminal_history_size");
}

bool MainConfig::check_config_file(const boost::property_tree::ptree &default_cfg, std::string parent_path) {
  if(parent_path.size()>0)
    parent_path+=".";
  bool exists=true;
  for(auto &node: default_cfg) {
    auto path=parent_path+node.first;
    try {
      cfg.get<std::string>(path);
    }
    catch(const std::exception &e) {
      cfg.add(path, node.second.data());
      exists=false;
    }
    try {
      exists&=check_config_file(node.second, path);
    }
    catch(const std::exception &e) {
    }
  }
  return exists;
}

void MainConfig::update_config_file() {
  boost::property_tree::ptree default_cfg;
  bool cfg_ok=true;
  try {
    if(cfg.get<std::string>("version")!=JUCI_VERSION) {
      std::stringstream ss;
      ss << configjson;
      boost::property_tree::read_json(ss, default_cfg);
      cfg_ok=false;
      if(cfg.count("version")>0)
        cfg.find("version")->second.data()=default_cfg.get<std::string>("version");
    }
    else
      return;
  }
  catch(const std::exception &e) {
    std::cerr << "Error reading json-file: " << e.what() << std::endl;
    cfg_ok=false;
  }
  cfg_ok&=check_config_file(default_cfg);
  if(!cfg_ok) {
    boost::property_tree::write_json((home/"config"/"config.json").string(), cfg);
  }
}

void MainConfig::GenerateSource() {
  auto source_cfg = Singleton::Config::source();
  auto source_json = cfg.get_child("source");

  Singleton::Config::source()->style=source_json.get<std::string>("style");
  source_cfg->font=source_json.get<std::string>("font");

  source_cfg->show_map = source_json.get<bool>("show_map");
  source_cfg->map_font_size = source_json.get<std::string>("map_font_size");

  source_cfg->spellcheck_language = source_json.get<std::string>("spellcheck_language");

  source_cfg->default_tab_char = source_json.get<char>("default_tab_char");
  source_cfg->default_tab_size = source_json.get<unsigned>("default_tab_size");
  source_cfg->auto_tab_char_and_size = source_json.get<bool>("auto_tab_char_and_size");

  source_cfg->wrap_lines = source_json.get<bool>("wrap_lines");

  source_cfg->highlight_current_line = source_json.get<bool>("highlight_current_line");
  source_cfg->show_line_numbers = source_json.get<bool>("show_line_numbers");

  for (auto &i : source_json.get_child("clang_types"))
    source_cfg->clang_types[i.first] = i.second.get_value<std::string>();

  auto pt_doc_search=cfg.get_child("documentation_searches");
  for(auto &pt_doc_search_lang: pt_doc_search) {
    source_cfg->documentation_searches[pt_doc_search_lang.first].separator=pt_doc_search_lang.second.get<std::string>("separator");
    auto &queries=source_cfg->documentation_searches.find(pt_doc_search_lang.first)->second.queries;
    for(auto &i: pt_doc_search_lang.second.get_child("queries")) {
      queries[i.first]=i.second.get_value<std::string>();
    }
  }
}

void MainConfig::GenerateDirectoryFilter() {
  auto dir_cfg=Singleton::Config::directories();
  boost::property_tree::ptree dir_json = cfg.get_child("directoryfilter");
  boost::property_tree::ptree ignore_json = dir_json.get_child("ignore");
  boost::property_tree::ptree except_json = dir_json.get_child("exceptions");
  for ( auto &i : except_json )
    dir_cfg->exceptions.emplace_back(i.second.get_value<std::string>());
  for ( auto &i : ignore_json )
    dir_cfg->ignored.emplace_back(i.second.get_value<std::string>());
}
std::vector<std::string> MainConfig::init_home_path(){
  std::vector<std::string> locations = JUCI_ENV_SEARCH_LOCATIONS;
  char *ptr = nullptr;
  for (auto &env : locations) {
    ptr=std::getenv(env.c_str());
    if (ptr==nullptr)
      continue;
    else
      if (boost::filesystem::exists(ptr)) {
        home /= ptr;
        home /= ".juci";
        return locations;
      }
  }
  home="";
  return locations;
}
<commit_msg>Clear the propterty tree after assigning to singleton configuration<commit_after>#include "singletons.h"
#include "config.h"
#include "logging.h"
#include <exception>
#include "files.h"
#include <iostream>

using namespace std; //TODO: remove

MainConfig::MainConfig() {
  auto search_envs = init_home_path();
  auto config_json = (home/"config"/"config.json").string(); // This causes some redundant copies, but assures windows support
  try {
    find_or_create_config_files();
    if(home.empty()) {
      std::string searched_envs = "[";
      for(auto &env : search_envs)
        searched_envs+=env+", ";
      searched_envs.erase(searched_envs.end()-2, searched_envs.end());
      searched_envs+="]";
      throw std::runtime_error("One of these environment variables needs to point to a writable directory to save configuration: " + searched_envs);
    }
    boost::property_tree::json_parser::read_json(config_json, cfg);
    update_config_file();
    retrieve_config();
  }
  catch(const std::exception &e) {
    std::stringstream ss;
    ss << configjson;
    boost::property_tree::read_json(ss, cfg);
    retrieve_config();
    JERROR("Error reading "+ config_json + ": "+e.what()+"\n"); // logs will print to cerr when init_log haven't been run yet
  }
  cfg.clear();
}

void MainConfig::find_or_create_config_files() {
  auto config_dir = home/"config";
  auto config_json = config_dir/"config.json";
  auto plugins_py = config_dir/"plugins.py";

  boost::filesystem::create_directories(config_dir); // io exp captured by calling method

  if (!boost::filesystem::exists(config_json))
    filesystem::write(config_json, configjson); // vars configjson and pluginspy
  if (!boost::filesystem::exists(plugins_py))   // live in files.h
    filesystem::write(plugins_py, pluginspy);

  auto juci_style_path = home/"styles";
  boost::filesystem::create_directories(juci_style_path); // io exp captured by calling method

  juci_style_path/="juci-light.xml";
  if(!boost::filesystem::exists(juci_style_path))
    filesystem::write(juci_style_path, juci_light_style);
  juci_style_path=juci_style_path.parent_path();
  juci_style_path/="juci-dark.xml";
  if(!boost::filesystem::exists(juci_style_path))
    filesystem::write(juci_style_path, juci_dark_style);
  juci_style_path=juci_style_path.parent_path();
  juci_style_path/="juci-dark-blue.xml";
  if(!boost::filesystem::exists(juci_style_path))
    filesystem::write(juci_style_path, juci_dark_blue_style);
}

void MainConfig::retrieve_config() {
  Singleton::Config::window()->keybindings = cfg.get_child("keybindings");
  GenerateSource();
  GenerateDirectoryFilter();

  Singleton::Config::window()->theme_name=cfg.get<std::string>("gtk_theme.name");
  Singleton::Config::window()->theme_variant=cfg.get<std::string>("gtk_theme.variant");
  Singleton::Config::window()->version = cfg.get<std::string>("version");
  Singleton::Config::window()->default_size = {cfg.get<int>("default_window_size.width"), cfg.get<int>("default_window_size.height")};
  Singleton::Config::terminal()->make_command=cfg.get<std::string>("project.make_command");
  Singleton::Config::terminal()->cmake_command=cfg.get<std::string>("project.cmake_command");
  Singleton::Config::terminal()->history_size=cfg.get<int>("terminal_history_size");
}

bool MainConfig::check_config_file(const boost::property_tree::ptree &default_cfg, std::string parent_path) {
  if(parent_path.size()>0)
    parent_path+=".";
  bool exists=true;
  for(auto &node: default_cfg) {
    auto path=parent_path+node.first;
    try {
      cfg.get<std::string>(path);
    }
    catch(const std::exception &e) {
      cfg.add(path, node.second.data());
      exists=false;
    }
    try {
      exists&=check_config_file(node.second, path);
    }
    catch(const std::exception &e) {
    }
  }
  return exists;
}

void MainConfig::update_config_file() {
  boost::property_tree::ptree default_cfg;
  bool cfg_ok=true;
  try {
    if(cfg.get<std::string>("version")!=JUCI_VERSION) {
      std::stringstream ss;
      ss << configjson;
      boost::property_tree::read_json(ss, default_cfg);
      cfg_ok=false;
      if(cfg.count("version")>0)
        cfg.find("version")->second.data()=default_cfg.get<std::string>("version");
    }
    else
      return;
  }
  catch(const std::exception &e) {
    std::cerr << "Error reading json-file: " << e.what() << std::endl;
    cfg_ok=false;
  }
  cfg_ok&=check_config_file(default_cfg);
  if(!cfg_ok) {
    boost::property_tree::write_json((home/"config"/"config.json").string(), cfg);
  }
}

void MainConfig::GenerateSource() {
  auto source_cfg = Singleton::Config::source();
  auto source_json = cfg.get_child("source");

  Singleton::Config::source()->style=source_json.get<std::string>("style");
  source_cfg->font=source_json.get<std::string>("font");

  source_cfg->show_map = source_json.get<bool>("show_map");
  source_cfg->map_font_size = source_json.get<std::string>("map_font_size");

  source_cfg->spellcheck_language = source_json.get<std::string>("spellcheck_language");

  source_cfg->default_tab_char = source_json.get<char>("default_tab_char");
  source_cfg->default_tab_size = source_json.get<unsigned>("default_tab_size");
  source_cfg->auto_tab_char_and_size = source_json.get<bool>("auto_tab_char_and_size");

  source_cfg->wrap_lines = source_json.get<bool>("wrap_lines");

  source_cfg->highlight_current_line = source_json.get<bool>("highlight_current_line");
  source_cfg->show_line_numbers = source_json.get<bool>("show_line_numbers");

  for (auto &i : source_json.get_child("clang_types"))
    source_cfg->clang_types[i.first] = i.second.get_value<std::string>();

  auto pt_doc_search=cfg.get_child("documentation_searches");
  for(auto &pt_doc_search_lang: pt_doc_search) {
    source_cfg->documentation_searches[pt_doc_search_lang.first].separator=pt_doc_search_lang.second.get<std::string>("separator");
    auto &queries=source_cfg->documentation_searches.find(pt_doc_search_lang.first)->second.queries;
    for(auto &i: pt_doc_search_lang.second.get_child("queries")) {
      queries[i.first]=i.second.get_value<std::string>();
    }
  }
}

void MainConfig::GenerateDirectoryFilter() {
  auto dir_cfg=Singleton::Config::directories();
  boost::property_tree::ptree dir_json = cfg.get_child("directoryfilter");
  boost::property_tree::ptree ignore_json = dir_json.get_child("ignore");
  boost::property_tree::ptree except_json = dir_json.get_child("exceptions");
  for ( auto &i : except_json )
    dir_cfg->exceptions.emplace_back(i.second.get_value<std::string>());
  for ( auto &i : ignore_json )
    dir_cfg->ignored.emplace_back(i.second.get_value<std::string>());
}
std::vector<std::string> MainConfig::init_home_path(){
  std::vector<std::string> locations = JUCI_ENV_SEARCH_LOCATIONS;
  char *ptr = nullptr;
  for (auto &env : locations) {
    ptr=std::getenv(env.c_str());
    if (ptr==nullptr)
      continue;
    else
      if (boost::filesystem::exists(ptr)) {
        home /= ptr;
        home /= ".juci";
        return locations;
      }
  }
  home="";
  return locations;
}
<|endoftext|>


<commit_before>#pragma once

/*
 * Copyright (C) 2015 ScyllaDB
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla 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 Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

// This class is the parts of java.util.UUID that we need

#include <stdint.h>
#include <cassert>
#include <array>
#include <iosfwd>

#include <seastar/core/sstring.hh>
#include <seastar/core/print.hh>
#include <seastar/net/byteorder.hh>
#include "bytes.hh"
#include "hashing.hh"
#include "utils/serialization.hh"

namespace utils {

class UUID {
private:
    int64_t most_sig_bits;
    int64_t least_sig_bits;
public:
    UUID() : most_sig_bits(0), least_sig_bits(0) {}
    UUID(int64_t most_sig_bits, int64_t least_sig_bits)
        : most_sig_bits(most_sig_bits), least_sig_bits(least_sig_bits) {}
    explicit UUID(const sstring& uuid_string) : UUID(sstring_view(uuid_string)) { }
    explicit UUID(const char * s) : UUID(sstring_view(s)) {}
    explicit UUID(sstring_view uuid_string);

    int64_t get_most_significant_bits() const {
        return most_sig_bits;
    }
    int64_t get_least_significant_bits() const {
        return least_sig_bits;
    }
    int version() const {
        return (most_sig_bits >> 12) & 0xf;
    }

    bool is_timestamp() const {
        return version() == 1;
    }

    int64_t timestamp() const {
        //if (version() != 1) {
        //     throw new UnsupportedOperationException("Not a time-based UUID");
        //}
        assert(is_timestamp());

        return ((most_sig_bits & 0xFFF) << 48) |
               (((most_sig_bits >> 16) & 0xFFFF) << 32) |
               (((uint64_t)most_sig_bits) >> 32);

    }

    // This matches Java's UUID.toString() actual implementation. Note that
    // that method's documentation suggest something completely different!
    sstring to_sstring() const {
        return format("{:08x}-{:04x}-{:04x}-{:04x}-{:012x}",
                ((uint64_t)most_sig_bits >> 32),
                ((uint64_t)most_sig_bits >> 16 & 0xffff),
                ((uint64_t)most_sig_bits & 0xffff),
                ((uint64_t)least_sig_bits >> 48 & 0xffff),
                ((uint64_t)least_sig_bits & 0xffffffffffffLL));
    }

    friend std::ostream& operator<<(std::ostream& out, const UUID& uuid);

    bool operator==(const UUID& v) const {
        return most_sig_bits == v.most_sig_bits
                && least_sig_bits == v.least_sig_bits
                ;
    }
    bool operator!=(const UUID& v) const {
        return !(*this == v);
    }

    bool operator<(const UUID& v) const {
         if (most_sig_bits != v.most_sig_bits) {
             return uint64_t(most_sig_bits) < uint64_t(v.most_sig_bits);
         } else {
             return uint64_t(least_sig_bits) < uint64_t(v.least_sig_bits);
         }
    }

    bool operator>(const UUID& v) const {
        return v < *this;
    }

    bool operator<=(const UUID& v) const {
        return !(*this > v);
    }

    bool operator>=(const UUID& v) const {
        return !(*this < v);
    }

    bytes serialize() const {
        bytes b(bytes::initialized_later(), serialized_size());
        auto i = b.begin();
        serialize(i);
        return b;
    }

    static size_t serialized_size() noexcept {
        return 16;
    }

    template <typename CharOutputIterator>
    void serialize(CharOutputIterator& out) const {
        serialize_int64(out, most_sig_bits);
        serialize_int64(out, least_sig_bits);
    }
};

UUID make_random_uuid();

}

template<>
struct appending_hash<utils::UUID> {
    template<typename Hasher>
    void operator()(Hasher& h, const utils::UUID& id) const {
        feed_hash(h, id.get_most_significant_bits());
        feed_hash(h, id.get_least_significant_bits());
    }
};

namespace std {
template<>
struct hash<utils::UUID> {
    size_t operator()(const utils::UUID& id) const {
        auto hilo = id.get_most_significant_bits()
                ^ id.get_least_significant_bits();
        return size_t((hilo >> 32) ^ hilo);
    }
};
}
<commit_msg>uuid: implement optimized timeuuid compare<commit_after>#pragma once

/*
 * Copyright (C) 2015 ScyllaDB
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla 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 Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

// This class is the parts of java.util.UUID that we need

#include <stdint.h>
#include <cassert>
#include <array>
#include <iosfwd>

#include <seastar/core/sstring.hh>
#include <seastar/core/print.hh>
#include <seastar/net/byteorder.hh>
#include "bytes.hh"
#include "hashing.hh"
#include "utils/serialization.hh"

namespace utils {

class UUID {
private:
    int64_t most_sig_bits;
    int64_t least_sig_bits;
public:
    UUID() : most_sig_bits(0), least_sig_bits(0) {}
    UUID(int64_t most_sig_bits, int64_t least_sig_bits)
        : most_sig_bits(most_sig_bits), least_sig_bits(least_sig_bits) {}
    explicit UUID(const sstring& uuid_string) : UUID(sstring_view(uuid_string)) { }
    explicit UUID(const char * s) : UUID(sstring_view(s)) {}
    explicit UUID(sstring_view uuid_string);

    int64_t get_most_significant_bits() const {
        return most_sig_bits;
    }
    int64_t get_least_significant_bits() const {
        return least_sig_bits;
    }
    int version() const {
        return (most_sig_bits >> 12) & 0xf;
    }

    bool is_timestamp() const {
        return version() == 1;
    }

    int64_t timestamp() const {
        //if (version() != 1) {
        //     throw new UnsupportedOperationException("Not a time-based UUID");
        //}
        assert(is_timestamp());

        return ((most_sig_bits & 0xFFF) << 48) |
               (((most_sig_bits >> 16) & 0xFFFF) << 32) |
               (((uint64_t)most_sig_bits) >> 32);

    }

    // This matches Java's UUID.toString() actual implementation. Note that
    // that method's documentation suggest something completely different!
    sstring to_sstring() const {
        return format("{:08x}-{:04x}-{:04x}-{:04x}-{:012x}",
                ((uint64_t)most_sig_bits >> 32),
                ((uint64_t)most_sig_bits >> 16 & 0xffff),
                ((uint64_t)most_sig_bits & 0xffff),
                ((uint64_t)least_sig_bits >> 48 & 0xffff),
                ((uint64_t)least_sig_bits & 0xffffffffffffLL));
    }

    friend std::ostream& operator<<(std::ostream& out, const UUID& uuid);

    bool operator==(const UUID& v) const {
        return most_sig_bits == v.most_sig_bits
                && least_sig_bits == v.least_sig_bits
                ;
    }
    bool operator!=(const UUID& v) const {
        return !(*this == v);
    }

    bool operator<(const UUID& v) const {
         if (most_sig_bits != v.most_sig_bits) {
             return uint64_t(most_sig_bits) < uint64_t(v.most_sig_bits);
         } else {
             return uint64_t(least_sig_bits) < uint64_t(v.least_sig_bits);
         }
    }

    bool operator>(const UUID& v) const {
        return v < *this;
    }

    bool operator<=(const UUID& v) const {
        return !(*this > v);
    }

    bool operator>=(const UUID& v) const {
        return !(*this < v);
    }

    bytes serialize() const {
        bytes b(bytes::initialized_later(), serialized_size());
        auto i = b.begin();
        serialize(i);
        return b;
    }

    static size_t serialized_size() noexcept {
        return 16;
    }

    template <typename CharOutputIterator>
    void serialize(CharOutputIterator& out) const {
        serialize_int64(out, most_sig_bits);
        serialize_int64(out, least_sig_bits);
    }
};

UUID make_random_uuid();

inline int uint64_t_tri_compare(uint64_t a, uint64_t b) {
    return a < b ? -1 : a > b;
}

// Read 8 most significant bytes of timeuuid from serialized bytes
inline uint64_t timeuuid_read_msb(const int8_t *b) {
    // cast to unsigned to avoid sign-compliment during shift.
    auto u64 = [](uint8_t i) -> uint64_t { return i; };
    // Scylla and Cassandra use a standard UUID memory layout for MSB:
    // 4 bytes    2 bytes    2 bytes
    // time_low - time_mid - time_hi_and_version
    //
    // The storage format uses network byte order.
    // Reorder bytes to allow for an integer compare.
    return u64(b[6] & 0xf) << 56 | u64(b[7]) << 48 |
           u64(b[4]) << 40 | u64(b[5]) << 32 |
           u64(b[0]) << 24 | u64(b[1]) << 16 |
           u64(b[2]) << 8  | u64(b[3]);
}

inline uint64_t uuid_read_lsb(const int8_t *b) {
    auto u64 = [](uint8_t i) -> uint64_t { return i; };
    return u64(b[8]) << 56 | u64(b[9]) << 48 |
           u64(b[10]) << 40 | u64(b[11]) << 32 |
           u64(b[12]) << 24 | u64(b[13]) << 16 |
           u64(b[14]) << 8  | u64(b[15]);
}

// Compare two values of timeuuid type.
// Cassandra legacy requires:
// - using signed compare for least significant bits.
// - masking off UUID version during compare, to
// treat possible non-version-1 UUID the same way as UUID.
//
// To avoid breaking ordering in existing sstables, Scylla preserves
// Cassandra compare order.
//
inline int timeuuid_tri_compare(bytes_view o1, bytes_view o2) {
    auto timeuuid_read_lsb = [](bytes_view o) -> uint64_t {
        return uuid_read_lsb(o.begin()) ^ 0x8080808080808080;
    };
    int res = uint64_t_tri_compare(timeuuid_read_msb(o1.begin()), timeuuid_read_msb(o2.begin()));
    if (res == 0) {
        res = uint64_t_tri_compare(timeuuid_read_lsb(o1), timeuuid_read_lsb(o2));
    }
    return res;
}

// Compare two values of UUID type, if they happen to be
// both of Version 1 (timeuuids).
//
// This function uses memory order for least significant bits,
// which is both faster and monotonic, so should be preferred
// to @timeuuid_tri_compare() used for all new features.
//
inline int uuid_tri_compare_timeuuid(bytes_view o1, bytes_view o2) {
    int res = uint64_t_tri_compare(timeuuid_read_msb(o1.begin()), timeuuid_read_msb(o2.begin()));
    if (res == 0) {
        res = uint64_t_tri_compare(uuid_read_lsb(o1.begin()), uuid_read_lsb(o2.begin()));
    }
    return res;
}

}

template<>
struct appending_hash<utils::UUID> {
    template<typename Hasher>
    void operator()(Hasher& h, const utils::UUID& id) const {
        feed_hash(h, id.get_most_significant_bits());
        feed_hash(h, id.get_least_significant_bits());
    }
};

namespace std {
template<>
struct hash<utils::UUID> {
    size_t operator()(const utils::UUID& id) const {
        auto hilo = id.get_most_significant_bits()
                ^ id.get_least_significant_bits();
        return size_t((hilo >> 32) ^ hilo);
    }
};
}
<|endoftext|>


<commit_before>#pragma once

/*
 * Copyright 2015 Cloudius Systems.
 */

// This class is the parts of java.util.UUID that we need

#include <stdint.h>
#include <cassert>

#include "core/sstring.hh"
#include "core/print.hh"

namespace utils {

class UUID {
private:
    int64_t most_sig_bits;
    int64_t least_sig_bits;
public:
    UUID(int64_t most_sig_bits, int64_t least_sig_bits)
        : most_sig_bits(most_sig_bits), least_sig_bits(least_sig_bits) {}

    int64_t get_most_significant_bits() const {
        return most_sig_bits;
    }
    int64_t get_least_significant_bits() const {
        return least_sig_bits;
    }
    int version() const {
        return (most_sig_bits >> 12) & 0xf;
    }

    int64_t timestamp() const {
        //if (version() != 1) {
        //     throw new UnsupportedOperationException("Not a time-based UUID");
        //}
        assert(version() == 1);

        return ((most_sig_bits & 0xFFF) << 48) |
               (((most_sig_bits >> 16) & 0xFFFF) << 32) |
               (((uint64_t)most_sig_bits) >> 32);

    }

    // This matches Java's UUID.toString() actual implementation. Note that
    // that method's documentation suggest something completely different!
    sstring to_sstring() const {
        return sprint("%08x-%04x-%04x-%04x-%012x",
                ((uint64_t)most_sig_bits >> 32),
                ((uint64_t)most_sig_bits >> 16 & 0xffff),
                ((uint64_t)most_sig_bits & 0xffff),
                ((uint64_t)least_sig_bits >> 48 & 0xffff),
                ((uint64_t)least_sig_bits & 0xffffffffffffLL));
    }
};

UUID make_random_uuid();

}
<commit_msg>Add hash function to UUID.<commit_after>#pragma once

/*
 * Copyright 2015 Cloudius Systems.
 */

// This class is the parts of java.util.UUID that we need

#include <stdint.h>
#include <cassert>

#include "core/sstring.hh"
#include "core/print.hh"

namespace utils {

class UUID {
private:
    int64_t most_sig_bits;
    int64_t least_sig_bits;
public:
    UUID(int64_t most_sig_bits, int64_t least_sig_bits)
        : most_sig_bits(most_sig_bits), least_sig_bits(least_sig_bits) {}

    int64_t get_most_significant_bits() const {
        return most_sig_bits;
    }
    int64_t get_least_significant_bits() const {
        return least_sig_bits;
    }
    int version() const {
        return (most_sig_bits >> 12) & 0xf;
    }

    int64_t timestamp() const {
        //if (version() != 1) {
        //     throw new UnsupportedOperationException("Not a time-based UUID");
        //}
        assert(version() == 1);

        return ((most_sig_bits & 0xFFF) << 48) |
               (((most_sig_bits >> 16) & 0xFFFF) << 32) |
               (((uint64_t)most_sig_bits) >> 32);

    }

    // This matches Java's UUID.toString() actual implementation. Note that
    // that method's documentation suggest something completely different!
    sstring to_sstring() const {
        return sprint("%08x-%04x-%04x-%04x-%012x",
                ((uint64_t)most_sig_bits >> 32),
                ((uint64_t)most_sig_bits >> 16 & 0xffff),
                ((uint64_t)most_sig_bits & 0xffff),
                ((uint64_t)least_sig_bits >> 48 & 0xffff),
                ((uint64_t)least_sig_bits & 0xffffffffffffLL));
    }

    bool operator==(const UUID& v) const {
        return most_sig_bits == v.most_sig_bits
                && least_sig_bits == v.least_sig_bits
                ;
    }
};

UUID make_random_uuid();

}

namespace std {
template<>
struct hash<utils::UUID> {
    size_t operator()(const utils::UUID& id) const {
        auto hilo = id.get_most_significant_bits()
                ^ id.get_least_significant_bits();
        return size_t((hilo >> 32) ^ hilo);
    }
};
}
<|endoftext|>


<commit_before>#include "openmc/dagmc.h"

#include "openmc/cell.h"
#include "openmc/error.h"
#include "openmc/file_utils.h"
#include "openmc/string_utils.h"
#include "openmc/settings.h"
#include "openmc/geometry.h"

#include <string>
#include <sstream>
#include <algorithm>
#include <fstream>

namespace openmc {

#ifdef DAGMC
const bool dagmc_enabled = true;
#else
const bool dagmc_enabled = false;
#endif

}

#ifdef DAGMC

#include "uwuw.hpp"
#include "dagmcmetadata.hpp"

const std::string DAGMC_FILENAME = "dagmc.h5m";

namespace openmc {

namespace model {

moab::DagMC* DAG;

} // namespace model

bool get_uwuw_materials_xml(std::string& s) {
  UWUW uwuw(DAGMC_FILENAME.c_str());

  std::stringstream ss;
  bool uwuw_mats_present = false;
  if (uwuw.material_library.size() != 0) {
    uwuw_mats_present = true;
    // write header
    ss << "<?xml version=\"1.0\"?>\n";
    ss << "<materials>\n";
    std::map<std::string, pyne::Material> ml = uwuw.material_library;
    std::map<std::string, pyne::Material>::iterator it;
    // write materials
    for (it = ml.begin(); it != ml.end(); it++) {
      ss << it->second.openmc("atom");
    }
    // write footer
    ss << "</materials>";
    s = ss.str();
  }

  return uwuw_mats_present;
}

pugi::xml_document* read_uwuw_materials() {
  pugi::xml_document* doc = NULL;

  std::string s;
  bool found_uwuw_mats = get_uwuw_materials_xml(s);
  if(found_uwuw_mats) {
    doc = new pugi::xml_document();
    pugi::xml_parse_result result = doc->load_string(s.c_str());
  }

  return doc;
}

bool write_uwuw_materials_xml() {
  std::string s;
  bool found_uwuw_mats = get_uwuw_materials_xml(s);
    // if there is a material library in the file
  if (found_uwuw_mats) {
    // write a material.xml file
    std::ofstream mats_xml("materials.xml");
    mats_xml << s;
    mats_xml.close();
  }

  return found_uwuw_mats;
}

void load_dagmc_geometry()
{
  if (!model::DAG) {
    model::DAG = new moab::DagMC();
  }

  /// Materials \\\

  // create uwuw instance
  UWUW uwuw(DAGMC_FILENAME.c_str());

  // check for uwuw material definitions
  bool using_uwuw = (uwuw.material_library.size() == 0) ? false : true;

  // notify user if UWUW materials are going to be used
  if (using_uwuw) {
    std::cout << "Found UWUW Materials in the DAGMC geometry file." << std::endl;
  }

  int32_t dagmc_univ_id = 0; // universe is always 0 for DAGMC runs

  // load the DAGMC geometry
  moab::ErrorCode rval = model::DAG->load_file(DAGMC_FILENAME.c_str());
  MB_CHK_ERR_CONT(rval);

  // initialize acceleration data structures
  rval = model::DAG->init_OBBTree();
  MB_CHK_ERR_CONT(rval);

  // parse model metadata
  dagmcMetaData DMD(model::DAG);
  if (using_uwuw) {
    DMD.load_property_data();
  }
  std::vector<std::string> keywords;
  keywords.push_back("mat");
  keywords.push_back("density");
  keywords.push_back("boundary");
  std::map<std::string, std::string> dum;
  std::string delimiters =  ":/";
  rval = model::DAG->parse_properties(keywords, dum, delimiters.c_str());

  /// Cells (Volumes) \\\

  // initialize cell objects
  model::n_cells = model::DAG->num_entities(3);

  for (int i = 0; i < model::n_cells; i++) {
    moab::EntityHandle vol_handle = model::DAG->entity_by_index(3, i+1);

    // set cell ids using global IDs
    DAGCell* c = new DAGCell();
    c->id_ = model::DAG->id_by_index(3, i+1);
    c->dagmc_ptr_ = model::DAG;
    c->universe_ = dagmc_univ_id; // set to zero for now
    c->fill_ = C_NONE; // no fill, single universe

    model::cells.push_back(c);
    model::cell_map[c->id_] = i;

    // Populate the Universe vector and dict
    auto it = model::universe_map.find(dagmc_univ_id);
    if (it == model::universe_map.end()) {
      model::universes.push_back(new Universe());
      model::universes.back()-> id_ = dagmc_univ_id;
      model::universes.back()->cells_.push_back(i);
      model::universe_map[dagmc_univ_id] = model::universes.size() - 1;
    } else {
      model::universes[it->second]->cells_.push_back(i);
    }

    if (model::DAG->is_implicit_complement(vol_handle)) {
      // assuming implicit complement is always void
      c->material_.push_back(MATERIAL_VOID);
      continue;
    }

    // determine volume material assignment
    std::string mat_value;
    if (model::DAG->has_prop(vol_handle, "mat")) {
      rval = model::DAG->prop_value(vol_handle, "mat", mat_value);
      MB_CHK_ERR_CONT(rval);
    } else {
      std::stringstream err_msg;
      err_msg << "Volume " << c->id_ << " has no material assignment.";
      fatal_error(err_msg.str());
    }

    std::string cmp_str = mat_value;
    to_lower(cmp_str);
    // material void checks
    if (cmp_str.find("void") != std::string::npos   ||
        cmp_str.find("vacuum") != std::string::npos ||
        cmp_str.find("graveyard") != std::string::npos) {
      c->material_.push_back(MATERIAL_VOID);
    } else {
      if (using_uwuw) {
        // lookup material in uwuw if the were present
        std::string uwuw_mat = DMD.volume_material_property_data_eh[vol_handle];
        if (uwuw.material_library.count(uwuw_mat) != 0) {
          int matnumber = uwuw.material_library[uwuw_mat].metadata["mat_number"].asInt();
          c->material_.push_back(matnumber);
        } else {
          std::stringstream err_msg;
          err_msg << "Material with value " << mat_value << " not found ";
          err_msg << "in the material library";
          fatal_error(err_msg.str());
        }
      } else {
        // if not using UWUW materials, we'll find this material
        // later in the materials.xml
        c->material_.push_back(std::stoi(mat_value));
      }
    }
  }

  // allocate the cell overlap count if necessary
  if (settings::check_overlaps) {
    model::overlap_check_count.resize(model::cells.size(), 0);
  }

  /// Surfaces \\\

  // initialize surface objects
  int n_surfaces = model::DAG->num_entities(2);
  model::surfaces.resize(n_surfaces);

  for (int i = 0; i < n_surfaces; i++) {
    moab::EntityHandle surf_handle = model::DAG->entity_by_index(2, i+1);

    // set cell ids using global IDs
    DAGSurface* s = new DAGSurface();
    s->id_ = model::DAG->id_by_index(2, i+1);
    s->dagmc_ptr_ = model::DAG;

    // set BCs
    std::string bc_value;
    if (model::DAG->has_prop(surf_handle, "boundary")) {
      rval = model::DAG->prop_value(surf_handle, "boundary", bc_value);
      MB_CHK_ERR_CONT(rval);
      to_lower(bc_value);

      if (bc_value == "transmit" || bc_value == "transmission") {
        s->bc_ = BC_TRANSMIT;
      } else if (bc_value == "vacuum") {
        s->bc_ = BC_VACUUM;
      } else if (bc_value == "reflective" || bc_value == "reflect" || bc_value == "reflecting") {
        s->bc_ = BC_REFLECT;
      } else if (bc_value == "periodic") {
        fatal_error("Periodic boundary condition not supported in DAGMC.");
      } else {
        std::stringstream err_msg;
        err_msg << "Unknown boundary condition \"" << s->bc_
                << "\" specified on surface " << s->id_;
        fatal_error(err_msg);
      }
    } else {
      // if no condition is found, set to transmit
      s->bc_ = BC_TRANSMIT;
    }

    // add to global array and map
    model::surfaces[i] = s;
    model::surface_map[s->id_] = s->id_;
  }

  return;
}

void free_memory_dagmc()
{
  delete model::DAG;
}

}
#endif
<commit_msg>Adding volume-based temperature reading from DagMC models.<commit_after>#include "openmc/dagmc.h"

#include "openmc/cell.h"
#include "openmc/constants.h"
#include "openmc/error.h"
#include "openmc/file_utils.h"
#include "openmc/string_utils.h"
#include "openmc/settings.h"
#include "openmc/geometry.h"

#include <string>
#include <sstream>
#include <algorithm>
#include <fstream>

namespace openmc {

#ifdef DAGMC
const bool dagmc_enabled = true;
#else
const bool dagmc_enabled = false;
#endif

}

#ifdef DAGMC

#include "uwuw.hpp"
#include "dagmcmetadata.hpp"

const std::string DAGMC_FILENAME = "dagmc.h5m";

namespace openmc {

namespace model {

moab::DagMC* DAG;

} // namespace model

bool get_uwuw_materials_xml(std::string& s) {
  UWUW uwuw(DAGMC_FILENAME.c_str());

  std::stringstream ss;
  bool uwuw_mats_present = false;
  if (uwuw.material_library.size() != 0) {
    uwuw_mats_present = true;
    // write header
    ss << "<?xml version=\"1.0\"?>\n";
    ss << "<materials>\n";
    std::map<std::string, pyne::Material> ml = uwuw.material_library;
    std::map<std::string, pyne::Material>::iterator it;
    // write materials
    for (it = ml.begin(); it != ml.end(); it++) {
      ss << it->second.openmc("atom");
    }
    // write footer
    ss << "</materials>";
    s = ss.str();
  }

  return uwuw_mats_present;
}

pugi::xml_document* read_uwuw_materials() {
  pugi::xml_document* doc = NULL;

  std::string s;
  bool found_uwuw_mats = get_uwuw_materials_xml(s);
  if(found_uwuw_mats) {
    doc = new pugi::xml_document();
    pugi::xml_parse_result result = doc->load_string(s.c_str());
  }

  return doc;
}

bool write_uwuw_materials_xml() {
  std::string s;
  bool found_uwuw_mats = get_uwuw_materials_xml(s);
    // if there is a material library in the file
  if (found_uwuw_mats) {
    // write a material.xml file
    std::ofstream mats_xml("materials.xml");
    mats_xml << s;
    mats_xml.close();
  }

  return found_uwuw_mats;
}

void load_dagmc_geometry()
{
  if (!model::DAG) {
    model::DAG = new moab::DagMC();
  }

  /// Materials \\\

  // create uwuw instance
  UWUW uwuw(DAGMC_FILENAME.c_str());

  // check for uwuw material definitions
  bool using_uwuw = (uwuw.material_library.size() == 0) ? false : true;

  // notify user if UWUW materials are going to be used
  if (using_uwuw) {
    std::cout << "Found UWUW Materials in the DAGMC geometry file." << std::endl;
  }

  int32_t dagmc_univ_id = 0; // universe is always 0 for DAGMC runs

  // load the DAGMC geometry
  moab::ErrorCode rval = model::DAG->load_file(DAGMC_FILENAME.c_str());
  MB_CHK_ERR_CONT(rval);

  // initialize acceleration data structures
  rval = model::DAG->init_OBBTree();
  MB_CHK_ERR_CONT(rval);

  // parse model metadata
  dagmcMetaData DMD(model::DAG);
  if (using_uwuw) {
    DMD.load_property_data();
  }
  std::vector<std::string> keywords;
  keywords.push_back("temp");
  keywords.push_back("mat");
  keywords.push_back("density");
  keywords.push_back("boundary");
  std::map<std::string, std::string> dum;
  std::string delimiters =  ":/";
  rval = model::DAG->parse_properties(keywords, dum, delimiters.c_str());

  /// Cells (Volumes) \\\

  // initialize cell objects
  model::n_cells = model::DAG->num_entities(3);

  for (int i = 0; i < model::n_cells; i++) {
    moab::EntityHandle vol_handle = model::DAG->entity_by_index(3, i+1);

    // set cell ids using global IDs
    DAGCell* c = new DAGCell();
    c->id_ = model::DAG->id_by_index(3, i+1);
    c->dagmc_ptr_ = model::DAG;
    c->universe_ = dagmc_univ_id; // set to zero for now
    c->fill_ = C_NONE; // no fill, single universe

    model::cells.push_back(c);
    model::cell_map[c->id_] = i;

    // Populate the Universe vector and dict
    auto it = model::universe_map.find(dagmc_univ_id);
    if (it == model::universe_map.end()) {
      model::universes.push_back(new Universe());
      model::universes.back()-> id_ = dagmc_univ_id;
      model::universes.back()->cells_.push_back(i);
      model::universe_map[dagmc_univ_id] = model::universes.size() - 1;
    } else {
      model::universes[it->second]->cells_.push_back(i);
    }

    if (model::DAG->is_implicit_complement(vol_handle)) {
      // assuming implicit complement is always void
      c->material_.push_back(MATERIAL_VOID);
      continue;
    }

    // check for temperature assignment
    std::string temp_value;
    if (model::DAG->has_prop(vol_handle, "temp")) {
      rval = model::DAG->prop_value(vol_handle, "temp", temp_value);
      MB_CHK_ERR_CONT(rval);
      double temp = std::stod(temp_value);
      c->sqrtkT_.push_back(std::sqrt(K_BOLTZMANN * temp));
    } else {
      c->sqrtkT_.push_back(std::sqrt(K_BOLTZMANN * settings::temperature_default));
    }

    // determine volume material assignment
    std::string mat_value;
    if (model::DAG->has_prop(vol_handle, "mat")) {
      rval = model::DAG->prop_value(vol_handle, "mat", mat_value);
      MB_CHK_ERR_CONT(rval);
    } else {
      std::stringstream err_msg;
      err_msg << "Volume " << c->id_ << " has no material assignment.";
      fatal_error(err_msg.str());
    }

    std::string cmp_str = mat_value;
    to_lower(cmp_str);
    // material void checks
    if (cmp_str.find("void") != std::string::npos   ||
        cmp_str.find("vacuum") != std::string::npos ||
        cmp_str.find("graveyard") != std::string::npos) {
      c->material_.push_back(MATERIAL_VOID);
    } else {
      if (using_uwuw) {
        // lookup material in uwuw if the were present
        std::string uwuw_mat = DMD.volume_material_property_data_eh[vol_handle];
        if (uwuw.material_library.count(uwuw_mat) != 0) {
          int matnumber = uwuw.material_library[uwuw_mat].metadata["mat_number"].asInt();
          c->material_.push_back(matnumber);
        } else {
          std::stringstream err_msg;
          err_msg << "Material with value " << mat_value << " not found ";
          err_msg << "in the material library";
          fatal_error(err_msg.str());
        }
      } else {
        // if not using UWUW materials, we'll find this material
        // later in the materials.xml
        c->material_.push_back(std::stoi(mat_value));
      }
    }
  }

  // allocate the cell overlap count if necessary
  if (settings::check_overlaps) {
    model::overlap_check_count.resize(model::cells.size(), 0);
  }

  /// Surfaces \\\

  // initialize surface objects
  int n_surfaces = model::DAG->num_entities(2);
  model::surfaces.resize(n_surfaces);

  for (int i = 0; i < n_surfaces; i++) {
    moab::EntityHandle surf_handle = model::DAG->entity_by_index(2, i+1);

    // set cell ids using global IDs
    DAGSurface* s = new DAGSurface();
    s->id_ = model::DAG->id_by_index(2, i+1);
    s->dagmc_ptr_ = model::DAG;

    // set BCs
    std::string bc_value;
    if (model::DAG->has_prop(surf_handle, "boundary")) {
      rval = model::DAG->prop_value(surf_handle, "boundary", bc_value);
      MB_CHK_ERR_CONT(rval);
      to_lower(bc_value);

      if (bc_value == "transmit" || bc_value == "transmission") {
        s->bc_ = BC_TRANSMIT;
      } else if (bc_value == "vacuum") {
        s->bc_ = BC_VACUUM;
      } else if (bc_value == "reflective" || bc_value == "reflect" || bc_value == "reflecting") {
        s->bc_ = BC_REFLECT;
      } else if (bc_value == "periodic") {
        fatal_error("Periodic boundary condition not supported in DAGMC.");
      } else {
        std::stringstream err_msg;
        err_msg << "Unknown boundary condition \"" << s->bc_
                << "\" specified on surface " << s->id_;
        fatal_error(err_msg);
      }
    } else {
      // if no condition is found, set to transmit
      s->bc_ = BC_TRANSMIT;
    }

    // add to global array and map
    model::surfaces[i] = s;
    model::surface_map[s->id_] = s->id_;
  }

  return;
}

void free_memory_dagmc()
{
  delete model::DAG;
}

}
#endif
<|endoftext|>


<commit_before>// ========================================================================== //
// This file is part of DO-CV, a basic set of libraries in C++ for computer
// vision.
//
// Copyright (C) 2015 David Ok <david.ok8@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License v. 2.0. If a copy of the MPL was not distributed with this file,
// you can obtain one at http://mozilla.org/MPL/2.0/.
// ========================================================================== //

#include <gtest/gtest.h>

#include <unordered_set>

#include <DO/Sara/DisjointSets/AdjacencyList.hpp>
#include <DO/Sara/DisjointSets/DisjointSets.hpp>

#include "../AssertHelpers.hpp"

using namespace std;
using namespace DO::Sara;

TEST(TestDisjointSets, test_on_image)
{
  auto regions = Image<int>{ 5, 5 };
  regions.matrix() <<
//  0  1  2  3  4
    0, 0, 1, 2, 3,
//  5  6  7  8  9
    0, 1, 1, 2, 3,
// 10 11 12 13 14
    0, 2, 2, 2, 2,
// 15 16 17 18 19
    4, 4, 2, 2, 2,
// 20 21 22 23 24
    4, 4, 2, 2, 5;

  // Compute the adjacency list using the 4-connectivity.
  auto adjacency_list = compute_adjacency_list_2d(regions);
  auto disjoint_sets = DisjointSets{ regions.size(), adjacency_list };
  disjoint_sets.compute_connected_components();
  auto components = disjoint_sets.get_connected_components();

  // Robustify the test because the components are enumerated in a peculiar way.
  auto true_components = vector<vector<size_t>>{
    { 24 },
    { 15, 16, 20, 21 },
    { 4, 9 },
    { 3, 8, 11, 12, 13, 14, 17, 18, 19, 22, 23 },
    { 2, 6, 7 },
    { 0, 1, 5, 10 },
  };

  EXPECT_EQ(components.size(), true_components.size());
  for (size_t i = 0; i < components.size(); ++i)
    ASSERT_ITEMS_EQ(true_components[i], components[i]);
}

int main(int argc, char** argv)
{
  testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}
<commit_msg>MAINT: robustify the unit test.<commit_after>// ========================================================================== //
// This file is part of DO-CV, a basic set of libraries in C++ for computer
// vision.
//
// Copyright (C) 2015 David Ok <david.ok8@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License v. 2.0. If a copy of the MPL was not distributed with this file,
// you can obtain one at http://mozilla.org/MPL/2.0/.
// ========================================================================== //

#include <gtest/gtest.h>

#include <unordered_set>

#include <DO/Sara/DisjointSets/AdjacencyList.hpp>
#include <DO/Sara/DisjointSets/DisjointSets.hpp>

#include "../AssertHelpers.hpp"

using namespace std;
using namespace DO::Sara;

TEST(TestDisjointSets, test_on_image)
{
  auto regions = Image<int>{ 5, 5 };
  regions.matrix() <<
//  0  1  2  3  4
    0, 0, 1, 2, 3,
//  5  6  7  8  9
    0, 1, 1, 2, 3,
// 10 11 12 13 14
    0, 2, 2, 2, 2,
// 15 16 17 18 19
    4, 4, 2, 2, 2,
// 20 21 22 23 24
    4, 4, 2, 2, 5;

  // Compute the adjacency list using the 4-connectivity.
  auto adjacency_list = compute_adjacency_list_2d(regions);
  auto disjoint_sets = DisjointSets{ regions.size(), adjacency_list };
  disjoint_sets.compute_connected_components();
  auto components = disjoint_sets.get_connected_components();
  for (auto& component : components)
    sort(component.begin(), component.end());

  auto true_components = vector<vector<size_t>>{
    { 0, 1, 5, 10 },
    { 2, 6, 7 },
    { 3, 8, 11, 12, 13, 14, 17, 18, 19, 22, 23 },
    { 4, 9 },
    { 15, 16, 20, 21 },
    { 24 },
  };

  EXPECT_EQ(components.size(), true_components.size());
  for (size_t i = 0; i < components.size(); ++i)
    EXPECT_NE(components.end(),
              find(components.begin(), components.end(), true_components[i]));
}

int main(int argc, char** argv)
{
  testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}
<|endoftext|>


<commit_before>// RUN: %clangxx_asan -O %s -o %t
// RUN: not %run %t crash 2>&1 | FileCheck --check-prefix=CHECK-CRASH %s
// RUN: not %run %t bad-bounds 2>&1 | FileCheck --check-prefix=CHECK-BAD-BOUNDS %s
// RUN: not %run %t bad-alignment 2>&1 | FileCheck --check-prefix=CHECK-BAD-ALIGNMENT %s
// RUN: %env_asan_opts=detect_container_overflow=0 %run %t crash
//
// Test crash due to __sanitizer_annotate_contiguous_container.

#include <assert.h>
#include <string.h>

extern "C" {
void __sanitizer_annotate_contiguous_container(const void *beg, const void *end,
                                               const void *old_mid,
                                               const void *new_mid);
}  // extern "C"

static volatile int one = 1;

int TestCrash() {
  long t[100];
  t[60] = 0;
  __sanitizer_annotate_contiguous_container(&t[0], &t[0] + 100, &t[0] + 100,
                                            &t[0] + 50);
// CHECK-CRASH: AddressSanitizer: container-overflow
// CHECK-CRASH: if you don't care about these errors you may set ASAN_OPTIONS=detect_container_overflow=0
  return (int)t[60 * one];  // Touches the poisoned memory.
}

void BadBounds() {
  long t[100];
// CHECK-BAD-BOUNDS: ERROR: AddressSanitizer: bad parameters to __sanitizer_annotate_contiguous_container
  __sanitizer_annotate_contiguous_container(&t[0], &t[0] + 100, &t[0] + 101,
                                            &t[0] + 50);
}

void BadAlignment() {
  int t[100];
// CHECK-BAD-ALIGNMENT: ERROR: AddressSanitizer: bad parameters to __sanitizer_annotate_contiguous_container
// CHECK-BAD-ALIGNMENT: ERROR: beg is not aligned by 8
  __sanitizer_annotate_contiguous_container(&t[1], &t[0] + 100, &t[1] + 10,
                                            &t[0] + 50);
}

int main(int argc, char **argv) {
  assert(argc == 2);
  if (!strcmp(argv[1], "crash"))
    return TestCrash();
  else if (!strcmp(argv[1], "bad-bounds"))
    BadBounds();
  else if (!strcmp(argv[1], "bad-alignment"))
    BadAlignment();
}
<commit_msg>[ThinLTO] Ensure sanitizer passes are run<commit_after>// RUN: %clangxx_asan -O %s -o %t
// RUN: not %run %t crash 2>&1 | FileCheck --check-prefix=CHECK-CRASH %s
// RUN: not %run %t bad-bounds 2>&1 | FileCheck --check-prefix=CHECK-BAD-BOUNDS %s
// RUN: not %run %t bad-alignment 2>&1 | FileCheck --check-prefix=CHECK-BAD-ALIGNMENT %s
// RUN: %env_asan_opts=detect_container_overflow=0 %run %t crash
//
// RUN: %clangxx_asan -flto=thin -O %s -o %t.thinlto
// RUN: not %run %t.thinlto crash 2>&1 | FileCheck --check-prefix=CHECK-CRASH %s
// RUN: not %run %t.thinlto bad-bounds 2>&1 | FileCheck --check-prefix=CHECK-BAD-BOUNDS %s
// RUN: not %run %t.thinlto bad-alignment 2>&1 | FileCheck --check-prefix=CHECK-BAD-ALIGNMENT %s
// RUN: %env_asan_opts=detect_container_overflow=0 %run %t.thinlto crash
//
// Test crash due to __sanitizer_annotate_contiguous_container.

#include <assert.h>
#include <string.h>

extern "C" {
void __sanitizer_annotate_contiguous_container(const void *beg, const void *end,
                                               const void *old_mid,
                                               const void *new_mid);
}  // extern "C"

static volatile int one = 1;

int TestCrash() {
  long t[100];
  t[60] = 0;
  __sanitizer_annotate_contiguous_container(&t[0], &t[0] + 100, &t[0] + 100,
                                            &t[0] + 50);
// CHECK-CRASH: AddressSanitizer: container-overflow
// CHECK-CRASH: if you don't care about these errors you may set ASAN_OPTIONS=detect_container_overflow=0
  return (int)t[60 * one];  // Touches the poisoned memory.
}

void BadBounds() {
  long t[100];
// CHECK-BAD-BOUNDS: ERROR: AddressSanitizer: bad parameters to __sanitizer_annotate_contiguous_container
  __sanitizer_annotate_contiguous_container(&t[0], &t[0] + 100, &t[0] + 101,
                                            &t[0] + 50);
}

void BadAlignment() {
  int t[100];
// CHECK-BAD-ALIGNMENT: ERROR: AddressSanitizer: bad parameters to __sanitizer_annotate_contiguous_container
// CHECK-BAD-ALIGNMENT: ERROR: beg is not aligned by 8
  __sanitizer_annotate_contiguous_container(&t[1], &t[0] + 100, &t[1] + 10,
                                            &t[0] + 50);
}

int main(int argc, char **argv) {
  assert(argc == 2);
  if (!strcmp(argv[1], "crash"))
    return TestCrash();
  else if (!strcmp(argv[1], "bad-bounds"))
    BadBounds();
  else if (!strcmp(argv[1], "bad-alignment"))
    BadAlignment();
}
<|endoftext|>


<commit_before>/*
 * Copyright 2010-2017 Branimir Karadzic. All rights reserved.
 * License: https://github.com/bkaradzic/bx#license-bsd-2-clause
 */

#include <bx/debug.h>
#include <bx/string.h> // isPrint
#include <inttypes.h>  // PRIx*

#if BX_PLATFORM_ANDROID
#	include <android/log.h>
#elif BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT || BX_PLATFORM_XBOX360 || BX_PLATFORM_XBOXONE
extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA(const char* _str);
#elif BX_PLATFORM_IOS || BX_PLATFORM_OSX
#	if defined(__OBJC__)
#		import <Foundation/NSObjCRuntime.h>
#	else
#		include <CoreFoundation/CFString.h>
extern "C" void NSLog(CFStringRef _format, ...);
#	endif // defined(__OBJC__)
#elif 0 // BX_PLATFORM_EMSCRIPTEN
#	include <emscripten.h>
#else
#	include <stdio.h> // fputs, fflush
#endif // BX_PLATFORM_WINDOWS

namespace bx
{
	void debugBreak()
	{
#if BX_COMPILER_MSVC
		__debugbreak();
#elif BX_CPU_ARM
		__builtin_trap();
//		asm("bkpt 0");
#elif !BX_PLATFORM_NACL && BX_CPU_X86 && (BX_COMPILER_GCC || BX_COMPILER_CLANG)
		// NaCl doesn't like int 3:
		// NativeClient: NaCl module load failed: Validation failure. File violates Native Client safety rules.
		__asm__ ("int $3");
#else // cross platform implementation
		int* int3 = (int*)3L;
		*int3 = 3;
#endif // BX
	}

	void debugOutput(const char* _out)
	{
#if BX_PLATFORM_ANDROID
#	ifndef BX_ANDROID_LOG_TAG
#		define BX_ANDROID_LOG_TAG ""
#	endif // BX_ANDROID_LOG_TAG
		__android_log_write(ANDROID_LOG_DEBUG, BX_ANDROID_LOG_TAG, _out);
#elif BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT || BX_PLATFORM_XBOX360 || BX_PLATFORM_XBOXONE
		OutputDebugStringA(_out);
#elif BX_PLATFORM_IOS || BX_PLATFORM_OSX
#	if defined(__OBJC__)
		NSLog(@"%s", _out);
#	else
		NSLog(__CFStringMakeConstantString("%s"), _out);
#	endif // defined(__OBJC__)
#elif 0 // BX_PLATFORM_EMSCRIPTEN
		emscripten_log(EM_LOG_CONSOLE, "%s", _out);
#else
		fputs(_out, stdout);
		fflush(stdout);
#endif // BX_PLATFORM_
	}

	void debugPrintfVargs(const char* _format, va_list _argList)
	{
		char temp[8192];
		char* out = temp;
		int32_t len = vsnprintf(out, sizeof(temp), _format, _argList);
		if ( (int32_t)sizeof(temp) < len)
		{
			out = (char*)alloca(len+1);
			len = vsnprintf(out, len, _format, _argList);
		}
		out[len] = '\0';
		debugOutput(out);
	}

	void debugPrintf(const char* _format, ...)
	{
		va_list argList;
		va_start(argList, _format);
		debugPrintfVargs(_format, argList);
		va_end(argList);
	}

#define DBG_ADDRESS "%" PRIxPTR

	void debugPrintfData(const void* _data, uint32_t _size, const char* _format, ...)
	{
#define HEX_DUMP_WIDTH 16
#define HEX_DUMP_SPACE_WIDTH 48
#define HEX_DUMP_FORMAT "%-" BX_STRINGIZE(HEX_DUMP_SPACE_WIDTH) "." BX_STRINGIZE(HEX_DUMP_SPACE_WIDTH) "s"

		va_list argList;
		va_start(argList, _format);
		debugPrintfVargs(_format, argList);
		va_end(argList);

		debugPrintf("\ndata: " DBG_ADDRESS ", size: %d\n", _data, _size);

		if (NULL != _data)
		{
			const uint8_t* data = reinterpret_cast<const uint8_t*>(_data);
			char hex[HEX_DUMP_WIDTH*3+1];
			char ascii[HEX_DUMP_WIDTH+1];
			uint32_t hexPos = 0;
			uint32_t asciiPos = 0;
			for (uint32_t ii = 0; ii < _size; ++ii)
			{
				snprintf(&hex[hexPos], sizeof(hex)-hexPos, "%02x ", data[asciiPos]);
				hexPos += 3;

				ascii[asciiPos] = isPrint(data[asciiPos]) ? data[asciiPos] : '.';
				asciiPos++;

				if (HEX_DUMP_WIDTH == asciiPos)
				{
					ascii[asciiPos] = '\0';
					debugPrintf("\t" DBG_ADDRESS "\t" HEX_DUMP_FORMAT "\t%s\n", data, hex, ascii);
					data += asciiPos;
					hexPos = 0;
					asciiPos = 0;
				}
			}

			if (0 != asciiPos)
			{
				ascii[asciiPos] = '\0';
				debugPrintf("\t" DBG_ADDRESS "\t" HEX_DUMP_FORMAT "\t%s\n", data, hex, ascii);
			}
		}

#undef HEX_DUMP_WIDTH
#undef HEX_DUMP_SPACE_WIDTH
#undef HEX_DUMP_FORMAT
	}

} // namespace bx
<commit_msg>Cleanup.<commit_after>/*
 * Copyright 2010-2017 Branimir Karadzic. All rights reserved.
 * License: https://github.com/bkaradzic/bx#license-bsd-2-clause
 */

#include <bx/debug.h>
#include <bx/string.h> // isPrint
#include <inttypes.h>  // PRIx*

#if BX_PLATFORM_ANDROID
#	include <android/log.h>
#elif BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT || BX_PLATFORM_XBOX360 || BX_PLATFORM_XBOXONE
extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA(const char* _str);
#elif BX_PLATFORM_IOS || BX_PLATFORM_OSX
#	if defined(__OBJC__)
#		import <Foundation/NSObjCRuntime.h>
#	else
#		include <CoreFoundation/CFString.h>
extern "C" void NSLog(CFStringRef _format, ...);
#	endif // defined(__OBJC__)
#elif 0 // BX_PLATFORM_EMSCRIPTEN
#	include <emscripten.h>
#else
#	include <stdio.h> // fputs, fflush
#endif // BX_PLATFORM_WINDOWS

namespace bx
{
	void debugBreak()
	{
#if BX_COMPILER_MSVC
		__debugbreak();
#elif BX_CPU_ARM
		__builtin_trap();
//		asm("bkpt 0");
#elif !BX_PLATFORM_NACL && BX_CPU_X86 && (BX_COMPILER_GCC || BX_COMPILER_CLANG)
		// NaCl doesn't like int 3:
		// NativeClient: NaCl module load failed: Validation failure. File violates Native Client safety rules.
		__asm__ ("int $3");
#else // cross platform implementation
		int* int3 = (int*)3L;
		*int3 = 3;
#endif // BX
	}

	void debugOutput(const char* _out)
	{
#if BX_PLATFORM_ANDROID
#	ifndef BX_ANDROID_LOG_TAG
#		define BX_ANDROID_LOG_TAG ""
#	endif // BX_ANDROID_LOG_TAG
		__android_log_write(ANDROID_LOG_DEBUG, BX_ANDROID_LOG_TAG, _out);
#elif BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT || BX_PLATFORM_XBOX360 || BX_PLATFORM_XBOXONE
		OutputDebugStringA(_out);
#elif BX_PLATFORM_IOS || BX_PLATFORM_OSX
#	if defined(__OBJC__)
		NSLog(@"%s", _out);
#	else
		NSLog(__CFStringMakeConstantString("%s"), _out);
#	endif // defined(__OBJC__)
#elif 0 // BX_PLATFORM_EMSCRIPTEN
		emscripten_log(EM_LOG_CONSOLE, "%s", _out);
#elif !BX_CRT_NONE
		fputs(_out, stdout);
		fflush(stdout);
#else
		BX_UNUSED(_out);
#endif // BX_PLATFORM_
	}

	void debugPrintfVargs(const char* _format, va_list _argList)
	{
		char temp[8192];
		char* out = temp;
		int32_t len = vsnprintf(out, sizeof(temp), _format, _argList);
		if ( (int32_t)sizeof(temp) < len)
		{
			out = (char*)alloca(len+1);
			len = vsnprintf(out, len, _format, _argList);
		}
		out[len] = '\0';
		debugOutput(out);
	}

	void debugPrintf(const char* _format, ...)
	{
		va_list argList;
		va_start(argList, _format);
		debugPrintfVargs(_format, argList);
		va_end(argList);
	}

#define DBG_ADDRESS "%" PRIxPTR

	void debugPrintfData(const void* _data, uint32_t _size, const char* _format, ...)
	{
#define HEX_DUMP_WIDTH 16
#define HEX_DUMP_SPACE_WIDTH 48
#define HEX_DUMP_FORMAT "%-" BX_STRINGIZE(HEX_DUMP_SPACE_WIDTH) "." BX_STRINGIZE(HEX_DUMP_SPACE_WIDTH) "s"

		va_list argList;
		va_start(argList, _format);
		debugPrintfVargs(_format, argList);
		va_end(argList);

		debugPrintf("\ndata: " DBG_ADDRESS ", size: %d\n", _data, _size);

		if (NULL != _data)
		{
			const uint8_t* data = reinterpret_cast<const uint8_t*>(_data);
			char hex[HEX_DUMP_WIDTH*3+1];
			char ascii[HEX_DUMP_WIDTH+1];
			uint32_t hexPos = 0;
			uint32_t asciiPos = 0;
			for (uint32_t ii = 0; ii < _size; ++ii)
			{
				snprintf(&hex[hexPos], sizeof(hex)-hexPos, "%02x ", data[asciiPos]);
				hexPos += 3;

				ascii[asciiPos] = isPrint(data[asciiPos]) ? data[asciiPos] : '.';
				asciiPos++;

				if (HEX_DUMP_WIDTH == asciiPos)
				{
					ascii[asciiPos] = '\0';
					debugPrintf("\t" DBG_ADDRESS "\t" HEX_DUMP_FORMAT "\t%s\n", data, hex, ascii);
					data += asciiPos;
					hexPos = 0;
					asciiPos = 0;
				}
			}

			if (0 != asciiPos)
			{
				ascii[asciiPos] = '\0';
				debugPrintf("\t" DBG_ADDRESS "\t" HEX_DUMP_FORMAT "\t%s\n", data, hex, ascii);
			}
		}

#undef HEX_DUMP_WIDTH
#undef HEX_DUMP_SPACE_WIDTH
#undef HEX_DUMP_FORMAT
	}

} // namespace bx
<|endoftext|>


<commit_before>#include "index/StringTable.hpp"

#include <boost/test/unit_test.hpp>

using namespace utymap::index;

struct Index_StringTableFixture
{
    Index_StringTableFixture() :
        indexPath("index.idx"),
        stringPath("strings.dat"),
        table(*new StringTable(indexPath, stringPath))
    {
        BOOST_TEST_MESSAGE("setup fixture");
    }

    ~Index_StringTableFixture()
    {
        BOOST_TEST_MESSAGE("teardown fixture");
        delete &table;
        std::remove(indexPath.c_str());
        std::remove(stringPath.c_str());
    }

    std::string indexPath;
    std::string stringPath;
    StringTable& table;
};

BOOST_FIXTURE_TEST_SUITE( Index_StringTable, Index_StringTableFixture )

BOOST_AUTO_TEST_CASE( GivenNonPresentString_WhenGetIdFirstTime_ThenReturnZero )
{
    uint32_t id = table.getId("some_string");

    BOOST_CHECK( id == 0 );
}

BOOST_AUTO_TEST_CASE( GivenTable_WhenInsertMultiple_ThenReturnSequentialId )
{
    uint32_t id1 = table.getId("string1");
    uint32_t id2 = table.getId("string2");
    uint32_t id3 = table.getId("string3");

    BOOST_CHECK( id1 == 0 );
    BOOST_CHECK( id2 == 1 );
    BOOST_CHECK( id3 == 2 );
}

BOOST_AUTO_TEST_CASE( GivenThreeStrings_WhenGetIdOfSecond_ThenReturnValidId )
{
    uint32_t id = table.getId("string1");
    id = table.getId("string2");
    id = table.getId("string3");

    id = table.getId("string2");

    BOOST_CHECK( id == 1 );
}

BOOST_AUTO_TEST_CASE( GivenThreeStrings_WhenGetStringOfSecond_ThenReturnValidString )
{
    uint32_t id = table.getId("string1");
    table.getId("string2");
    table.getId("string3");

    std::string str = table.getString(1);

    BOOST_CHECK( str == "string2" );
}

BOOST_AUTO_TEST_SUITE_END()<commit_msg>cross platform: add missing include<commit_after>#include "index/StringTable.hpp"

#include <boost/test/unit_test.hpp>

#include <cstdio>

using namespace utymap::index;

struct Index_StringTableFixture
{
    Index_StringTableFixture() :
        indexPath("index.idx"),
        stringPath("strings.dat"),
        table(*new StringTable(indexPath, stringPath))
    {
        BOOST_TEST_MESSAGE("setup fixture");
    }

    ~Index_StringTableFixture()
    {
        BOOST_TEST_MESSAGE("teardown fixture");
        delete &table;
        std::remove(indexPath.c_str());
        std::remove(stringPath.c_str());
    }

    std::string indexPath;
    std::string stringPath;
    StringTable& table;
};

BOOST_FIXTURE_TEST_SUITE( Index_StringTable, Index_StringTableFixture )

BOOST_AUTO_TEST_CASE( GivenNonPresentString_WhenGetIdFirstTime_ThenReturnZero )
{
    uint32_t id = table.getId("some_string");

    BOOST_CHECK( id == 0 );
}

BOOST_AUTO_TEST_CASE( GivenTable_WhenInsertMultiple_ThenReturnSequentialId )
{
    uint32_t id1 = table.getId("string1");
    uint32_t id2 = table.getId("string2");
    uint32_t id3 = table.getId("string3");

    BOOST_CHECK( id1 == 0 );
    BOOST_CHECK( id2 == 1 );
    BOOST_CHECK( id3 == 2 );
}

BOOST_AUTO_TEST_CASE( GivenThreeStrings_WhenGetIdOfSecond_ThenReturnValidId )
{
    uint32_t id = table.getId("string1");
    id = table.getId("string2");
    id = table.getId("string3");

    id = table.getId("string2");

    BOOST_CHECK( id == 1 );
}

BOOST_AUTO_TEST_CASE( GivenThreeStrings_WhenGetStringOfSecond_ThenReturnValidString )
{
    uint32_t id = table.getId("string1");
    table.getId("string2");
    table.getId("string3");

    std::string str = table.getString(1);

    BOOST_CHECK( str == "string2" );
}

BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>


<commit_before>#include <map>

#include <llvm/IR/Value.h>
#include <llvm/IR/Instruction.h>
#include <llvm/IR/Instructions.h>
#include <llvm/IR/IntrinsicInst.h>
#include <llvm/IR/Constants.h>
#include <llvm/IR/GlobalVariable.h>
#include <llvm/IR/Module.h>
#include <llvm/IR/DataLayout.h>
#include <llvm/Support/raw_ostream.h>

#include "llvm/LLVMNode.h"
#include "llvm/LLVMDependenceGraph.h"
#include "llvm/llvm-util.h"

#include "llvm/analysis/PointsTo/PointsTo.h"
#include "ReachingDefinitions/ReachingDefinitions.h"
#include "DefUse.h"

#include "analysis/PointsTo/PointerSubgraph.h"
#include "analysis/DFS.h"

using dg::analysis::rd::LLVMReachingDefinitions;
using dg::analysis::rd::RDNode;

using namespace llvm;

/// --------------------------------------------------
//   Add def-use edges
/// --------------------------------------------------
namespace dg {

static void handleInstruction(const Instruction *Inst, LLVMNode *node)
{
    LLVMDependenceGraph *dg = node->getDG();

    for (auto I = Inst->op_begin(), E = Inst->op_end(); I != E; ++I) {
        LLVMNode *op = dg->getNode(*I);
        if (op)
            op->addDataDependence(node);
    }
}

static void addReturnEdge(LLVMNode *callNode, LLVMDependenceGraph *subgraph)
{
    // FIXME we may loose some accuracy here and
    // this edges causes that we'll go into subprocedure
    // even with summary edges
    if (!callNode->isVoidTy())
        subgraph->getExit()->addDataDependence(callNode);
}

LLVMDefUseAnalysis::LLVMDefUseAnalysis(LLVMDependenceGraph *dg,
                                       LLVMReachingDefinitions *rd,
                                       LLVMPointerAnalysis *pta)
    : analysis::DataFlowAnalysis<LLVMNode>(dg->getEntryBB(),
                                           analysis::DATAFLOW_INTERPROCEDURAL),
      dg(dg), RD(rd), PTA(pta), DL(new DataLayout(dg->getModule()))
{
    assert(PTA && "Need points-to information");
    assert(RD && "Need reaching definitions");
}

void LLVMDefUseAnalysis::handleInlineAsm(LLVMNode *callNode)
{
    CallInst *CI = cast<CallInst>(callNode->getValue());
    LLVMDependenceGraph *dg = callNode->getDG();

    // the last operand is the asm itself, so iterate only to e - 1
    for (unsigned i = 0, e = CI->getNumOperands(); i < e - 1; ++i) {
        Value *opVal = CI->getOperand(i);
        if (!opVal->getType()->isPointerTy())
            continue;

        LLVMNode *opNode = dg->getNode(opVal->stripInBoundsOffsets());
        if (!opNode) {
            // FIXME: ConstantExpr
            llvmutil::printerr("WARN: unhandled inline asm operand: ", opVal);
            continue;
        }

        assert(opNode && "Do not have an operand for inline asm");

        // if nothing else, this call at least uses the operands
        opNode->addDataDependence(callNode);
    }
}

void LLVMDefUseAnalysis::handleIntrinsicCall(LLVMNode *callNode,
                                             CallInst *CI)
{
    IntrinsicInst *I = cast<IntrinsicInst>(CI);
    Value *dest, *src = nullptr;

    switch (I->getIntrinsicID())
    {
        case Intrinsic::memmove:
        case Intrinsic::memcpy:
            dest = I->getOperand(0);
            src = I->getOperand(1);
            break;
        case Intrinsic::memset:
            dest = I->getOperand(0);
            break;
        case Intrinsic::vastart:
            dest = I->getOperand(0);
            break;
        default:
            //assert(0 && "DEF-USE: Unhandled intrinsic call");
            //handleUndefinedCall(callNode, CI);
            return;
    }

    // we must have dest set
    assert(dest);

    // these functions touch the memory of the pointers
    addDataDependence(callNode, CI, dest, UNKNOWN_OFFSET /* FIXME */);

    if (src)
        addDataDependence(callNode, CI, src, UNKNOWN_OFFSET /* FIXME */);
}

void LLVMDefUseAnalysis::handleCallInst(LLVMNode *node)
{
    CallInst *CI = cast<CallInst>(node->getKey());

    if (CI->isInlineAsm()) {
        handleInlineAsm(node);
        return;
    }

    Function *func
        = dyn_cast<Function>(CI->getCalledValue()->stripPointerCasts());
    if (func) {
        if (func->isIntrinsic() && !isa<DbgValueInst>(CI)) {
            handleIntrinsicCall(node, CI);
            return;
        }

        // for realloc, we need to make it data dependent on the
        // memory it reallocates, since that is the memory it copies
        if (strcmp(func->getName().data(), "realloc") == 0)
            addDataDependence(node, CI, CI->getOperand(0), UNKNOWN_OFFSET /* FIXME */);
    }

    /*
    if (func && func->size() == 0) {
        handleUndefinedCall(node);
        return;
    }
    */

    // add edges from the return nodes of subprocedure
    // to the call (if the call returns something)
    for (LLVMDependenceGraph *subgraph : node->getSubgraphs())
        addReturnEdge(node, subgraph);
}

// Add data dependence edges from all memory location that may write
// to memory pointed by 'pts' to 'node'
void LLVMDefUseAnalysis::addUnknownDataDependence(LLVMNode *node, PSNode *pts)
{
    // iterate over all nodes from ReachingDefinitions Subgraph. It is faster than
    // going over all llvm nodes and querying the pointer to analysis
    for (auto it : RD->getNodesMap()) {
        RDNode *rdnode = it.second;

        // only STORE may be a definition site
        if (rdnode->getType() != analysis::rd::STORE)
            continue;

        llvm::Value *rdVal = rdnode->getUserData<llvm::Value>();
        // artificial node?
        if (!rdVal)
            continue;

        // does this store define some value that is in pts?
        for (const analysis::rd::DefSite& ds : rdnode->getDefines()) {
            llvm::Value *llvmVal = ds.target->getUserData<llvm::Value>();
            // is this an artificial node?
            if (!llvmVal)
                continue;

            // if these two sets have an over-lap, we must add the data dependence
            for (const auto& ptr : pts->pointsTo)
                if (ptr.target->getUserData<llvm::Value>() == llvmVal) {
                    addDataDependence(node, rdVal);
            }
        }
    }
}

void LLVMDefUseAnalysis::addDataDependence(LLVMNode *node, llvm::Value *rdval)
{
    LLVMNode *rdnode = dg->getNode(rdval);
    if (!rdnode) {
        // that means that the value is not from this graph.
        // We need to add interprocedural edge
        llvm::Function *F
            = llvm::cast<llvm::Instruction>(rdval)->getParent()->getParent();
        LLVMNode *entryNode = dg->getGlobalNode(F);
        assert(entryNode && "Don't have built function");

        // get the graph where the node lives
        LLVMDependenceGraph *graph = entryNode->getDG();
        assert(graph != dg && "Cannot find a node");
        rdnode = graph->getNode(rdval);
        if (!rdnode) {
            llvmutil::printerr("ERROR: DG has not val: ", rdval);
            return;
        }
    }

    assert(rdnode);
    rdnode->addDataDependence(node);
}

void LLVMDefUseAnalysis::addDataDependence(LLVMNode *node, RDNode *rd)
{
    llvm::Value *rdval = rd->getUserData<llvm::Value>();
    assert(rdval && "RDNode has not set the coresponding value");
    addDataDependence(node, rdval);
}

// \param mem   current reaching definitions point
void LLVMDefUseAnalysis::addDataDependence(LLVMNode *node, PSNode *pts,
                                           RDNode *mem, uint64_t size)
{
    using namespace dg::analysis;

    for (const pta::Pointer& ptr : pts->pointsTo) {
        if (!ptr.isValid())
            continue;

        llvm::Value *llvmVal = ptr.target->getUserData<llvm::Value>();
        assert(llvmVal && "Don't have Value in PSNode");

        RDNode *val = RD->getNode(llvmVal);
        if(!val) {
            llvmutil::printerr("Don't have mapping:\n  ", llvmVal);
            continue;
        }

        std::set<RDNode *> defs;
        // Get even reaching definitions for UNKNOWN_MEMORY.
        // Since those can be ours definitions, we must add them always
        mem->getReachingDefinitions(rd::UNKNOWN_MEMORY, UNKNOWN_OFFSET, UNKNOWN_OFFSET, defs);
        if (!defs.empty()) {
            for (RDNode *rd : defs) {
                assert(!rd->isUnknown() && "Unknown memory defined at unknown location?");
                addDataDependence(node, rd);
            }

            defs.clear();
        }

        mem->getReachingDefinitions(val, ptr.offset, size, defs);
        if (defs.empty()) {
            llvm::GlobalVariable *GV
                = llvm::dyn_cast<llvm::GlobalVariable>(llvmVal);
            if (!GV || !GV->hasInitializer())
                llvm::errs() << "No reaching definition for: " << *llvmVal
                             << " off: " << *ptr.offset << "\n";
            continue;
        }

        // add data dependence
        for (RDNode *rd : defs) {
            if (rd->isUnknown()) {
                // we don't know what definitions reach this node,
                // se we must add data dependence to all possible
                // write to this memory
                addUnknownDataDependence(node, pts);

                // we can bail out, since we have added all
                break;
            }

            addDataDependence(node, rd);
        }
    }
}

void LLVMDefUseAnalysis::addDataDependence(LLVMNode *node,
                                           const llvm::Value *where, /* in CFG */
                                           const llvm::Value *ptrOp,
                                           uint64_t size)
{
    using namespace dg::analysis;

    // get points-to information for the operand
    pta::PSNode *pts = PTA->getPointsTo(ptrOp);
    //assert(pts && "Don't have points-to information for LoadInst");
    if (!pts) {
        llvmutil::printerr("ERROR: No points-to: ", ptrOp);
        return;
    }

    // get the node from reaching definition where we have
    // all the reaching definitions
    RDNode *mem = RD->getMapping(where);
    if(!mem) {
        llvmutil::printerr("ERROR: Don't have mapping: ", where);
        return;
    }

    // take every memory the load inst can use and get the
    // reaching definition
    addDataDependence(node, pts, mem, size);
}

static uint64_t getAllocatedSize(llvm::Type *Ty, const llvm::DataLayout *DL)
{
    // Type can be i8 *null or similar
    if (!Ty->isSized())
            return UNKNOWN_OFFSET;

    return DL->getTypeAllocSize(Ty);
}

void LLVMDefUseAnalysis::handleLoadInst(llvm::LoadInst *Inst, LLVMNode *node)
{
    using namespace dg::analysis;

    uint64_t size = getAllocatedSize(Inst->getType(), DL);
    addDataDependence(node, Inst, Inst->getPointerOperand(), size);
}

bool LLVMDefUseAnalysis::runOnNode(LLVMNode *node, LLVMNode *prev)
{
    Value *val = node->getKey();
    (void) prev;

    if (LoadInst *Inst = dyn_cast<LoadInst>(val)) {
        handleLoadInst(Inst, node);
    } else if (isa<CallInst>(val)) {
        handleCallInst(node);
    /*} else if (StoreInst *Inst = dyn_cast<StoreInst>(val)) {
        handleStoreInst(Inst, node);*/
    }

    /* just add direct def-use edges to every instruction */
    if (Instruction *Inst = dyn_cast<Instruction>(val))
        handleInstruction(Inst, node);

    // we will run only once
    return false;
}

} // namespace dg
<commit_msg>print warning about missing RD only once<commit_after>#include <map>

#include <llvm/IR/Value.h>
#include <llvm/IR/Instruction.h>
#include <llvm/IR/Instructions.h>
#include <llvm/IR/IntrinsicInst.h>
#include <llvm/IR/Constants.h>
#include <llvm/IR/GlobalVariable.h>
#include <llvm/IR/Module.h>
#include <llvm/IR/DataLayout.h>
#include <llvm/Support/raw_ostream.h>

#include "llvm/LLVMNode.h"
#include "llvm/LLVMDependenceGraph.h"
#include "llvm/llvm-util.h"

#include "llvm/analysis/PointsTo/PointsTo.h"
#include "ReachingDefinitions/ReachingDefinitions.h"
#include "DefUse.h"

#include "analysis/PointsTo/PointerSubgraph.h"
#include "analysis/DFS.h"

using dg::analysis::rd::LLVMReachingDefinitions;
using dg::analysis::rd::RDNode;

using namespace llvm;

/// --------------------------------------------------
//   Add def-use edges
/// --------------------------------------------------
namespace dg {

static void handleInstruction(const Instruction *Inst, LLVMNode *node)
{
    LLVMDependenceGraph *dg = node->getDG();

    for (auto I = Inst->op_begin(), E = Inst->op_end(); I != E; ++I) {
        LLVMNode *op = dg->getNode(*I);
        if (op)
            op->addDataDependence(node);
    }
}

static void addReturnEdge(LLVMNode *callNode, LLVMDependenceGraph *subgraph)
{
    // FIXME we may loose some accuracy here and
    // this edges causes that we'll go into subprocedure
    // even with summary edges
    if (!callNode->isVoidTy())
        subgraph->getExit()->addDataDependence(callNode);
}

LLVMDefUseAnalysis::LLVMDefUseAnalysis(LLVMDependenceGraph *dg,
                                       LLVMReachingDefinitions *rd,
                                       LLVMPointerAnalysis *pta)
    : analysis::DataFlowAnalysis<LLVMNode>(dg->getEntryBB(),
                                           analysis::DATAFLOW_INTERPROCEDURAL),
      dg(dg), RD(rd), PTA(pta), DL(new DataLayout(dg->getModule()))
{
    assert(PTA && "Need points-to information");
    assert(RD && "Need reaching definitions");
}

void LLVMDefUseAnalysis::handleInlineAsm(LLVMNode *callNode)
{
    CallInst *CI = cast<CallInst>(callNode->getValue());
    LLVMDependenceGraph *dg = callNode->getDG();

    // the last operand is the asm itself, so iterate only to e - 1
    for (unsigned i = 0, e = CI->getNumOperands(); i < e - 1; ++i) {
        Value *opVal = CI->getOperand(i);
        if (!opVal->getType()->isPointerTy())
            continue;

        LLVMNode *opNode = dg->getNode(opVal->stripInBoundsOffsets());
        if (!opNode) {
            // FIXME: ConstantExpr
            llvmutil::printerr("WARN: unhandled inline asm operand: ", opVal);
            continue;
        }

        assert(opNode && "Do not have an operand for inline asm");

        // if nothing else, this call at least uses the operands
        opNode->addDataDependence(callNode);
    }
}

void LLVMDefUseAnalysis::handleIntrinsicCall(LLVMNode *callNode,
                                             CallInst *CI)
{
    IntrinsicInst *I = cast<IntrinsicInst>(CI);
    Value *dest, *src = nullptr;

    switch (I->getIntrinsicID())
    {
        case Intrinsic::memmove:
        case Intrinsic::memcpy:
            dest = I->getOperand(0);
            src = I->getOperand(1);
            break;
        case Intrinsic::memset:
            dest = I->getOperand(0);
            break;
        case Intrinsic::vastart:
            dest = I->getOperand(0);
            break;
        default:
            //assert(0 && "DEF-USE: Unhandled intrinsic call");
            //handleUndefinedCall(callNode, CI);
            return;
    }

    // we must have dest set
    assert(dest);

    // these functions touch the memory of the pointers
    addDataDependence(callNode, CI, dest, UNKNOWN_OFFSET /* FIXME */);

    if (src)
        addDataDependence(callNode, CI, src, UNKNOWN_OFFSET /* FIXME */);
}

void LLVMDefUseAnalysis::handleCallInst(LLVMNode *node)
{
    CallInst *CI = cast<CallInst>(node->getKey());

    if (CI->isInlineAsm()) {
        handleInlineAsm(node);
        return;
    }

    Function *func
        = dyn_cast<Function>(CI->getCalledValue()->stripPointerCasts());
    if (func) {
        if (func->isIntrinsic() && !isa<DbgValueInst>(CI)) {
            handleIntrinsicCall(node, CI);
            return;
        }

        // for realloc, we need to make it data dependent on the
        // memory it reallocates, since that is the memory it copies
        if (strcmp(func->getName().data(), "realloc") == 0)
            addDataDependence(node, CI, CI->getOperand(0), UNKNOWN_OFFSET /* FIXME */);
    }

    /*
    if (func && func->size() == 0) {
        handleUndefinedCall(node);
        return;
    }
    */

    // add edges from the return nodes of subprocedure
    // to the call (if the call returns something)
    for (LLVMDependenceGraph *subgraph : node->getSubgraphs())
        addReturnEdge(node, subgraph);
}

// Add data dependence edges from all memory location that may write
// to memory pointed by 'pts' to 'node'
void LLVMDefUseAnalysis::addUnknownDataDependence(LLVMNode *node, PSNode *pts)
{
    // iterate over all nodes from ReachingDefinitions Subgraph. It is faster than
    // going over all llvm nodes and querying the pointer to analysis
    for (auto it : RD->getNodesMap()) {
        RDNode *rdnode = it.second;

        // only STORE may be a definition site
        if (rdnode->getType() != analysis::rd::STORE)
            continue;

        llvm::Value *rdVal = rdnode->getUserData<llvm::Value>();
        // artificial node?
        if (!rdVal)
            continue;

        // does this store define some value that is in pts?
        for (const analysis::rd::DefSite& ds : rdnode->getDefines()) {
            llvm::Value *llvmVal = ds.target->getUserData<llvm::Value>();
            // is this an artificial node?
            if (!llvmVal)
                continue;

            // if these two sets have an over-lap, we must add the data dependence
            for (const auto& ptr : pts->pointsTo)
                if (ptr.target->getUserData<llvm::Value>() == llvmVal) {
                    addDataDependence(node, rdVal);
            }
        }
    }
}

void LLVMDefUseAnalysis::addDataDependence(LLVMNode *node, llvm::Value *rdval)
{
    LLVMNode *rdnode = dg->getNode(rdval);
    if (!rdnode) {
        // that means that the value is not from this graph.
        // We need to add interprocedural edge
        llvm::Function *F
            = llvm::cast<llvm::Instruction>(rdval)->getParent()->getParent();
        LLVMNode *entryNode = dg->getGlobalNode(F);
        assert(entryNode && "Don't have built function");

        // get the graph where the node lives
        LLVMDependenceGraph *graph = entryNode->getDG();
        assert(graph != dg && "Cannot find a node");
        rdnode = graph->getNode(rdval);
        if (!rdnode) {
            llvmutil::printerr("ERROR: DG has not val: ", rdval);
            return;
        }
    }

    assert(rdnode);
    rdnode->addDataDependence(node);
}

void LLVMDefUseAnalysis::addDataDependence(LLVMNode *node, RDNode *rd)
{
    llvm::Value *rdval = rd->getUserData<llvm::Value>();
    assert(rdval && "RDNode has not set the coresponding value");
    addDataDependence(node, rdval);
}

// \param mem   current reaching definitions point
void LLVMDefUseAnalysis::addDataDependence(LLVMNode *node, PSNode *pts,
                                           RDNode *mem, uint64_t size)
{
    using namespace dg::analysis;

    for (const pta::Pointer& ptr : pts->pointsTo) {
        if (!ptr.isValid())
            continue;

        llvm::Value *llvmVal = ptr.target->getUserData<llvm::Value>();
        assert(llvmVal && "Don't have Value in PSNode");

        RDNode *val = RD->getNode(llvmVal);
        if(!val) {
            llvmutil::printerr("Don't have mapping:\n  ", llvmVal);
            continue;
        }

        std::set<RDNode *> defs;
        // Get even reaching definitions for UNKNOWN_MEMORY.
        // Since those can be ours definitions, we must add them always
        mem->getReachingDefinitions(rd::UNKNOWN_MEMORY, UNKNOWN_OFFSET, UNKNOWN_OFFSET, defs);
        if (!defs.empty()) {
            for (RDNode *rd : defs) {
                assert(!rd->isUnknown() && "Unknown memory defined at unknown location?");
                addDataDependence(node, rd);
            }

            defs.clear();
        }

        mem->getReachingDefinitions(val, ptr.offset, size, defs);
        if (defs.empty()) {
            llvm::GlobalVariable *GV
                = llvm::dyn_cast<llvm::GlobalVariable>(llvmVal);
            if (!GV || !GV->hasInitializer()) {
                static std::set<const llvm::Value *> reported;
                if (reported.insert(llvmVal).second) {
                    llvm::errs() << "No reaching definition for: " << *llvmVal
                                 << " off: " << *ptr.offset << "\n";
                }
            }

            continue;
        }

        // add data dependence
        for (RDNode *rd : defs) {
            if (rd->isUnknown()) {
                // we don't know what definitions reach this node,
                // se we must add data dependence to all possible
                // write to this memory
                addUnknownDataDependence(node, pts);

                // we can bail out, since we have added all
                break;
            }

            addDataDependence(node, rd);
        }
    }
}

void LLVMDefUseAnalysis::addDataDependence(LLVMNode *node,
                                           const llvm::Value *where, /* in CFG */
                                           const llvm::Value *ptrOp,
                                           uint64_t size)
{
    using namespace dg::analysis;

    // get points-to information for the operand
    pta::PSNode *pts = PTA->getPointsTo(ptrOp);
    //assert(pts && "Don't have points-to information for LoadInst");
    if (!pts) {
        llvmutil::printerr("ERROR: No points-to: ", ptrOp);
        return;
    }

    // get the node from reaching definition where we have
    // all the reaching definitions
    RDNode *mem = RD->getMapping(where);
    if(!mem) {
        llvmutil::printerr("ERROR: Don't have mapping: ", where);
        return;
    }

    // take every memory the load inst can use and get the
    // reaching definition
    addDataDependence(node, pts, mem, size);
}

static uint64_t getAllocatedSize(llvm::Type *Ty, const llvm::DataLayout *DL)
{
    // Type can be i8 *null or similar
    if (!Ty->isSized())
            return UNKNOWN_OFFSET;

    return DL->getTypeAllocSize(Ty);
}

void LLVMDefUseAnalysis::handleLoadInst(llvm::LoadInst *Inst, LLVMNode *node)
{
    using namespace dg::analysis;

    uint64_t size = getAllocatedSize(Inst->getType(), DL);
    addDataDependence(node, Inst, Inst->getPointerOperand(), size);
}

bool LLVMDefUseAnalysis::runOnNode(LLVMNode *node, LLVMNode *prev)
{
    Value *val = node->getKey();
    (void) prev;

    if (LoadInst *Inst = dyn_cast<LoadInst>(val)) {
        handleLoadInst(Inst, node);
    } else if (isa<CallInst>(val)) {
        handleCallInst(node);
    /*} else if (StoreInst *Inst = dyn_cast<StoreInst>(val)) {
        handleStoreInst(Inst, node);*/
    }

    /* just add direct def-use edges to every instruction */
    if (Instruction *Inst = dyn_cast<Instruction>(val))
        handleInstruction(Inst, node);

    // we will run only once
    return false;
}

} // namespace dg
<|endoftext|>