<commit_before>#include "common.h"
#include <stdarg.h>

// android
#if defined(ANDROID)
#include <android/log.h>
#endif

// win32
#if defined(_WIN32) && defined(_WINDOWS)
#include <windows.h>
#endif

namespace Common {

namespace {

std::string __format(const char *fmt, va_list ap) {
    std::string ret;

    size_t fmtlen = strlen(fmt);
    if (LIKELY(fmtlen < INT_MAX)) {  // Ensure fmtlen is in an int
        int len = static_cast<int>(fmtlen) + 1;

        // For each %, reserve 64 characters
        for (const char *p = strchr(fmt, '%'); p != nullptr; p = strchr(p, '%')) {
            char ch = *++p;
            if (ch != '%' && ch != '\0') len += 64;  // skip %%
        }

        do {
            ret.resize(len);
            va_list temp;
            va_copy(temp, ap);
            int size = vsnprintf(&ret[0], len, fmt, temp);
            va_end(temp);
            if (LIKELY(size >= 0)) {
                if (LIKELY(size < len)) {  // Everything worked
                    ret.resize(size);
                    ret.shrink_to_fit();
                    break;
                }
                len = size + 1;  // Needed size returned
                continue;
            }
            len *= 2;  // Guess at a larger size
        } while (1);
    }

    return ret;
}

}

std::string format(const char *fmt, ...) {
    va_list ap;
    va_start(ap, fmt);
    std::string ret = __format(fmt, ap);
    va_end(ap);
    return std::move(ret);
}

void __log(const char *fmt, ...) {
    va_list ap;
    va_start(ap, fmt);
    std::string ret = __format(fmt, ap);
    va_end(ap);
    ret.append(1, '\n');

#if defined(ANDROID)
    __android_log_print(ANDROID_LOG_DEBUG, "debug info", "%s", ret.c_str());
#elif defined(_WIN32) && defined(_WINDOWS)
    std::wstring wszBuf;
    int len = ::MultiByteToWideChar(CP_UTF8, 0, ret.c_str(), -1, nullptr, 0);
    if (len > 0) {
        wszBuf.resize(len);
        ::MultiByteToWideChar(CP_UTF8, 0, ret.c_str(), -1, &wszBuf[0], len);
        ::OutputDebugStringW(wszBuf.c_str());
    }
#else
    // Linux, Mac, iOS, etc
    fprintf(stdout, "%s", ret.c_str());
    fflush(stdout);
#endif
}

std::string getStringFromFile(const char *file) {
    std::string str;
    FILE *fp = fopen(file, "rb");
    if (LIKELY(fp != nullptr)) {
        fseek(fp, 0, SEEK_END);
        long size = ftell(fp);
        fseek(fp, 0, SEEK_SET);
        try {
            str.resize(size + 1);
            fread(&str[0], sizeof(char), size, fp);
        }
        catch (...) {
        }
        fclose(fp);
    }
    return str;
}

bool compareVersion(const char *remote, const char *local) {
    int major1, minor1, build1, revision1;
    if (sscanf(remote, "%d.%d.%d.%d", &major1, &minor1, &build1, &revision1) != 4) {
        return false;
    }

    int major2, minor2, build2, revision2;
    if (sscanf(local, "%d.%d.%d.%d", &major2, &minor2, &build2, &revision2) != 4) {
        return false;
    }

    if (major1 > major2) {
        return true;
    }
    if (major1 == major2) {
        if (minor1 > minor2) {
            return true;
        }
        if (minor1 == minor2) {
            if (build1 > build2) {
                return true;
            }
            if (build1 == build2) {
                if (revision1 > revision2) {
                    return true;
                }
            }
        }
    }

    return false;
}

}
<commit_msg>新的读文件方法<commit_after>#include "common.h"
#include <stdarg.h>
#include <fstream>

// android
#if defined(ANDROID)
#include <android/log.h>
#endif

// win32
#if defined(_WIN32) && defined(_WINDOWS)
#include <windows.h>
#endif

namespace Common {

namespace {

std::string __format(const char *fmt, va_list ap) {
    std::string ret;

    size_t fmtlen = strlen(fmt);
    if (LIKELY(fmtlen < INT_MAX)) {  // Ensure fmtlen is in an int
        int len = static_cast<int>(fmtlen) + 1;

        // For each %, reserve 64 characters
        for (const char *p = strchr(fmt, '%'); p != nullptr; p = strchr(p, '%')) {
            char ch = *++p;
            if (ch != '%' && ch != '\0') len += 64;  // skip %%
        }

        do {
            ret.resize(len);
            va_list temp;
            va_copy(temp, ap);
            int size = vsnprintf(&ret[0], len, fmt, temp);
            va_end(temp);
            if (LIKELY(size >= 0)) {
                if (LIKELY(size < len)) {  // Everything worked
                    ret.resize(size);
                    ret.shrink_to_fit();
                    break;
                }
                len = size + 1;  // Needed size returned
                continue;
            }
            len *= 2;  // Guess at a larger size
        } while (1);
    }

    return ret;
}

}

std::string format(const char *fmt, ...) {
    va_list ap;
    va_start(ap, fmt);
    std::string ret = __format(fmt, ap);
    va_end(ap);
    return std::move(ret);
}

void __log(const char *fmt, ...) {
    va_list ap;
    va_start(ap, fmt);
    std::string ret = __format(fmt, ap);
    va_end(ap);
    ret.append(1, '\n');

#if defined(ANDROID)
    __android_log_print(ANDROID_LOG_DEBUG, "debug info", "%s", ret.c_str());
#elif defined(_WIN32) && defined(_WINDOWS)
    std::wstring wszBuf;
    int len = ::MultiByteToWideChar(CP_UTF8, 0, ret.c_str(), -1, nullptr, 0);
    if (len > 0) {
        wszBuf.resize(len);
        ::MultiByteToWideChar(CP_UTF8, 0, ret.c_str(), -1, &wszBuf[0], len);
        ::OutputDebugStringW(wszBuf.c_str());
    }
#else
    // Linux, Mac, iOS, etc
    fprintf(stdout, "%s", ret.c_str());
    fflush(stdout);
#endif
}

std::string getStringFromFile(const char *file) {
    std::ifstream is(file, std::ios::binary);
    if (is.good()) {
        return std::string({ std::istreambuf_iterator<char>(is), std::istreambuf_iterator<char>() });
    }
    return "";
}

bool compareVersion(const char *remote, const char *local) {
    int major1, minor1, build1, revision1;
    if (sscanf(remote, "%d.%d.%d.%d", &major1, &minor1, &build1, &revision1) != 4) {
        return false;
    }

    int major2, minor2, build2, revision2;
    if (sscanf(local, "%d.%d.%d.%d", &major2, &minor2, &build2, &revision2) != 4) {
        return false;
    }

    if (major1 > major2) {
        return true;
    }
    if (major1 == major2) {
        if (minor1 > minor2) {
            return true;
        }
        if (minor1 == minor2) {
            if (build1 > build2) {
                return true;
            }
            if (build1 == build2) {
                if (revision1 > revision2) {
                    return true;
                }
            }
        }
    }

    return false;
}

}
<|endoftext|>


<commit_before>//===--- CodeGenTypes.cpp - Type translation for LLVM CodeGen -------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by Chris Lattner and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This is the code that handles AST -> LLVM type lowering.
//
//===----------------------------------------------------------------------===//

#include "CodeGenTypes.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/AST/AST.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"

using namespace clang;
using namespace CodeGen;

CodeGenTypes::CodeGenTypes(ASTContext &Ctx, llvm::Module& M)
  : Context(Ctx), Target(Ctx.Target), TheModule(M) {
}

/// ConvertType - Convert the specified type to its LLVM form.
const llvm::Type *CodeGenTypes::ConvertType(QualType T) {
  // FIXME: Cache these, move the CodeGenModule, expand, etc.
  const clang::Type &Ty = *T.getCanonicalType();

  switch (Ty.getTypeClass()) {
  case Type::TypeName:        // typedef isn't canonical.
  case Type::TypeOfExp:       // typeof isn't canonical.
  case Type::TypeOfTyp:       // typeof isn't canonical.
    assert(0 && "Non-canonical type, shouldn't happen");
  case Type::Builtin: {
    switch (cast<BuiltinType>(Ty).getKind()) {
    case BuiltinType::Void:
      // LLVM void type can only be used as the result of a function call.  Just
      // map to the same as char.
      return llvm::IntegerType::get(8);

    case BuiltinType::Bool:
      // FIXME: This is very strange.  We want scalars to be i1, but in memory
      // they can be i1 or i32.  Should the codegen handle this issue?
      return llvm::Type::Int1Ty;

    case BuiltinType::Char_S:
    case BuiltinType::Char_U:
    case BuiltinType::SChar:
    case BuiltinType::UChar:
    case BuiltinType::Short:
    case BuiltinType::UShort:
    case BuiltinType::Int:
    case BuiltinType::UInt:
    case BuiltinType::Long:
    case BuiltinType::ULong:
    case BuiltinType::LongLong:
    case BuiltinType::ULongLong:
      return llvm::IntegerType::get(Context.getTypeSize(T, SourceLocation()));

    case BuiltinType::Float:      return llvm::Type::FloatTy;
    case BuiltinType::Double:     return llvm::Type::DoubleTy;
    case BuiltinType::LongDouble:
      // FIXME: mapping long double onto double.
      return llvm::Type::DoubleTy;
    }
    break;
  }
  case Type::Complex: {
    std::vector<const llvm::Type*> Elts;
    Elts.push_back(ConvertType(cast<ComplexType>(Ty).getElementType()));
    Elts.push_back(Elts[0]);
    return llvm::StructType::get(Elts);
  }
  case Type::Pointer: {
    const PointerType &P = cast<PointerType>(Ty);
    return llvm::PointerType::get(ConvertType(P.getPointeeType()));
  }
  case Type::Reference: {
    const ReferenceType &R = cast<ReferenceType>(Ty);
    return llvm::PointerType::get(ConvertType(R.getReferenceeType()));
  }

  case Type::Array: {
    const ArrayType &A = cast<ArrayType>(Ty);
    assert(A.getSizeModifier() == ArrayType::Normal &&
           A.getIndexTypeQualifier() == 0 &&
           "FIXME: We only handle trivial array types so far!");

    llvm::APSInt Size(32);
    if (A.getSizeExpr() &&
        A.getSizeExpr()->isIntegerConstantExpr(Size, Context)) {
      const llvm::Type *EltTy = ConvertType(A.getElementType());
      return llvm::ArrayType::get(EltTy, Size.getZExtValue());
    } else {
      assert(0 && "FIXME: VLAs not implemented yet!");
    }
  }
  case Type::OCUVector:
  case Type::Vector: {
    const VectorType &VT = cast<VectorType>(Ty);
    return llvm::VectorType::get(ConvertType(VT.getElementType()),
                                 VT.getNumElements());
  }
  case Type::FunctionNoProto:
  case Type::FunctionProto: {
    const FunctionType &FP = cast<FunctionType>(Ty);
    const llvm::Type *ResultType;

    if (FP.getResultType()->isVoidType())
      ResultType = llvm::Type::VoidTy;    // Result of function uses llvm void.
    else
      ResultType = ConvertType(FP.getResultType());

    // FIXME: Convert argument types.
    bool isVarArg;
    std::vector<const llvm::Type*> ArgTys;

    // Struct return passes the struct byref.
    if (!ResultType->isFirstClassType() && ResultType != llvm::Type::VoidTy) {
      ArgTys.push_back(llvm::PointerType::get(ResultType));
      ResultType = llvm::Type::VoidTy;
    }

    if (const FunctionTypeProto *FTP = dyn_cast<FunctionTypeProto>(&FP)) {
      DecodeArgumentTypes(*FTP, ArgTys);
      isVarArg = FTP->isVariadic();
    } else {
      isVarArg = true;
    }

    return llvm::FunctionType::get(ResultType, ArgTys, isVarArg, 0);
  }
  case Type::Tagged:
    const TagType &TT = cast<TagType>(Ty);
    const TagDecl *TD = TT.getDecl();
    llvm::Type *&ResultType = TagDeclTypes[TD];

    if (ResultType)
      return ResultType;

    if (!TD->isDefinition()) {
      ResultType = llvm::OpaqueType::get();
    } else {
      if (TD->getKind() == Decl::Struct) {
        const RecordDecl *RD = cast<const RecordDecl>(TD);
        std::vector<const llvm::Type*> Fields;
        for (unsigned i = 0, e = RD->getNumMembers(); i != e; ++i)
          Fields.push_back(ConvertType(RD->getMember(i)->getType()));
        ResultType = llvm::StructType::get(Fields);
      } else
        assert(0 && "FIXME: Implement tag decl kind!");
    }

    std::string TypeName(TD->getKindName());
    TypeName += '.';
    TypeName += TD->getName();

    TheModule.addTypeName(TypeName, ResultType);
    return ResultType;
  }

  // FIXME: implement.
  return llvm::OpaqueType::get();
}

void CodeGenTypes::DecodeArgumentTypes(const FunctionTypeProto &FTP,
                                       std::vector<const llvm::Type*> &ArgTys) {
  for (unsigned i = 0, e = FTP.getNumArgs(); i != e; ++i) {
    const llvm::Type *Ty = ConvertType(FTP.getArgType(i));
    if (Ty->isFirstClassType())
      ArgTys.push_back(Ty);
    else
      ArgTys.push_back(llvm::PointerType::get(Ty));
  }
}

<commit_msg>implement rudimentary union layout support.<commit_after>//===--- CodeGenTypes.cpp - Type translation for LLVM CodeGen -------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by Chris Lattner and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This is the code that handles AST -> LLVM type lowering.
//
//===----------------------------------------------------------------------===//

#include "CodeGenTypes.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/AST/AST.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"

using namespace clang;
using namespace CodeGen;

CodeGenTypes::CodeGenTypes(ASTContext &Ctx, llvm::Module& M)
  : Context(Ctx), Target(Ctx.Target), TheModule(M) {
}

/// ConvertType - Convert the specified type to its LLVM form.
const llvm::Type *CodeGenTypes::ConvertType(QualType T) {
  // FIXME: Cache these, move the CodeGenModule, expand, etc.
  const clang::Type &Ty = *T.getCanonicalType();

  switch (Ty.getTypeClass()) {
  case Type::TypeName:        // typedef isn't canonical.
  case Type::TypeOfExp:       // typeof isn't canonical.
  case Type::TypeOfTyp:       // typeof isn't canonical.
    assert(0 && "Non-canonical type, shouldn't happen");
  case Type::Builtin: {
    switch (cast<BuiltinType>(Ty).getKind()) {
    case BuiltinType::Void:
      // LLVM void type can only be used as the result of a function call.  Just
      // map to the same as char.
      return llvm::IntegerType::get(8);

    case BuiltinType::Bool:
      // FIXME: This is very strange.  We want scalars to be i1, but in memory
      // they can be i1 or i32.  Should the codegen handle this issue?
      return llvm::Type::Int1Ty;

    case BuiltinType::Char_S:
    case BuiltinType::Char_U:
    case BuiltinType::SChar:
    case BuiltinType::UChar:
    case BuiltinType::Short:
    case BuiltinType::UShort:
    case BuiltinType::Int:
    case BuiltinType::UInt:
    case BuiltinType::Long:
    case BuiltinType::ULong:
    case BuiltinType::LongLong:
    case BuiltinType::ULongLong:
      return llvm::IntegerType::get(Context.getTypeSize(T, SourceLocation()));

    case BuiltinType::Float:      return llvm::Type::FloatTy;
    case BuiltinType::Double:     return llvm::Type::DoubleTy;
    case BuiltinType::LongDouble:
      // FIXME: mapping long double onto double.
      return llvm::Type::DoubleTy;
    }
    break;
  }
  case Type::Complex: {
    std::vector<const llvm::Type*> Elts;
    Elts.push_back(ConvertType(cast<ComplexType>(Ty).getElementType()));
    Elts.push_back(Elts[0]);
    return llvm::StructType::get(Elts);
  }
  case Type::Pointer: {
    const PointerType &P = cast<PointerType>(Ty);
    return llvm::PointerType::get(ConvertType(P.getPointeeType()));
  }
  case Type::Reference: {
    const ReferenceType &R = cast<ReferenceType>(Ty);
    return llvm::PointerType::get(ConvertType(R.getReferenceeType()));
  }

  case Type::Array: {
    const ArrayType &A = cast<ArrayType>(Ty);
    assert(A.getSizeModifier() == ArrayType::Normal &&
           A.getIndexTypeQualifier() == 0 &&
           "FIXME: We only handle trivial array types so far!");

    llvm::APSInt Size(32);
    if (A.getSizeExpr() &&
        A.getSizeExpr()->isIntegerConstantExpr(Size, Context)) {
      const llvm::Type *EltTy = ConvertType(A.getElementType());
      return llvm::ArrayType::get(EltTy, Size.getZExtValue());
    } else {
      assert(0 && "FIXME: VLAs not implemented yet!");
    }
  }
  case Type::OCUVector:
  case Type::Vector: {
    const VectorType &VT = cast<VectorType>(Ty);
    return llvm::VectorType::get(ConvertType(VT.getElementType()),
                                 VT.getNumElements());
  }
  case Type::FunctionNoProto:
  case Type::FunctionProto: {
    const FunctionType &FP = cast<FunctionType>(Ty);
    const llvm::Type *ResultType;

    if (FP.getResultType()->isVoidType())
      ResultType = llvm::Type::VoidTy;    // Result of function uses llvm void.
    else
      ResultType = ConvertType(FP.getResultType());

    // FIXME: Convert argument types.
    bool isVarArg;
    std::vector<const llvm::Type*> ArgTys;

    // Struct return passes the struct byref.
    if (!ResultType->isFirstClassType() && ResultType != llvm::Type::VoidTy) {
      ArgTys.push_back(llvm::PointerType::get(ResultType));
      ResultType = llvm::Type::VoidTy;
    }

    if (const FunctionTypeProto *FTP = dyn_cast<FunctionTypeProto>(&FP)) {
      DecodeArgumentTypes(*FTP, ArgTys);
      isVarArg = FTP->isVariadic();
    } else {
      isVarArg = true;
    }

    return llvm::FunctionType::get(ResultType, ArgTys, isVarArg, 0);
  }
  case Type::Tagged:
    const TagType &TT = cast<TagType>(Ty);
    const TagDecl *TD = TT.getDecl();
    llvm::Type *&ResultType = TagDeclTypes[TD];

    if (ResultType)
      return ResultType;

    if (!TD->isDefinition()) {
      ResultType = llvm::OpaqueType::get();
    } else if (TD->getKind() == Decl::Struct) {
      const RecordDecl *RD = cast<const RecordDecl>(TD);
      std::vector<const llvm::Type*> Fields;
      for (unsigned i = 0, e = RD->getNumMembers(); i != e; ++i)
        Fields.push_back(ConvertType(RD->getMember(i)->getType()));
      ResultType = llvm::StructType::get(Fields);
    } else if (TD->getKind() == Decl::Union) {
      const RecordDecl *RD = cast<const RecordDecl>(TD);
      // Just use the largest element of the union, breaking ties with the
      // highest aligned member.
      std::vector<const llvm::Type*> Fields;
      if (RD->getNumMembers() != 0) {
        std::pair<uint64_t, unsigned> MaxElt =
          Context.getTypeInfo(RD->getMember(0)->getType(), SourceLocation());
        unsigned MaxEltNo = 0;

        for (unsigned i = 1, e = RD->getNumMembers(); i != e; ++i) {
          std::pair<uint64_t, unsigned> EltInfo =
            Context.getTypeInfo(RD->getMember(i)->getType(), SourceLocation());
          if (EltInfo.first > MaxElt.first ||
              (EltInfo.first == MaxElt.first &&
               EltInfo.second > MaxElt.second)) {
            MaxElt = EltInfo;
            MaxEltNo = i;
          }
        }

        Fields.push_back(ConvertType(RD->getMember(MaxEltNo)->getType()));
      }
      ResultType = llvm::StructType::get(Fields);
    } else {
      assert(0 && "FIXME: Implement tag decl kind!");
    }

    std::string TypeName(TD->getKindName());
    TypeName += '.';
    TypeName += TD->getName();

    TheModule.addTypeName(TypeName, ResultType);
    return ResultType;
  }

  // FIXME: implement.
  return llvm::OpaqueType::get();
}

void CodeGenTypes::DecodeArgumentTypes(const FunctionTypeProto &FTP,
                                       std::vector<const llvm::Type*> &ArgTys) {
  for (unsigned i = 0, e = FTP.getNumArgs(); i != e; ++i) {
    const llvm::Type *Ty = ConvertType(FTP.getArgType(i));
    if (Ty->isFirstClassType())
      ArgTys.push_back(Ty);
    else
      ArgTys.push_back(llvm::PointerType::get(Ty));
  }
}

<|endoftext|>


<commit_before>/*
	This file is part of cpp-ethereum.

	cpp-ethereum is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

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

	You should have received a copy of the GNU General Public License
	along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/**
 * @author Lefteris <lefteris@ethdev.com>
 * @date 2014
 * Solidity command line interface.
 */
#include "CommandLineInterface.h"

#include <string>
#include <iostream>
#include <fstream>

#include <boost/filesystem.hpp>

#include "BuildInfo.h"
#include <libdevcore/Common.h>
#include <libdevcore/CommonData.h>
#include <libdevcore/CommonIO.h>
#include <libevmcore/Instruction.h>
#include <libsolidity/Scanner.h>
#include <libsolidity/Parser.h>
#include <libsolidity/ASTPrinter.h>
#include <libsolidity/NameAndTypeResolver.h>
#include <libsolidity/Exceptions.h>
#include <libsolidity/CompilerStack.h>
#include <libsolidity/SourceReferenceFormatter.h>

using namespace std;
namespace po = boost::program_options;

// LTODO: Maybe some argument class pairing names with
// extensions and other attributes would be a better choice here?
#define ARG_ABI_STR            "abi"
#define ARG_ASM_STR            "asm"
#define ARG_AST_STR            "ast"
#define ARG_BINARY_STR         "binary"
#define ARG_OPCODES_STR        "opcodes"
#define ARG_NATSPECDEV_STR     "natspec-dev"
#define ARG_NATSPECUSER_STR    "natspec-user"

namespace dev
{
namespace solidity
{

static void version()
{
	cout << "solc, the solidity complier commandline interface " << dev::Version << endl
		 << "  by Christian <c@ethdev.com> and Lefteris <lefteris@ethdev.com>, (c) 2014." << endl
		 << "Build: " << DEV_QUOTED(ETH_BUILD_PLATFORM) << "/" << DEV_QUOTED(ETH_BUILD_TYPE) << endl;
	exit(0);
}

static inline bool argToStdout(po::variables_map const& _args, const char* _name)
{
	return _args.count(_name) && _args[_name].as<OutputType>() != OutputType::FILE;
}

static bool needStdout(po::variables_map const& _args)
{
	return argToStdout(_args, ARG_ABI_STR) || argToStdout(_args, ARG_NATSPECUSER_STR) ||
		   argToStdout(_args, ARG_NATSPECDEV_STR) || argToStdout(_args, ARG_ASM_STR) ||
		   argToStdout(_args, ARG_OPCODES_STR) || argToStdout(_args, ARG_BINARY_STR);
}

static inline bool outputToFile(OutputType type)
{
	return type == OutputType::FILE || type == OutputType::BOTH;
}

static inline bool outputToStdout(OutputType type)
{
	return type == OutputType::STDOUT || type == OutputType::BOTH;
}

static std::istream& operator>>(std::istream& _in, OutputType& io_output)
{
	std::string token;
	_in >> token;
	if (token == "stdout")
		io_output = OutputType::STDOUT;
	else if (token == "file")
		io_output = OutputType::FILE;
	else if (token == "both")
		io_output = OutputType::BOTH;
	else
		throw boost::program_options::invalid_option_value(token);
	return _in;
}

void CommandLineInterface::handleBinary(string const& _contract)
{
	auto choice = m_args[ARG_BINARY_STR].as<OutputType>();
	if (outputToStdout(choice))
	{
		cout << "Binary: " << endl;
		cout << toHex(m_compiler.getBytecode(_contract)) << endl;
	}

	if (outputToFile(choice))
	{
		ofstream outFile(_contract + ".binary");
		outFile << toHex(m_compiler.getBytecode(_contract));
		outFile.close();
	}
}

void CommandLineInterface::handleOpcode(string const& _contract)
{
	auto choice = m_args[ARG_OPCODES_STR].as<OutputType>();
	if (outputToStdout(choice))
	{
		cout << "Opcodes: " << endl;
		cout << eth::disassemble(m_compiler.getBytecode(_contract));
		cout << endl;
	}

	if (outputToFile(choice))
	{
		ofstream outFile(_contract + ".opcode");
		outFile << eth::disassemble(m_compiler.getBytecode(_contract));
		outFile.close();
	}
}

void CommandLineInterface::handleBytecode(string const& _contract)
{
	if (m_args.count(ARG_OPCODES_STR))
		handleOpcode(_contract);
	if (m_args.count(ARG_BINARY_STR))
		handleBinary(_contract);
}

void CommandLineInterface::handleJson(DocumentationType _type,
									  string const& _contract)
{
	std::string argName;
	std::string suffix;
	std::string title;
	switch(_type)
	{
	case DocumentationType::ABI_INTERFACE:
		argName = ARG_ABI_STR;
		suffix = ".abi";
		title = "Contract ABI";
		break;
	case DocumentationType::NATSPEC_USER:
		argName = "ARG_NATSPECUSER_STR";
		suffix = ".docuser";
		title = "User Documentation";
		break;
	case DocumentationType::NATSPEC_DEV:
		argName = ARG_NATSPECDEV_STR;
		suffix = ".docdev";
		title = "Developer Documentation";
		break;
	default:
		// should never happen
		BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Unknown documentation _type"));
	}

	if (m_args.count(argName))
	{
		auto choice = m_args[argName].as<OutputType>();
		if (outputToStdout(choice))
		{
			cout << title << endl;
			cout << m_compiler.getJsonDocumentation(_contract, _type);
		}

		if (outputToFile(choice))
		{
			ofstream outFile(_contract + suffix);
			outFile << m_compiler.getJsonDocumentation(_contract, _type);
			outFile.close();
		}
	}
}

bool CommandLineInterface::parseArguments(int argc, char** argv)
{
#define OUTPUT_TYPE_STR "Legal values:\n"				\
		"\tstdout: Print it to standard output\n"		\
		"\tfile: Print it to a file with same name\n"	\
		"\tboth: Print both to a file and the stdout\n"
	// Declare the supported options.
	po::options_description desc("Allowed options");
	desc.add_options()
		("help", "Show help message and exit")
		("version", "Show version and exit")
		("optimize", po::value<bool>()->default_value(false), "Optimize bytecode for size")
		("input-file", po::value<vector<string>>(), "input file")
		(ARG_AST_STR, po::value<OutputType>(),
		 "Request to output the AST of the contract. " OUTPUT_TYPE_STR)
		(ARG_ASM_STR, po::value<OutputType>(),
		 "Request to output the EVM assembly of the contract. "	 OUTPUT_TYPE_STR)
		(ARG_OPCODES_STR, po::value<OutputType>(),
		 "Request to output the Opcodes of the contract. "	OUTPUT_TYPE_STR)
		(ARG_BINARY_STR, po::value<OutputType>(),
		 "Request to output the contract in binary (hexadecimal). "	 OUTPUT_TYPE_STR)
		(ARG_ABI_STR, po::value<OutputType>(),
		 "Request to output the contract's ABI interface. "	 OUTPUT_TYPE_STR)
		(ARG_NATSPECUSER_STR, po::value<OutputType>(),
		 "Request to output the contract's Natspec user documentation. "  OUTPUT_TYPE_STR)
		(ARG_NATSPECDEV_STR, po::value<OutputType>(),
		 "Request to output the contract's Natspec developer documentation. "  OUTPUT_TYPE_STR);
#undef OUTPUT_TYPE_STR

	// All positional options should be interpreted as input files
	po::positional_options_description p;
	p.add("input-file", -1);

	// parse the compiler arguments
	try
	{
		po::store(po::command_line_parser(argc, argv).options(desc).positional(p).allow_unregistered().run(), m_args);
	}
	catch (po::error const& exception)
	{
		cout << exception.what() << endl;
		return false;
	}
	po::notify(m_args);

	if (m_args.count("help"))
	{
		cout << desc;
		return false;
	}

	if (m_args.count("version"))
	{
		version();
		return false;
	}

	return true;
}

bool CommandLineInterface::processInput()
{
	if (!m_args.count("input-file"))
	{
		string s;
		while (!cin.eof())
		{
			getline(cin, s);
			m_sourceCodes["<stdin>"].append(s);
		}
	}
	else
		for (string const& infile: m_args["input-file"].as<vector<string>>())
		{
			auto path = boost::filesystem::path(infile);
			if (!boost::filesystem::exists(path))
			{
				cout << "Skipping non existant input file \"" << infile << "\"" << endl;
				continue;
			}

			if (!boost::filesystem::is_regular_file(path))
			{
				cout << "\"" << infile << "\" is not a valid file. Skipping" << endl;
				continue;
			}

			m_sourceCodes[infile] = asString(dev::contents(infile));
		}

	try
	{
		for (auto const& sourceCode: m_sourceCodes)
			m_compiler.addSource(sourceCode.first, sourceCode.second);
		// TODO: Perhaps we should not compile unless requested
		m_compiler.compile(m_args["optimize"].as<bool>());
	}
	catch (ParserError const& exception)
	{
		SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Parser error", m_compiler);
		return false;
	}
	catch (DeclarationError const& exception)
	{
		SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Declaration error", m_compiler);
		return false;
	}
	catch (TypeError const& exception)
	{
		SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Type error", m_compiler);
		return false;
	}
	catch (CompilerError const& exception)
	{
		SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Compiler error", m_compiler);
		return false;
	}
	catch (InternalCompilerError const& exception)
	{
		SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Internal compiler error", m_compiler);
		return false;
	}
	catch (Exception const& exception)
	{
		cerr << "Exception during compilation: " << boost::diagnostic_information(exception) << endl;
		return false;
	}
	catch (...)
	{
		cerr << "Unknown exception during compilation." << endl;
		return false;
	}

	return true;
}

void CommandLineInterface::actOnInput()
{
	// do we need AST output?
	if (m_args.count(ARG_AST_STR))
	{
		auto choice = m_args[ARG_AST_STR].as<OutputType>();
		if (outputToStdout(choice))
		{
			cout << "Syntax trees:" << endl << endl;
			for (auto const& sourceCode: m_sourceCodes)
			{
				cout << endl << "======= " << sourceCode.first << " =======" << endl;
				ASTPrinter printer(m_compiler.getAST(sourceCode.first), sourceCode.second);
				printer.print(cout);
			}
		}

		if (outputToFile(choice))
		{
			for (auto const& sourceCode: m_sourceCodes)
			{
				boost::filesystem::path p(sourceCode.first);
				ofstream outFile(p.stem().string() + ".ast");
				ASTPrinter printer(m_compiler.getAST(sourceCode.first), sourceCode.second);
				printer.print(outFile);
				outFile.close();
			}
		}
	}

	vector<string> contracts = m_compiler.getContractNames();
	for (string const& contract: contracts)
	{
		if (needStdout(m_args))
			cout << endl << "======= " << contract << " =======" << endl;

		// do we need EVM assembly?
		if (m_args.count(ARG_ASM_STR))
		{
			auto choice = m_args[ARG_ASM_STR].as<OutputType>();
			if (outputToStdout(choice))
			{
				cout << "EVM assembly:" << endl;
				m_compiler.streamAssembly(cout, contract);
			}

			if (outputToFile(choice))
			{
				ofstream outFile(contract + ".evm");
				m_compiler.streamAssembly(outFile, contract);
				outFile.close();
			}
		}

		handleBytecode(contract);
		handleJson(DocumentationType::ABI_INTERFACE, contract);
		handleJson(DocumentationType::NATSPEC_DEV, contract);
		handleJson(DocumentationType::NATSPEC_USER, contract);
	} // end of contracts iteration
}

}
}
<commit_msg>Using strings instead of #defined literals in solc<commit_after>/*
	This file is part of cpp-ethereum.

	cpp-ethereum is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

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

	You should have received a copy of the GNU General Public License
	along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/**
 * @author Lefteris <lefteris@ethdev.com>
 * @date 2014
 * Solidity command line interface.
 */
#include "CommandLineInterface.h"

#include <string>
#include <iostream>
#include <fstream>

#include <boost/filesystem.hpp>

#include "BuildInfo.h"
#include <libdevcore/Common.h>
#include <libdevcore/CommonData.h>
#include <libdevcore/CommonIO.h>
#include <libevmcore/Instruction.h>
#include <libsolidity/Scanner.h>
#include <libsolidity/Parser.h>
#include <libsolidity/ASTPrinter.h>
#include <libsolidity/NameAndTypeResolver.h>
#include <libsolidity/Exceptions.h>
#include <libsolidity/CompilerStack.h>
#include <libsolidity/SourceReferenceFormatter.h>

using namespace std;
namespace po = boost::program_options;

namespace dev
{
namespace solidity
{

// LTODO: Maybe some argument class pairing names with
// extensions and other attributes would be a better choice here?
static string const g_argAbiStr =           "abi";
static string const g_argAsmStr =           "asm";
static string const g_argAstStr =           "ast";
static string const g_argBinaryStr =       "binary";
static string const g_argOpcodesStr =       "opcodes";
static string const g_argNatspecDevStr =    "natspec-dev";
static string const g_argNatspecUserStr =   "natspec-user";

static void version()
{
	cout << "solc, the solidity complier commandline interface " << dev::Version << endl
		 << "  by Christian <c@ethdev.com> and Lefteris <lefteris@ethdev.com>, (c) 2014." << endl
		 << "Build: " << DEV_QUOTED(ETH_BUILD_PLATFORM) << "/" << DEV_QUOTED(ETH_BUILD_TYPE) << endl;
	exit(0);
}

static inline bool argToStdout(po::variables_map const& _args, string const& _name)
{
	return _args.count(_name) && _args[_name].as<OutputType>() != OutputType::FILE;
}

static bool needStdout(po::variables_map const& _args)
{
	return argToStdout(_args, g_argAbiStr) || argToStdout(_args, g_argNatspecUserStr) ||
		   argToStdout(_args, g_argNatspecDevStr) || argToStdout(_args, g_argAsmStr) ||
		   argToStdout(_args, g_argOpcodesStr) || argToStdout(_args, g_argBinaryStr);
}

static inline bool outputToFile(OutputType type)
{
	return type == OutputType::FILE || type == OutputType::BOTH;
}

static inline bool outputToStdout(OutputType type)
{
	return type == OutputType::STDOUT || type == OutputType::BOTH;
}

static std::istream& operator>>(std::istream& _in, OutputType& io_output)
{
	std::string token;
	_in >> token;
	if (token == "stdout")
		io_output = OutputType::STDOUT;
	else if (token == "file")
		io_output = OutputType::FILE;
	else if (token == "both")
		io_output = OutputType::BOTH;
	else
		throw boost::program_options::invalid_option_value(token);
	return _in;
}

void CommandLineInterface::handleBinary(string const& _contract)
{
	auto choice = m_args[g_argBinaryStr].as<OutputType>();
	if (outputToStdout(choice))
	{
		cout << "Binary: " << endl;
		cout << toHex(m_compiler.getBytecode(_contract)) << endl;
	}

	if (outputToFile(choice))
	{
		ofstream outFile(_contract + ".binary");
		outFile << toHex(m_compiler.getBytecode(_contract));
		outFile.close();
	}
}

void CommandLineInterface::handleOpcode(string const& _contract)
{
	auto choice = m_args[g_argOpcodesStr].as<OutputType>();
	if (outputToStdout(choice))
	{
		cout << "Opcodes: " << endl;
		cout << eth::disassemble(m_compiler.getBytecode(_contract));
		cout << endl;
	}

	if (outputToFile(choice))
	{
		ofstream outFile(_contract + ".opcode");
		outFile << eth::disassemble(m_compiler.getBytecode(_contract));
		outFile.close();
	}
}

void CommandLineInterface::handleBytecode(string const& _contract)
{
	if (m_args.count(g_argOpcodesStr))
		handleOpcode(_contract);
	if (m_args.count(g_argBinaryStr))
		handleBinary(_contract);
}

void CommandLineInterface::handleJson(DocumentationType _type,
									  string const& _contract)
{
	std::string argName;
	std::string suffix;
	std::string title;
	switch(_type)
	{
	case DocumentationType::ABI_INTERFACE:
		argName = g_argAbiStr;
		suffix = ".abi";
		title = "Contract ABI";
		break;
	case DocumentationType::NATSPEC_USER:
		argName = "g_argNatspecUserStr";
		suffix = ".docuser";
		title = "User Documentation";
		break;
	case DocumentationType::NATSPEC_DEV:
		argName = g_argNatspecDevStr;
		suffix = ".docdev";
		title = "Developer Documentation";
		break;
	default:
		// should never happen
		BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Unknown documentation _type"));
	}

	if (m_args.count(argName))
	{
		auto choice = m_args[argName].as<OutputType>();
		if (outputToStdout(choice))
		{
			cout << title << endl;
			cout << m_compiler.getJsonDocumentation(_contract, _type);
		}

		if (outputToFile(choice))
		{
			ofstream outFile(_contract + suffix);
			outFile << m_compiler.getJsonDocumentation(_contract, _type);
			outFile.close();
		}
	}
}

bool CommandLineInterface::parseArguments(int argc, char** argv)
{
#define OUTPUT_TYPE_STR "Legal values:\n"				\
		"\tstdout: Print it to standard output\n"		\
		"\tfile: Print it to a file with same name\n"	\
		"\tboth: Print both to a file and the stdout\n"
	// Declare the supported options.
	po::options_description desc("Allowed options");
	desc.add_options()
		("help", "Show help message and exit")
		("version", "Show version and exit")
		("optimize", po::value<bool>()->default_value(false), "Optimize bytecode for size")
		("input-file", po::value<vector<string>>(), "input file")
		(g_argAstStr.c_str(), po::value<OutputType>(),
		 "Request to output the AST of the contract. " OUTPUT_TYPE_STR)
		(g_argAsmStr.c_str(), po::value<OutputType>(),
		 "Request to output the EVM assembly of the contract. " OUTPUT_TYPE_STR)
		(g_argOpcodesStr.c_str(), po::value<OutputType>(),
		 "Request to output the Opcodes of the contract. " OUTPUT_TYPE_STR)
		(g_argBinaryStr.c_str(), po::value<OutputType>(),
		 "Request to output the contract in binary (hexadecimal). " OUTPUT_TYPE_STR)
		(g_argAbiStr.c_str(), po::value<OutputType>(),
		 "Request to output the contract's ABI interface. "  OUTPUT_TYPE_STR)
		(g_argNatspecUserStr.c_str(), po::value<OutputType>(),
		 "Request to output the contract's Natspec user documentation. " OUTPUT_TYPE_STR)
		(g_argNatspecDevStr.c_str(), po::value<OutputType>(),
		 "Request to output the contract's Natspec developer documentation. " OUTPUT_TYPE_STR);
#undef OUTPUT_TYPE_STR

	// All positional options should be interpreted as input files
	po::positional_options_description p;
	p.add("input-file", -1);

	// parse the compiler arguments
	try
	{
		po::store(po::command_line_parser(argc, argv).options(desc).positional(p).allow_unregistered().run(), m_args);
	}
	catch (po::error const& exception)
	{
		cout << exception.what() << endl;
		return false;
	}
	po::notify(m_args);

	if (m_args.count("help"))
	{
		cout << desc;
		return false;
	}

	if (m_args.count("version"))
	{
		version();
		return false;
	}

	return true;
}

bool CommandLineInterface::processInput()
{
	if (!m_args.count("input-file"))
	{
		string s;
		while (!cin.eof())
		{
			getline(cin, s);
			m_sourceCodes["<stdin>"].append(s);
		}
	}
	else
		for (string const& infile: m_args["input-file"].as<vector<string>>())
		{
			auto path = boost::filesystem::path(infile);
			if (!boost::filesystem::exists(path))
			{
				cout << "Skipping non existant input file \"" << infile << "\"" << endl;
				continue;
			}

			if (!boost::filesystem::is_regular_file(path))
			{
				cout << "\"" << infile << "\" is not a valid file. Skipping" << endl;
				continue;
			}

			m_sourceCodes[infile] = asString(dev::contents(infile));
		}

	try
	{
		for (auto const& sourceCode: m_sourceCodes)
			m_compiler.addSource(sourceCode.first, sourceCode.second);
		// TODO: Perhaps we should not compile unless requested
		m_compiler.compile(m_args["optimize"].as<bool>());
	}
	catch (ParserError const& exception)
	{
		SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Parser error", m_compiler);
		return false;
	}
	catch (DeclarationError const& exception)
	{
		SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Declaration error", m_compiler);
		return false;
	}
	catch (TypeError const& exception)
	{
		SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Type error", m_compiler);
		return false;
	}
	catch (CompilerError const& exception)
	{
		SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Compiler error", m_compiler);
		return false;
	}
	catch (InternalCompilerError const& exception)
	{
		SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Internal compiler error", m_compiler);
		return false;
	}
	catch (Exception const& exception)
	{
		cerr << "Exception during compilation: " << boost::diagnostic_information(exception) << endl;
		return false;
	}
	catch (...)
	{
		cerr << "Unknown exception during compilation." << endl;
		return false;
	}

	return true;
}

void CommandLineInterface::actOnInput()
{
	// do we need AST output?
	if (m_args.count(g_argAstStr))
	{
		auto choice = m_args[g_argAstStr].as<OutputType>();
		if (outputToStdout(choice))
		{
			cout << "Syntax trees:" << endl << endl;
			for (auto const& sourceCode: m_sourceCodes)
			{
				cout << endl << "======= " << sourceCode.first << " =======" << endl;
				ASTPrinter printer(m_compiler.getAST(sourceCode.first), sourceCode.second);
				printer.print(cout);
			}
		}

		if (outputToFile(choice))
		{
			for (auto const& sourceCode: m_sourceCodes)
			{
				boost::filesystem::path p(sourceCode.first);
				ofstream outFile(p.stem().string() + ".ast");
				ASTPrinter printer(m_compiler.getAST(sourceCode.first), sourceCode.second);
				printer.print(outFile);
				outFile.close();
			}
		}
	}

	vector<string> contracts = m_compiler.getContractNames();
	for (string const& contract: contracts)
	{
		if (needStdout(m_args))
			cout << endl << "======= " << contract << " =======" << endl;

		// do we need EVM assembly?
		if (m_args.count(g_argAsmStr))
		{
			auto choice = m_args[g_argAsmStr].as<OutputType>();
			if (outputToStdout(choice))
			{
				cout << "EVM assembly:" << endl;
				m_compiler.streamAssembly(cout, contract);
			}

			if (outputToFile(choice))
			{
				ofstream outFile(contract + ".evm");
				m_compiler.streamAssembly(outFile, contract);
				outFile.close();
			}
		}

		handleBytecode(contract);
		handleJson(DocumentationType::ABI_INTERFACE, contract);
		handleJson(DocumentationType::NATSPEC_DEV, contract);
		handleJson(DocumentationType::NATSPEC_USER, contract);
	} // end of contracts iteration
}

}
}
<|endoftext|>


<commit_before>/*
 *  EventCallbackHandler.cpp
 *  MonkeyWorksCore
 *
 *  Created by David Cox on 12/9/09.
 *  Copyright 2009 Harvard University. All rights reserved.
 *
 */

#include "EventCallbackHandler.h"

KeyedEventCallbackPair::KeyedEventCallbackPair(){
    key = "<invalid>";
    callback = shared_ptr<EventCallback>();
}

KeyedEventCallbackPair::KeyedEventCallbackPair(string _key, EventCallback _callback){
    key = _key;
    callback = shared_ptr<EventCallback>(new EventCallback(_callback));
}

void KeyedEventCallbackPair::operator=(const KeyedEventCallbackPair& cb_pair){
    key = cb_pair.key;
    callback = cb_pair.callback;
}

EventCallback KeyedEventCallbackPair::getCallback(){
    if(callback != NULL){
        return *callback;
    } else {
        return boost::bind(&KeyedEventCallbackPair::dummyCallback, shared_from_this(), _1);
    }
}

string KeyedEventCallbackPair::getKey(){ return key; }

void KeyedEventCallbackPair::dummyCallback(shared_ptr<Event> evt){
    merror(M_SYSTEM_MESSAGE_DOMAIN, "Attempt to call an invalid callback functor");
}

void EventCallbackHandler::lock_callbacks(){
    if(recursively_lock_callbacks){
        recursive_callbacks_lock.lock();
    } else {
        callbacks_lock.lock();
    }
}

void EventCallbackHandler::unlock_callbacks(){
    if(recursively_lock_callbacks){
        recursive_callbacks_lock.unlock();
    } else {
        callbacks_lock.unlock();
    }
}

void EventCallbackHandler::handleCallbacks(shared_ptr<Event> evt){

    if(evt == NULL){
        return;
    }

    int code = evt->getEventCode();

    //std::cerr << "handleCallbacks called in: " << this << " with event code " << code << std::endl;

    pair<EventCallbackMap::iterator, EventCallbackMap::iterator> itp;
    EventCallbackMap::iterator callback_iterator;

    // issue any "always" callbacks
    // TODO: this can be made more efficient (e.g. search doesn't always need to be done)
    itp = callbacks_by_code.equal_range(ALWAYS_CALLBACK);
    for(callback_iterator = itp.first; callback_iterator != itp.second; ++callback_iterator){
        KeyedEventCallbackPair callback_pair = (*callback_iterator).second;
        EventCallback callback = (*callback_iterator).second.getCallback();
        callback(evt);
    }

    lock_callbacks();

    // Issue callbacks registered for particular codes
    itp = callbacks_by_code.equal_range(code);

    for(callback_iterator = itp.first; callback_iterator != itp.second; ++callback_iterator){
        KeyedEventCallbackPair callback_pair = (*callback_iterator).second;
        EventCallback callback = (*callback_iterator).second.getCallback();
        callback(evt);
        //std::cerr << "callback called for evt: " << code << " in: " << this << std::endl;

    }

    unlock_callbacks();
}

void EventCallbackHandler::registerCallback(EventCallback cb, string callback_key){
    registerCallback(ALWAYS_CALLBACK, cb, callback_key);
}

void EventCallbackHandler::registerCallback(int code, EventCallback cb, string callback_key){
    lock_callbacks();
    //std::cerr << "Registering callback for code: " << code << ", key: " << callback_key << std::endl;
    callbacks_by_code.insert(pair< int, KeyedEventCallbackPair >(code, KeyedEventCallbackPair(callback_key, cb)));
    codes_by_key.insert( pair<string, int>(callback_key, code) );
    unlock_callbacks();
}

void EventCallbackHandler::unregisterCallbacksNoLocking(const std::string &key){
    return unregisterCallbacks(key, false);
}

void EventCallbackHandler::unregisterCallbacks(const std::string &key, bool locked) {

    if(locked){
        lock_callbacks();
    }

    //std::cerr << "Unregistering callbacks for key: " << key << std::endl;
    // For now, just do a straight linear time search
    EventCallbackMap::iterator callback_iterator;
    for(callback_iterator = callbacks_by_code.begin(); callback_iterator != callbacks_by_code.end(); ++callback_iterator){
        if((*callback_iterator).second.getKey() == key){
            //std::cerr << "\tunregistering code: " << (*callback_iterator).first << std::endl;
            callbacks_by_code.erase(callback_iterator);
        }
    }

    if(locked){
        unlock_callbacks();
    }
}
<commit_msg>Call lock_callbacks() before issuing "always" callbacks (failure to do so was causing the client to crash)<commit_after>/*
 *  EventCallbackHandler.cpp
 *  MonkeyWorksCore
 *
 *  Created by David Cox on 12/9/09.
 *  Copyright 2009 Harvard University. All rights reserved.
 *
 */

#include "EventCallbackHandler.h"

KeyedEventCallbackPair::KeyedEventCallbackPair(){
    key = "<invalid>";
    callback = shared_ptr<EventCallback>();
}

KeyedEventCallbackPair::KeyedEventCallbackPair(string _key, EventCallback _callback){
    key = _key;
    callback = shared_ptr<EventCallback>(new EventCallback(_callback));
}

void KeyedEventCallbackPair::operator=(const KeyedEventCallbackPair& cb_pair){
    key = cb_pair.key;
    callback = cb_pair.callback;
}

EventCallback KeyedEventCallbackPair::getCallback(){
    if(callback != NULL){
        return *callback;
    } else {
        return boost::bind(&KeyedEventCallbackPair::dummyCallback, shared_from_this(), _1);
    }
}

string KeyedEventCallbackPair::getKey(){ return key; }

void KeyedEventCallbackPair::dummyCallback(shared_ptr<Event> evt){
    merror(M_SYSTEM_MESSAGE_DOMAIN, "Attempt to call an invalid callback functor");
}

void EventCallbackHandler::lock_callbacks(){
    if(recursively_lock_callbacks){
        recursive_callbacks_lock.lock();
    } else {
        callbacks_lock.lock();
    }
}

void EventCallbackHandler::unlock_callbacks(){
    if(recursively_lock_callbacks){
        recursive_callbacks_lock.unlock();
    } else {
        callbacks_lock.unlock();
    }
}

void EventCallbackHandler::handleCallbacks(shared_ptr<Event> evt){

    if(evt == NULL){
        return;
    }

    int code = evt->getEventCode();

    //std::cerr << "handleCallbacks called in: " << this << " with event code " << code << std::endl;

    pair<EventCallbackMap::iterator, EventCallbackMap::iterator> itp;
    EventCallbackMap::iterator callback_iterator;

    lock_callbacks();

    // issue any "always" callbacks
    // TODO: this can be made more efficient (e.g. search doesn't always need to be done)
    itp = callbacks_by_code.equal_range(ALWAYS_CALLBACK);
    for(callback_iterator = itp.first; callback_iterator != itp.second; ++callback_iterator){
        KeyedEventCallbackPair callback_pair = (*callback_iterator).second;
        EventCallback callback = (*callback_iterator).second.getCallback();
        callback(evt);
    }

    // Issue callbacks registered for particular codes
    itp = callbacks_by_code.equal_range(code);

    for(callback_iterator = itp.first; callback_iterator != itp.second; ++callback_iterator){
        KeyedEventCallbackPair callback_pair = (*callback_iterator).second;
        EventCallback callback = (*callback_iterator).second.getCallback();
        callback(evt);
        //std::cerr << "callback called for evt: " << code << " in: " << this << std::endl;

    }

    unlock_callbacks();
}

void EventCallbackHandler::registerCallback(EventCallback cb, string callback_key){
    registerCallback(ALWAYS_CALLBACK, cb, callback_key);
}

void EventCallbackHandler::registerCallback(int code, EventCallback cb, string callback_key){
    lock_callbacks();
    //std::cerr << "Registering callback for code: " << code << ", key: " << callback_key << std::endl;
    callbacks_by_code.insert(pair< int, KeyedEventCallbackPair >(code, KeyedEventCallbackPair(callback_key, cb)));
    codes_by_key.insert( pair<string, int>(callback_key, code) );
    unlock_callbacks();
}

void EventCallbackHandler::unregisterCallbacksNoLocking(const std::string &key){
    return unregisterCallbacks(key, false);
}

void EventCallbackHandler::unregisterCallbacks(const std::string &key, bool locked) {

    if(locked){
        lock_callbacks();
    }

    //std::cerr << "Unregistering callbacks for key: " << key << std::endl;
    // For now, just do a straight linear time search
    EventCallbackMap::iterator callback_iterator;
    for(callback_iterator = callbacks_by_code.begin(); callback_iterator != callbacks_by_code.end(); ++callback_iterator){
        if((*callback_iterator).second.getKey() == key){
            //std::cerr << "\tunregistering code: " << (*callback_iterator).first << std::endl;
            callbacks_by_code.erase(callback_iterator);
        }
    }

    if(locked){
        unlock_callbacks();
    }
}
<|endoftext|>


<commit_before>// For conditions of distribution and use, see copyright notice in license.txt

#include "StableHeaders.h"

#include <Poco/Logger.h>
#include <Poco/LoggingFactory.h>
#include <Poco/FormattingChannel.h>
#include <Poco/SplitterChannel.h>
#include <Poco/LocalDateTime.h>

#include "Foundation.h"

namespace Foundation
{
    Framework::Framework() : exit_signal_(false)
    {
        platform_ = PlatformPtr(new Platform(this));

        config_.DeclareSetting(Framework::ConfigurationGroup(), "application_name", "realXtend");
        platform_->PrepareApplicationDataDirectory(); // depends on config

        CreateLoggingSystem(); // depends on config and platform

        // create managers
        module_manager_ = ModuleManagerPtr(new ModuleManager(this));
        component_manager_ = ComponentManagerPtr(new ComponentManager(this));
        service_manager_ = ServiceManagerPtr(new ServiceManager(this));
    }

    Framework::~Framework()
    {
        Poco::Logger::shutdown();

        for (size_t i=0 ; i<log_channels_.size() ; ++i)
            log_channels_[i]->release();

        log_channels_.clear();
        log_formatter_->release();
    }

    void Framework::CreateLoggingSystem()
    {

        Poco::LoggingFactory *loggingfactory = new Poco::LoggingFactory();

        Poco::Channel *consolechannel = loggingfactory->createChannel("ConsoleChannel");
        Poco::Channel *filechannel = loggingfactory->createChannel("FileChannel");

        std::string logfilepath = platform_->GetUserDocumentsDirectory();
        logfilepath += "/" + config_.GetString(Framework::ConfigurationGroup(), "application_name") + ".log";

        filechannel->setProperty("path",logfilepath);
        filechannel->setProperty("rotation","3M");
        filechannel->setProperty("archive","number");
        filechannel->setProperty("compress","false");

        Poco::SplitterChannel *splitterchannel = new Poco::SplitterChannel();
        splitterchannel->addChannel(consolechannel);
        splitterchannel->addChannel(filechannel);

        log_formatter_ = loggingfactory->createFormatter("PatternFormatter");
        log_formatter_->setProperty("pattern","%H:%M:%S [%s] %t");
        log_formatter_->setProperty("times","local");
        Poco::Channel *formatchannel = new Poco::FormattingChannel(log_formatter_,splitterchannel);

        try
        {
            Poco::Logger::create("",formatchannel,Poco::Message::PRIO_TRACE);
            Poco::Logger::create("Foundation",Poco::Logger::root().getChannel() ,Poco::Message::PRIO_TRACE);
        } catch (Poco::ExistsException)
        {
            assert (false && "Somewhere, a message is pushed to log before the logger is initialized.");
        }

        Poco::LocalDateTime *currenttime = new Poco::LocalDateTime();
        std::string timestring = boost::lexical_cast<std::string>(currenttime->day()) + "/";
        timestring.append(boost::lexical_cast<std::string>(currenttime->month()) + "/");
        timestring.append(boost::lexical_cast<std::string>(currenttime->year()) + " ");
        timestring.append(boost::lexical_cast<std::string>(currenttime->hour()) + ":");
        timestring.append(boost::lexical_cast<std::string>(currenttime->minute()) + ":");
        timestring.append(boost::lexical_cast<std::string>(currenttime->second()));
        Foundation::RootLogInfo("Log file opened on " + timestring);

        log_channels_.push_back(consolechannel);
        log_channels_.push_back(filechannel);
        log_channels_.push_back(splitterchannel);
        log_channels_.push_back(formatchannel);

        delete currenttime;
        delete loggingfactory;
    }

    void Framework::Go()
    {
        LoadModules();

        // main loop
        while (exit_signal_ == false)
        {
            // do synchronized update for modules
            module_manager_->UpdateModules();

            // call asynchronous update on modules / do parallel tasks

            // synchronize shared data across modules
            //mChangeManager->_propagateChanges();
        }

         UnloadModules();
    }

    void Framework::LoadModules()
    {
        module_manager_->LoadAvailableModules();
        module_manager_->InitializeModules();
    }

    void Framework::UnloadModules()
    {
        module_manager_->UninitializeModules();
        module_manager_->UnloadModules();
    }
}

<commit_msg>Two empty lines are now added at beginning of log file to better separate between runs.<commit_after>// For conditions of distribution and use, see copyright notice in license.txt

#include "StableHeaders.h"

#include <Poco/Logger.h>
#include <Poco/LoggingFactory.h>
#include <Poco/FormattingChannel.h>
#include <Poco/SplitterChannel.h>
#include <Poco/LocalDateTime.h>

#include "Foundation.h"

namespace Foundation
{
    Framework::Framework() : exit_signal_(false)
    {
        platform_ = PlatformPtr(new Platform(this));

        config_.DeclareSetting(Framework::ConfigurationGroup(), "application_name", "realXtend");
        platform_->PrepareApplicationDataDirectory(); // depends on config

        CreateLoggingSystem(); // depends on config and platform

        // create managers
        module_manager_ = ModuleManagerPtr(new ModuleManager(this));
        component_manager_ = ComponentManagerPtr(new ComponentManager(this));
        service_manager_ = ServiceManagerPtr(new ServiceManager(this));
    }

    Framework::~Framework()
    {
        Poco::Logger::shutdown();

        for (size_t i=0 ; i<log_channels_.size() ; ++i)
            log_channels_[i]->release();

        log_channels_.clear();
        log_formatter_->release();
    }

    void Framework::CreateLoggingSystem()
    {

        Poco::LoggingFactory *loggingfactory = new Poco::LoggingFactory();

        Poco::Channel *consolechannel = loggingfactory->createChannel("ConsoleChannel");
        Poco::Channel *filechannel = loggingfactory->createChannel("FileChannel");

        std::string logfilepath = platform_->GetUserDocumentsDirectory();
        logfilepath += "/" + config_.GetString(Framework::ConfigurationGroup(), "application_name") + ".log";

        std::fstream log(logfilepath.c_str(), std::ios::app | std::ios::out);
        log << std::endl;
        log << std::endl;
        log.close();

        filechannel->setProperty("path",logfilepath);
        filechannel->setProperty("rotation","3M");
        filechannel->setProperty("archive","number");
        filechannel->setProperty("compress","false");

        Poco::SplitterChannel *splitterchannel = new Poco::SplitterChannel();
        splitterchannel->addChannel(consolechannel);
        splitterchannel->addChannel(filechannel);

        log_formatter_ = loggingfactory->createFormatter("PatternFormatter");
        log_formatter_->setProperty("pattern","%H:%M:%S [%s] %t");
        log_formatter_->setProperty("times","local");
        Poco::Channel *formatchannel = new Poco::FormattingChannel(log_formatter_,splitterchannel);

        try
        {
            Poco::Logger::create("",formatchannel,Poco::Message::PRIO_TRACE);
            Poco::Logger::create("Foundation",Poco::Logger::root().getChannel() ,Poco::Message::PRIO_TRACE);
        } catch (Poco::ExistsException)
        {
            assert (false && "Somewhere, a message is pushed to log before the logger is initialized.");
        }

        Poco::LocalDateTime *currenttime = new Poco::LocalDateTime();
        std::string timestring = boost::lexical_cast<std::string>(currenttime->day()) + "/";
        timestring.append(boost::lexical_cast<std::string>(currenttime->month()) + "/");
        timestring.append(boost::lexical_cast<std::string>(currenttime->year()) + " ");
        timestring.append(boost::lexical_cast<std::string>(currenttime->hour()) + ":");
        timestring.append(boost::lexical_cast<std::string>(currenttime->minute()) + ":");
        timestring.append(boost::lexical_cast<std::string>(currenttime->second()));
        Foundation::RootLogInfo("Log file opened on " + timestring);

        log_channels_.push_back(consolechannel);
        log_channels_.push_back(filechannel);
        log_channels_.push_back(splitterchannel);
        log_channels_.push_back(formatchannel);

        delete currenttime;
        delete loggingfactory;
    }

    void Framework::Go()
    {
        LoadModules();

        // main loop
        while (exit_signal_ == false)
        {
            // do synchronized update for modules
            module_manager_->UpdateModules();

            // call asynchronous update on modules / do parallel tasks

            // synchronize shared data across modules
            //mChangeManager->_propagateChanges();
        }

         UnloadModules();
    }

    void Framework::LoadModules()
    {
        module_manager_->LoadAvailableModules();
        module_manager_->InitializeModules();
    }

    void Framework::UnloadModules()
    {
        module_manager_->UninitializeModules();
        module_manager_->UnloadModules();
    }
}

<|endoftext|>


<commit_before>
/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkRAdapter.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
/*-------------------------------------------------------------------------
  Copyright 2009 Sandia Corporation.
  Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
  the U.S. Government retains certain rights in this software.
-------------------------------------------------------------------------*/

#include "vtkObjectFactory.h"
#include "vtkRAdapter.h"
#include "vtkAbstractArray.h"
#include "vtkDoubleArray.h"
#include "vtkIntArray.h"
#include "vtkXYPlotActor.h"
#include "vtkXYPlotWidget.h"
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkStdString.h"
#include "vtkStringArray.h"
#include "vtkTable.h"
#include "vtkArray.h"
#include "vtkArrayExtents.h"
#include "vtkArrayCoordinates.h"
#include "vtkTypedArray.h"
#include "vtkVariantArray.h"
#include "vtkDoubleArray.h"
#include "vtkIntArray.h"
#include "vtkStringArray.h"
#include "vtkDataArrayCollection.h"
#include "vtkArrayData.h"
#include "vtkDataObjectCollection.h"

#include <vtkstd/map>

#include <stdio.h>
#include <assert.h>

#define R_NO_REMAP /* AVOID SOME SERIOUS STUPIDITY. DO NOT REMOVE. */

#include "R.h"
#include "Rdefines.h"
#include "R_ext/Parse.h"
#include "R_ext/Rdynload.h"

vtkCxxRevisionMacro(vtkRAdapter, "1.8");

vtkStandardNewMacro(vtkRAdapter);

namespace
{

int R_FindArrayIndex(vtkArrayCoordinates& coordinates, const vtkArrayExtents& extents)
{

  vtkIdType i;
  int ret = 0;
  vtkIdType divisor = 1;
  vtkIdType d = coordinates.GetDimensions();

  for(i = 0; i < d; ++i)
    {
    ret = ret + coordinates[i]*divisor;
    divisor *= extents[i].GetSize();
    }

  return(ret);

}

} // End anonymous namespace

//----------------------------------------------------------------------------
vtkRAdapter::vtkRAdapter()
{

  this->vad =  vtkArrayData::New();
  this->vdoc = vtkDataObjectCollection::New();
  this->vdac = vtkDataArrayCollection::New();

}

//----------------------------------------------------------------------------
vtkRAdapter::~vtkRAdapter()
{

  if(this->vad)
    {
    this->vad->Delete();
    }

  if(this->vdoc)
    {
    this->vdoc->Delete();
    }

  if(this->vdac)
    {
    this->vdac->Delete();
    }

}

vtkDataArray* vtkRAdapter::RToVTKDataArray(SEXP variable)
{

  int i;
  int j;
  int nr;
  int nc;
  vtkDoubleArray* result;
  double* data;

  if( Rf_isMatrix(variable) || Rf_isVector(variable) )
    {
    nc = Rf_ncols(variable);
    nr = Rf_nrows(variable);

    result = vtkDoubleArray::New();

    result->SetNumberOfTuples(nr);
    result->SetNumberOfComponents(nc);

    data = new double[nc];

    for(i=0;i<nr;i++)
      {
      for(j=0;j<nc;j++)
        {
        if ( isReal(variable) )
          {
          data[j] = REAL(variable)[j*nr + i];
          }
        else if ( isInteger(variable) )
          {
          data[j] = static_cast<double>(INTEGER(variable)[j*nr + i]);
          }
        else
          {
          vtkErrorMacro(<< "Bad return variable, tried REAL and INTEGER.");
          }
        result->InsertTuple(i,data);
        }
      }

    delete [] data;
    this->vdac->AddItem(result);
    result->Delete();
    return(result);
    }
  else
    {
    return(0);
    }

}

SEXP vtkRAdapter::VTKDataArrayToR(vtkDataArray* da)
{

  SEXP a;
  int nr;
  int nc;
  int i;
  int j;
  double* data;

  nr = da->GetNumberOfTuples();
  nc = da->GetNumberOfComponents();

  PROTECT(a = Rf_allocMatrix(REALSXP,nr,nc));

  for(i=0;i<nr;i++)
    {
    for(j=0;j<nc;j++)
      {
      data = da->GetTuple(i);
      REAL(a)[j*nr + i] = data[j];
      }
    }

  return(a);

}

vtkArray* vtkRAdapter::RToVTKArray(SEXP variable)
{

  int i;
  int ndim;
  SEXP dims;
  vtkArrayExtents extents;
  vtkTypedArray<double>* da;
  da = vtkTypedArray<double>::SafeDownCast(vtkArray::CreateArray(vtkArray::DENSE, VTK_DOUBLE));

  dims = getAttrib(variable, R_DimSymbol);
  ndim = length(dims);

  if (!isMatrix(variable)&&!isArray(variable)&&isVector(variable))
    {
    ndim = 1;
    }

  extents.SetDimensions(ndim);

  if (isMatrix(variable)||isArray(variable))
    {
    for(i=0;i< ndim;i++)
      {
      extents[i] = vtkArrayRange(0,INTEGER(dims)[i]);
      }
    }
  else
    {
    extents[0] = vtkArrayRange(0,length(variable));
    }

  da->Resize(extents);

  vtkArrayCoordinates index;

  index.SetDimensions(ndim);

  for(i=0;i<da->GetSize();i++)
    {
    da->GetCoordinatesN(i,index);
    if ( isReal(variable) )
      {
      da->SetVariantValue(index,REAL(variable)[i]);
      }
    else if ( isInteger(variable) )
      {
      da->SetVariantValue(index,static_cast<double>(INTEGER(variable)[i]));
      }
    else
      {
      vtkErrorMacro(<< "Bad return variable, tried REAL and INTEGER.");
      }
    }

  this->vad->AddArray(da);
  da->Delete();
  return(da);

}

SEXP vtkRAdapter::VTKArrayToR(vtkArray* da)
{

  SEXP a;
  SEXP dim;
  int i;
  vtkArrayCoordinates coords;

  PROTECT(dim = Rf_allocVector(INTSXP, da->GetDimensions()));

  assert(da->GetExtents().ZeroBased());
  for(i=0;i<da->GetDimensions();i++)
    {
    INTEGER(dim)[i] = da->GetExtents()[i].GetSize();
    }

  PROTECT(a = Rf_allocArray(REALSXP, dim));

  for(i=0;i<da->GetSize();i++)
    {
    REAL(a)[i] = 0.0;
    }

  assert(da->GetExtents().ZeroBased());
  for(i=0;i<da->GetNonNullSize();i++)
    {
    da->GetCoordinatesN(i,coords);
    REAL(a)[R_FindArrayIndex(coords,da->GetExtents())] = da->GetVariantValue(coords).ToDouble();
    }

  UNPROTECT(1);

  return(a);

}

SEXP vtkRAdapter::VTKTableToR(vtkTable* table)
{

  SEXP a;
  SEXP b;
  SEXP names;
  int i;
  int j;
  int nr = table->GetNumberOfRows();
  int nc = table->GetNumberOfColumns();
  vtkVariant data;

  PROTECT(a = allocVector(VECSXP, nc));
  PROTECT(names = allocVector(STRSXP, nc));

  for(j=0;j<nc;j++)
    {
    SET_STRING_ELT(names,j,mkChar(table->GetColumn(j)->GetName()));
    if(vtkDataArray::SafeDownCast(table->GetColumn(j)))
      {
      PROTECT(b = allocVector(REALSXP,nr));
      SET_VECTOR_ELT(a,j,b);
      for(i=0;i<nr;i++)
        {
        data = table->GetValue(i,j);
        REAL(b)[i] = data.ToDouble();
        }
      }
    else
      {
      PROTECT(b = allocVector(STRSXP,nr));
      SET_VECTOR_ELT(a,j,b);
      for(i=0;i<nr;i++)
        {
        data = table->GetValue(i,j);
        SET_STRING_ELT(b,i,mkChar(data.ToString().c_str()));
        }
      }
    }

  setAttrib(a,R_NamesSymbol,names);

  return(a);

}

vtkTable* vtkRAdapter::RToVTKTable(SEXP variable)
{

  int i;
  int j;
  int nr;
  int nc;
  SEXP names;
  vtkVariant v;
  vtkTable* result;

  if( isMatrix(variable) )
    {
    nc = Rf_ncols(variable);
    nr = Rf_nrows(variable);
    result = vtkTable::New();

    for(j=0;j<nc;j++)
      {
      vtkDoubleArray* da = vtkDoubleArray::New();
      da->SetNumberOfComponents(1);
      names = getAttrib(variable, R_DimNamesSymbol);
      if(!isNull(names))
        {
        da->SetName(CHAR(STRING_ELT(VECTOR_ELT(names,1),j)));
        }
      else
        {
        v = j;
        da->SetName(v.ToString().c_str());
        }
      for(i=0;i<nr;i++)
        {
        da->InsertNextValue(REAL(variable)[j*nr + i]);
        }
      result->AddColumn(da);
      da->Delete();
      }
    }
  else if( isNewList(variable) )
    {
    nc = length(variable);
    nr = length(VECTOR_ELT(variable,0));
    for(j=1;j<nc;j++)
      {
      if(isReal(VECTOR_ELT(variable,j)) ||
         isInteger(VECTOR_ELT(variable,j)) ||
         isString(VECTOR_ELT(variable,j)) )
        {
        if(length(VECTOR_ELT(variable,j)) != nr)
          {
          vtkGenericWarningMacro(<<"Cannot convert R data type to vtkTable");
          return(0);
          }
        }
      else
        {
        vtkGenericWarningMacro(<<"Cannot convert R data type to vtkTable");
        return(0);
        }
      }

    result = vtkTable::New();
    names = getAttrib(variable, R_NamesSymbol);
    vtkAbstractArray *aa;
    for(j=0;j<nc;j++)
      {
      if(isReal(VECTOR_ELT(variable,j)))
        {
        vtkDoubleArray* da = vtkDoubleArray::New();
        da->SetNumberOfComponents(1);
        aa = da;
        for(i=0;i<nr;i++)
          {
          da->InsertNextValue(REAL(VECTOR_ELT(variable,j))[i]);
          }
        }
      else if(isInteger(VECTOR_ELT(variable,j)))
        {
        vtkIntArray* da = vtkIntArray::New();
        da->SetNumberOfComponents(1);
        aa = da;
        for(i=0;i<nr;i++)
          {
          da->InsertNextValue(INTEGER(VECTOR_ELT(variable,j))[i]);
          }
        }
      else
        {
        vtkStringArray* da = vtkStringArray::New();
        da->SetNumberOfComponents(1);
        aa = da;
        for(i=0;i<nr;i++)
          {
          da->InsertNextValue(CHAR(STRING_ELT(VECTOR_ELT(variable,j),i)));
          }
        }

      if(!isNull(names))
        {
        aa->SetName(CHAR(STRING_ELT(names,j)));
        }
      else
        {
        v = j;
        aa->SetName(v.ToString().c_str());
        }
      result->AddColumn(aa);
      aa->Delete();
      }
    }
  else
    {
    vtkGenericWarningMacro(<<"Cannot convert R data type to vtkTable");
    return(0);
    }

  this->vdoc->AddItem(result);
  result->Delete();
  return(result);

}

void vtkRAdapter::PrintSelf(ostream& os, vtkIndent indent)
{

  this->Superclass::PrintSelf(os,indent);

  if(this->vad)
    {
    this->vad->PrintSelf(os,indent);
    }

  if(this->vdoc)
    {
    this->vdoc->PrintSelf(os,indent);
    }

  if(this->vdac)
    {
    this->vdac->PrintSelf(os,indent);
    }

}

<commit_msg>COMP: Remove unneccessary includes in R adapter.<commit_after>
/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkRAdapter.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
/*-------------------------------------------------------------------------
  Copyright 2009 Sandia Corporation.
  Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
  the U.S. Government retains certain rights in this software.
-------------------------------------------------------------------------*/

#include "vtkObjectFactory.h"
#include "vtkRAdapter.h"
#include "vtkAbstractArray.h"
#include "vtkDoubleArray.h"
#include "vtkIntArray.h"
#include "vtkStdString.h"
#include "vtkStringArray.h"
#include "vtkTable.h"
#include "vtkArray.h"
#include "vtkArrayExtents.h"
#include "vtkArrayCoordinates.h"
#include "vtkTypedArray.h"
#include "vtkVariantArray.h"
#include "vtkDoubleArray.h"
#include "vtkIntArray.h"
#include "vtkStringArray.h"
#include "vtkDataArrayCollection.h"
#include "vtkArrayData.h"
#include "vtkDataObjectCollection.h"

#include <vtkstd/map>

#include <stdio.h>
#include <assert.h>

#define R_NO_REMAP /* AVOID SOME SERIOUS STUPIDITY. DO NOT REMOVE. */

#include "R.h"
#include "Rdefines.h"
#include "R_ext/Parse.h"
#include "R_ext/Rdynload.h"

vtkCxxRevisionMacro(vtkRAdapter, "1.9");

vtkStandardNewMacro(vtkRAdapter);

namespace
{

int R_FindArrayIndex(vtkArrayCoordinates& coordinates, const vtkArrayExtents& extents)
{

  vtkIdType i;
  int ret = 0;
  vtkIdType divisor = 1;
  vtkIdType d = coordinates.GetDimensions();

  for(i = 0; i < d; ++i)
    {
    ret = ret + coordinates[i]*divisor;
    divisor *= extents[i].GetSize();
    }

  return(ret);

}

} // End anonymous namespace

//----------------------------------------------------------------------------
vtkRAdapter::vtkRAdapter()
{

  this->vad =  vtkArrayData::New();
  this->vdoc = vtkDataObjectCollection::New();
  this->vdac = vtkDataArrayCollection::New();

}

//----------------------------------------------------------------------------
vtkRAdapter::~vtkRAdapter()
{

  if(this->vad)
    {
    this->vad->Delete();
    }

  if(this->vdoc)
    {
    this->vdoc->Delete();
    }

  if(this->vdac)
    {
    this->vdac->Delete();
    }

}

vtkDataArray* vtkRAdapter::RToVTKDataArray(SEXP variable)
{

  int i;
  int j;
  int nr;
  int nc;
  vtkDoubleArray* result;
  double* data;

  if( Rf_isMatrix(variable) || Rf_isVector(variable) )
    {
    nc = Rf_ncols(variable);
    nr = Rf_nrows(variable);

    result = vtkDoubleArray::New();

    result->SetNumberOfTuples(nr);
    result->SetNumberOfComponents(nc);

    data = new double[nc];

    for(i=0;i<nr;i++)
      {
      for(j=0;j<nc;j++)
        {
        if ( isReal(variable) )
          {
          data[j] = REAL(variable)[j*nr + i];
          }
        else if ( isInteger(variable) )
          {
          data[j] = static_cast<double>(INTEGER(variable)[j*nr + i]);
          }
        else
          {
          vtkErrorMacro(<< "Bad return variable, tried REAL and INTEGER.");
          }
        result->InsertTuple(i,data);
        }
      }

    delete [] data;
    this->vdac->AddItem(result);
    result->Delete();
    return(result);
    }
  else
    {
    return(0);
    }

}

SEXP vtkRAdapter::VTKDataArrayToR(vtkDataArray* da)
{

  SEXP a;
  int nr;
  int nc;
  int i;
  int j;
  double* data;

  nr = da->GetNumberOfTuples();
  nc = da->GetNumberOfComponents();

  PROTECT(a = Rf_allocMatrix(REALSXP,nr,nc));

  for(i=0;i<nr;i++)
    {
    for(j=0;j<nc;j++)
      {
      data = da->GetTuple(i);
      REAL(a)[j*nr + i] = data[j];
      }
    }

  return(a);

}

vtkArray* vtkRAdapter::RToVTKArray(SEXP variable)
{

  int i;
  int ndim;
  SEXP dims;
  vtkArrayExtents extents;
  vtkTypedArray<double>* da;
  da = vtkTypedArray<double>::SafeDownCast(vtkArray::CreateArray(vtkArray::DENSE, VTK_DOUBLE));

  dims = getAttrib(variable, R_DimSymbol);
  ndim = length(dims);

  if (!isMatrix(variable)&&!isArray(variable)&&isVector(variable))
    {
    ndim = 1;
    }

  extents.SetDimensions(ndim);

  if (isMatrix(variable)||isArray(variable))
    {
    for(i=0;i< ndim;i++)
      {
      extents[i] = vtkArrayRange(0,INTEGER(dims)[i]);
      }
    }
  else
    {
    extents[0] = vtkArrayRange(0,length(variable));
    }

  da->Resize(extents);

  vtkArrayCoordinates index;

  index.SetDimensions(ndim);

  for(i=0;i<da->GetSize();i++)
    {
    da->GetCoordinatesN(i,index);
    if ( isReal(variable) )
      {
      da->SetVariantValue(index,REAL(variable)[i]);
      }
    else if ( isInteger(variable) )
      {
      da->SetVariantValue(index,static_cast<double>(INTEGER(variable)[i]));
      }
    else
      {
      vtkErrorMacro(<< "Bad return variable, tried REAL and INTEGER.");
      }
    }

  this->vad->AddArray(da);
  da->Delete();
  return(da);

}

SEXP vtkRAdapter::VTKArrayToR(vtkArray* da)
{

  SEXP a;
  SEXP dim;
  int i;
  vtkArrayCoordinates coords;

  PROTECT(dim = Rf_allocVector(INTSXP, da->GetDimensions()));

  assert(da->GetExtents().ZeroBased());
  for(i=0;i<da->GetDimensions();i++)
    {
    INTEGER(dim)[i] = da->GetExtents()[i].GetSize();
    }

  PROTECT(a = Rf_allocArray(REALSXP, dim));

  for(i=0;i<da->GetSize();i++)
    {
    REAL(a)[i] = 0.0;
    }

  assert(da->GetExtents().ZeroBased());
  for(i=0;i<da->GetNonNullSize();i++)
    {
    da->GetCoordinatesN(i,coords);
    REAL(a)[R_FindArrayIndex(coords,da->GetExtents())] = da->GetVariantValue(coords).ToDouble();
    }

  UNPROTECT(1);

  return(a);

}

SEXP vtkRAdapter::VTKTableToR(vtkTable* table)
{

  SEXP a;
  SEXP b;
  SEXP names;
  int i;
  int j;
  int nr = table->GetNumberOfRows();
  int nc = table->GetNumberOfColumns();
  vtkVariant data;

  PROTECT(a = allocVector(VECSXP, nc));
  PROTECT(names = allocVector(STRSXP, nc));

  for(j=0;j<nc;j++)
    {
    SET_STRING_ELT(names,j,mkChar(table->GetColumn(j)->GetName()));
    if(vtkDataArray::SafeDownCast(table->GetColumn(j)))
      {
      PROTECT(b = allocVector(REALSXP,nr));
      SET_VECTOR_ELT(a,j,b);
      for(i=0;i<nr;i++)
        {
        data = table->GetValue(i,j);
        REAL(b)[i] = data.ToDouble();
        }
      }
    else
      {
      PROTECT(b = allocVector(STRSXP,nr));
      SET_VECTOR_ELT(a,j,b);
      for(i=0;i<nr;i++)
        {
        data = table->GetValue(i,j);
        SET_STRING_ELT(b,i,mkChar(data.ToString().c_str()));
        }
      }
    }

  setAttrib(a,R_NamesSymbol,names);

  return(a);

}

vtkTable* vtkRAdapter::RToVTKTable(SEXP variable)
{

  int i;
  int j;
  int nr;
  int nc;
  SEXP names;
  vtkVariant v;
  vtkTable* result;

  if( isMatrix(variable) )
    {
    nc = Rf_ncols(variable);
    nr = Rf_nrows(variable);
    result = vtkTable::New();

    for(j=0;j<nc;j++)
      {
      vtkDoubleArray* da = vtkDoubleArray::New();
      da->SetNumberOfComponents(1);
      names = getAttrib(variable, R_DimNamesSymbol);
      if(!isNull(names))
        {
        da->SetName(CHAR(STRING_ELT(VECTOR_ELT(names,1),j)));
        }
      else
        {
        v = j;
        da->SetName(v.ToString().c_str());
        }
      for(i=0;i<nr;i++)
        {
        da->InsertNextValue(REAL(variable)[j*nr + i]);
        }
      result->AddColumn(da);
      da->Delete();
      }
    }
  else if( isNewList(variable) )
    {
    nc = length(variable);
    nr = length(VECTOR_ELT(variable,0));
    for(j=1;j<nc;j++)
      {
      if(isReal(VECTOR_ELT(variable,j)) ||
         isInteger(VECTOR_ELT(variable,j)) ||
         isString(VECTOR_ELT(variable,j)) )
        {
        if(length(VECTOR_ELT(variable,j)) != nr)
          {
          vtkGenericWarningMacro(<<"Cannot convert R data type to vtkTable");
          return(0);
          }
        }
      else
        {
        vtkGenericWarningMacro(<<"Cannot convert R data type to vtkTable");
        return(0);
        }
      }

    result = vtkTable::New();
    names = getAttrib(variable, R_NamesSymbol);
    vtkAbstractArray *aa;
    for(j=0;j<nc;j++)
      {
      if(isReal(VECTOR_ELT(variable,j)))
        {
        vtkDoubleArray* da = vtkDoubleArray::New();
        da->SetNumberOfComponents(1);
        aa = da;
        for(i=0;i<nr;i++)
          {
          da->InsertNextValue(REAL(VECTOR_ELT(variable,j))[i]);
          }
        }
      else if(isInteger(VECTOR_ELT(variable,j)))
        {
        vtkIntArray* da = vtkIntArray::New();
        da->SetNumberOfComponents(1);
        aa = da;
        for(i=0;i<nr;i++)
          {
          da->InsertNextValue(INTEGER(VECTOR_ELT(variable,j))[i]);
          }
        }
      else
        {
        vtkStringArray* da = vtkStringArray::New();
        da->SetNumberOfComponents(1);
        aa = da;
        for(i=0;i<nr;i++)
          {
          da->InsertNextValue(CHAR(STRING_ELT(VECTOR_ELT(variable,j),i)));
          }
        }

      if(!isNull(names))
        {
        aa->SetName(CHAR(STRING_ELT(names,j)));
        }
      else
        {
        v = j;
        aa->SetName(v.ToString().c_str());
        }
      result->AddColumn(aa);
      aa->Delete();
      }
    }
  else
    {
    vtkGenericWarningMacro(<<"Cannot convert R data type to vtkTable");
    return(0);
    }

  this->vdoc->AddItem(result);
  result->Delete();
  return(result);

}

void vtkRAdapter::PrintSelf(ostream& os, vtkIndent indent)
{

  this->Superclass::PrintSelf(os,indent);

  if(this->vad)
    {
    this->vad->PrintSelf(os,indent);
    }

  if(this->vdoc)
    {
    this->vdoc->PrintSelf(os,indent);
    }

  if(this->vdac)
    {
    this->vdac->PrintSelf(os,indent);
    }

}

<|endoftext|>


<commit_before>//  Natron
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*
 *Created by Alexandre GAUTHIER-FOICHAT on 6/1/2012.
 *contact: immarespond at gmail dot com
 *
 */

#include "PreferencesPanel.h"

#include <QVBoxLayout>
#include <QDesktopWidget>
#include <QApplication>
#include "Engine/Settings.h"
#include "Gui/DockablePanel.h"
#include "Gui/Button.h"
#include "Gui/Gui.h"
PreferencesPanel::PreferencesPanel(boost::shared_ptr<Settings> settings,Gui *parent)
    : QWidget(parent)
    , _gui(parent)
    , _settings(settings)
{

    setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);

    setWindowFlags(Qt::WindowStaysOnTopHint | Qt::Window);
    setWindowTitle("Preferences");
    _mainLayout = new QVBoxLayout(this);
    _mainLayout->setContentsMargins(0,0,0,0);
    _mainLayout->setSpacing(0);

    _panel = new DockablePanel(_gui,_settings.get(),_mainLayout,DockablePanel::NO_HEADER,true,
                               "","",false,"",this);
    // _panel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    _mainLayout->addWidget(_panel);

    _buttonsContainer = new QWidget(this);
    _buttonsLayout = new QHBoxLayout(_buttonsContainer);
    _buttonsLayout->addStretch();
    _restoreDefaultsB = new Button("Restore default",_buttonsContainer);
    _cancelB = new Button("Cancel",_buttonsContainer);
    _okB = new Button("Save",_buttonsContainer);
    _buttonsLayout->addWidget(_restoreDefaultsB);
    _buttonsLayout->addWidget(_cancelB);
    _buttonsLayout->addWidget(_okB);

    _mainLayout->addStretch();
    _mainLayout->addWidget(_buttonsContainer);

    QObject::connect(_restoreDefaultsB, SIGNAL(clicked()), this, SLOT(restoreDefaults()));
    QObject::connect(_cancelB, SIGNAL(clicked()), this, SLOT(cancelChanges()));
    QObject::connect(_okB, SIGNAL(clicked()), this, SLOT(saveChanges()));

    _panel->initializeKnobs();

    resize(500, 400);

}

void PreferencesPanel::restoreDefaults() {
    Natron::StandardButton reply = Natron::questionDialog("Preferences",
                                        "Restoring the settings will delete any custom configuration, are you sure you want to do this?");
    if (reply == Natron::Yes) {
        _settings->restoreDefault();
    }

}

void PreferencesPanel::cancelChanges() {
    close();
}

void PreferencesPanel::saveChanges() {
    _settings->saveSettings();
    close();
}

void PreferencesPanel::showEvent(QShowEvent* /*e*/) {
    QDesktopWidget* desktop = QApplication::desktop();
    const QRect rect = desktop->screenGeometry();
    move(QPoint(rect.width() / 2 - width() / 2,rect.height() / 2 - height() / 2));
}

void PreferencesPanel::closeEvent(QCloseEvent*) {
    if (_settings->wereChangesMadeSinceLastSave()) {
        _settings->restoreSettings();
    }
}<commit_msg>Preferences: add tooltip<commit_after>//  Natron
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*
 *Created by Alexandre GAUTHIER-FOICHAT on 6/1/2012.
 *contact: immarespond at gmail dot com
 *
 */

#include "PreferencesPanel.h"

#include <QVBoxLayout>
#include <QDesktopWidget>
#include <QApplication>
#include <QTextDocument> // for Qt::convertFromPlainText

#include "Engine/Settings.h"
#include "Gui/DockablePanel.h"
#include "Gui/Button.h"
#include "Gui/Gui.h"

PreferencesPanel::PreferencesPanel(boost::shared_ptr<Settings> settings,Gui *parent)
    : QWidget(parent)
    , _gui(parent)
    , _settings(settings)
{

    setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);

    setWindowFlags(Qt::WindowStaysOnTopHint | Qt::Window);
    setWindowTitle("Preferences");
    _mainLayout = new QVBoxLayout(this);
    _mainLayout->setContentsMargins(0,0,0,0);
    _mainLayout->setSpacing(0);

    _panel = new DockablePanel(_gui,_settings.get(),_mainLayout,DockablePanel::NO_HEADER,true,
                               "","",false,"",this);
    // _panel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    _mainLayout->addWidget(_panel);

    _buttonsContainer = new QWidget(this);
    _buttonsLayout = new QHBoxLayout(_buttonsContainer);
    _buttonsLayout->addStretch();
    _restoreDefaultsB = new Button("Restore defaults",_buttonsContainer);
    _restoreDefaultsB->setToolTip(Qt::convertFromPlainText("Restore default values for all preferences.",Qt::WhiteSpaceNormal));
    _cancelB = new Button("Cancel",_buttonsContainer);
    _okB = new Button("Save",_buttonsContainer);
    _buttonsLayout->addWidget(_restoreDefaultsB);
    _buttonsLayout->addWidget(_cancelB);
    _buttonsLayout->addWidget(_okB);

    _mainLayout->addStretch();
    _mainLayout->addWidget(_buttonsContainer);

    QObject::connect(_restoreDefaultsB, SIGNAL(clicked()), this, SLOT(restoreDefaults()));
    QObject::connect(_cancelB, SIGNAL(clicked()), this, SLOT(cancelChanges()));
    QObject::connect(_okB, SIGNAL(clicked()), this, SLOT(saveChanges()));

    _panel->initializeKnobs();

    resize(500, 400);

}

void PreferencesPanel::restoreDefaults() {
    Natron::StandardButton reply = Natron::questionDialog("Preferences",
                                        "Restoring the settings will delete any custom configuration, are you sure you want to do this?");
    if (reply == Natron::Yes) {
        _settings->restoreDefault();
    }

}

void PreferencesPanel::cancelChanges() {
    close();
}

void PreferencesPanel::saveChanges() {
    _settings->saveSettings();
    close();
}

void PreferencesPanel::showEvent(QShowEvent* /*e*/) {
    QDesktopWidget* desktop = QApplication::desktop();
    const QRect rect = desktop->screenGeometry();
    move(QPoint(rect.width() / 2 - width() / 2,rect.height() / 2 - height() / 2));
}

void PreferencesPanel::closeEvent(QCloseEvent*) {
    if (_settings->wereChangesMadeSinceLastSave()) {
        _settings->restoreSettings();
    }
}<|endoftext|>


<commit_before>#include "StateMachine.h"
#include <algorithm>
#define THREADLESS_STATEMACHINE
bool DriveInstruction::aimTarget(const ObjectPosition &target, Speed &speed, double errorMargin){
	double heading = target.getHeading();
	double distance = target.getDistance();
	if (fabs(heading) > errorMargin){
		speed.rotation = -sign0(heading) * std::min(40.0, std::max(5*log(fabs(heading)), 5.0));
		return false;
	}
	else return fabs(heading) < errorMargin;
}
bool DriveInstruction::catchTarget(const ObjectPosition &target, Speed &speed){
	if (m_pCom->BallInTribbler()) return true;
	double heading = target.getHeading();
	double dist = target.getDistance();
	speed.velocity = 60;
	speed.heading = 0;
	return false;
}

bool DriveInstruction::driveToTarget(const ObjectPosition &target, Speed &speed, double maxDistance){
	double dist = target.getDistance();
	if (dist > maxDistance){
		speed.velocity = std::max(20.0, dist);
		return false;
	}
	else{
		speed.velocity = 20;
		return true;
	}
}

bool DriveInstruction::driveToTargetWithAngle(const ObjectPosition &target, Speed &speed, double maxDistance, double errorMargin){
	double heading = target.getHeading();
	double dist = target.getDistance();
	double velocity = 0;
	double direction = 0;
	double angularSpeed = 0;
	bool onPoint = false;
	if (fabs(heading) > errorMargin){
		if (dist > maxDistance){
			velocity = std::max(30.0, dist); //max speed is limited to 190 in wheelController.cpp
			direction = heading; //drive towards target
			angularSpeed = sign0(heading) * 20; //meanwhile rotate slowly to face the target
		}
		else{ //at location but facing wrong way
			angularSpeed = sign0(heading) * std::max(fabs(heading) * 0.5, 10.0); //rotate
		}
	}
	else{
		if (dist > maxDistance){
			velocity = std::max(30.0, dist);
			direction = heading; //drive towards target
		}
		else onPoint = true;
	}
	speed.velocity = velocity;
	speed.heading = direction;
	speed.rotation = -angularSpeed;
	return onPoint;
}

const BallPosition &DriveInstruction::getClosestBall(bool includeHeading, bool reset){
	return  m_pFieldState->balls.getClosest();
}

StateMachine::StateMachine(ICommunicationModule *pComModule, FieldState *pState,
	const std::map<DriveMode, DriveInstruction*> &driveModes) :driveModes(driveModes), ThreadedClass("Autopilot/StateMachine")
{
	m_pComModule = pComModule;
	m_pFieldState = pState;
	for (auto driveMode : driveModes) driveMode.second->Init(pComModule, pState);
	curDriveMode = this->driveModes.find(DRIVEMODE_IDLE);

}

void StateMachine::setTestMode(DriveMode mode){ testDriveMode = mode; }

void StateMachine::enableTestMode(bool enable)
{
	setTestMode(DRIVEMODE_IDLE);
	testMode = enable;
	if (!testMode) m_pComModule->Drive(0, 0, 0);
}

void StateMachine::StepOnce()
{
#ifdef THREADLESS_STATEMACHINE

	if (!running) return;
	DriveMode newMode = curDriveMode->first;
	curDriveMode->second->onEnter();

	boost::posix_time::ptime time = boost::posix_time::microsec_clock::local_time();
	boost::posix_time::time_duration::tick_type dt = (time - lastStep).total_milliseconds();
	newMode = testMode ? curDriveMode->second->step2(double(dt), newMode) : curDriveMode->second->step1(double(dt), newMode);
	auto old = curDriveMode;
	if (testMode){
		if (testDriveMode != DRIVEMODE_IDLE && newMode == DRIVEMODE_IDLE) newMode = testDriveMode;
		else if (newMode != testDriveMode) {
			newMode = DRIVEMODE_IDLE;
			testDriveMode = DRIVEMODE_IDLE;
		}
	}

	if (newMode != curDriveMode->first){
		boost::mutex::scoped_lock lock(mutex);
		std::cout << "state: " << curDriveMode->second->name;

		curDriveMode->second->onExit();
		curDriveMode = driveModes.find(newMode);
		if (curDriveMode == driveModes.end()){
			curDriveMode = driveModes.find(DRIVEMODE_IDLE);
			std::cout << "-> unknown state: " << newMode << std::endl;
		}
		std::cout << " -> " << curDriveMode->second->name << std::endl;

		curDriveMode->second->onEnter1();
	}
#else
#endif
}

void StateMachine::Run()
{
	lastStep = boost::posix_time::microsec_clock::local_time();
	DriveMode newMode = curDriveMode->first;
	curDriveMode->second->onEnter();
	while (!stop_thread) {
#ifdef THREADLESS_STATEMACHINE
		Sleep(100);
		continue;
#else
		// StepOnce is called from FrontCameraVision
		boost::posix_time::ptime time = boost::posix_time::microsec_clock::local_time();
		boost::posix_time::time_duration::tick_type dt = (time - lastStep).total_milliseconds();
		newMode = testMode ? curDriveMode->second->step2(double(dt), newMode) : curDriveMode->second->step1(double(dt), newMode);
		auto old = curDriveMode;
		if (testMode){
			if (testDriveMode != DRIVEMODE_IDLE && newMode == DRIVEMODE_IDLE) newMode = testDriveMode;
			else if (newMode != testDriveMode) {
				//newMode = DRIVEMODE_IDLE;
				//testDriveMode = DRIVEMODE_IDLE;
			}
		}

		if (newMode != curDriveMode->first){
			boost::mutex::scoped_lock lock(mutex);
			std::cout << "state: " << curDriveMode->second->name;

			curDriveMode->second->onExit();
			curDriveMode = driveModes.find(newMode);
			if (curDriveMode == driveModes.end()){
				curDriveMode = driveModes.find(DRIVEMODE_IDLE);
				std::cout << "-> unknown state: " << newMode << std::endl;
			}
			std::cout << " -> " << curDriveMode->second->name << std::endl;

			curDriveMode->second->onEnter1();
			std::this_thread::sleep_for(std::chrono::milliseconds(50)); // this seems to be neccecary
		}
#endif
	}
}

std::string StateMachine::GetDebugInfo(){
	std::ostringstream oss;
	boost::mutex::scoped_lock lock(mutex);
	oss << "[StateMachine] State: " << curDriveMode->second->name;
	return oss.str();
}

StateMachine::~StateMachine()
{
	WaitForStop();
	for (auto &mode : driveModes){ delete mode.second; }
}

DriveMode DriveInstruction::prevDriveMode = DRIVEMODE_IDLE;
DriveMode DriveInstruction::ACTIVE_DRIVE_TO_BALL_MODE = DRIVEMODE_IDLE;
cv::Point2d DriveInstruction::lastBallPos = cv::Point2d(0,0);

<commit_msg>Threadful stateMachine<commit_after>#include "StateMachine.h"
#include <algorithm>
//#define THREADLESS_STATEMACHINE
bool DriveInstruction::aimTarget(const ObjectPosition &target, Speed &speed, double errorMargin){
	double heading = target.getHeading();
	double distance = target.getDistance();
	if (fabs(heading) > errorMargin){
		speed.rotation = -sign0(heading) * std::min(40.0, std::max(5*log(fabs(heading)), 5.0));
		return false;
	}
	else return fabs(heading) < errorMargin;
}
bool DriveInstruction::catchTarget(const ObjectPosition &target, Speed &speed){
	if (m_pCom->BallInTribbler()) return true;
	double heading = target.getHeading();
	double dist = target.getDistance();
	speed.velocity = 60;
	speed.heading = 0;
	return false;
}

bool DriveInstruction::driveToTarget(const ObjectPosition &target, Speed &speed, double maxDistance){
	double dist = target.getDistance();
	if (dist > maxDistance){
		speed.velocity = std::max(20.0, dist);
		return false;
	}
	else{
		speed.velocity = 20;
		return true;
	}
}

bool DriveInstruction::driveToTargetWithAngle(const ObjectPosition &target, Speed &speed, double maxDistance, double errorMargin){
	double heading = target.getHeading();
	double dist = target.getDistance();
	double velocity = 0;
	double direction = 0;
	double angularSpeed = 0;
	bool onPoint = false;
	if (fabs(heading) > errorMargin){
		if (dist > maxDistance){
			velocity = std::max(30.0, dist); //max speed is limited to 190 in wheelController.cpp
			direction = heading; //drive towards target
			angularSpeed = sign0(heading) * 20; //meanwhile rotate slowly to face the target
		}
		else{ //at location but facing wrong way
			angularSpeed = sign0(heading) * std::max(fabs(heading) * 0.5, 10.0); //rotate
		}
	}
	else{
		if (dist > maxDistance){
			velocity = std::max(30.0, dist);
			direction = heading; //drive towards target
		}
		else onPoint = true;
	}
	speed.velocity = velocity;
	speed.heading = direction;
	speed.rotation = -angularSpeed;
	return onPoint;
}

const BallPosition &DriveInstruction::getClosestBall(bool includeHeading, bool reset){
	return  m_pFieldState->balls.getClosest();
}

StateMachine::StateMachine(ICommunicationModule *pComModule, FieldState *pState,
	const std::map<DriveMode, DriveInstruction*> &driveModes) :driveModes(driveModes), ThreadedClass("Autopilot/StateMachine")
{
	m_pComModule = pComModule;
	m_pFieldState = pState;
	for (auto driveMode : driveModes) driveMode.second->Init(pComModule, pState);
	curDriveMode = this->driveModes.find(DRIVEMODE_IDLE);

}

void StateMachine::setTestMode(DriveMode mode){ testDriveMode = mode; }

void StateMachine::enableTestMode(bool enable)
{
	setTestMode(DRIVEMODE_IDLE);
	testMode = enable;
	if (!testMode) m_pComModule->Drive(0, 0, 0);
}

void StateMachine::StepOnce()
{
#ifdef THREADLESS_STATEMACHINE

	if (!running) return;
	DriveMode newMode = curDriveMode->first;
	curDriveMode->second->onEnter();

	boost::posix_time::ptime time = boost::posix_time::microsec_clock::local_time();
	boost::posix_time::time_duration::tick_type dt = (time - lastStep).total_milliseconds();
	newMode = testMode ? curDriveMode->second->step2(double(dt), newMode) : curDriveMode->second->step1(double(dt), newMode);
	auto old = curDriveMode;
	if (testMode){
		if (testDriveMode != DRIVEMODE_IDLE && newMode == DRIVEMODE_IDLE) newMode = testDriveMode;
		else if (newMode != testDriveMode) {
			newMode = DRIVEMODE_IDLE;
			testDriveMode = DRIVEMODE_IDLE;
		}
	}

	if (newMode != curDriveMode->first){
		boost::mutex::scoped_lock lock(mutex);
		std::cout << "state: " << curDriveMode->second->name;

		curDriveMode->second->onExit();
		curDriveMode = driveModes.find(newMode);
		if (curDriveMode == driveModes.end()){
			curDriveMode = driveModes.find(DRIVEMODE_IDLE);
			std::cout << "-> unknown state: " << newMode << std::endl;
		}
		std::cout << " -> " << curDriveMode->second->name << std::endl;

		curDriveMode->second->onEnter1();
	}
#else
#endif
}

void StateMachine::Run()
{
	lastStep = boost::posix_time::microsec_clock::local_time();
	DriveMode newMode = curDriveMode->first;
	curDriveMode->second->onEnter();
	while (!stop_thread) {
#ifdef THREADLESS_STATEMACHINE
		Sleep(100);
		continue;
#else
		// StepOnce is called from FrontCameraVision
		boost::posix_time::ptime time = boost::posix_time::microsec_clock::local_time();
		boost::posix_time::time_duration::tick_type dt = (time - lastStep).total_milliseconds();
		newMode = testMode ? curDriveMode->second->step2(double(dt), newMode) : curDriveMode->second->step1(double(dt), newMode);
		auto old = curDriveMode;
		if (testMode){
			if (testDriveMode != DRIVEMODE_IDLE && newMode == DRIVEMODE_IDLE) newMode = testDriveMode;
			else if (newMode != testDriveMode) {
				//newMode = DRIVEMODE_IDLE;
				//testDriveMode = DRIVEMODE_IDLE;
			}
		}

		if (newMode != curDriveMode->first){
			boost::mutex::scoped_lock lock(mutex);
			std::cout << "state: " << curDriveMode->second->name;

			curDriveMode->second->onExit();
			curDriveMode = driveModes.find(newMode);
			if (curDriveMode == driveModes.end()){
				curDriveMode = driveModes.find(DRIVEMODE_IDLE);
				std::cout << "-> unknown state: " << newMode << std::endl;
			}
			std::cout << " -> " << curDriveMode->second->name << std::endl;

			curDriveMode->second->onEnter1();
			std::this_thread::sleep_for(std::chrono::milliseconds(50)); // this seems to be neccecary
		}
#endif
	}
}

std::string StateMachine::GetDebugInfo(){
	std::ostringstream oss;
	boost::mutex::scoped_lock lock(mutex);
	oss << "[StateMachine] State: " << curDriveMode->second->name;
	return oss.str();
}

StateMachine::~StateMachine()
{
	WaitForStop();
	for (auto &mode : driveModes){ delete mode.second; }
}

DriveMode DriveInstruction::prevDriveMode = DRIVEMODE_IDLE;
DriveMode DriveInstruction::ACTIVE_DRIVE_TO_BALL_MODE = DRIVEMODE_IDLE;
cv::Point2d DriveInstruction::lastBallPos = cv::Point2d(0,0);

<|endoftext|>