<commit_before>/**
 * This file is part of the "libfnord" project
 *   Copyright (c) 2015 Paul Asmuth
 *
 * FnordMetric is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License v3.0. You should have received a
 * copy of the GNU General Public License along with this program. If not, see
 * <http://www.gnu.org/licenses/>.
 */
#include <chartsql/qtree/ChartStatementNode.h>

using namespace stx;

namespace csql {

ChartStatementNode::ChartStatementNode(const ChartStatementNode& other) {
  for (const auto& draw_stmt : other.draw_stmts_) {
    draw_stmts_.emplace_back(draw_stmt->deepCopy());
  }

  for (auto& stmt : draw_stmts_) {
    addChild(&stmt);
  }
}

ChartStatementNode::ChartStatementNode(
    Vector<RefPtr<QueryTreeNode>> draw_stmts) :
    draw_stmts_(draw_stmts) {
  for (auto& stmt : draw_stmts_) {
    addChild(&stmt);
  }
}

RefPtr<QueryTreeNode> ChartStatementNode::deepCopy() const {
  return new ChartStatementNode(*this);
}

} // namespace csql
<commit_msg>ChartStatementNode::toString<commit_after>/**
 * This file is part of the "libfnord" project
 *   Copyright (c) 2015 Paul Asmuth
 *
 * FnordMetric is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License v3.0. You should have received a
 * copy of the GNU General Public License along with this program. If not, see
 * <http://www.gnu.org/licenses/>.
 */
#include <chartsql/qtree/ChartStatementNode.h>

using namespace stx;

namespace csql {

ChartStatementNode::ChartStatementNode(const ChartStatementNode& other) {
  for (const auto& draw_stmt : other.draw_stmts_) {
    draw_stmts_.emplace_back(draw_stmt->deepCopy());
  }

  for (auto& stmt : draw_stmts_) {
    addChild(&stmt);
  }
}

ChartStatementNode::ChartStatementNode(
    Vector<RefPtr<QueryTreeNode>> draw_stmts) :
    draw_stmts_(draw_stmts) {
  for (auto& stmt : draw_stmts_) {
    addChild(&stmt);
  }
}

RefPtr<QueryTreeNode> ChartStatementNode::deepCopy() const {
  return new ChartStatementNode(*this);
}

String ChartStatementNode::toString() const {
  String str = "(chart";

  for (const auto& stmt : draw_stmts_) {
    str += stmt->toString();
  }

  str += ")";
  return str;
}

} // namespace csql
<|endoftext|>


<commit_before>#ifndef CDM_GTEST_HPP
#define CDM_GTEST_HPP

#include <silicium/absolute_path.hpp>
#include <silicium/run_process.hpp>
#include <silicium/sink/ostream_sink.hpp>

namespace cdm
{
	struct gtest_paths
	{
		Si::absolute_path include;
		Si::absolute_path library;
		Si::absolute_path library_main;
	};

	inline void copy_recursively(Si::absolute_path const &from, Si::absolute_path const &to)
	{
		auto output = Si::Sink<char, Si::success>::erase(Si::ostream_ref_sink(std::cerr));
		std::vector<Si::noexcept_string> arguments = {"-Rv", from.c_str(), to.c_str()};
		if (Si::run_process("/bin/cp", arguments, from.to_boost_path(), output) != 0)
		{
			throw std::runtime_error("cp failed");
		}
	}

	inline Si::error_or<gtest_paths> install_gtest(
	    Si::absolute_path const &gtest_source,
		Si::absolute_path const &temporarily_writable,
	    Si::absolute_path const &install_root)
	{
		Si::absolute_path const cmake_exe = *Si::absolute_path::create("/usr/bin/cmake");
		auto output = Si::Sink<char, Si::success>::erase(Si::ostream_ref_sink(std::cerr));
		{
			std::vector<Si::noexcept_string> arguments;
			arguments.push_back(gtest_source.c_str());
			arguments.push_back(("-DCMAKE_INSTALL_PREFIX=" + install_root.to_boost_path().string()).c_str());
			int rc = Si::run_process(cmake_exe.to_boost_path(), arguments, temporarily_writable.to_boost_path(), output);
			assert(rc == 0);
		}
		{
			std::vector<Si::noexcept_string> arguments;
			arguments.push_back("--build");
			arguments.push_back(".");
			int rc = Si::run_process(cmake_exe.to_boost_path(), arguments, temporarily_writable.to_boost_path(), output);
			assert(rc == 0);
		}
		gtest_paths result;
		result.include = install_root / *Si::path_segment::create("include");
		auto lib_dir = install_root / *Si::path_segment::create("lib");
		Si::recreate_directories(lib_dir);
		result.library = lib_dir / *Si::path_segment::create("libgtest.a");
		result.library_main = lib_dir / *Si::path_segment::create("libgtest_main.a");

		Si::throw_if_error(Si::copy(temporarily_writable / *Si::path_segment::create("libgtest.a"), result.library));
		Si::throw_if_error(Si::copy(temporarily_writable / *Si::path_segment::create("libgtest_main.a"), result.library_main));
		Si::remove_all(result.include).move_value();
		copy_recursively(gtest_source / *Si::path_segment::create("include") / *Si::path_segment::create("gtest"), result.include);

		return std::move(result);
	}
}

#endif
<commit_msg>fix GCC release build<commit_after>#ifndef CDM_GTEST_HPP
#define CDM_GTEST_HPP

#include <silicium/absolute_path.hpp>
#include <silicium/run_process.hpp>
#include <silicium/sink/ostream_sink.hpp>

namespace cdm
{
	struct gtest_paths
	{
		Si::absolute_path include;
		Si::absolute_path library;
		Si::absolute_path library_main;
	};

	inline void copy_recursively(Si::absolute_path const &from, Si::absolute_path const &to)
	{
		auto output = Si::Sink<char, Si::success>::erase(Si::ostream_ref_sink(std::cerr));
		std::vector<Si::noexcept_string> arguments = {"-Rv", from.c_str(), to.c_str()};
		if (Si::run_process("/bin/cp", arguments, from.to_boost_path(), output) != 0)
		{
			throw std::runtime_error("cp failed");
		}
	}

	inline Si::error_or<gtest_paths> install_gtest(
		Si::absolute_path const &gtest_source,
		Si::absolute_path const &temporarily_writable,
		Si::absolute_path const &install_root)
	{
		Si::absolute_path const cmake_exe = *Si::absolute_path::create("/usr/bin/cmake");
		auto output = Si::Sink<char, Si::success>::erase(Si::ostream_ref_sink(std::cerr));
		{
			std::vector<Si::noexcept_string> arguments;
			arguments.push_back(gtest_source.c_str());
			arguments.push_back(("-DCMAKE_INSTALL_PREFIX=" + install_root.to_boost_path().string()).c_str());
			int rc = Si::run_process(cmake_exe.to_boost_path(), arguments, temporarily_writable.to_boost_path(), output);
			if (rc != 0)
			{
				throw std::runtime_error("cmake configure failed");
			}
		}
		{
			std::vector<Si::noexcept_string> arguments;
			arguments.push_back("--build");
			arguments.push_back(".");
			int rc = Si::run_process(cmake_exe.to_boost_path(), arguments, temporarily_writable.to_boost_path(), output);
			if (rc != 0)
			{
				throw std::runtime_error("cmake build failed");
			}
		}
		gtest_paths result;
		result.include = install_root / *Si::path_segment::create("include");
		auto lib_dir = install_root / *Si::path_segment::create("lib");
		Si::recreate_directories(lib_dir);
		result.library = lib_dir / *Si::path_segment::create("libgtest.a");
		result.library_main = lib_dir / *Si::path_segment::create("libgtest_main.a");

		Si::throw_if_error(Si::copy(temporarily_writable / *Si::path_segment::create("libgtest.a"), result.library));
		Si::throw_if_error(Si::copy(temporarily_writable / *Si::path_segment::create("libgtest_main.a"), result.library_main));
		Si::remove_all(result.include).move_value();
		copy_recursively(gtest_source / *Si::path_segment::create("include") / *Si::path_segment::create("gtest"), result.include);

		return std::move(result);
	}
}

#endif
<|endoftext|>


<commit_before>
#include "MethodDeclHandler.h"

#include <regex>

namespace typegrind
{

      MethodDeclHandler::MethodDeclHandler(clang::Rewriter*& rewriter, MethodMatcher const& matchers)
              : mRewriter(rewriter)
              , mMatchers(matchers)
      {
      }

      clang::StringRef MethodDeclHandler::getID() const {
          return "typegrind";
      }

      void MethodDeclHandler::run(const clang::ast_matchers::MatchFinder::MatchResult &result)
      {
        const clang::CXXMethodDecl* decl = result.Nodes.getNodeAs<clang::CXXMethodDecl>("decl");
        if(!decl) return;
        if (!decl->hasBody()) return;

        if(decl->getTemplateSpecializationKind() == clang::TSK_ImplicitInstantiation) return;

        //llvm::outs() << decl->getNameInfo().getAsString() << "\n";
        std::string prettyName;
        {
          llvm::raw_string_ostream prettyNameStream(prettyName);
          decl->getCanonicalDecl()->getNameForDiagnostic(prettyNameStream, clang::PrintingPolicy(result.Context->getPrintingPolicy()), true);
          prettyNameStream.flush();
        }

        if(!mMatchers.matches(prettyName)) return;

        //if(mVisited.find(prettyName) != mVisited.end()) return;
        //mVisited.insert(prettyName);

        clang::Stmt *funcBody = decl->getBody();
        mRewriter->InsertTextAfterToken(funcBody->getSourceRange().getBegin(), " TYPEGRIND_METHOD_ENTER(\""+prettyName+"\") ");

        // if constructor - initializer lists
        {
          const clang::CXXConstructorDecl* constrDecl = result.Nodes.getNodeAs<clang::CXXConstructorDecl>("decl");
          if(constrDecl)
          {
            for(auto initer: constrDecl->inits())
            {
              if(!initer->isMemberInitializer()) continue;
              mRewriter->InsertTextAfterToken(initer->getLParenLoc(), "TYPEGRIND_METHOD_INITIALIZER(\""+prettyName+"\", (");
              mRewriter->InsertTextBefore(initer->getRParenLoc(), "))");
            }
          }
        }
      }
}
<commit_msg>method matcher uses the new macro format, with the additional custom name and flags parameter<commit_after>
#include "MethodDeclHandler.h"

#include <regex>

namespace typegrind
{

      MethodDeclHandler::MethodDeclHandler(clang::Rewriter*& rewriter, MethodMatcher const& matchers)
              : mRewriter(rewriter)
              , mMatchers(matchers)
      {
      }

      clang::StringRef MethodDeclHandler::getID() const {
          return "typegrind";
      }

      void MethodDeclHandler::run(const clang::ast_matchers::MatchFinder::MatchResult &result)
      {
        const clang::CXXMethodDecl* decl = result.Nodes.getNodeAs<clang::CXXMethodDecl>("decl");
        if(!decl) return;
        if (!decl->hasBody()) return;

        if(decl->getTemplateSpecializationKind() == clang::TSK_ImplicitInstantiation) return;

        //llvm::outs() << decl->getNameInfo().getAsString() << "\n";
        std::string prettyName;
        {
          llvm::raw_string_ostream prettyNameStream(prettyName);
          decl->getCanonicalDecl()->getNameForDiagnostic(prettyNameStream, clang::PrintingPolicy(result.Context->getPrintingPolicy()), true);
          prettyNameStream.flush();
        }

        auto match = mMatchers.matches(prettyName);
        if(!match) return;

        //if(mVisited.find(prettyName) != mVisited.end()) return;
        //mVisited.insert(prettyName);

        clang::Stmt *funcBody = decl->getBody();
        mRewriter->InsertTextAfterToken(funcBody->getSourceRange().getBegin(), " TYPEGRIND_METHOD_ENTER(\""+prettyName+"\", \""+match->custom_name+"\", "+std::to_string(match->flags)+") ");

        // if constructor - initializer lists
        {
          const clang::CXXConstructorDecl* constrDecl = result.Nodes.getNodeAs<clang::CXXConstructorDecl>("decl");
          if(constrDecl)
          {
            for(auto initer: constrDecl->inits())
            {
              if(!initer->isMemberInitializer()) continue;
              mRewriter->InsertTextAfterToken(initer->getLParenLoc(), "TYPEGRIND_METHOD_INITIALIZER(\""+prettyName+"\", \""+match->custom_name+"\", "+std::to_string(match->flags)+", (");
              mRewriter->InsertTextBefore(initer->getRParenLoc(), "))");
            }
          }
        }
      }
}
<|endoftext|>


<commit_before>/*
   This file is part of the clazy static checker.

  Copyright (C) 2015 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
  Author: Sérgio Martins <sergio.martins@kdab.com>

  Copyright (C) 2015 Sergio Martins <smartins@kde.org>

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

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

  You should have received a copy of the GNU Library General Public License
  along with this library; see the file COPYING.LIB.  If not, write to
  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  Boston, MA 02110-1301, USA.
*/

#include "inefficientqlist.h"
#include "Utils.h"
#include "TemplateUtils.h"
#include "checkmanager.h"

#include <clang/AST/Decl.h>
#include <clang/AST/DeclCXX.h>
#include <clang/AST/AST.h>
#include <clang/AST/DeclTemplate.h>

using namespace clang;
using namespace std;

enum IgnoreMode {
    None = 0,
    NonLocalVariable = 1,
    InFunctionWithSameReturnType = 2,
    IsAssignedTooInFunction = 4
};

InefficientQList::InefficientQList(const std::string &name, const clang::CompilerInstance &ci)
    : CheckBase(name, ci)
{
}

static bool shouldIgnoreVariable(VarDecl *varDecl, int ignoreMode)
{
    DeclContext *context = varDecl->getDeclContext();
    FunctionDecl *fDecl = context ? dyn_cast<FunctionDecl>(context) : nullptr;

    if (ignoreMode & NonLocalVariable) {
        if (!fDecl)
            return true;
    }

    if (ignoreMode & IsAssignedTooInFunction) {
        if (fDecl && fDecl->getReturnType() == varDecl->getType())
            return true;
    }

    if (ignoreMode & IsAssignedTooInFunction) {
        if (fDecl) {
            if (Utils::containsAssignment(fDecl->getBody(), varDecl))
                return true;
        }
    }

    return false;
}

void InefficientQList::VisitDecl(clang::Decl *decl)
{
    VarDecl *varDecl = dyn_cast<VarDecl>(decl);
    if (!varDecl)
        return;

    QualType type = varDecl->getType();
    const Type *t = type.getTypePtrOrNull();
    if (!t)
        return;

    if (shouldIgnoreVariable(varDecl, NonLocalVariable | InFunctionWithSameReturnType | IsAssignedTooInFunction))
        return;

    CXXRecordDecl *recordDecl = t->getAsCXXRecordDecl();
    if (!recordDecl || recordDecl->getNameAsString() != "QList")
        return;

    const std::vector<clang::QualType> types = TemplateUtils::getTemplateArgumentsTypes(recordDecl);
    if (types.empty())
        return;
    QualType qt2 = types[0];
    const int size_of_void = 8 * 8; // 64 bits
    const int size_of_T = m_ci.getASTContext().getTypeSize(qt2);

    if (size_of_T > size_of_void) {
        string s = string("Use QVector instead of QList for type with size " + to_string(size_of_T / 8) + " bytes");
        emitWarning(decl->getLocStart(), s.c_str());
    }
}

REGISTER_CHECK_WITH_FLAGS("inefficient-qlist", InefficientQList, CheckLevel3)
<commit_msg>inneficient-qlist: Don't hardcode 64-bit as the size of a pointer<commit_after>/*
   This file is part of the clazy static checker.

  Copyright (C) 2015 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
  Author: Sérgio Martins <sergio.martins@kdab.com>

  Copyright (C) 2015 Sergio Martins <smartins@kde.org>

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

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

  You should have received a copy of the GNU Library General Public License
  along with this library; see the file COPYING.LIB.  If not, write to
  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  Boston, MA 02110-1301, USA.
*/

#include "inefficientqlist.h"
#include "Utils.h"
#include "TypeUtils.h"
#include "TemplateUtils.h"
#include "checkmanager.h"

#include <clang/AST/Decl.h>
#include <clang/AST/DeclCXX.h>
#include <clang/AST/AST.h>
#include <clang/AST/DeclTemplate.h>

using namespace clang;
using namespace std;

enum IgnoreMode {
    None = 0,
    NonLocalVariable = 1,
    InFunctionWithSameReturnType = 2,
    IsAssignedTooInFunction = 4
};

InefficientQList::InefficientQList(const std::string &name, const clang::CompilerInstance &ci)
    : CheckBase(name, ci)
{
}

static bool shouldIgnoreVariable(VarDecl *varDecl, int ignoreMode)
{
    DeclContext *context = varDecl->getDeclContext();
    FunctionDecl *fDecl = context ? dyn_cast<FunctionDecl>(context) : nullptr;

    if (ignoreMode & NonLocalVariable) {
        if (!fDecl)
            return true;
    }

    if (ignoreMode & IsAssignedTooInFunction) {
        if (fDecl && fDecl->getReturnType() == varDecl->getType())
            return true;
    }

    if (ignoreMode & IsAssignedTooInFunction) {
        if (fDecl) {
            if (Utils::containsAssignment(fDecl->getBody(), varDecl))
                return true;
        }
    }

    return false;
}

void InefficientQList::VisitDecl(clang::Decl *decl)
{
    VarDecl *varDecl = dyn_cast<VarDecl>(decl);
    if (!varDecl)
        return;

    QualType type = varDecl->getType();
    const Type *t = type.getTypePtrOrNull();
    if (!t)
        return;

    if (shouldIgnoreVariable(varDecl, NonLocalVariable | InFunctionWithSameReturnType | IsAssignedTooInFunction))
        return;

    CXXRecordDecl *recordDecl = t->getAsCXXRecordDecl();
    if (!recordDecl || recordDecl->getNameAsString() != "QList")
        return;

    const std::vector<clang::QualType> types = TemplateUtils::getTemplateArgumentsTypes(recordDecl);
    if (types.empty())
        return;
    QualType qt2 = types[0];
    if (!qt2.getTypePtrOrNull())
        return;

    const int size_of_ptr = TypeUtils::sizeOfPointer(m_ci, qt2); // in bits
    const int size_of_T = m_ci.getASTContext().getTypeSize(qt2);

    if (size_of_T > size_of_ptr) {
        string s = string("Use QVector instead of QList for type with size " + to_string(size_of_T / 8) + " bytes");
        emitWarning(decl->getLocStart(), s.c_str());
    }
}

REGISTER_CHECK_WITH_FLAGS("inefficient-qlist", InefficientQList, CheckLevel3)
<|endoftext|>


<commit_before>/**
**  Simple ROS Node
**/
#include <ros/ros.h>
#include <fake_ar_publisher/ARMarker.h>
#include <myworkcell_core/LocalizePart.h>
#include <tf/transform_listener.h>

class Localizer
{
public:
    Localizer(ros::NodeHandle& nh)
    {
        ar_sub_ = nh.subscribe<fake_ar_publisher::ARMarker>("ar_pose_marker", 1,
        &Localizer::visionCallback, this);

        server_ = nh.advertiseService("localize_part", &Localizer::localizePart, this);
    }

    void visionCallback(const fake_ar_publisher::ARMarkerConstPtr& msg)
    {
        last_msg_ = msg;
        //ROS_INFO_STREAM(last_msg_->pose.pose);
    }

    bool localizePart(myworkcell_core::LocalizePart::Request& req,
                      myworkcell_core::LocalizePart::Response& res)
    {
       // Read last message
       fake_ar_publisher::ARMarkerConstPtr p = last_msg_;
       if (!p) return false;

       tf::Transform cam_to_target;
       tf::poseMsgToTF(p->pose.pose, cam_to_target);

       tf::StampedTransform req_to_cam;
       listener_.lookupTransform(req.base_frame, p->header.frame_id, ros::Time(0), req_to_cam);

       tf::Transform req_to_target;
       req_to_target = req_to_cam * cam_to_target;

       tf::poseTFToMsg(req_to_target, res.pose);
       return true;
    }

    ros::Subscriber ar_sub_;
    fake_ar_publisher::ARMarkerConstPtr last_msg_;
    ros::ServiceServer server_;
    tf::TransformListener listener_;
};

int main(int argc, char* argv[])
{
    // This must be called before anything else ROS-related
    ros::init(argc, argv, "vision_node");

    // Create a ROS node handle
    ros::NodeHandle nh;

    // The Localizer class provides this node's ROS interfaces
    Localizer localizer(nh);

    ROS_INFO("Vision node starting");

        // The Localizer class provides this node's ROS interfaces
    	Localizer localizer(nh);

    	//ROS_INFO("Vision node starting");

       	// Don't exit the program.
       	ros::spin();
}

<commit_msg>Added a library to 4.1 that will make it run properly.<commit_after>/**
**  Simple ROS Node
**/
#include <ros/ros.h>
#include <fake_ar_publisher/ARMarker.h>
#include <myworkcell_core/LocalizePart.h>
#include <tf/transform_listener.h>
#include <moveit/move_group_interface/move_group.h>

class Localizer
{
public:
    Localizer(ros::NodeHandle& nh)
    {
        ar_sub_ = nh.subscribe<fake_ar_publisher::ARMarker>("ar_pose_marker", 1,
        &Localizer::visionCallback, this);

        server_ = nh.advertiseService("localize_part", &Localizer::localizePart, this);
    }

    void visionCallback(const fake_ar_publisher::ARMarkerConstPtr& msg)
    {
        last_msg_ = msg;
        //ROS_INFO_STREAM(last_msg_->pose.pose);
    }

    bool localizePart(myworkcell_core::LocalizePart::Request& req,
                      myworkcell_core::LocalizePart::Response& res)
    {
       // Read last message
       fake_ar_publisher::ARMarkerConstPtr p = last_msg_;
       if (!p) return false;

       tf::Transform cam_to_target;
       tf::poseMsgToTF(p->pose.pose, cam_to_target);

       tf::StampedTransform req_to_cam;
       listener_.lookupTransform(req.base_frame, p->header.frame_id, ros::Time(0), req_to_cam);

       tf::Transform req_to_target;
       req_to_target = req_to_cam * cam_to_target;

       tf::poseTFToMsg(req_to_target, res.pose);
       return true;
    }

    ros::Subscriber ar_sub_;
    fake_ar_publisher::ARMarkerConstPtr last_msg_;
    ros::ServiceServer server_;
    tf::TransformListener listener_;
};

int main(int argc, char* argv[])
{
    // This must be called before anything else ROS-related
    ros::init(argc, argv, "vision_node");

    // Create a ROS node handle
    ros::NodeHandle nh;

    // The Localizer class provides this node's ROS interfaces
    Localizer localizer(nh);

    ROS_INFO("Vision node starting");

    // Don't exit the program.
    ros::spin();
}

<|endoftext|>


<commit_before>// 8/31/2017
// Easy
#include <iostream>

using namespace std;

struct ListNode {
    int val;
    ListNode *next;
    ListNode(int x): val(x), next(NULL) {}
};

ListNode* removedups(ListNode *head) {
    if (head == NULL) return NULL;

    for (ListNode *prev = head, *cur = head->next; cur; cur = prev->next) {
        if (prev->val == cur->val) {
            prev->next = cur->next;
            delete cur;
        } else
            prev = cur;
    }

    return head;
}

int main()
{
    ListNode *n1 = new ListNode(1);
    ListNode *n2 = new ListNode(1);
    ListNode *n3 = new ListNode(2);
    n1->next = n2;
    n2->next = n3;

    ListNode *head = removedups(n1);

    for (ListNode *n = head; n; n = n->next)
        cout << n->val << " ";

    cout << endl;
    return 0;
}
<commit_msg>remove dup from slist-recursive<commit_after>// remove duplicates from sorted list
// 8/31/2017
// Easy
#include <iostream>

using namespace std;

struct ListNode {
    int val;
    ListNode *next;
    ListNode(int x): val(x), next(NULL) {}
};

ListNode* removedups(ListNode *head) {
    if (head == NULL) return NULL;

    for (ListNode *prev = head, *cur = head->next; cur; cur = prev->next) {
        if (prev->val == cur->val) {
            prev->next = cur->next;
            delete cur;
        } else
            prev = cur;
    }

    return head;
}

void recur(ListNode *prev, ListNode *cur) {
    if (!cur) return;

    if (prev->val == cur->val) {
        prev->next = cur->next;
        delete cur;
        recur(prev, prev->next);
    } else {
        recur(cur, cur->next);
    }
}

// recursive
ListNode *removedup2(ListNode *head) {
    if (!head) return NULL;

    ListNode dummy(head->val + 1);
    dummy.next = head;

    recur(&dummy, head);

    return dummy.next;
}

int main()
{
    {
        ListNode *n1 = new ListNode(1);
        ListNode *n2 = new ListNode(1);
        ListNode *n3 = new ListNode(2);
        n1->next = n2;
        n2->next = n3;

        ListNode *head = removedups(n1);

        for (ListNode *n = head; n; n = n->next)
            cout << n->val << " ";

        cout << endl;
    }

    {
        ListNode *n1 = new ListNode(1);
        ListNode *n2 = new ListNode(1);
        ListNode *n3 = new ListNode(2);
        n1->next = n2;
        n2->next = n3;

        ListNode *head = removedup2(n1);

        for (ListNode *n = head; n; n = n->next)
            cout << n->val << " ";

        cout << endl;
    }
    return 0;
}
<|endoftext|>


<commit_before>#include "root_system.h"
#include "general_utilities.h"
#include "ocv_utilities.h"
#include "root_image_preprocessor.h"
#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;

//////////////////////////////////////////////////////////////////////////////////
// RootSystem::RootSystem()
//
// Constructor to specify the image to compute the root system from.
//////////////////////////////////////////////////////////////////////////////////
RootSystem::RootSystem(Mat image)
{
	_image = RootImagePreprocessor::prepareForAnalysis(image);
	_contour = RootImagePreprocessor::getRootContour();
	_skeleton = RootImagePreprocessor::getSkeleton();

	//TODO_DESIGN: Calling getRootContour() is ugly as it depends on prepareForAnalysis to be called first. We may want to precompute the contours,
	//      and pull some of the functionality from RootImagePreprocessor into OcvUtilities. For now, just leave it as is in order to finish first pass of trait computation.

	//TODO_PERF: We may want to consider only iterating through the image once, and computing all of these in one pass. This would speed things up significantly

	//TODO_ROBUST: Consider a set of defensive checks here to verify _image and _contour were constructed properly.
}

//////////////////////////////////////////////////////////////////////////////////
// RootSystem::getImage()
//
// Returns the image that we are operating on.
//////////////////////////////////////////////////////////////////////////////////
cv::Mat RootSystem::getImage()
{
	return _image.clone();
}

//////////////////////////////////////////////////////////////////////////////////
// bushiness()
//
// Units: n / n
//
// The ratio of the maximum to the median number of roots.
//////////////////////////////////////////////////////////////////////////////////
double RootSystem::bushiness()
{
	return maximumNumberOfRoots() / medianNumberOfRoots();	//TODO_ROBUST: Check for division by zero here and below.
}

//////////////////////////////////////////////////////////////////////////////////
// convexArea()
//
// Units: cm^2
//
// The area of the convex hull that encompasses the root.
//////////////////////////////////////////////////////////////////////////////////
double RootSystem::convexArea()
{
	vector<Point> hull;
	convexHull(_contour, hull);

	//TODO_ROBUST: Make a debugging flag to write out an image if the flag is turned on?
	//drawContours(_image, vector<vector<Point>>(1, hull), 0, Scalar(255));	// drawContours expects a vector of vectors, so we need to construct the expected type from our largest hull contour.

	return contourArea(hull);
}

//////////////////////////////////////////////////////////////////////////////////
// networkDepth()
//
// Units: cm
//
// The number of pixels in the vertical direction from the upper-most network
// pixel to the lower-most network pixel.
//////////////////////////////////////////////////////////////////////////////////
double RootSystem::networkDepth()
{
	if (_contour.size() < 1)
		return -1;

	int minY = _contour[0].y;
	int maxY = _contour[0].y;

	for each (auto point in _contour)
	{
		if (point.y > maxY)
			maxY = point.y;
		if (point.y < minY)
			minY = point.y;
	}

	return maxY - minY;
}

//////////////////////////////////////////////////////////////////////////////////
// networkLengthDistribution()
//
// Units: n / n
//
// The fraction of network pixels found in the lower 2/3 of the network. The
// lower 2/3 of the network is defined based on the network depth.
//////////////////////////////////////////////////////////////////////////////////
double RootSystem::networkLengthDistribution()
{
	int lowerTwoThirdsStart = static_cast<int>(round(0.33 * networkDepth()));	//TODO: Network depth computation makes sense here only if the top of the image is where the network starts (true in current sample image case)

	double lowerTwoThirdsArea = 0;

	for (int row = lowerTwoThirdsStart; row <= networkDepth(); ++row)
	{
		for (int col = 0; col < _image.size().width; ++col)
		{
			if (OcvUtilities::isPointWhite(_image, Point(col, row)))
			{
				lowerTwoThirdsArea++;
			}
		}
	}

	//TODO_ROBUST: Allow debugging image to be output.
	//for (int col = 0; col < _image.size().width; ++col)
	//{
	//	_image.at<uchar>(Point(col, lowerTwoThirdsStart)) = 255;
	//	imshow("Lower Two-Thirds Line", _image);
	//}

	return lowerTwoThirdsArea / networkArea();	//TODO_PERF: Don't iterate through 2/3 of the image twice to compute this.
}

//////////////////////////////////////////////////////////////////////////////////
// majorAxis()
//
// Units: cm
//
// The length of the major axis of the best fitting ellipse to the network.
//////////////////////////////////////////////////////////////////////////////////
double RootSystem::majorAxis()
{
	RotatedRect bestFittingEllipse = fitEllipse(_contour);

	return round(max(bestFittingEllipse.size.width, bestFittingEllipse.size.height));
}

//////////////////////////////////////////////////////////////////////////////////
// networkWidth()
//
// Units: cm
//
// The number of pixels in the horizontal direction from the left-most network
// pixel to the right-most network pixel. Only pixels lying in the same row are
// considered.
//////////////////////////////////////////////////////////////////////////////////
double RootSystem::networkWidth()
{
	if (_contour.size() < 1)
		return -1;

	int minX = _contour[0].x;
	int maxX = _contour[0].x;

	for each (auto point in _contour)
	{
		if (point.x > maxX)
			maxX = point.x;
		if (point.x < minX)
			minX = point.x;
	}

	return maxX - minX;	//TODO: Note that this does not assume that pixels are in the same row as specified in the comment above. We should confirm that this is the desired behavior.
}

//////////////////////////////////////////////////////////////////////////////////
// maximumNumberOfRoots()
//
// Units: n
//
// After sorting the number of roots crossing a horizontal line from smallest to
// largest, the maximum number is considered to be the 84th-percentile value
// (one standard deviation).
//////////////////////////////////////////////////////////////////////////////////
double RootSystem::maximumNumberOfRoots()
{
	const double PERCENTILE = 0.84;

	vector<int> numberOfRootsInRow = computeNumberOfRootsInRows();

	sort(numberOfRootsInRow.begin(), numberOfRootsInRow.end());

	int maximumIndex = static_cast<int>(round(PERCENTILE * numberOfRootsInRow.size()));

	return numberOfRootsInRow[maximumIndex];
}

//////////////////////////////////////////////////////////////////////////////////
// averageRootWidth()
//
// Units: cm
//
// The mean value of the root width estimation computed for all pixels of the
// medial axis of the entire root system. This trait corresponds to diameter
// of a root.
//////////////////////////////////////////////////////////////////////////////////
double RootSystem::averageRootWidth()
{
	return 0;
}

//////////////////////////////////////////////////////////////////////////////////
// medianNumberOfRoots()
//
// Units: n
//
// The result of a vertical line sweep in which the number of roots that crossed
// a horizontal line was estimated, and then the median of all values for the
// extent of the network was calculated.
//////////////////////////////////////////////////////////////////////////////////
double RootSystem::medianNumberOfRoots()
{
	return GeneralUtilities::computeMedian(computeNumberOfRootsInRows());
}

//////////////////////////////////////////////////////////////////////////////////
// minorAxis()
//
// Units: cm
//
// The length of the minor axis of the best fitting ellipse to the network.
//////////////////////////////////////////////////////////////////////////////////
double RootSystem::minorAxis()
{
	RotatedRect bestFittingEllipse = fitEllipse(_contour);	//TODO_PERF: Compute the best fitting ellipse only once.

	return round(min(bestFittingEllipse.size.width, bestFittingEllipse.size.height));
}

//////////////////////////////////////////////////////////////////////////////////
// networkArea()
//
// Units: cm^2
//
// The number of network pixels in the image.
//////////////////////////////////////////////////////////////////////////////////
double RootSystem::networkArea()
{
	double networkArea = 0;

	MatIterator_<uchar> it, end;
	for (it = _image.begin<uchar>(), end = _image.end<uchar>(); it != end; ++it)
	{
		if (*it == RootImagePreprocessor::getMaximumThresholdValue())
		{
			networkArea++;
		}
	}

	//TODO_DESIGN: Consider using countNonZero(_image) here, although may not be useful for images that have different threshold settings.

	return networkArea;	//TODO_DESIGN: Is there a way we can use the contour rather than the entire image here?
}

//////////////////////////////////////////////////////////////////////////////////
// perimeter()
//
// Units: cm
//
// The total number of network pixels connected to a background pixel (using a
// 8-nearest neighbor neighborhood).
//////////////////////////////////////////////////////////////////////////////////
double RootSystem::perimeter()
{
	double perimeter = 0;

	for (int row = 0; row < _image.size().height; ++row)
	{
		for (int col = 0; col < _image.size().width; ++col)
		{
			if (OcvUtilities::isPointWhite(_image, Point(col, row)))
			{
				vector<Point> neighbors = OcvUtilities::getNeighboringPixels(_image, Point(col, row));

				bool allWhiteNeighbors = true;

				for (vector<Point>::iterator it = neighbors.begin(); it != neighbors.end(); ++it)
				{
					if (!OcvUtilities::isPointWhite(_image, *it))
					{
						allWhiteNeighbors = false;
					}
				}

				if (allWhiteNeighbors)
					perimeter++;
			}
		}
	}

	return perimeter;
}

//////////////////////////////////////////////////////////////////////////////////
// aspectRatio()
//
// Units: cm/cm
//
// The ratio of the minor to the major axis of best fitting ellipse.
//////////////////////////////////////////////////////////////////////////////////
double RootSystem::aspectRatio()
{
	return minorAxis() / majorAxis();
}

//////////////////////////////////////////////////////////////////////////////////
// networkSolidity()
//
// Units: cm^2/cm^2
//
// The total network area divided by the network convex area.
//////////////////////////////////////////////////////////////////////////////////
double RootSystem::networkSolidity()
{
	return networkArea() / convexArea();	//TODO: networkArea is computed based on pixels, convexArea is computed based on the contour. This ratio might not be apples to apples...
}

//////////////////////////////////////////////////////////////////////////////////
// specificRootLength()
//
// Units: cm/cm^3
//
// Total network length divided by network volume. Volume is estimated as the sum
// of cross-sectional areas for all pixels of the medial axis of the root system.
// The total root length is the number of pixels in the medial axis of the root
// system.
//////////////////////////////////////////////////////////////////////////////////
double RootSystem::specificRootLength()
{
	return 0;
}

//////////////////////////////////////////////////////////////////////////////////
// networkSurfaceArea()
//
// Units: cm^2
//
// The sum of the local surface area at each pixel of the network skeleton, as
// approximated by a tubular shape whose radius is estimated from the image.
//////////////////////////////////////////////////////////////////////////////////
double RootSystem::networkSurfaceArea()
{
	return 0;
}

//////////////////////////////////////////////////////////////////////////////////
// networkLength()
//
// Units: cm
//
// The total number of pixels in the network skeleton.
//////////////////////////////////////////////////////////////////////////////////
double RootSystem::networkLength()
{
	return 0;
}

//////////////////////////////////////////////////////////////////////////////////
// networkVolume()
//
// Units: cm^3
//
// The sum of the local volume at each pixel of the network skeleton, as
// approximated by a tubular shape whose radius is estimated from the image.
//////////////////////////////////////////////////////////////////////////////////
double RootSystem::networkVolume()
{
	return 0;
}

//////////////////////////////////////////////////////////////////////////////////
// networkWidthToDepthRatio()
//
// Units: cm/cm
//
// The value of network width divided by the value of network depth.
//////////////////////////////////////////////////////////////////////////////////
double RootSystem::networkWidthToDepthRatio()
{
	return networkWidth() / networkDepth();
}

//////////////////////////////////////////////////////////////////////////////////
// computeNumberOfRootsInRow()
//
// Returns a list of integers corresponding to the number of roots that were found
// in each row of the image. A root can be considered to be "found" when we find
// a white pixel when the previous pixel was black.
//////////////////////////////////////////////////////////////////////////////////
vector<int> RootSystem::computeNumberOfRootsInRows(bool includeZeroes)	//TODO_PERF: Compute this only once, rather than once for both maxmimum and minimum.
{
	vector<int> numberOfRootsInRows(_image.size().height);

	for (int row = 0; row < _image.size().height; ++row)
	{
		for (int col = 0; col < _image.size().width; ++col)
		{
			// If the current point is white, and the previous point was black, then we have found a new root.
			if (OcvUtilities::isPointWhite(_image, Point(col, row)) && !OcvUtilities::isPointWhite(_image, Point(col - 1, row)))
			{
				numberOfRootsInRows[row]++;
			}
		}

		if (numberOfRootsInRows[row] == 0)	// It should be safe to assume that once we have hit a row with no roots, there will be no more roots below that row.
			break;
	}

	if (!includeZeroes)
	{
		// Remove all zeroes from the list.
		numberOfRootsInRows.erase(
			remove_if(numberOfRootsInRows.begin(), numberOfRootsInRows.end(), [](const int numberOfRootsInRow) { return numberOfRootsInRow == 0; } ),
			numberOfRootsInRows.end()
			);
	}

	return numberOfRootsInRows;
}
<commit_msg>Compute network length<commit_after>#include "root_system.h"
#include "general_utilities.h"
#include "ocv_utilities.h"
#include "root_image_preprocessor.h"
#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;

//////////////////////////////////////////////////////////////////////////////////
// RootSystem::RootSystem()
//
// Constructor to specify the image to compute the root system from.
//////////////////////////////////////////////////////////////////////////////////
RootSystem::RootSystem(Mat image)
{
	_image = RootImagePreprocessor::prepareForAnalysis(image);
	_contour = RootImagePreprocessor::getRootContour();
	_skeleton = RootImagePreprocessor::getSkeleton();

	//TODO_DESIGN: Calling getRootContour() is ugly as it depends on prepareForAnalysis to be called first. We may want to precompute the contours,
	//      and pull some of the functionality from RootImagePreprocessor into OcvUtilities. For now, just leave it as is in order to finish first pass of trait computation.

	//TODO_PERF: We may want to consider only iterating through the image once, and computing all of these in one pass. This would speed things up significantly

	//TODO_ROBUST: Consider a set of defensive checks here to verify _image and _contour were constructed properly.
}

//////////////////////////////////////////////////////////////////////////////////
// RootSystem::getImage()
//
// Returns the image that we are operating on.
//////////////////////////////////////////////////////////////////////////////////
cv::Mat RootSystem::getImage()
{
	return _image.clone();
}

//////////////////////////////////////////////////////////////////////////////////
// bushiness()
//
// Units: n / n
//
// The ratio of the maximum to the median number of roots.
//////////////////////////////////////////////////////////////////////////////////
double RootSystem::bushiness()
{
	return maximumNumberOfRoots() / medianNumberOfRoots();	//TODO_ROBUST: Check for division by zero here and below.
}

//////////////////////////////////////////////////////////////////////////////////
// convexArea()
//
// Units: cm^2
//
// The area of the convex hull that encompasses the root.
//////////////////////////////////////////////////////////////////////////////////
double RootSystem::convexArea()
{
	vector<Point> hull;
	convexHull(_contour, hull);

	//TODO_ROBUST: Make a debugging flag to write out an image if the flag is turned on?
	//drawContours(_image, vector<vector<Point>>(1, hull), 0, Scalar(255));	// drawContours expects a vector of vectors, so we need to construct the expected type from our largest hull contour.

	return contourArea(hull);
}

//////////////////////////////////////////////////////////////////////////////////
// networkDepth()
//
// Units: cm
//
// The number of pixels in the vertical direction from the upper-most network
// pixel to the lower-most network pixel.
//////////////////////////////////////////////////////////////////////////////////
double RootSystem::networkDepth()
{
	if (_contour.size() < 1)
		return -1;

	int minY = _contour[0].y;
	int maxY = _contour[0].y;

	for each (auto point in _contour)
	{
		if (point.y > maxY)
			maxY = point.y;
		if (point.y < minY)
			minY = point.y;
	}

	return maxY - minY;
}

//////////////////////////////////////////////////////////////////////////////////
// networkLengthDistribution()
//
// Units: n / n
//
// The fraction of network pixels found in the lower 2/3 of the network. The
// lower 2/3 of the network is defined based on the network depth.
//////////////////////////////////////////////////////////////////////////////////
double RootSystem::networkLengthDistribution()
{
	int lowerTwoThirdsStart = static_cast<int>(round(0.33 * networkDepth()));	//TODO: Network depth computation makes sense here only if the top of the image is where the network starts (true in current sample image case)

	double lowerTwoThirdsArea = 0;

	for (int row = lowerTwoThirdsStart; row <= networkDepth(); ++row)
	{
		for (int col = 0; col < _image.size().width; ++col)
		{
			if (OcvUtilities::isPointWhite(_image, Point(col, row)))
			{
				lowerTwoThirdsArea++;
			}
		}
	}

	//TODO_ROBUST: Allow debugging image to be output.
	//for (int col = 0; col < _image.size().width; ++col)
	//{
	//	_image.at<uchar>(Point(col, lowerTwoThirdsStart)) = 255;
	//	imshow("Lower Two-Thirds Line", _image);
	//}

	return lowerTwoThirdsArea / networkArea();	//TODO_PERF: Don't iterate through 2/3 of the image twice to compute this.
}

//////////////////////////////////////////////////////////////////////////////////
// majorAxis()
//
// Units: cm
//
// The length of the major axis of the best fitting ellipse to the network.
//////////////////////////////////////////////////////////////////////////////////
double RootSystem::majorAxis()
{
	RotatedRect bestFittingEllipse = fitEllipse(_contour);

	return round(max(bestFittingEllipse.size.width, bestFittingEllipse.size.height));
}

//////////////////////////////////////////////////////////////////////////////////
// networkWidth()
//
// Units: cm
//
// The number of pixels in the horizontal direction from the left-most network
// pixel to the right-most network pixel. Only pixels lying in the same row are
// considered.
//////////////////////////////////////////////////////////////////////////////////
double RootSystem::networkWidth()
{
	if (_contour.size() < 1)
		return -1;

	int minX = _contour[0].x;
	int maxX = _contour[0].x;

	for each (auto point in _contour)
	{
		if (point.x > maxX)
			maxX = point.x;
		if (point.x < minX)
			minX = point.x;
	}

	return maxX - minX;	//TODO: Note that this does not assume that pixels are in the same row as specified in the comment above. We should confirm that this is the desired behavior.
}

//////////////////////////////////////////////////////////////////////////////////
// maximumNumberOfRoots()
//
// Units: n
//
// After sorting the number of roots crossing a horizontal line from smallest to
// largest, the maximum number is considered to be the 84th-percentile value
// (one standard deviation).
//////////////////////////////////////////////////////////////////////////////////
double RootSystem::maximumNumberOfRoots()
{
	const double PERCENTILE = 0.84;

	vector<int> numberOfRootsInRow = computeNumberOfRootsInRows();

	sort(numberOfRootsInRow.begin(), numberOfRootsInRow.end());

	int maximumIndex = static_cast<int>(round(PERCENTILE * numberOfRootsInRow.size()));

	return numberOfRootsInRow[maximumIndex];
}

//////////////////////////////////////////////////////////////////////////////////
// averageRootWidth()
//
// Units: cm
//
// The mean value of the root width estimation computed for all pixels of the
// medial axis of the entire root system. This trait corresponds to diameter
// of a root.
//////////////////////////////////////////////////////////////////////////////////
double RootSystem::averageRootWidth()
{
	return 0;
}

//////////////////////////////////////////////////////////////////////////////////
// medianNumberOfRoots()
//
// Units: n
//
// The result of a vertical line sweep in which the number of roots that crossed
// a horizontal line was estimated, and then the median of all values for the
// extent of the network was calculated.
//////////////////////////////////////////////////////////////////////////////////
double RootSystem::medianNumberOfRoots()
{
	return GeneralUtilities::computeMedian(computeNumberOfRootsInRows());
}

//////////////////////////////////////////////////////////////////////////////////
// minorAxis()
//
// Units: cm
//
// The length of the minor axis of the best fitting ellipse to the network.
//////////////////////////////////////////////////////////////////////////////////
double RootSystem::minorAxis()
{
	RotatedRect bestFittingEllipse = fitEllipse(_contour);	//TODO_PERF: Compute the best fitting ellipse only once.

	return round(min(bestFittingEllipse.size.width, bestFittingEllipse.size.height));
}

//////////////////////////////////////////////////////////////////////////////////
// networkArea()
//
// Units: cm^2
//
// The number of network pixels in the image.
//////////////////////////////////////////////////////////////////////////////////
double RootSystem::networkArea()
{
	return countNonZero(_image);	//TODO_DESIGN: Is there a way we can use the contour rather than the entire image here?
}

//////////////////////////////////////////////////////////////////////////////////
// perimeter()
//
// Units: cm
//
// The total number of network pixels connected to a background pixel (using a
// 8-nearest neighbor neighborhood).
//////////////////////////////////////////////////////////////////////////////////
double RootSystem::perimeter()
{
	double perimeter = 0;

	for (int row = 0; row < _image.size().height; ++row)
	{
		for (int col = 0; col < _image.size().width; ++col)
		{
			if (OcvUtilities::isPointWhite(_image, Point(col, row)))
			{
				vector<Point> neighbors = OcvUtilities::getNeighboringPixels(_image, Point(col, row));

				bool allWhiteNeighbors = true;

				for (vector<Point>::iterator it = neighbors.begin(); it != neighbors.end(); ++it)
				{
					if (!OcvUtilities::isPointWhite(_image, *it))
					{
						allWhiteNeighbors = false;
					}
				}

				if (allWhiteNeighbors)
					perimeter++;
			}
		}
	}

	return perimeter;
}

//////////////////////////////////////////////////////////////////////////////////
// aspectRatio()
//
// Units: cm/cm
//
// The ratio of the minor to the major axis of best fitting ellipse.
//////////////////////////////////////////////////////////////////////////////////
double RootSystem::aspectRatio()
{
	return minorAxis() / majorAxis();
}

//////////////////////////////////////////////////////////////////////////////////
// networkSolidity()
//
// Units: cm^2/cm^2
//
// The total network area divided by the network convex area.
//////////////////////////////////////////////////////////////////////////////////
double RootSystem::networkSolidity()
{
	return networkArea() / convexArea();	//TODO: networkArea is computed based on pixels, convexArea is computed based on the contour. This ratio might not be apples to apples...
}

//////////////////////////////////////////////////////////////////////////////////
// specificRootLength()
//
// Units: cm/cm^3
//
// Total network length divided by network volume. Volume is estimated as the sum
// of cross-sectional areas for all pixels of the medial axis of the root system.
// The total root length is the number of pixels in the medial axis of the root
// system.
//////////////////////////////////////////////////////////////////////////////////
double RootSystem::specificRootLength()
{
	return 0;
}

//////////////////////////////////////////////////////////////////////////////////
// networkSurfaceArea()
//
// Units: cm^2
//
// The sum of the local surface area at each pixel of the network skeleton, as
// approximated by a tubular shape whose radius is estimated from the image.
//////////////////////////////////////////////////////////////////////////////////
double RootSystem::networkSurfaceArea()
{
	return 0;
}

//////////////////////////////////////////////////////////////////////////////////
// networkLength()
//
// Units: cm
//
// The total number of pixels in the network skeleton.
//////////////////////////////////////////////////////////////////////////////////
double RootSystem::networkLength()
{
	return countNonZero(_skeleton);
}

//////////////////////////////////////////////////////////////////////////////////
// networkVolume()
//
// Units: cm^3
//
// The sum of the local volume at each pixel of the network skeleton, as
// approximated by a tubular shape whose radius is estimated from the image.
//////////////////////////////////////////////////////////////////////////////////
double RootSystem::networkVolume()
{
	return 0;
}

//////////////////////////////////////////////////////////////////////////////////
// networkWidthToDepthRatio()
//
// Units: cm/cm
//
// The value of network width divided by the value of network depth.
//////////////////////////////////////////////////////////////////////////////////
double RootSystem::networkWidthToDepthRatio()
{
	return networkWidth() / networkDepth();
}

//////////////////////////////////////////////////////////////////////////////////
// computeNumberOfRootsInRow()
//
// Returns a list of integers corresponding to the number of roots that were found
// in each row of the image. A root can be considered to be "found" when we find
// a white pixel when the previous pixel was black.
//////////////////////////////////////////////////////////////////////////////////
vector<int> RootSystem::computeNumberOfRootsInRows(bool includeZeroes)	//TODO_PERF: Compute this only once, rather than once for both maxmimum and minimum.
{
	vector<int> numberOfRootsInRows(_image.size().height);

	for (int row = 0; row < _image.size().height; ++row)
	{
		for (int col = 0; col < _image.size().width; ++col)
		{
			// If the current point is white, and the previous point was black, then we have found a new root.
			if (OcvUtilities::isPointWhite(_image, Point(col, row)) && !OcvUtilities::isPointWhite(_image, Point(col - 1, row)))
			{
				numberOfRootsInRows[row]++;
			}
		}

		if (numberOfRootsInRows[row] == 0)	// It should be safe to assume that once we have hit a row with no roots, there will be no more roots below that row.
			break;
	}

	if (!includeZeroes)
	{
		// Remove all zeroes from the list.
		numberOfRootsInRows.erase(
			remove_if(numberOfRootsInRows.begin(), numberOfRootsInRows.end(), [](const int numberOfRootsInRow) { return numberOfRootsInRow == 0; } ),
			numberOfRootsInRows.end()
			);
	}

	return numberOfRootsInRows;
}
<|endoftext|>


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

#include <session/prefs/UserPrefs.hpp>
#include <session/SessionConsoleProcess.hpp>
#include <session/SessionModuleContext.hpp>

#include <core/system/Environment.hpp>
#include <core/system/Process.hpp>

#include <r/RExec.hpp>

#include <r/session/RSessionUtils.hpp>

#include <session/SessionAsyncRProcess.hpp>

namespace rstudio {
namespace session {
namespace async_r {

AsyncRProcess::AsyncRProcess():
   isRunning_(false),
   terminationRequested_(false)
{
}

void AsyncRProcess::start(const char* rCommand,
                          core::system::Options environment,
                          const core::FilePath& workingDir,
                          AsyncRProcessOptions rOptions,
                          std::vector<core::FilePath> rSourceFiles,
                          const std::string& input)
{
   // file paths to be used for IPC (if any) requested by child process
   ipcRequests_  = module_context::tempFile("rstudio-ipc-requests-", "rds");
   ipcResponse_  = module_context::tempFile("rstudio-ipc-response-", "rds");
   sharedSecret_ = core::system::generateUuid();

   // R binary
   core::FilePath rProgramPath;
   core::Error error = module_context::rScriptPath(&rProgramPath);
   if (error)
   {
      LOG_ERROR(error);
      onCompleted(EXIT_FAILURE);
      return;
   }

   // core R files for augmented async processes
   if (rOptions & R_PROCESS_AUGMENTED)
   {
      // R files we wish to source to provide functionality to async process
      const core::FilePath modulesPath =
            session::options().modulesRSourcePath();

      const core::FilePath rPath =
            session::options().coreRSourcePath();

      const core::FilePath rTools = rPath.childPath("Tools.R");

      // insert at begin as Tools.R needs to be sourced first
      rSourceFiles.insert(rSourceFiles.begin(), rTools);
   }

   // args
   std::vector<std::string> args;
   args.push_back("--slave");
   if (rOptions & R_PROCESS_VANILLA)
      args.push_back("--vanilla");
   if (rOptions & R_PROCESS_NO_RDATA)
   {
      args.push_back("--no-save");
      args.push_back("--no-restore");
   }

   // for windows we need to forward setInternet2
#ifdef _WIN32
   if (!r::session::utils::isR3_3() && prefs::userPrefs().useInternet2())
      args.push_back("--internet2");
#endif

   args.push_back("-e");

   bool needsQuote = false;

   // On Windows, we turn the vector of strings into a single
   // string to send over the command line, so we must ensure
   // that the arguments following '-e' are quoted, so that
   // they are all interpretted as a single argument (rather
   // than multiple arguments) to '-e'.

#ifdef _WIN32
   needsQuote = strlen(rCommand) > 0 && rCommand[0] != '"';
#endif

   std::stringstream command;
   if (needsQuote)
      command << "\"";

   std::string escapedCommand = rCommand;

   if (needsQuote)
      boost::algorithm::replace_all(escapedCommand, "\"", "\\\"");

   if (rSourceFiles.size())
   {
      // add in the r source files requested
      for (std::vector<core::FilePath>::const_iterator it = rSourceFiles.begin();
           it != rSourceFiles.end();
           ++it)
      {
         command << "source('" << it->absolutePath() << "');";
      }

      command << escapedCommand;
   }
   else
   {
      command << escapedCommand;
   }

   if (needsQuote)
      command << "\"";

   args.push_back(command.str());

   // options
   core::system::ProcessOptions options;
   options.terminateChildren = true;
   if (rOptions & R_PROCESS_REDIRECTSTDERR)
      options.redirectStdErrToStdOut = true;

   // if a working directory was specified, use it
   if (!workingDir.empty())
   {
      options.workingDir = workingDir;
   }

   // forward R_LIBS so the child process has access to the same libraries
   // we do
   core::system::Options childEnv;
   core::system::environment(&childEnv);
   std::string libPaths = module_context::libPathsString();
   if (!libPaths.empty())
   {
      core::system::setenv(&childEnv, "R_LIBS", libPaths);
   }

   // forward passed environment variables
   for (const core::system::Option& var : environment)
   {
      core::system::setenv(&childEnv, var.first, var.second);
   }

   // set environment variables used for IPC
   core::system::setenv(&childEnv, "RSTUDIOAPI_IPC_REQUESTS_FILE", ipcRequests_.absolutePath());
   core::system::setenv(&childEnv, "RSTUDIOAPI_IPC_RESPONSE_FILE", ipcResponse_.absolutePath());
   core::system::setenv(&childEnv, "RSTUDIOAPI_IPC_SHARED_SECRET", sharedSecret_);

   // update environment used for child process
   options.environment = childEnv;

   core::system::ProcessCallbacks cb;
   using namespace module_context;
   cb.onContinue = boost::bind(&AsyncRProcess::onContinue,
                               AsyncRProcess::shared_from_this());
   cb.onStdout = boost::bind(&AsyncRProcess::onStdout,
                             AsyncRProcess::shared_from_this(),
                             _2);
   cb.onStderr = boost::bind(&AsyncRProcess::onStderr,
                             AsyncRProcess::shared_from_this(),
                             _2);
   cb.onExit =  boost::bind(&AsyncRProcess::onProcessCompleted,
                             AsyncRProcess::shared_from_this(),
                             _1);
   cb.onStarted = boost::bind(&AsyncRProcess::onStarted,
                              AsyncRProcess::shared_from_this(),
                              _1);

   // forward input if requested
   input_ = input;

   error = module_context::processSupervisor().runProgram(
            rProgramPath.absolutePath(),
            args,
            options,
            cb);
   if (error)
   {
      LOG_ERROR(error);
      onCompleted(EXIT_FAILURE);
   }
   else
   {
      isRunning_ = true;
   }
}

void AsyncRProcess::onStarted(core::system::ProcessOperations& operations)
{
   if (!input_.empty())
   {
      core::Error error = operations.writeToStdin(input_, true);
      if (error)
      {
         LOG_ERROR(error);
         error = operations.terminate();
         if (error)
            LOG_ERROR(error);
      }
   }
}

void AsyncRProcess::onStdout(const std::string& output)
{
   // no-op stub for optional implementation by derived classees
}

void AsyncRProcess::onStderr(const std::string& output)
{
   // no-op stub for optional implementation by derived classees
}

bool AsyncRProcess::onContinue()
{
   if (terminationRequested_)
      return false;

   // check for request requiring a response
   if (ipcRequests_.exists())
   {
      core::Error error = r::exec::RFunction(".rs.rstudioapi.processRequest")
            .addParam(ipcRequests_.absolutePathNative())
            .addParam(ipcResponse_.absolutePathNative())
            .addParam(sharedSecret_)
            .call();

      if (error)
      {
         LOG_ERROR(error);
         return false;
      }
   }

   return true;
}

bool AsyncRProcess::terminationRequested()
{
   return terminationRequested_;
}

void AsyncRProcess::onProcessCompleted(int exitStatus)
{
   markCompleted();
   onCompleted(exitStatus);
}

bool AsyncRProcess::isRunning()
{
   return isRunning_;
}

void AsyncRProcess::terminate()
{
   terminationRequested_ = true;
}

void AsyncRProcess::markCompleted()
{
   isRunning_ = false;
}

AsyncRProcess::~AsyncRProcess()
{
}

} // namespace async_r
} // namespace session
} // namespace rstudio

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

#include <session/prefs/UserPrefs.hpp>
#include <session/SessionConsoleProcess.hpp>
#include <session/SessionModuleContext.hpp>

#include <core/system/Environment.hpp>
#include <core/system/Process.hpp>

#include <r/RExec.hpp>

#include <r/session/RSessionUtils.hpp>

#include <session/SessionAsyncRProcess.hpp>

namespace rstudio {
namespace session {
namespace async_r {

AsyncRProcess::AsyncRProcess():
   isRunning_(false),
   terminationRequested_(false)
{
}

void AsyncRProcess::start(const char* rCommand,
                          core::system::Options environment,
                          const core::FilePath& workingDir,
                          AsyncRProcessOptions rOptions,
                          std::vector<core::FilePath> rSourceFiles,
                          const std::string& input)
{
   // file paths to be used for IPC (if any) requested by child process
   ipcRequests_  = module_context::tempFile("rstudio-ipc-requests-", "rds");
   ipcResponse_  = module_context::tempFile("rstudio-ipc-response-", "rds");
   sharedSecret_ = core::system::generateUuid();

   // R binary
   core::FilePath rProgramPath;
   core::Error error = module_context::rScriptPath(&rProgramPath);
   if (error)
   {
      LOG_ERROR(error);
      onCompleted(EXIT_FAILURE);
      return;
   }

   // core R files for augmented async processes
   if (rOptions & R_PROCESS_AUGMENTED)
   {
      // R files we wish to source to provide functionality to async process
      const core::FilePath modulesPath =
            session::options().modulesRSourcePath();

      const core::FilePath rPath =
            session::options().coreRSourcePath();

      const core::FilePath rTools = rPath.childPath("Tools.R");

      // insert at begin as Tools.R needs to be sourced first
      rSourceFiles.insert(rSourceFiles.begin(), rTools);
   }

   // args
   std::vector<std::string> args;
   args.push_back("--slave");
   if (rOptions & R_PROCESS_VANILLA)
      args.push_back("--vanilla");
   if (rOptions & R_PROCESS_NO_RDATA)
   {
      args.push_back("--no-save");
      args.push_back("--no-restore");
   }

   // for windows we need to forward setInternet2
#ifdef _WIN32
   if (!r::session::utils::isR3_3() && prefs::userPrefs().useInternet2())
      args.push_back("--internet2");
#endif

   args.push_back("-e");

   bool needsQuote = false;

   // On Windows, we turn the vector of strings into a single
   // string to send over the command line, so we must ensure
   // that the arguments following '-e' are quoted, so that
   // they are all interpretted as a single argument (rather
   // than multiple arguments) to '-e'.

#ifdef _WIN32
   needsQuote = strlen(rCommand) > 0 && rCommand[0] != '"';
#endif

   std::stringstream command;
   if (needsQuote)
      command << "\"";

   std::string escapedCommand = rCommand;

   if (needsQuote)
      boost::algorithm::replace_all(escapedCommand, "\"", "\\\"");

   if (rSourceFiles.size())
   {
      // add in the r source files requested
      for (std::vector<core::FilePath>::const_iterator it = rSourceFiles.begin();
           it != rSourceFiles.end();
           ++it)
      {
         command << "source('" << it->absolutePath() << "');";
      }

      command << escapedCommand;
   }
   else
   {
      command << escapedCommand;
   }

   if (needsQuote)
      command << "\"";

   args.push_back(command.str());

   // options
   core::system::ProcessOptions options;
   options.terminateChildren = true;
   if (rOptions & R_PROCESS_REDIRECTSTDERR)
      options.redirectStdErrToStdOut = true;

   // if a working directory was specified, use it
   if (!workingDir.empty())
   {
      options.workingDir = workingDir;
   }

   // forward R_LIBS so the child process has access to the same libraries
   // we do
   core::system::Options childEnv;
   core::system::environment(&childEnv);
   std::string libPaths = module_context::libPathsString();
   if (!libPaths.empty())
   {
      core::system::setenv(&childEnv, "R_LIBS", libPaths);
   }

   // forward passed environment variables
   for (const core::system::Option& var : environment)
   {
      core::system::setenv(&childEnv, var.first, var.second);
   }

   // set environment variables used for IPC
   core::system::setenv(&childEnv, "RSTUDIOAPI_IPC_REQUESTS_FILE", ipcRequests_.absolutePath());
   core::system::setenv(&childEnv, "RSTUDIOAPI_IPC_RESPONSE_FILE", ipcResponse_.absolutePath());
   core::system::setenv(&childEnv, "RSTUDIOAPI_IPC_SHARED_SECRET", sharedSecret_);

   // update environment used for child process
   options.environment = childEnv;

   core::system::ProcessCallbacks cb;
   using namespace module_context;
   cb.onContinue = boost::bind(&AsyncRProcess::onContinue,
                               AsyncRProcess::shared_from_this());
   cb.onStdout = boost::bind(&AsyncRProcess::onStdout,
                             AsyncRProcess::shared_from_this(),
                             _2);
   cb.onStderr = boost::bind(&AsyncRProcess::onStderr,
                             AsyncRProcess::shared_from_this(),
                             _2);
   cb.onExit =  boost::bind(&AsyncRProcess::onProcessCompleted,
                             AsyncRProcess::shared_from_this(),
                             _1);
   cb.onStarted = boost::bind(&AsyncRProcess::onStarted,
                              AsyncRProcess::shared_from_this(),
                              _1);

   // forward input if requested
   input_ = input;

   error = module_context::processSupervisor().runProgram(
            rProgramPath.absolutePath(),
            args,
            options,
            cb);
   if (error)
   {
      LOG_ERROR(error);
      onCompleted(EXIT_FAILURE);
   }
   else
   {
      isRunning_ = true;
   }
}

void AsyncRProcess::onStarted(core::system::ProcessOperations& operations)
{
   if (!input_.empty())
   {
      core::Error error = operations.writeToStdin(input_, true);
      if (error)
      {
         LOG_ERROR(error);
         error = operations.terminate();
         if (error)
            LOG_ERROR(error);
      }
   }
}

void AsyncRProcess::onStdout(const std::string& output)
{
   // no-op stub for optional implementation by derived classees
}

void AsyncRProcess::onStderr(const std::string& output)
{
   // no-op stub for optional implementation by derived classees
}

bool AsyncRProcess::onContinue()
{
   if (terminationRequested_)
      return false;

   // check for request requiring a response
   if (ipcRequests_.exists())
   {
      core::Error error = r::exec::RFunction(".rs.rstudioapi.processRequest")
            .addParam(ipcRequests_.absolutePathNative())
            .addParam(ipcResponse_.absolutePathNative())
            .addParam(sharedSecret_)
            .call();

      if (error)
      {
         LOG_ERROR(error);
         return false;
      }
   }

   return true;
}

bool AsyncRProcess::terminationRequested()
{
   return terminationRequested_;
}

void AsyncRProcess::onProcessCompleted(int exitStatus)
{
   markCompleted();
   ipcRequests_.removeIfExists();
   ipcResponse_.removeIfExists();
   onCompleted(exitStatus);
}

bool AsyncRProcess::isRunning()
{
   return isRunning_;
}

void AsyncRProcess::terminate()
{
   terminationRequested_ = true;
}

void AsyncRProcess::markCompleted()
{
   isRunning_ = false;
}

AsyncRProcess::~AsyncRProcess()
{
}

} // namespace async_r
} // namespace session
} // namespace rstudio

<|endoftext|>


<commit_before>/*
 * SessionRPubs.cpp
 *
 * Copyright (C) 2009-12 by RStudio, Inc.
 *
 * This program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

// TODO: why is the id and continue url printed to the server err console?

// TODO: test curl error reporting on osx
// TODO: test chrome popup blocking
// TODO: test on desktop
// TODO: test all error state (correct dialog & window dismissal)

// TODO: wininet ssl
// TODO: sync function over to markup package

#include "SessionRPubs.hpp"

#include <boost/bind.hpp>
#include <boost/utility.hpp>
#include <boost/format.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>

#include <core/Error.hpp>
#include <core/Exec.hpp>
#include <core/Log.hpp>
#include <core/Settings.hpp>

#include <core/text/CsvParser.hpp>
#include <core/http/Util.hpp>
#include <core/system/Process.hpp>

#include <session/SessionModuleContext.hpp>

#include <session/projects/SessionProjects.hpp>

using namespace core ;

namespace session {
namespace modules {
namespace rpubs {

namespace {

// we get a fresh settings object for each read or write so multiple
// processes can all read and write without cache issues
void getUploadIdSettings(Settings* pSettings)
{
   FilePath rpubsUploadIds =
         module_context::scopedScratchPath().complete("rpubs_upload_ids");
   Error error = pSettings->initialize(rpubsUploadIds);
   if (error)
      LOG_ERROR(error);
}

std::string pathIdentifier(const FilePath& filePath)
{
   // use a relative path if we are in a project
   std::string path;
   projects::ProjectContext& projectContext = projects::projectContext();
   if (projectContext.hasProject() &&
       filePath.isWithin(projectContext.directory()))
   {
      path = filePath.relativePath(projectContext.directory());
   }
   else
   {
      path = filePath.absolutePath();
   }

   // urlencode so we can use it as a key
   return http::util::urlEncode(path);
}

std::string previousUploadId(const FilePath& filePath)
{
   Settings settings;
   getUploadIdSettings(&settings);
   return settings.get(pathIdentifier(filePath));
}

void saveUploadId(const FilePath& filePath, const std::string& uploadId)
{
   Settings settings;
   getUploadIdSettings(&settings);
   settings.set(pathIdentifier(filePath), uploadId);
}

class RPubsUpload : boost::noncopyable,
                    public boost::enable_shared_from_this<RPubsUpload>
{
public:
   static boost::shared_ptr<RPubsUpload> create(const std::string& title,
                                                const FilePath& htmlFile)
   {
      boost::shared_ptr<RPubsUpload> pUpload(new RPubsUpload());
      pUpload->start(title, htmlFile);
      return pUpload;
   }

   virtual ~RPubsUpload()
   {
   }

   bool isRunning() const { return isRunning_; }

   void terminate()
   {
      terminationRequested_ = true;
   }

private:
   RPubsUpload()
      : terminationRequested_(false), isRunning_(false)
   {
   }

   void start(const std::string& title, const FilePath& htmlFile)
   {
      using namespace core::string_utils;
      using namespace module_context;

      htmlFile_ = htmlFile;
      isRunning_ = true;

      // see if we already know of an upload id for this file
      std::string id = previousUploadId(htmlFile_);

      // R binary
      FilePath rProgramPath;
      Error error = rScriptPath(&rProgramPath);
      if (error)
      {
         terminateWithError(error);
         return;
      }

      // args
      std::vector<std::string> args;
      args.push_back("--slave");
      args.push_back("--vanilla");
      args.push_back("-e");

      boost::format fmt(
               "source(\"%1%\"); "
               "result <- rpubsUpload(\"%2%\", \"%3%\", %4%); "
               "utils::write.csv(as.data.frame(result), row.names=FALSE);");

      FilePath modulesPath = session::options().modulesRSourcePath();;
      std::string scriptPath = utf8ToSystem(
                        modulesPath.complete("SessionRPubs.R").absolutePath());
      std::string htmlPath = utf8ToSystem(htmlFile.absolutePath());

      std::string escapedScriptPath = string_utils::jsLiteralEscape(scriptPath);
      std::string escapedTitle = string_utils::jsLiteralEscape(title);
      std::string escapedHtmlPath = string_utils::jsLiteralEscape(htmlPath);
      std::string escapedId = string_utils::jsLiteralEscape(id);

      std::string cmd = boost::str(fmt %
                    escapedScriptPath % escapedTitle % escapedHtmlPath %
                    (!escapedId.empty() ? "\"" + escapedId + "\"" : "NULL"));
      args.push_back(cmd);

      // options
      core::system::ProcessOptions options;
      options.terminateChildren = true;
      options.workingDir = htmlFile.parent();

      // callbacks
      core::system::ProcessCallbacks cb;
      cb.onContinue = boost::bind(&RPubsUpload::onContinue,
                                  RPubsUpload::shared_from_this());
      cb.onStdout = boost::bind(&RPubsUpload::onStdOut,
                                RPubsUpload::shared_from_this(), _2);
      cb.onStderr = boost::bind(&RPubsUpload::onStdErr,
                                RPubsUpload::shared_from_this(), _2);
      cb.onExit =  boost::bind(&RPubsUpload::onCompleted,
                                RPubsUpload::shared_from_this(), _1);

      // execute
      processSupervisor().runProgram(rProgramPath.absolutePath(),
                                     args,
                                     options,
                                     cb);
   }

   bool onContinue()
   {
      return !terminationRequested_;
   }

   void onStdOut(const std::string& output)
   {
      output_.append(output);
   }

   void onStdErr(const std::string& error)
   {
      error_.append(error);
   }

   void onCompleted(int exitStatus)
   {
      if (exitStatus == EXIT_SUCCESS)
      {
         Result result = parseOutput(output_);
         if (!result.empty())
            terminateWithResult(result);
         else
            terminateWithError("Unexpected output from upload: " + output_);
      }
      else
      {
         terminateWithError(error_);
      }
   }

   void terminateWithError(const Error& error)
   {
      terminateWithError(error.summary());
   }

   void terminateWithError(const std::string& error)
   {
      terminateWithResult(Result(error));
   }

   struct Result
   {
      Result()
      {
      }

      Result(const std::string& error)
         : error(error)
      {
      }

      Result(const std::string& id, const std::string& continueUrl)
         : id(id), continueUrl(continueUrl)
      {
      }

      bool empty() const { return id.empty() && error.empty();  }

      std::string id;
      std::string continueUrl;
      std::string error;
   };

   void terminateWithResult(const Result& result)
   {
      isRunning_ = false;

      if (!result.id.empty())
         saveUploadId(htmlFile_, result.id);

      json::Object statusJson;
      statusJson["id"] = result.id;
      statusJson["continueUrl"] = result.continueUrl;
      statusJson["error"] = result.error;
      ClientEvent event(client_events::kRPubsUploadStatus, statusJson);
      module_context::enqueClientEvent(event);
   }

   Result parseOutput(const std::string& output)
   {
      std::pair<std::vector<std::string>, std::string::const_iterator>
                  line = text::parseCsvLine(output.begin(), output.end());
      if (!line.first.empty())
      {
         std::vector<std::string> headers = line.first;

         line = text::parseCsvLine(line.second, output.end());
         if (!line.first.empty())
         {
            std::vector<std::string> data = line.first;

            if (headers.size() == 1 &&
                data.size() == 1 &&
                headers[0] == "error")
            {
               return Result(data[0]);
            }
            else if (headers.size() == 2 &&
                     data.size() == 2 &&
                     headers[0] == "id" &&
                     headers[1] == "continueUrl")
            {
               return Result(data[0], data[1]);
            }
         }
      }

      return Result();
   }

private:
   FilePath htmlFile_;
   bool terminationRequested_;
   bool isRunning_;
   std::string output_;
   std::string error_;
};

boost::shared_ptr<RPubsUpload> s_pCurrentUpload;

bool isUploadRunning()
{
   return s_pCurrentUpload && s_pCurrentUpload->isRunning();
}

Error rpubsUpload(const json::JsonRpcRequest& request,
                  json::JsonRpcResponse* pResponse)
{
   std::string title, htmlFile;
   Error error = json::readParams(request.params, &title, &htmlFile);
   if (error)
      return error;

   if (isUploadRunning())
   {
      pResponse->setResult(false);
   }
   else
   {
      FilePath filePath = module_context::resolveAliasedPath(htmlFile);
      s_pCurrentUpload = RPubsUpload::create(title, filePath);
      pResponse->setResult(true);
   }

   return Success();
}

Error terminateRpubsUpload(const json::JsonRpcRequest& request,
                           json::JsonRpcResponse* pResponse)
{
   if (isUploadRunning())
      s_pCurrentUpload->terminate();

   return Success();
}

} // anonymous namespace

Error initialize()
{
   using boost::bind;
   using namespace module_context;
   ExecBlock initBlock ;
   initBlock.addFunctions()
      (bind(registerRpcMethod, "rpubs_upload", rpubsUpload))
      (bind(registerRpcMethod, "terminate_rpubs_upload", terminateRpubsUpload))
   ;
   return initBlock.execute();
}

} // namespace rpubs
} // namespace modules
} // namesapce session

<commit_msg>update todos<commit_after>/*
 * SessionRPubs.cpp
 *
 * Copyright (C) 2009-12 by RStudio, Inc.
 *
 * This program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

// TODO: test curl error reporting on osx
// TODO: test all error state (correct dialog & window dismissal)

// TODO: sync function over to markup package

#include "SessionRPubs.hpp"

#include <boost/bind.hpp>
#include <boost/utility.hpp>
#include <boost/format.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>

#include <core/Error.hpp>
#include <core/Exec.hpp>
#include <core/Log.hpp>
#include <core/Settings.hpp>

#include <core/text/CsvParser.hpp>
#include <core/http/Util.hpp>
#include <core/system/Process.hpp>

#include <session/SessionModuleContext.hpp>

#include <session/projects/SessionProjects.hpp>

using namespace core ;

namespace session {
namespace modules {
namespace rpubs {

namespace {

// we get a fresh settings object for each read or write so multiple
// processes can all read and write without cache issues
void getUploadIdSettings(Settings* pSettings)
{
   FilePath rpubsUploadIds =
         module_context::scopedScratchPath().complete("rpubs_upload_ids");
   Error error = pSettings->initialize(rpubsUploadIds);
   if (error)
      LOG_ERROR(error);
}

std::string pathIdentifier(const FilePath& filePath)
{
   // use a relative path if we are in a project
   std::string path;
   projects::ProjectContext& projectContext = projects::projectContext();
   if (projectContext.hasProject() &&
       filePath.isWithin(projectContext.directory()))
   {
      path = filePath.relativePath(projectContext.directory());
   }
   else
   {
      path = filePath.absolutePath();
   }

   // urlencode so we can use it as a key
   return http::util::urlEncode(path);
}

std::string previousUploadId(const FilePath& filePath)
{
   Settings settings;
   getUploadIdSettings(&settings);
   return settings.get(pathIdentifier(filePath));
}

void saveUploadId(const FilePath& filePath, const std::string& uploadId)
{
   Settings settings;
   getUploadIdSettings(&settings);
   settings.set(pathIdentifier(filePath), uploadId);
}

class RPubsUpload : boost::noncopyable,
                    public boost::enable_shared_from_this<RPubsUpload>
{
public:
   static boost::shared_ptr<RPubsUpload> create(const std::string& title,
                                                const FilePath& htmlFile)
   {
      boost::shared_ptr<RPubsUpload> pUpload(new RPubsUpload());
      pUpload->start(title, htmlFile);
      return pUpload;
   }

   virtual ~RPubsUpload()
   {
   }

   bool isRunning() const { return isRunning_; }

   void terminate()
   {
      terminationRequested_ = true;
   }

private:
   RPubsUpload()
      : terminationRequested_(false), isRunning_(false)
   {
   }

   void start(const std::string& title, const FilePath& htmlFile)
   {
      using namespace core::string_utils;
      using namespace module_context;

      htmlFile_ = htmlFile;
      isRunning_ = true;

      // see if we already know of an upload id for this file
      std::string id = previousUploadId(htmlFile_);

      // R binary
      FilePath rProgramPath;
      Error error = rScriptPath(&rProgramPath);
      if (error)
      {
         terminateWithError(error);
         return;
      }

      // args
      std::vector<std::string> args;
      args.push_back("--slave");
      args.push_back("--vanilla");
      args.push_back("-e");

      boost::format fmt(
               "source(\"%1%\"); "
               "result <- rpubsUpload(\"%2%\", \"%3%\", %4%); "
               "utils::write.csv(as.data.frame(result), row.names=FALSE);");

      FilePath modulesPath = session::options().modulesRSourcePath();;
      std::string scriptPath = utf8ToSystem(
                        modulesPath.complete("SessionRPubs.R").absolutePath());
      std::string htmlPath = utf8ToSystem(htmlFile.absolutePath());

      std::string escapedScriptPath = string_utils::jsLiteralEscape(scriptPath);
      std::string escapedTitle = string_utils::jsLiteralEscape(title);
      std::string escapedHtmlPath = string_utils::jsLiteralEscape(htmlPath);
      std::string escapedId = string_utils::jsLiteralEscape(id);

      std::string cmd = boost::str(fmt %
                    escapedScriptPath % escapedTitle % escapedHtmlPath %
                    (!escapedId.empty() ? "\"" + escapedId + "\"" : "NULL"));
      args.push_back(cmd);

      // options
      core::system::ProcessOptions options;
      options.terminateChildren = true;
      options.workingDir = htmlFile.parent();

      // callbacks
      core::system::ProcessCallbacks cb;
      cb.onContinue = boost::bind(&RPubsUpload::onContinue,
                                  RPubsUpload::shared_from_this());
      cb.onStdout = boost::bind(&RPubsUpload::onStdOut,
                                RPubsUpload::shared_from_this(), _2);
      cb.onStderr = boost::bind(&RPubsUpload::onStdErr,
                                RPubsUpload::shared_from_this(), _2);
      cb.onExit =  boost::bind(&RPubsUpload::onCompleted,
                                RPubsUpload::shared_from_this(), _1);

      // execute
      processSupervisor().runProgram(rProgramPath.absolutePath(),
                                     args,
                                     options,
                                     cb);
   }

   bool onContinue()
   {
      return !terminationRequested_;
   }

   void onStdOut(const std::string& output)
   {
      output_.append(output);
   }

   void onStdErr(const std::string& error)
   {
      error_.append(error);
   }

   void onCompleted(int exitStatus)
   {
      if (exitStatus == EXIT_SUCCESS)
      {
         Result result = parseOutput(output_);
         if (!result.empty())
            terminateWithResult(result);
         else
            terminateWithError("Unexpected output from upload: " + output_);
      }
      else
      {
         terminateWithError(error_);
      }
   }

   void terminateWithError(const Error& error)
   {
      terminateWithError(error.summary());
   }

   void terminateWithError(const std::string& error)
   {
      terminateWithResult(Result(error));
   }

   struct Result
   {
      Result()
      {
      }

      Result(const std::string& error)
         : error(error)
      {
      }

      Result(const std::string& id, const std::string& continueUrl)
         : id(id), continueUrl(continueUrl)
      {
      }

      bool empty() const { return id.empty() && error.empty();  }

      std::string id;
      std::string continueUrl;
      std::string error;
   };

   void terminateWithResult(const Result& result)
   {
      isRunning_ = false;

      if (!result.id.empty())
         saveUploadId(htmlFile_, result.id);

      json::Object statusJson;
      statusJson["id"] = result.id;
      statusJson["continueUrl"] = result.continueUrl;
      statusJson["error"] = result.error;
      ClientEvent event(client_events::kRPubsUploadStatus, statusJson);
      module_context::enqueClientEvent(event);
   }

   Result parseOutput(const std::string& output)
   {
      std::pair<std::vector<std::string>, std::string::const_iterator>
                  line = text::parseCsvLine(output.begin(), output.end());
      if (!line.first.empty())
      {
         std::vector<std::string> headers = line.first;

         line = text::parseCsvLine(line.second, output.end());
         if (!line.first.empty())
         {
            std::vector<std::string> data = line.first;

            if (headers.size() == 1 &&
                data.size() == 1 &&
                headers[0] == "error")
            {
               return Result(data[0]);
            }
            else if (headers.size() == 2 &&
                     data.size() == 2 &&
                     headers[0] == "id" &&
                     headers[1] == "continueUrl")
            {
               return Result(data[0], data[1]);
            }
         }
      }

      return Result();
   }

private:
   FilePath htmlFile_;
   bool terminationRequested_;
   bool isRunning_;
   std::string output_;
   std::string error_;
};

boost::shared_ptr<RPubsUpload> s_pCurrentUpload;

bool isUploadRunning()
{
   return s_pCurrentUpload && s_pCurrentUpload->isRunning();
}

Error rpubsUpload(const json::JsonRpcRequest& request,
                  json::JsonRpcResponse* pResponse)
{
   std::string title, htmlFile;
   Error error = json::readParams(request.params, &title, &htmlFile);
   if (error)
      return error;

   if (isUploadRunning())
   {
      pResponse->setResult(false);
   }
   else
   {
      FilePath filePath = module_context::resolveAliasedPath(htmlFile);
      s_pCurrentUpload = RPubsUpload::create(title, filePath);
      pResponse->setResult(true);
   }

   return Success();
}

Error terminateRpubsUpload(const json::JsonRpcRequest& request,
                           json::JsonRpcResponse* pResponse)
{
   if (isUploadRunning())
      s_pCurrentUpload->terminate();

   return Success();
}

} // anonymous namespace

Error initialize()
{
   using boost::bind;
   using namespace module_context;
   ExecBlock initBlock ;
   initBlock.addFunctions()
      (bind(registerRpcMethod, "rpubs_upload", rpubsUpload))
      (bind(registerRpcMethod, "terminate_rpubs_upload", terminateRpubsUpload))
   ;
   return initBlock.execute();
}

} // namespace rpubs
} // namespace modules
} // namesapce session

<|endoftext|>


<commit_before>#include "estimator/dcm_attitude_estimator.hpp"

#include "hal.h"
#include "protocol/messages.hpp"

#include "unit_config.hpp"

DCMAttitudeEstimator::DCMAttitudeEstimator(Communicator& communicator)
  : dcm(Eigen::Matrix3f::Identity()),
    attitudeMessageStream(communicator, 100) {
}

attitude_estimate_t DCMAttitudeEstimator::update(gyroscope_reading_t& gyroReading, accelerometer_reading_t& accelReading) {
  Eigen::Vector3f gyro(gyroReading.axes.data());
  Eigen::Vector3f accel(accelReading.axes.data());

  float accWeight = 0.02f;
  palClearPad(GPIOE, GPIOE_LED4_BLUE);
  if(accel.norm() > 1.05 * 9.8 || accel.norm() < 0.95 * 9.8) {
    palSetPad(GPIOE, GPIOE_LED4_BLUE);
    accWeight = 0.0f;
  }

  accel.normalize();

  Eigen::Vector3f corr = Eigen::Vector3f::Zero();
  corr += gyro * unit_config::DT * (1.0f - accWeight);
  corr += dcm.col(2).cross(accel) * accWeight;

  Eigen::Matrix3f dcmStep;
  dcmStep <<      1.0f,  corr.z(), -corr.y(),
             -corr.z(),      1.0f,  corr.x(),
              corr.y(), -corr.x(),      1.0f;

  dcm *= dcmStep;

  orthonormalize();

  attitude_estimate_t estimate {
    // TODO: Are these trig functions safe at extreme angles?
    .roll = -atan2f(dcm(2, 1), dcm(2, 2)) * dcm(0, 0) + atan2f(dcm(2, 0), dcm(2, 2)) * dcm(0, 1),
    .pitch = atan2f(dcm(2, 0), dcm(2, 2)) * dcm(1, 1) - atan2f(dcm(2, 1), dcm(2, 2)) * dcm(1, 0),
    .yaw = 0.0f, // atan2f(dcm(1, 1), dcm(0, 1)),
    .roll_vel = gyro.x(),
    .pitch_vel = gyro.y(),
    .yaw_vel = gyro.z()
  };

  if(attitudeMessageStream.ready()) {
    protocol::message::attitude_message_t m {
      .dcm = {
        // estimate.roll, estimate.pitch, estimate.yaw,
        // accel(0), accel(1), accel(2),
        // gyro(0), gyro(1), gyro(2),
        dcm(0, 0), dcm(0, 1), dcm(0, 2),
        dcm(1, 0), dcm(1, 1), dcm(1, 2),
        dcm(2, 0), dcm(2, 1), dcm(2, 2)
      }
    };

    attitudeMessageStream.publish(m);
  }

  return estimate;
}

void DCMAttitudeEstimator::orthonormalize() {
  // Make the i and j vectors orthogonal
  float error = dcm.row(0).dot(dcm.row(1));

  Eigen::Matrix3f corr = Eigen::Matrix3f::Zero();
  corr.row(0) = dcm.row(1) * (-error) / 2;
  corr.row(1) = dcm.row(0) * (-error) / 2;

  dcm.row(0) += corr.row(0);
  dcm.row(1) += corr.row(1);

  // Estimate k vector from corrected i and j vectors
  dcm.row(2) = dcm.row(0).cross(dcm.row(1));

  // Normalize all vectors
  dcm.rowwise().normalize();
}
<commit_msg>Final DCM fixes.<commit_after>#include "estimator/dcm_attitude_estimator.hpp"

#include "hal.h"
#include "protocol/messages.hpp"

#include "unit_config.hpp"

DCMAttitudeEstimator::DCMAttitudeEstimator(Communicator& communicator)
  : dcm(Eigen::Matrix3f::Identity()),
    attitudeMessageStream(communicator, 100) {
}

attitude_estimate_t DCMAttitudeEstimator::update(gyroscope_reading_t& gyroReading, accelerometer_reading_t& accelReading) {
  Eigen::Vector3f gyro(gyroReading.axes.data());
  Eigen::Vector3f accel(accelReading.axes.data());

  float accWeight = 0.02f;
  palClearPad(GPIOE, GPIOE_LED4_BLUE);
  if(accel.norm() > 1.05 * 9.8 || accel.norm() < 0.95 * 9.8) {
    palSetPad(GPIOE, GPIOE_LED4_BLUE);
    accWeight = 0.0f;
  }

  accel.normalize();

  Eigen::Vector3f corr = Eigen::Vector3f::Zero();
  corr += gyro * unit_config::DT * (1.0f - accWeight);
  corr -= dcm.col(2).cross(-accel) * accWeight;

  Eigen::Matrix3f dcmStep;
  dcmStep <<      1.0f,  corr.z(), -corr.y(),
             -corr.z(),      1.0f,  corr.x(),
              corr.y(), -corr.x(),      1.0f;

  dcm = dcmStep * dcm;

  orthonormalize();

  attitude_estimate_t estimate {
    // TODO: Are these trig functions safe at extreme angles?
    .roll = -atan2f(dcm(2, 1), dcm(2, 2)) * dcm(0, 0) + atan2f(dcm(2, 0), dcm(2, 2)) * dcm(0, 1),
    .pitch = atan2f(dcm(2, 0), dcm(2, 2)) * dcm(1, 1) - atan2f(dcm(2, 1), dcm(2, 2)) * dcm(1, 0),
    .yaw = 0.0f, // atan2f(dcm(1, 1), dcm(0, 1)),
    .roll_vel = gyro.x(),
    .pitch_vel = gyro.y(),
    .yaw_vel = gyro.z()
  };

  if(attitudeMessageStream.ready()) {
    protocol::message::attitude_message_t m {
      .dcm = {
        // estimate.roll, estimate.pitch, estimate.yaw,
        // accel(0), accel(1), accel(2),
        // gyro(0), gyro(1), gyro(2),
        dcm(0, 0), dcm(0, 1), dcm(0, 2),
        dcm(1, 0), dcm(1, 1), dcm(1, 2),
        dcm(2, 0), dcm(2, 1), dcm(2, 2)
      }
    };

    attitudeMessageStream.publish(m);
  }

  return estimate;
}

void DCMAttitudeEstimator::orthonormalize() {
  // Make the i and j vectors orthogonal
  float error = dcm.row(0).dot(dcm.row(1));

  Eigen::Matrix3f corr = Eigen::Matrix3f::Zero();
  corr.row(0) = dcm.row(1) * (-error) / 2;
  corr.row(1) = dcm.row(0) * (-error) / 2;

  dcm.row(0) += corr.row(0);
  dcm.row(1) += corr.row(1);

  // Estimate k vector from corrected i and j vectors
  dcm.row(2) = dcm.row(0).cross(dcm.row(1));

  // Normalize all vectors
  dcm.rowwise().normalize();
}
<|endoftext|>


<commit_before>//
// Copyright 2014 John Manferdelli, All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//     http://www.apache.org/licenses/LICENSE-2.0
// or in the the file LICENSE-2.0.txt in the top level sourcedirectory
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License
// Project: New Cloudproxy Crypto
// File: support_test.cc

#include "gtest/gtest.h"

#include <gtest/gtest.h>
#include <gflags/gflags.h>
#include <stdio.h>
#include <string>

#include "helpers.h"

bool readwritetest() {
  return true;
}

TEST(ReadWriteTest, ReadWriteTest) { EXPECT_TRUE(readwritetest()); }
<commit_msg>test file<commit_after>//
// Copyright 2014 John Manferdelli, All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//     http://www.apache.org/licenses/LICENSE-2.0
// or in the the file LICENSE-2.0.txt in the top level sourcedirectory
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License
// Project: New Cloudproxy Crypto
// File: support_test.cc

#include "gtest/gtest.h"

#include <gtest/gtest.h>
#include <gflags/gflags.h>
#include <stdio.h>
#include <string>

#include "helpers.h"

bool readwritetest() {
  string filename("/tmp/test1");
  string in("12345");
  string out;

  if (!WriteFile(filename, in)) {
    return false
  }
  if (!ReadFile(filename, &out)) {
    return false
  }
  if (out != in) {
    return false
  }
  return true;
}

TEST(ReadWriteTest, ReadWriteTest) { EXPECT_TRUE(readwritetest()); }
<|endoftext|>