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

#include "cling/Interpreter/Value.h"

#include "cling/Interpreter/Interpreter.h"
#include "cling/Interpreter/Transaction.h"
#include "cling/Interpreter/ValuePrinter.h"
#include "cling/Utils/AST.h"

#include "clang/AST/ASTContext.h"
#include "clang/AST/CanonicalType.h"
#include "clang/AST/Type.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Sema.h"

#include "llvm/Support/raw_os_ostream.h"
#include "llvm/Support/raw_ostream.h"

#include <iostream>
#include <sstream>

namespace {
  ///\brief The allocation starts with this layout; it is followed by the
  ///  value's object at m_Payload. This class does not inherit from
  ///  llvm::RefCountedBase because deallocation cannot use this type but must
  ///  free the character array.

  class AllocatedValue {
  public:
    typedef void (*DtorFunc_t)(void*);

  private:
    ///\brief The reference count - once 0, this object will be deallocated.
    mutable unsigned m_RefCnt;

    ///\brief The destructor function.
    DtorFunc_t m_DtorFunc;

    ///\brief The size of the allocation (for arrays)
    unsigned long m_AllocSize;

    ///\brief The number of elements in the array
    unsigned long m_NElements;

    ///\brief The start of the allocation.
    char m_Payload[1];

    static DtorFunc_t PtrToFunc(void* ptr) {
      union {
        void* m_Ptr;
        DtorFunc_t m_Func;
      };
      m_Ptr = ptr;
      return m_Func;
    }

  public:
    ///\brief Initialize the storage management part of the allocated object.
    ///  The allocator is referencing it, thus initialize m_RefCnt with 1.
    ///\param [in] dtorFunc - the function to be called before deallocation.
    AllocatedValue(void* dtorFunc, size_t allocSize, size_t nElements):
      m_RefCnt(1), m_DtorFunc(PtrToFunc(dtorFunc)), m_AllocSize(allocSize),
      m_NElements(nElements)
    {}

    char* getPayload() { return m_Payload; }

    static unsigned getPayloadOffset() {
      static const AllocatedValue Dummy(0,0,0);
      return Dummy.m_Payload - (const char*)&Dummy;
    }

    static AllocatedValue* getFromPayload(void* payload) {
      return
        reinterpret_cast<AllocatedValue*>((char*)payload - getPayloadOffset());
    }

    void Retain() { ++m_RefCnt; }

    ///\brief This object must be allocated as a char array. Deallocate it as
    ///   such.
    void Release() {
      assert (m_RefCnt > 0 && "Reference count is already zero.");
      if (--m_RefCnt == 0) {
        if (m_DtorFunc) {
          char* payload = getPayload();
          for (size_t el = 0; el < m_NElements; ++el)
            (*m_DtorFunc)(payload + el * m_AllocSize / m_NElements);
        }
        delete [] (char*)this;
      }
    }
  };
}

namespace cling {

Value::Value(const Value& other):
  m_Storage(other.m_Storage), m_Type(other.m_Type),
  m_Interpreter(other.m_Interpreter) {
  if (needsManagedAllocation())
    AllocatedValue::getFromPayload(m_Storage.m_Ptr)->Retain();
}

Value::Value(Value&& other):
  m_Storage(other.m_Storage), m_Type(other.m_Type),
  m_Interpreter(other.m_Interpreter) {
  // Invalidate other so it will not release.
  other.m_Type = 0;
}

Value::Value(clang::QualType clangTy, Interpreter& Interp):
  m_Type(clangTy.getAsOpaquePtr()), m_Interpreter(&Interp) {
  if (needsManagedAllocation())
    ManagedAllocate();
}

Value& Value::operator =(const Value& other) {
  // Release old value.
  if (needsManagedAllocation())
    AllocatedValue::getFromPayload(m_Storage.m_Ptr)->Release();

  // Retain new one.
  m_Type = other.m_Type;
  m_Storage = other.m_Storage;
  m_Interpreter = other.m_Interpreter;
  if (needsManagedAllocation())
    AllocatedValue::getFromPayload(m_Storage.m_Ptr)->Retain();
  return *this;
}

Value& Value::operator =(Value&& other) {
  // Release old value.
  if (needsManagedAllocation())
    AllocatedValue::getFromPayload(m_Storage.m_Ptr)->Release();

  // Move new one.
  m_Type = other.m_Type;
  m_Storage = other.m_Storage;
  m_Interpreter = other.m_Interpreter;
  // Invalidate other so it will not release.
  other.m_Type = 0;

  return *this;
}

Value::~Value() {
  if (needsManagedAllocation())
    AllocatedValue::getFromPayload(m_Storage.m_Ptr)->Release();
}

clang::QualType Value::getType() const {
  return clang::QualType::getFromOpaquePtr(m_Type);
}

clang::ASTContext& Value::getASTContext() const {
  return m_Interpreter->getCI()->getASTContext();
}

bool Value::isValid() const { return !getType().isNull(); }

bool Value::isVoid() const {
  const clang::ASTContext& Ctx = getASTContext();
  return isValid() && Ctx.hasSameType(getType(), Ctx.VoidTy);
}

unsigned long Value::GetNumberOfElements() const {
  if (const clang::ConstantArrayType* ArrTy
      = llvm::dyn_cast<clang::ConstantArrayType>(getType())) {
    llvm::APInt arrSize(sizeof(unsigned long)*8, 1);
    do {
      arrSize *= ArrTy->getSize();
      ArrTy = llvm::dyn_cast<clang::ConstantArrayType>(ArrTy->getElementType()
                                                       .getTypePtr());
    } while (ArrTy);
    return (unsigned long)arrSize.getZExtValue();
  }
  return 1;
}

Value::EStorageType Value::getStorageType() const {
  const clang::Type* desugCanon = getType()->getUnqualifiedDesugaredType();
  desugCanon = desugCanon->getCanonicalTypeUnqualified()->getTypePtr()
    ->getUnqualifiedDesugaredType();
  if (desugCanon->isSignedIntegerOrEnumerationType())
    return kSignedIntegerOrEnumerationType;
  else if (desugCanon->isUnsignedIntegerOrEnumerationType())
    return kUnsignedIntegerOrEnumerationType;
  else if (desugCanon->isRealFloatingType()) {
    const clang::BuiltinType* BT = desugCanon->getAs<clang::BuiltinType>();
    if (BT->getKind() == clang::BuiltinType::Double)
      return kDoubleType;
    else if (BT->getKind() == clang::BuiltinType::Float)
      return kFloatType;
    else if (BT->getKind() == clang::BuiltinType::LongDouble)
      return kLongDoubleType;
  } else if (desugCanon->isPointerType() || desugCanon->isObjectType()
             || desugCanon->isReferenceType())
    return kPointerType;
  return kUnsupportedType;
}

bool Value::needsManagedAllocation() const {
  if (!isValid()) return false;
  const clang::Type* UnqDes = getType()->getUnqualifiedDesugaredType();
  return UnqDes->isRecordType() || UnqDes->isConstantArrayType()
    || UnqDes->isMemberPointerType();
}

void Value::ManagedAllocate() {
  void* dtorFunc = 0;
  clang::QualType DtorType = getType();
  // For arrays we destruct the elements.
  if (const clang::ConstantArrayType* ArrTy
      = llvm::dyn_cast<clang::ConstantArrayType>(DtorType.getTypePtr())) {
    DtorType = ArrTy->getElementType();
  }
  if (const clang::RecordType* RTy = DtorType->getAs<clang::RecordType>())
    dtorFunc = GetDtorWrapperPtr(RTy->getDecl());

  const clang::ASTContext& ctx = getASTContext();
  unsigned payloadSize = ctx.getTypeSizeInChars(getType()).getQuantity();
  char* alloc = new char[AllocatedValue::getPayloadOffset() + payloadSize];
  AllocatedValue* allocVal = new (alloc) AllocatedValue(dtorFunc, payloadSize,
                                                        GetNumberOfElements());
  m_Storage.m_Ptr = allocVal->getPayload();
}

void Value::AssertOnUnsupportedTypeCast() const {
  assert("unsupported type in Value, cannot cast simplistically!" && 0);
}

/// \brief Get the function address of the wrapper of the destructor.
void* Value::GetDtorWrapperPtr(const clang::RecordDecl* RD) const {
  std::string funcname;
  {
    llvm::raw_string_ostream namestr(funcname);
    namestr << "__cling_StoredValue_Destruct_" << RD;
  }

  std::string code("extern \"C\" void ");
  {
    clang::QualType RDQT(RD->getTypeForDecl(), 0);
    std::string typeName
      = utils::TypeName::GetFullyQualifiedName(RDQT, RD->getASTContext());
    std::string dtorName = RD->getNameAsString();
    code += funcname + "(void* obj){((" + typeName + "*)obj)->~"
      + dtorName + "();}";
  }

  return m_Interpreter->compileFunction(funcname, code, true /*ifUniq*/,
                                        false /*withAccessControl*/);
}

  void Value::print(llvm::raw_ostream& Out) const {
    // Try to find user defined printing functions:
    // cling::printType(const void* const p, TY* const u, const Value& V) and
    // cling::printValue(const void* const p, TY* const u, const Value& V)

    using namespace clang;
    Sema& SemaR = m_Interpreter->getSema();
    ASTContext& C = SemaR.getASTContext();
    NamespaceDecl* ClingNSD = utils::Lookup::Namespace(&SemaR, "cling");
    SourceLocation noLoc;
    LookupResult R(SemaR, &C.Idents.get("printType"), noLoc,
                   Sema::LookupOrdinaryName, Sema::ForRedeclaration);
    assert(ClingNSD && "There must be a valid namespace.");

    {
      // Could trigger deserialization of decls.
      cling::Interpreter::PushTransactionRAII RAII(m_Interpreter);
      SemaR.LookupQualifiedName(R, ClingNSD);
      // We commit here because the possibly deserialized decls from the lookup
      // will be needed by evaluate.
    }
    QualType ValueTy = this->getType();
    std::string ValueTyStr = ValueTy.getAsString();
    std::string typeStr;
    std::string valueStr;
    if (!R.empty() && ValueTy->isPointerType()) {
      // There is such a routine call it:
      std::stringstream printTypeSS;
      printTypeSS << "cling::printType(";
      printTypeSS << '(' << ValueTyStr << ')' << this->getPtr() << ',';
      printTypeSS << '(' << ValueTyStr << ')' << this->getPtr() << ',';
      printTypeSS <<"(*(cling::Value*)" << this << "));";
      Value printTypeV;
      m_Interpreter->evaluate(printTypeSS.str(), printTypeV);
      assert(printTypeV.isValid() && "Must return valid value.");
      typeStr = *(std::string*)printTypeV.getPtr();
      // CXXScopeSpec CSS;
      // Expr* UnresolvedLookup
      //   = m_Sema->BuildDeclarationNameExpr(CSS, R, /*ADL*/ false).take();
      // // Build Arg1: const void* const p
      // QualType ConstVoidPtrTy = C.VoidPtrTy.withConst();
      // Expr* Arg1
      //   = utils::Synthesize::CStyleCastPtrExpr(SemaR, ConstVoidPtrTy,
      //                                          (uint64_t)this->getPtr());

      // // Build Arg2: TY* const u
      // Expr* Arg2
      //   = utils::Synthesize::CStyleCastPtrExpr(SemaR, ValueTy,
      //                                          (uint64_t)this->getPtr());

      // // Build Arg3: const Value&
      // RecordDecl* ClingValueDecl
      //   = dyn_cast<RecordDecl>(utils::Lookup::Named(SemaR, "Value",ClingNSD));
      // assert(ClingValueDecl && "Declaration must be found!");
      // QualType ClingValueTy = m_Context->getTypeDeclType(ClingValueDecl);
      // Expr* Arg3
      //   = utils::Synthesize::CStyleCastPtrExpr(m_Sema, ClingValueTy,
      //                                          (uint64_t)this);
      // llvm::SmallVector<Expr*, 4> CallArgs;
      // CallArgs.push_back(Arg1);
      // CallArgs.push_back(Arg2);
      // CallArgs.push_back(Arg3);
      // Expr* Call = m_Sema->ActOnCallExpr(/*Scope*/0, UnresolvedLookup, noLoc,
      //                                    CallArgs, noLoc).take();
    }
    else {
      llvm::raw_string_ostream o(typeStr);
      cling::valuePrinterInternal::printType_Default(o, *this);
    }
    R.clear();
    R.setLookupName(&C.Idents.get("printValue"));
    {
      // Could trigger deserialization of decls.
      cling::Interpreter::PushTransactionRAII RAII(m_Interpreter);
      SemaR.LookupQualifiedName(R, ClingNSD);
      // We commit here because the possibly deserialized decls from the lookup
      // will be needed by evaluate.
    }

    if (!R.empty() && ValueTy->isPointerType()) {
      // There is such a routine call it:
      std::stringstream printValueSS;
      printValueSS << "cling::printValue(";
      printValueSS << '(' << ValueTyStr << ')' << this->getPtr() << ',';
      printValueSS << '(' << ValueTyStr << ')' << this->getPtr() << ',';
      printValueSS <<"(*(cling::Value*)" << this << "));";
      Value printValueV;
      m_Interpreter->evaluate(printValueSS.str(), printValueV);
      assert(printValueV.isValid() && "Must return valid value.");
      valueStr = *(std::string*)printValueV.getPtr();
    }
    else {
      llvm::raw_string_ostream o(valueStr);
      cling::valuePrinterInternal::printValue_Default(o, *this);
    }

    // print the type and the value:
    Out << typeStr + valueStr << "\n";
  }

  void Value::dump() const {
    // We need stream that doesn't close its file descriptor, thus we are not
    // using llvm::outs. Keeping file descriptor open we will be able to use
    // the results in pipes (Savannah #99234).

    // Alternatively we could use llvm::errs()
    llvm::OwningPtr<llvm::raw_ostream> Out;
    Out.reset(new llvm::raw_os_ostream(std::cout));
    print(*Out.get());
  }
} // namespace cling
<commit_msg>Add a simple overload candidate selector.<commit_after>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// author:  Axel Naumann <axel@cern.ch>
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
//------------------------------------------------------------------------------

#include "cling/Interpreter/Value.h"

#include "cling/Interpreter/Interpreter.h"
#include "cling/Interpreter/Transaction.h"
#include "cling/Interpreter/ValuePrinter.h"
#include "cling/Utils/AST.h"

#include "clang/AST/ASTContext.h"
#include "clang/AST/CanonicalType.h"
#include "clang/AST/Type.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Sema.h"

#include "llvm/Support/raw_os_ostream.h"
#include "llvm/Support/raw_ostream.h"

#include <iostream>
#include <sstream>

namespace {
  ///\brief The allocation starts with this layout; it is followed by the
  ///  value's object at m_Payload. This class does not inherit from
  ///  llvm::RefCountedBase because deallocation cannot use this type but must
  ///  free the character array.

  class AllocatedValue {
  public:
    typedef void (*DtorFunc_t)(void*);

  private:
    ///\brief The reference count - once 0, this object will be deallocated.
    mutable unsigned m_RefCnt;

    ///\brief The destructor function.
    DtorFunc_t m_DtorFunc;

    ///\brief The size of the allocation (for arrays)
    unsigned long m_AllocSize;

    ///\brief The number of elements in the array
    unsigned long m_NElements;

    ///\brief The start of the allocation.
    char m_Payload[1];

    static DtorFunc_t PtrToFunc(void* ptr) {
      union {
        void* m_Ptr;
        DtorFunc_t m_Func;
      };
      m_Ptr = ptr;
      return m_Func;
    }

  public:
    ///\brief Initialize the storage management part of the allocated object.
    ///  The allocator is referencing it, thus initialize m_RefCnt with 1.
    ///\param [in] dtorFunc - the function to be called before deallocation.
    AllocatedValue(void* dtorFunc, size_t allocSize, size_t nElements):
      m_RefCnt(1), m_DtorFunc(PtrToFunc(dtorFunc)), m_AllocSize(allocSize),
      m_NElements(nElements)
    {}

    char* getPayload() { return m_Payload; }

    static unsigned getPayloadOffset() {
      static const AllocatedValue Dummy(0,0,0);
      return Dummy.m_Payload - (const char*)&Dummy;
    }

    static AllocatedValue* getFromPayload(void* payload) {
      return
        reinterpret_cast<AllocatedValue*>((char*)payload - getPayloadOffset());
    }

    void Retain() { ++m_RefCnt; }

    ///\brief This object must be allocated as a char array. Deallocate it as
    ///   such.
    void Release() {
      assert (m_RefCnt > 0 && "Reference count is already zero.");
      if (--m_RefCnt == 0) {
        if (m_DtorFunc) {
          char* payload = getPayload();
          for (size_t el = 0; el < m_NElements; ++el)
            (*m_DtorFunc)(payload + el * m_AllocSize / m_NElements);
        }
        delete [] (char*)this;
      }
    }
  };
}

namespace cling {

Value::Value(const Value& other):
  m_Storage(other.m_Storage), m_Type(other.m_Type),
  m_Interpreter(other.m_Interpreter) {
  if (needsManagedAllocation())
    AllocatedValue::getFromPayload(m_Storage.m_Ptr)->Retain();
}

Value::Value(Value&& other):
  m_Storage(other.m_Storage), m_Type(other.m_Type),
  m_Interpreter(other.m_Interpreter) {
  // Invalidate other so it will not release.
  other.m_Type = 0;
}

Value::Value(clang::QualType clangTy, Interpreter& Interp):
  m_Type(clangTy.getAsOpaquePtr()), m_Interpreter(&Interp) {
  if (needsManagedAllocation())
    ManagedAllocate();
}

Value& Value::operator =(const Value& other) {
  // Release old value.
  if (needsManagedAllocation())
    AllocatedValue::getFromPayload(m_Storage.m_Ptr)->Release();

  // Retain new one.
  m_Type = other.m_Type;
  m_Storage = other.m_Storage;
  m_Interpreter = other.m_Interpreter;
  if (needsManagedAllocation())
    AllocatedValue::getFromPayload(m_Storage.m_Ptr)->Retain();
  return *this;
}

Value& Value::operator =(Value&& other) {
  // Release old value.
  if (needsManagedAllocation())
    AllocatedValue::getFromPayload(m_Storage.m_Ptr)->Release();

  // Move new one.
  m_Type = other.m_Type;
  m_Storage = other.m_Storage;
  m_Interpreter = other.m_Interpreter;
  // Invalidate other so it will not release.
  other.m_Type = 0;

  return *this;
}

Value::~Value() {
  if (needsManagedAllocation())
    AllocatedValue::getFromPayload(m_Storage.m_Ptr)->Release();
}

clang::QualType Value::getType() const {
  return clang::QualType::getFromOpaquePtr(m_Type);
}

clang::ASTContext& Value::getASTContext() const {
  return m_Interpreter->getCI()->getASTContext();
}

bool Value::isValid() const { return !getType().isNull(); }

bool Value::isVoid() const {
  const clang::ASTContext& Ctx = getASTContext();
  return isValid() && Ctx.hasSameType(getType(), Ctx.VoidTy);
}

unsigned long Value::GetNumberOfElements() const {
  if (const clang::ConstantArrayType* ArrTy
      = llvm::dyn_cast<clang::ConstantArrayType>(getType())) {
    llvm::APInt arrSize(sizeof(unsigned long)*8, 1);
    do {
      arrSize *= ArrTy->getSize();
      ArrTy = llvm::dyn_cast<clang::ConstantArrayType>(ArrTy->getElementType()
                                                       .getTypePtr());
    } while (ArrTy);
    return (unsigned long)arrSize.getZExtValue();
  }
  return 1;
}

Value::EStorageType Value::getStorageType() const {
  const clang::Type* desugCanon = getType()->getUnqualifiedDesugaredType();
  desugCanon = desugCanon->getCanonicalTypeUnqualified()->getTypePtr()
    ->getUnqualifiedDesugaredType();
  if (desugCanon->isSignedIntegerOrEnumerationType())
    return kSignedIntegerOrEnumerationType;
  else if (desugCanon->isUnsignedIntegerOrEnumerationType())
    return kUnsignedIntegerOrEnumerationType;
  else if (desugCanon->isRealFloatingType()) {
    const clang::BuiltinType* BT = desugCanon->getAs<clang::BuiltinType>();
    if (BT->getKind() == clang::BuiltinType::Double)
      return kDoubleType;
    else if (BT->getKind() == clang::BuiltinType::Float)
      return kFloatType;
    else if (BT->getKind() == clang::BuiltinType::LongDouble)
      return kLongDoubleType;
  } else if (desugCanon->isPointerType() || desugCanon->isObjectType()
             || desugCanon->isReferenceType())
    return kPointerType;
  return kUnsupportedType;
}

bool Value::needsManagedAllocation() const {
  if (!isValid()) return false;
  const clang::Type* UnqDes = getType()->getUnqualifiedDesugaredType();
  return UnqDes->isRecordType() || UnqDes->isConstantArrayType()
    || UnqDes->isMemberPointerType();
}

void Value::ManagedAllocate() {
  void* dtorFunc = 0;
  clang::QualType DtorType = getType();
  // For arrays we destruct the elements.
  if (const clang::ConstantArrayType* ArrTy
      = llvm::dyn_cast<clang::ConstantArrayType>(DtorType.getTypePtr())) {
    DtorType = ArrTy->getElementType();
  }
  if (const clang::RecordType* RTy = DtorType->getAs<clang::RecordType>())
    dtorFunc = GetDtorWrapperPtr(RTy->getDecl());

  const clang::ASTContext& ctx = getASTContext();
  unsigned payloadSize = ctx.getTypeSizeInChars(getType()).getQuantity();
  char* alloc = new char[AllocatedValue::getPayloadOffset() + payloadSize];
  AllocatedValue* allocVal = new (alloc) AllocatedValue(dtorFunc, payloadSize,
                                                        GetNumberOfElements());
  m_Storage.m_Ptr = allocVal->getPayload();
}

void Value::AssertOnUnsupportedTypeCast() const {
  assert("unsupported type in Value, cannot cast simplistically!" && 0);
}

/// \brief Get the function address of the wrapper of the destructor.
void* Value::GetDtorWrapperPtr(const clang::RecordDecl* RD) const {
  std::string funcname;
  {
    llvm::raw_string_ostream namestr(funcname);
    namestr << "__cling_StoredValue_Destruct_" << RD;
  }

  std::string code("extern \"C\" void ");
  {
    clang::QualType RDQT(RD->getTypeForDecl(), 0);
    std::string typeName
      = utils::TypeName::GetFullyQualifiedName(RDQT, RD->getASTContext());
    std::string dtorName = RD->getNameAsString();
    code += funcname + "(void* obj){((" + typeName + "*)obj)->~"
      + dtorName + "();}";
  }

  return m_Interpreter->compileFunction(funcname, code, true /*ifUniq*/,
                                        false /*withAccessControl*/);
}

  void Value::print(llvm::raw_ostream& Out) const {
    // Try to find user defined printing functions:
    // cling::printType(const void* const p, TY* const u, const Value& V) and
    // cling::printValue(const void* const p, TY* const u, const Value& V)

    using namespace clang;
    Sema& SemaR = m_Interpreter->getSema();
    ASTContext& C = SemaR.getASTContext();
    NamespaceDecl* ClingNSD = utils::Lookup::Namespace(&SemaR, "cling");
    SourceLocation noLoc;
    LookupResult R(SemaR, &C.Idents.get("printType"), noLoc,
                   Sema::LookupOrdinaryName, Sema::ForRedeclaration);
    assert(ClingNSD && "There must be a valid namespace.");

    {
      // Could trigger deserialization of decls.
      cling::Interpreter::PushTransactionRAII RAII(m_Interpreter);
      SemaR.LookupQualifiedName(R, ClingNSD);
      // We commit here because the possibly deserialized decls from the lookup
      // will be needed by evaluate.
    }
    QualType ValueTy = this->getType();
    std::string ValueTyStr = ValueTy.getAsString();
    std::string typeStr;
    std::string valueStr;

    bool hasViablePrintTypeCandidate = false;
    if (!R.empty() && ValueTy->isPointerType()) {
      // Check if among the candidates there are functions with the same type:
      const UnresolvedSetImpl& unresolved = R.asUnresolvedSet();
      // FIXME: Find a way to use the 'proper' overload checks.
      for (UnresolvedSetImpl::const_iterator I = unresolved.begin(),
             E = unresolved.end(); I < E; ++I) {
        if (FunctionDecl* FD = dyn_cast<FunctionDecl>(*I))
          if (C.hasSameType(FD->getParamDecl(0)->getType(), ValueTy)) {
              hasViablePrintTypeCandidate = true;
              break;
          }
      }
    }

    if (hasViablePrintTypeCandidate) {
      // There is such a routine call it:
      std::stringstream printTypeSS;
      printTypeSS << "cling::printType(";
      printTypeSS << '(' << ValueTyStr << ')' << this->getPtr() << ',';
      printTypeSS << '(' << ValueTyStr << ')' << this->getPtr() << ',';
      printTypeSS <<"(*(cling::Value*)" << this << "));";
      Value printTypeV;
      m_Interpreter->evaluate(printTypeSS.str(), printTypeV);
      assert(printTypeV.isValid() && "Must return valid value.");
      typeStr = *(std::string*)printTypeV.getPtr();
      // CXXScopeSpec CSS;
      // Expr* UnresolvedLookup
      //   = m_Sema->BuildDeclarationNameExpr(CSS, R, /*ADL*/ false).take();
      // // Build Arg1: const void* const p
      // QualType ConstVoidPtrTy = C.VoidPtrTy.withConst();
      // Expr* Arg1
      //   = utils::Synthesize::CStyleCastPtrExpr(SemaR, ConstVoidPtrTy,
      //                                          (uint64_t)this->getPtr());

      // // Build Arg2: TY* const u
      // Expr* Arg2
      //   = utils::Synthesize::CStyleCastPtrExpr(SemaR, ValueTy,
      //                                          (uint64_t)this->getPtr());

      // // Build Arg3: const Value&
      // RecordDecl* ClingValueDecl
      //   = dyn_cast<RecordDecl>(utils::Lookup::Named(SemaR, "Value",ClingNSD));
      // assert(ClingValueDecl && "Declaration must be found!");
      // QualType ClingValueTy = m_Context->getTypeDeclType(ClingValueDecl);
      // Expr* Arg3
      //   = utils::Synthesize::CStyleCastPtrExpr(m_Sema, ClingValueTy,
      //                                          (uint64_t)this);
      // llvm::SmallVector<Expr*, 4> CallArgs;
      // CallArgs.push_back(Arg1);
      // CallArgs.push_back(Arg2);
      // CallArgs.push_back(Arg3);
      // Expr* Call = m_Sema->ActOnCallExpr(/*Scope*/0, UnresolvedLookup, noLoc,
      //                                    CallArgs, noLoc).take();
    }
    else {
      llvm::raw_string_ostream o(typeStr);
      cling::valuePrinterInternal::printType_Default(o, *this);
    }
    R.clear();
    R.setLookupName(&C.Idents.get("printValue"));
    {
      // Could trigger deserialization of decls.
      cling::Interpreter::PushTransactionRAII RAII(m_Interpreter);
      SemaR.LookupQualifiedName(R, ClingNSD);
      // We commit here because the possibly deserialized decls from the lookup
      // will be needed by evaluate.
    }

    bool hasViablePrintValueCandidate = false;
    if (!R.empty() && ValueTy->isPointerType()) {
      // Check if among the candidates there are functions with the same type:
      const UnresolvedSetImpl& unresolved = R.asUnresolvedSet();
      // FIXME: Find a way to use the 'proper' overload checks.
      for (UnresolvedSetImpl::const_iterator I = unresolved.begin(),
             E = unresolved.end(); I < E; ++I) {
        if (FunctionDecl* FD = dyn_cast<FunctionDecl>(*I))
          if (C.hasSameType(FD->getParamDecl(0)->getType(), ValueTy)) {
              hasViablePrintValueCandidate = true;
              break;
          }
      }
    }
    if (hasViablePrintValueCandidate) {
      // There is such a routine call it:
      std::stringstream printValueSS;
      printValueSS << "cling::printValue(";
      printValueSS << '(' << ValueTyStr << ')' << this->getPtr() << ',';
      printValueSS << '(' << ValueTyStr << ')' << this->getPtr() << ',';
      printValueSS <<"(*(cling::Value*)" << this << "));";
      Value printValueV;
      m_Interpreter->evaluate(printValueSS.str(), printValueV);
      assert(printValueV.isValid() && "Must return valid value.");
      valueStr = *(std::string*)printValueV.getPtr();
    }
    else {
      llvm::raw_string_ostream o(valueStr);
      cling::valuePrinterInternal::printValue_Default(o, *this);
    }

    // print the type and the value:
    Out << typeStr + valueStr << "\n";
  }

  void Value::dump() const {
    // We need stream that doesn't close its file descriptor, thus we are not
    // using llvm::outs. Keeping file descriptor open we will be able to use
    // the results in pipes (Savannah #99234).

    // Alternatively we could use llvm::errs()
    llvm::OwningPtr<llvm::raw_ostream> Out;
    Out.reset(new llvm::raw_os_ostream(std::cout));
    print(*Out.get());
  }
} // namespace cling
<|endoftext|>


<commit_before>#ifndef DENSE_ONE_TO_ONE_HOUGH_HH
#define DENSE_ONE_TO_ONE_HOUGH_HH

#include "openacc.h"
#include "vpp/algorithms/Line_tracker_4_sfm/miscellanous/operations.hh"
#include <opencv2/highgui.hpp>
#include <opencv2/videoio.hpp>
#include <vpp/vpp.hh>
#include <Eigen/Core>
#include <vpp/utils/opencv_bridge.hh>
#include <iod/timer.hh>

using namespace vpp;
using namespace std;
using namespace Eigen;
using namespace iod;
using namespace cv;

namespace vpp{

#define Two_PI 2*M_PI

std::list<vint2> Hough_Lines_Parallel(image2d<uchar> img,
                                      std::vector<float>& t_accumulator,
                                      int Theta_max, float& max_of_the_accu
                                      ,  image2d<uchar> &out
                                      , std::vector<std::list<vint2> > &points50);
std::list<vint2> Hough_Lines_Parallel_Kmeans(image2d<uchar> img,
                                      std::vector<float>& t_accumulator,
                                      int Theta_max,int rhomax, float& max_of_the_accu
                                      ,  image2d<uchar> &grad_img );
std::list<vint2> Hough_Lines_Parallel(image2d<uchar> img,
                                      std::vector<float>& t_accumulator,
                                      int Theta_max, float& max_of_the_accu
                                      ,  image2d<uchar> &grad_img, std::vector<vint4>& extremites);
std::list<vint2> Hough_Lines_Parallel(image2d<uchar> img,
                                      std::vector<float>& t_accumulator,
                                      int Theta_max, float& max_of_the_accu
                                      ,  image2d<uchar> &grad_img);
std::list<vint2> Hough_Lines_Parallel_Update_Threshold(image2d<uchar> img,
                                      std::vector<float>& t_accumulator,
                                      int Theta_max,int rhomax, float& max_of_the_accu
                                      ,  image2d<uchar> &grad_img , float& grad_threshold , int N);
std::list<vint2> Hough_Lines_Parallel_Sparse(image2d<uchar> img,
                                      std::vector<float>& t_accumulator,
                                      int Theta_max, int rhomax, float& max_of_the_accu
                                      ,  image2d<uchar> &grad_img , float grad_threshold , int N);
std::list<vint2> Hough_Lines_Parallel_Sparse1(image2d<uchar> img,
                                      std::vector<float>& t_accumulator,
                                      int Theta_max, float& max_of_the_accu
                                      ,  image2d<uchar> &grad_img);
std::list<vint2> Hough_Lines_Parallel(image2d<uchar> img,
                                      std::vector<float>& t_accumulator,
                                      int Theta_max, int rhomax, float& max_of_the_accu
                                      ,  image2d<uchar> &grad_img , float acc_threshold);

std::list<vint2> Hough_Lines_Parallel_one(Mat bv,
                                      std::vector<float>& t_accumulator,
                                      int Theta_max, float& max_of_the_accu
                                      ,  Mat &grad_img);

std::list<vint2> Hough_Lines_Parallel_one(image2d<uchar> img, Mat bv,
                           std::vector<float>& t_accumulator,
                           int Theta_max, float& max_of_the_accu
                           ,  Mat &grad_img , std::vector<LineIterator> list_interest);

void Hough_Lines_Sequentiel(image2d<vuchar1> img,int sigma,int nbsigma,std::vector<float>& t_accumulator, int nrows, int ncols);

std::list<vint2> Hough_Lines_Parallel_Gradient(image2d<uchar> img,
                                          std::vector<float>& t_accumulator,
                                          int Theta_max, float& max_of_the_accu,
                                               image2d<uchar> &grad_img, std::vector<vint4> &points50);
std::list<vint2> Hough_Lines_Parallel_Basic(image2d<uchar> img,
                                      std::vector<float>& t_accumulator,
                                      int Theta_max, float& max_of_the_accu);
std::priority_queue<vint2> Hough_Lines_Parallel_V3(image2d<vuchar1> img,
                                      std::vector<float>& t_accumulator,
                                      int Theta_max, float& max_of_the_accu, int threshold,
                                         image2d<vuchar3> &cluster_colors , int nb_old);
void adap_thresold(std::list<vfloat3> &list_temp , float &threshold_hough , int &calls ,
                   int &nb_calls_limits_reached , int rhomax, int T_theta, std::vector<float> t_accumulator);
void reduce_number_of_max_local(std::list<vfloat3> &list_temp , float threshold_hough , int rhomax, int T_theta , std::vector<float> t_accumulator);

void Hough_Lines_Parallel_Map(image2d<vuchar1> img);

}
#include "dense_one_to_one_hough.hpp"

#endif // DENSE_ONE_TO_ONE_HOUGH_HH
<commit_msg>Update dense_one_to_one_hough.hh<commit_after>#pragma once

#include "openacc.h"
#include "vpp/algorithms/Line_tracker_4_sfm/miscellanous/operations.hh"
#include <opencv2/highgui.hpp>
#include <opencv2/videoio.hpp>
#include <vpp/vpp.hh>
#include <Eigen/Core>
#include <vpp/utils/opencv_bridge.hh>
#include <iod/timer.hh>

using namespace vpp;
using namespace std;
using namespace Eigen;
using namespace iod;
using namespace cv;

namespace vpp{

#define Two_PI 2*M_PI

std::list<vint2> Hough_Lines_Parallel(image2d<uchar> img,
                                      std::vector<float>& t_accumulator,
                                      int Theta_max, float& max_of_the_accu
                                      ,  image2d<uchar> &out
                                      , std::vector<std::list<vint2> > &points50);
std::list<vint2> Hough_Lines_Parallel_Kmeans(image2d<uchar> img,
                                      std::vector<float>& t_accumulator,
                                      int Theta_max,int rhomax, float& max_of_the_accu
                                      ,  image2d<uchar> &grad_img );
std::list<vint2> Hough_Lines_Parallel(image2d<uchar> img,
                                      std::vector<float>& t_accumulator,
                                      int Theta_max, float& max_of_the_accu
                                      ,  image2d<uchar> &grad_img, std::vector<vint4>& extremites);
std::list<vint2> Hough_Lines_Parallel(image2d<uchar> img,
                                      std::vector<float>& t_accumulator,
                                      int Theta_max, float& max_of_the_accu
                                      ,  image2d<uchar> &grad_img);
std::list<vint2> Hough_Lines_Parallel_Update_Threshold(image2d<uchar> img,
                                      std::vector<float>& t_accumulator,
                                      int Theta_max,int rhomax, float& max_of_the_accu
                                      ,  image2d<uchar> &grad_img , float& grad_threshold , int N);
std::list<vint2> Hough_Lines_Parallel_Sparse(image2d<uchar> img,
                                      std::vector<float>& t_accumulator,
                                      int Theta_max, int rhomax, float& max_of_the_accu
                                      ,  image2d<uchar> &grad_img , float grad_threshold , int N);
std::list<vint2> Hough_Lines_Parallel_Sparse1(image2d<uchar> img,
                                      std::vector<float>& t_accumulator,
                                      int Theta_max, float& max_of_the_accu
                                      ,  image2d<uchar> &grad_img);
std::list<vint2> Hough_Lines_Parallel(image2d<uchar> img,
                                      std::vector<float>& t_accumulator,
                                      int Theta_max, int rhomax, float& max_of_the_accu
                                      ,  image2d<uchar> &grad_img , float acc_threshold);

std::list<vint2> Hough_Lines_Parallel_one(Mat bv,
                                      std::vector<float>& t_accumulator,
                                      int Theta_max, float& max_of_the_accu
                                      ,  Mat &grad_img);

std::list<vint2> Hough_Lines_Parallel_one(image2d<uchar> img, Mat bv,
                           std::vector<float>& t_accumulator,
                           int Theta_max, float& max_of_the_accu
                           ,  Mat &grad_img , std::vector<LineIterator> list_interest);

void Hough_Lines_Sequentiel(image2d<vuchar1> img,int sigma,int nbsigma,std::vector<float>& t_accumulator, int nrows, int ncols);

std::list<vint2> Hough_Lines_Parallel_Gradient(image2d<uchar> img,
                                          std::vector<float>& t_accumulator,
                                          int Theta_max, float& max_of_the_accu,
                                               image2d<uchar> &grad_img, std::vector<vint4> &points50);
std::list<vint2> Hough_Lines_Parallel_Basic(image2d<uchar> img,
                                      std::vector<float>& t_accumulator,
                                      int Theta_max, float& max_of_the_accu);
std::priority_queue<vint2> Hough_Lines_Parallel_V3(image2d<vuchar1> img,
                                      std::vector<float>& t_accumulator,
                                      int Theta_max, float& max_of_the_accu, int threshold,
                                         image2d<vuchar3> &cluster_colors , int nb_old);
void adap_thresold(std::list<vfloat3> &list_temp , float &threshold_hough , int &calls ,
                   int &nb_calls_limits_reached , int rhomax, int T_theta, std::vector<float> t_accumulator);
void reduce_number_of_max_local(std::list<vfloat3> &list_temp , float threshold_hough , int rhomax, int T_theta , std::vector<float> t_accumulator);

void Hough_Lines_Parallel_Map(image2d<vuchar1> img);

}
#include "dense_one_to_one_hough.hpp"

<|endoftext|>


<commit_before>/******************************************************************************
 * This file is part of the Gluon Development Platform
 * Copyright (c) 2010 Arjen Hiemstra <ahiemstra@heimr.nl>
 * Copyright (c) 2011 Giulio Camuffo <giuliocamuffo@gmail.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "uimanagercomponent.h"

#include <core/debughelper.h>
#include <graphics/item.h>
#include <graphics/engine.h>
#include <graphics/item.h>
#include <graphics/material.h>
#include <graphics/mesh.h>
#include <graphics/rendertarget.h>
#include <graphics/materialinstance.h>
#include <engine/gameobject.h>
#include <engine/asset.h>

#include <QtCore/QMimeData>
#include <QtCore/QVariant>
#include <QtGui/QMatrix4x4>
#include <QtGui/QColor>
#include <QtGui/QGraphicsView>
#include <QtGui/QGraphicsScene>
#include <QtGui/QGraphicsWidget>
#include <QtGui/QPixmap>
#include <QtOpenGL/QGLFramebufferObject>
#include <QtDeclarative/QDeclarativeEngine>
#include <QtDeclarative/QDeclarativeExpression>
#include <QtDeclarative/QDeclarativeContext>
#include <QtDeclarative/qdeclarative.h>
#include <QtScript/QScriptValue>
#include <QtScript/QScriptEngine>
#include <QtScript/QScriptValueIterator>
#include <texture.h>
#include <game.h>

#include "uiasset.h"
#include "engineaccess.h"
#include "renderablescene.h"

REGISTER_OBJECTTYPE( GluonEngine, UiManagerComponent )

using namespace GluonEngine;
using namespace GluonGraphics;

template <typename Tp>
QScriptValue scriptValueFromQObject( QScriptEngine *engine, Tp const& qobject)
{
    return engine->newQObject( qobject );
}

template <typename Tp>
void scriptValueToQObject(const QScriptValue &value, Tp &qobject)
{
    qobject = qobject_cast<Tp>( value.toQObject() );
}

template <typename Tp>
int qScriptRegisterQObjectMetaType( QScriptEngine *engine )
{
    return qScriptRegisterMetaType<Tp>( engine, scriptValueFromQObject, scriptValueToQObject );
}

class UiManagerComponent::UiManagerComponentPrivate
{
    public:
        UiManagerComponentPrivate( UiManagerComponent *component )
            : q(component)
            , scene(0)
            , ui(0)
            , updateFunction(0)
        {
        }

        void setupBindings( QScriptEngine* engine )
        {
            //FIXME: this code is duplicated with the scripting conponent.
            //It should be moved to a common place.

            engine->importExtension( "jsmoke.qtcore" );
            engine->importExtension( "jsmoke.qtgui" );
            engine->importExtension( "jsmoke.qtopengl" );

            qScriptRegisterQObjectMetaType<GameObject*>( engine );
            qScriptRegisterQObjectMetaType<GluonObject*>( engine );
            qScriptRegisterQObjectMetaType<Component*>( engine );
            qScriptRegisterQObjectMetaType<Asset*>( engine );
            qScriptRegisterQObjectMetaType<Scene*>( engine );
            qScriptRegisterQObjectMetaType<GameProject*>( engine );

            QScriptEngine::QObjectWrapOptions wrapOptions = QScriptEngine::AutoCreateDynamicProperties | QScriptEngine::ExcludeDeleteLater | QScriptEngine::PreferExistingWrapperObject;
            QScriptEngine::ValueOwnership ownership = QScriptEngine::QtOwnership;
            QScriptValue object = engine->globalObject();

            QScriptValue component = engine->newQObject( q, ownership, wrapOptions );
            object.setProperty( "Component", component );

            QScriptValue gameObj = engine->newQObject( q->gameObject(), ownership, wrapOptions );
            object.setProperty( "GameObject", gameObj );

            QScriptValue sceneObj = engine->newQObject( q->gameObject()->scene(), ownership, wrapOptions );
            object.setProperty( "Scene", sceneObj );

            QScriptValue gameProjectObj = engine->newQObject( GluonEngine::Game::instance()->gameProject(), ownership, wrapOptions );
            object.setProperty( "GameProject", gameProjectObj );

            QScriptValue game = engine->newQObject( GluonEngine::Game::instance(), ownership, wrapOptions );
            object.setProperty( "Game", game );
        }

        UiManagerComponent* q;
        QPixmap pixmap;
        QGraphicsView* view;
        RenderableScene* scene;
        UiAsset *ui;
        QSizeF size;
        Item *item;
        EngineAccess* engineAccess;

        QDeclarativeExpression *updateFunction;
};

UiManagerComponent::UiManagerComponent( QObject* parent )
    : Component( parent )
    , d( new UiManagerComponentPrivate( this ) )
{

}

UiManagerComponent::UiManagerComponent( const UiManagerComponent& other )
    : Component( other )
    , d( other.d )
{
}

UiManagerComponent::~UiManagerComponent()
{
    delete d;
}

QString UiManagerComponent::category() const
{
    return QString( "Graphics Rendering" );
}

void UiManagerComponent::initialize()
{
//     d->fbo = GluonGraphics::Engine::instance()->fbo();
//     d->pixmap = QPixmap( widget->size() );
//     d->pixmap.fill( Qt::transparent );
//     d->view->setParent(widget->parentWidget());
//     d->view->setAttribute(Qt::WA_TranslucentBackground);
//     d->view->setAttribute(Qt::WA_NoSystemBackground);
//     d->view->viewport()->setAttribute(Qt::WA_TranslucentBackground);
//     d->view->viewport()->setAttribute(Qt::WA_NoSystemBackground);
//     d->view->setStyleSheet("border: none");
//     QPalette p = d->view->viewport()->palette();
//     p.setColor(QPalette::Base, Qt::transparent);
//     d->view->viewport()->setPalette(p);
//     d->view->setScene(d->scene);
//     d->view->setSceneRect(QRectF(0,0,1000,1000));

//     d->view->resize(widget->size());
//     d->view->show();
//     d->scene->setBackgroundBrush(Qt::blue);

//     d->texture = widget->bindTexture(d->pixmap);
//     widget->update();
//     widget->updateGL();
//     widget->makeCurrent();

    if( !d->scene )
    {
        d->scene = new RenderableScene( this );
        d->scene->setSceneRect(QRectF(QPointF(0,0), QSize(1024,768)));
    }

    if( d->ui && !d->ui->isLoaded() )
    {
        qmlRegisterType<GluonEngine::GameObject>("org.kde.gluon", 1, 0, "GameObject" );
        qmlRegisterInterface<GluonEngine::GameObject>("gameObject");

        d->ui->load();

        QDeclarativeEngine* engine = d->ui->engine();

        d->engineAccess = new EngineAccess(this);
        engine->rootContext()->setContextProperty( "__engineAccess", d->engineAccess );

        //Glorious hack:steal the engine
        QDeclarativeExpression *expr = new QDeclarativeExpression( engine->rootContext(), d->ui->widget(),
                                                                   "__engineAccess.setEngine( this )" );
        expr->evaluate();
        delete expr;
    }

    if( d->ui && d->ui->isLoaded() )
    {

        d->ui->execute();

        QGraphicsWidget* gWidget = d->ui->widget();
        if( gWidget )
        {
            d->scene->addItem( gWidget );

            d->updateFunction = new QDeclarativeExpression( d->ui->engine()->rootContext(),
                                                            d->ui->widget(), "update()" );
        }
    }
}

void UiManagerComponent::setScriptEngine( QScriptValue &value )
{
    QScriptEngine* engine = value.engine();

    QScriptValue originalGlobalObject = engine->globalObject();
    QScriptValue newGlobalObject = engine->newObject();

    QString eval = QLatin1String( "eval" );
    QString version = QLatin1String( "version" );

    QScriptValueIterator iter( originalGlobalObject );
    QVector<QString> names;
    QVector<QScriptValue> values;
    QVector<QScriptValue::PropertyFlags> flags;
    while ( iter.hasNext() )
    {
        iter.next();

        QString name = iter.name();

        if ( name == version )
        {
            continue;
        }

        if ( name != eval )
        {
            names.append( name );
            values.append( iter.value() );
            flags.append( iter.flags() | QScriptValue::Undeletable );
        }
        newGlobalObject.setProperty( iter.scriptName(), iter.value() );
    }

    engine->setGlobalObject( newGlobalObject );

    d->setupBindings( engine );

    delete d->engineAccess;
    d->ui->engine()->rootContext()->setContextProperty( "__engineAccess", 0 );
}

void UiManagerComponent::start()
{

}

void UiManagerComponent::draw( int timeLapse )
{
    Q_UNUSED( timeLapse )

    if( !d->scene || !d->ui || !d->ui->widget() )
    {
        return;
    }

    d->scene->renderScene();
}

void UiManagerComponent::update( int elapsedMilliseconds )
{
    if( d->updateFunction )
    {
        d->updateFunction->evaluate();

        if( d->updateFunction->hasError() )
        {
            debug( d->updateFunction->error().toString() );
        }
    }
}

void UiManagerComponent::cleanup()
{
    if( !d->ui )
    {
        return;
    }

    QGraphicsWidget* widget = d->ui->widget();
    if( d->scene && widget && widget->scene() == d->scene )
    {
        d->scene->removeItem( widget );
    }

    delete d->scene;
    d->scene = 0;

    delete d->updateFunction;
    d->updateFunction = 0;
}

void UiManagerComponent::setUi(UiAsset* ui)
{
    d->ui = ui;
}

UiAsset* UiManagerComponent::ui() const
{
    return d->ui;
}

void UiManagerComponent::setSize( const QSizeF& size )
{
    d->size = size;
}

QSizeF UiManagerComponent::size() const
{
    return d->size;
}

Q_EXPORT_PLUGIN2( gluon_component_uimanager, GluonEngine::UiManagerComponent );

#include "uimanagercomponent.moc"
<commit_msg>Cleanings.<commit_after>/******************************************************************************
 * This file is part of the Gluon Development Platform
 * Copyright (c) 2010 Arjen Hiemstra <ahiemstra@heimr.nl>
 * Copyright (c) 2011 Giulio Camuffo <giuliocamuffo@gmail.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "uimanagercomponent.h"

#include <core/debughelper.h>
#include <graphics/item.h>
#include <graphics/engine.h>
#include <graphics/item.h>
#include <graphics/material.h>
#include <graphics/mesh.h>
#include <graphics/rendertarget.h>
#include <graphics/materialinstance.h>
#include <engine/gameobject.h>
#include <engine/asset.h>

#include <QtCore/QMimeData>
#include <QtCore/QVariant>
#include <QtGui/QMatrix4x4>
#include <QtGui/QColor>
#include <QtGui/QGraphicsView>
#include <QtGui/QGraphicsScene>
#include <QtGui/QGraphicsWidget>
#include <QtGui/QPixmap>
#include <QtOpenGL/QGLFramebufferObject>
#include <QtDeclarative/QDeclarativeEngine>
#include <QtDeclarative/QDeclarativeExpression>
#include <QtDeclarative/QDeclarativeContext>
#include <QtDeclarative/qdeclarative.h>
#include <QtScript/QScriptValue>
#include <QtScript/QScriptEngine>
#include <QtScript/QScriptValueIterator>
#include <texture.h>
#include <game.h>

#include "uiasset.h"
#include "engineaccess.h"
#include "renderablescene.h"

REGISTER_OBJECTTYPE( GluonEngine, UiManagerComponent )

using namespace GluonEngine;
using namespace GluonGraphics;

template <typename Tp>
QScriptValue scriptValueFromQObject( QScriptEngine *engine, Tp const& qobject)
{
    return engine->newQObject( qobject );
}

template <typename Tp>
void scriptValueToQObject(const QScriptValue &value, Tp &qobject)
{
    qobject = qobject_cast<Tp>( value.toQObject() );
}

template <typename Tp>
int qScriptRegisterQObjectMetaType( QScriptEngine *engine )
{
    return qScriptRegisterMetaType<Tp>( engine, scriptValueFromQObject, scriptValueToQObject );
}

class UiManagerComponent::UiManagerComponentPrivate
{
    public:
        UiManagerComponentPrivate( UiManagerComponent *component )
            : q(component)
            , scene(0)
            , ui(0)
            , updateFunction(0)
        {
        }

        void setupBindings( QScriptEngine* engine )
        {
            //FIXME: this code is duplicated with the scripting conponent.
            //It should be moved to a common place.

            engine->importExtension( "jsmoke.qtcore" );
            engine->importExtension( "jsmoke.qtgui" );
            engine->importExtension( "jsmoke.qtopengl" );

            qScriptRegisterQObjectMetaType<GameObject*>( engine );
            qScriptRegisterQObjectMetaType<GluonObject*>( engine );
            qScriptRegisterQObjectMetaType<Component*>( engine );
            qScriptRegisterQObjectMetaType<Asset*>( engine );
            qScriptRegisterQObjectMetaType<Scene*>( engine );
            qScriptRegisterQObjectMetaType<GameProject*>( engine );

            QScriptEngine::QObjectWrapOptions wrapOptions = QScriptEngine::AutoCreateDynamicProperties | QScriptEngine::ExcludeDeleteLater | QScriptEngine::PreferExistingWrapperObject;
            QScriptEngine::ValueOwnership ownership = QScriptEngine::QtOwnership;
            QScriptValue object = engine->globalObject();

            QScriptValue component = engine->newQObject( q, ownership, wrapOptions );
            object.setProperty( "Component", component );

            QScriptValue gameObj = engine->newQObject( q->gameObject(), ownership, wrapOptions );
            object.setProperty( "GameObject", gameObj );

            QScriptValue sceneObj = engine->newQObject( q->gameObject()->scene(), ownership, wrapOptions );
            object.setProperty( "Scene", sceneObj );

            QScriptValue gameProjectObj = engine->newQObject( GluonEngine::Game::instance()->gameProject(), ownership, wrapOptions );
            object.setProperty( "GameProject", gameProjectObj );

            QScriptValue game = engine->newQObject( GluonEngine::Game::instance(), ownership, wrapOptions );
            object.setProperty( "Game", game );
        }

        UiManagerComponent* q;
        RenderableScene* scene;
        UiAsset *ui;
        QSizeF size;
        Item *item;
        EngineAccess* engineAccess;

        QDeclarativeExpression *updateFunction;
};

UiManagerComponent::UiManagerComponent( QObject* parent )
    : Component( parent )
    , d( new UiManagerComponentPrivate( this ) )
{

}

UiManagerComponent::UiManagerComponent( const UiManagerComponent& other )
    : Component( other )
    , d( other.d )
{
}

UiManagerComponent::~UiManagerComponent()
{
    delete d;
}

QString UiManagerComponent::category() const
{
    return QString( "Graphics Rendering" );
}

void UiManagerComponent::initialize()
{
    if( !d->scene )
    {
        d->scene = new RenderableScene( this );
        d->scene->setSceneRect(QRectF(QPointF(0,0), QSize(1024,768)));
    }

    if( d->ui && !d->ui->isLoaded() )
    {
        qmlRegisterType<GluonEngine::GameObject>("org.kde.gluon", 1, 0, "GameObject" );
        qmlRegisterInterface<GluonEngine::GameObject>("gameObject");

        d->ui->load();

        QDeclarativeEngine* engine = d->ui->engine();

        d->engineAccess = new EngineAccess(this);
        engine->rootContext()->setContextProperty( "__engineAccess", d->engineAccess );

        //Glorious hack:steal the engine
        QDeclarativeExpression *expr = new QDeclarativeExpression( engine->rootContext(), d->ui->widget(),
                                                                   "__engineAccess.setEngine( this )" );
        expr->evaluate();
        delete expr;
    }

    if( d->ui && d->ui->isLoaded() )
    {
        d->ui->execute();

        QGraphicsWidget* gWidget = d->ui->widget();
        if( gWidget )
        {
            d->scene->addItem( gWidget );

            d->updateFunction = new QDeclarativeExpression( d->ui->engine()->rootContext(),
                                                            d->ui->widget(), "update()" );
        }
    }
}

void UiManagerComponent::setScriptEngine( QScriptValue &value )
{
    QScriptEngine* engine = value.engine();

    QScriptValue originalGlobalObject = engine->globalObject();
    QScriptValue newGlobalObject = engine->newObject();

    QString eval = QLatin1String( "eval" );
    QString version = QLatin1String( "version" );

    QScriptValueIterator iter( originalGlobalObject );
    QVector<QString> names;
    QVector<QScriptValue> values;
    QVector<QScriptValue::PropertyFlags> flags;
    while ( iter.hasNext() )
    {
        iter.next();

        QString name = iter.name();

        if ( name == version )
        {
            continue;
        }

        if ( name != eval )
        {
            names.append( name );
            values.append( iter.value() );
            flags.append( iter.flags() | QScriptValue::Undeletable );
        }
        newGlobalObject.setProperty( iter.scriptName(), iter.value() );
    }

    engine->setGlobalObject( newGlobalObject );

    d->setupBindings( engine );

    delete d->engineAccess;
    d->ui->engine()->rootContext()->setContextProperty( "__engineAccess", 0 );
}

void UiManagerComponent::start()
{

}

void UiManagerComponent::draw( int timeLapse )
{
    Q_UNUSED( timeLapse )

    if( !d->scene || !d->ui || !d->ui->widget() )
    {
        return;
    }

    d->scene->renderScene();
}

void UiManagerComponent::update( int elapsedMilliseconds )
{
    if( d->updateFunction )
    {
        d->updateFunction->evaluate();

        if( d->updateFunction->hasError() )
        {
            debug( d->updateFunction->error().toString() );
        }
    }
}

void UiManagerComponent::cleanup()
{
    if( !d->ui )
    {
        return;
    }

    QGraphicsWidget* widget = d->ui->widget();
    if( d->scene && widget && widget->scene() == d->scene )
    {
        d->scene->removeItem( widget );
    }

    delete d->scene;
    d->scene = 0;

    delete d->updateFunction;
    d->updateFunction = 0;
}

void UiManagerComponent::setUi(UiAsset* ui)
{
    d->ui = ui;
}

UiAsset* UiManagerComponent::ui() const
{
    return d->ui;
}

void UiManagerComponent::setSize( const QSizeF& size )
{
    d->size = size;
}

QSizeF UiManagerComponent::size() const
{
    return d->size;
}

Q_EXPORT_PLUGIN2( gluon_component_uimanager, GluonEngine::UiManagerComponent );

#include "uimanagercomponent.moc"
<|endoftext|>


<commit_before>/**
 *	\file
 */

#pragma once

#include <rleahylib/rleahylib.hpp>
#include <traits.hpp>
#include <cstddef>
#include <new>
#include <type_traits>
#include <utility>

namespace MCPP {

	/**
	 *	\cond
	 */

	namespace VariantImpl {

		template <typename...>
		class MaxAlignOfImpl {	};

		template <>
		class MaxAlignOfImpl<> {

			public:

				constexpr static Word Value=0;

		};

		template <typename T, typename... Args>
		class MaxAlignOfImpl<T,Args...> {

			private:

				constexpr static Word next=MaxAlignOfImpl<Args...>::Value;

			public:

				constexpr static Word Value=(alignof(T)>next) ? alignof(T) : next;

		};

		template <typename...>
		class MaxSizeOfImpl {	};

		template <>
		class MaxSizeOfImpl<> {

			public:

				constexpr static Word Value=0;

		};

		template <typename T, typename... Args>
		class MaxSizeOfImpl<T,Args...> {

			private:

				constexpr static Word next=MaxSizeOfImpl<Args...>::Value;

			public:

				constexpr static Word Value=(sizeof(T)>next) ? sizeof(T) : next;

		};

		template <Word, typename, typename...>
		class FindTypeImpl {	};

		template <Word i, typename T>
		class FindTypeImpl<i,T> {

			public:

				constexpr static Word Value=i;

		};

		template <Word i, typename T, typename Curr, typename... Args>
		class FindTypeImpl<i,T,Curr,Args...> {

			public:

				constexpr static Word Value=std::is_same<
					typename std::decay<T>::type,
					typename std::decay<Curr>::type
				>::value ? i : FindTypeImpl<i+1,T,Args...>::Value;

		};

		template <typename...>
		class NoThrowCopyableImpl {	};

		template <typename T, typename... Args>
		class NoThrowCopyableImpl<T,Args...> {

			public:

				constexpr static bool Value=std::is_nothrow_copy_constructible<T>::value ? NoThrowCopyableImpl<Args...>::Value : false;

		};

		template <>
		class NoThrowCopyableImpl<> {

			public:

				constexpr static bool Value=true;

		};

		template <typename...>
		class NoThrowMovableImpl {	};

		template <typename T, typename... Args>
		class NoThrowMovableImpl<T,Args...> {

			public:

				constexpr static bool Value=std::is_nothrow_move_constructible<T>::value ? NoThrowMovableImpl<Args...>::Value : false;

		};

		template <>
		class NoThrowMovableImpl<> {

			public:

				constexpr static bool Value=true;

		};

		template <typename... Args>
		class VariantInfo {

			public:

				template <Word i>
				class Types {

					public:

						typedef typename std::decay<typename GetType<i,Args...>::Type>::type Type;

				};

				template <typename T>
				class FindType {

					public:

						constexpr static Word Value=FindTypeImpl<0,T,Args...>::Value;

				};

				constexpr static Word MaxAlignOf=MaxAlignOfImpl<Args...>::Value;

				constexpr static Word MaxSizeOf=MaxSizeOfImpl<Args...>::Value;

				constexpr static bool NoThrowCopyable=NoThrowCopyableImpl<Args...>::Value;

				constexpr static bool NoThrowMovable=NoThrowMovableImpl<Args...>::Value;

		};

	}

	/**
	 *	\endcond
	 */

	class BadVariantOperation : public std::exception {

		public:

			__attribute__((noreturn))
			static void Raise () {

				throw BadVariantOperation();

			}

	};

	template <typename... Args>
	class Variant {

		private:

			typedef VariantImpl::VariantInfo<Args...> info;

			bool engaged;
			Word active;
			alignas(
				max_align_t
				//info::MaxAlignOf
			) Byte buffer [info::MaxSizeOf];

			template <typename T>
			T * get_ptr () noexcept {

				return reinterpret_cast<T *>(
					reinterpret_cast<void *>(
						buffer
					)
				);

			}

			template <typename T>
			const T * get_ptr () const noexcept {

				return reinterpret_cast<const T *>(
					reinterpret_cast<const void *>(
						buffer
					)
				);

			}

			template <Word i>
			typename std::enable_if<
				i>=sizeof...(Args)
			>::type destroy_impl () const noexcept {	}

			template <Word i>
			typename std::enable_if<
				i<sizeof...(Args)
			>::type destroy_impl () noexcept {

				typedef typename info::template Types<i>::Type type;

				if (active==i) get_ptr<type>()->~type();
				else destroy_impl<i+1>();

			}

			void destroy () noexcept {

				if (engaged) {

					destroy_impl<0>();

					engaged=false;

				}

			}

			template <typename T>
			typename std::enable_if<
				!std::is_same<
					typename std::decay<T>::type,
					Variant
				>::value
			>::type construct (T && item) noexcept(
				std::is_nothrow_constructible<
					typename std::decay<T>::type,
					T
				>::value
			) {

				constexpr Word index=info::template FindType<T>::Value;

				static_assert(
					index!=sizeof...(Args),
					"Variant does not contain that type"
				);

				new (buffer) typename std::decay<T>::type (std::forward<T>(item));

				engaged=true;
				active=index;

			}

			template <Word i>
			typename std::enable_if<
				i>=sizeof...(Args)
			>::type copy_impl (const Variant &) const noexcept {	}

			template <Word i>
			typename std::enable_if<
				std::is_copy_constructible<typename info::template Types<i>::Type>::value
			>::type copy_impl_impl (const Variant & other) noexcept(
				std::is_nothrow_copy_constructible<typename info::template Types<i>::Type>::value
			) {

				typedef typename info::template Types<i>::Type type;

				new (buffer) type (*other.get_ptr<type>());

				engaged=true;
				active=i;

			}

			template <Word i>
			typename std::enable_if<
				!std::is_copy_constructible<typename info::template Types<i>::Type>::value
			>::type copy_impl_impl (const Variant &) {

				BadVariantOperation::Raise();

			}

			template <Word i>
			typename std::enable_if<
				i<sizeof...(Args)
			>::type copy_impl (const Variant & other) noexcept (
				info::NoThrowCopyable
			) {

				if (i==other.active) copy_impl_impl<i>(other);
				else copy_impl<i+1>(other);

			}

			template <Word i>
			typename std::enable_if<
				i>=sizeof...(Args)
			>::type move_impl (const Variant &) const noexcept {	}

			template <Word i>
			typename std::enable_if<
				std::is_move_constructible<typename info::template Types<i>::Type>::value
			>::type move_impl_impl (Variant && other) noexcept(
				std::is_nothrow_move_constructible<typename info::template Types<i>::Type>::value
			) {

				typedef typename info::template Types<i>::Type type;

				new (buffer) type (std::move(*other.get_ptr<type>()));

				engaged=true;
				active=i;

			}

			template <Word i>
			typename std::enable_if<
				!std::is_move_constructible<typename info::template Types<i>::Type>::value
			>::type move_impl_impl (const Variant &) {

				BadVariantOperation::Raise();

			}

			template <Word i>
			typename std::enable_if<
				i<sizeof...(Args)
			>::type move_impl (Variant && other) noexcept(
				info::NoThrowMovable
			) {

				if (i==other.active) move_impl_impl<i>(std::move(other));
				else move_impl<i+1>(std::move(other));

			}

			void construct (const Variant & other) noexcept(
				info::NoThrowCopyable
			) {

				if (other.engaged) copy_impl<0>(other);

			}

			void construct (Variant && other) noexcept(
				info::NoThrowMovable
			) {

				if (other.engaged) {

					move_impl<0>(std::move(other));

					other.destroy();

				}

			}

			template <typename T>
			void assign_impl (T && item) noexcept(
				info::NoThrowMovable && info::NoThrowCopyable
			) {

				destroy();

				construct(std::forward<T>(item));

			}

			template <typename T>
			typename std::enable_if<
				std::is_same<
					typename std::decay<T>::type,
					Variant
				>::value
			>::type assign (T && item) noexcept(
				info::NoThrowMovable && info::NoThrowCopyable
			) {

				if (reinterpret_cast<const void *>(&item)!=this) assign_impl(std::forward<T>(item));

			}

			template <typename T>
			typename std::enable_if<
				!std::is_same<
					typename std::decay<T>::type,
					Variant
				>::value
			>::type assign (T && item) noexcept(
				info::NoThrowMovable && info::NoThrowCopyable
			) {

				assign_impl(std::forward<T>(item));

			}

		public:

			Variant () noexcept : engaged(false) {	}

			Variant (Variant && other) noexcept(
				info::NoThrowMovable
			) : engaged(false) {

				construct(std::move(other));

			}

			Variant (const Variant & other) noexcept(
				info::NoThrowCopyable
			) : engaged(false) {

				construct(other);

			}

			template <typename T>
			Variant (T && item) noexcept(
				info::NoThrowMovable && info::NoThrowCopyable
			) : engaged(false) {

				construct(std::forward<T>(item));

			}

			template <typename T>
			Variant & operator = (T && item) noexcept(
				info::NoThrowMovable && info::NoThrowCopyable
			) {

				assign(std::forward<T>(item));

				return *this;

			}

			template <typename T, typename... EmplaceArgs>
			typename std::enable_if<
				info::template FindType<T>::Value!=sizeof...(Args)
			>::type Construct (EmplaceArgs &&... args) noexcept(
				std::is_nothrow_constructible<
					T,
					EmplaceArgs...
				>::value
			) {

				destroy();

				new (buffer) T (std::forward<EmplaceArgs>(args)...);

				engaged=true;
				active=info::template FindType<T>::Value;

			}

			~Variant () noexcept {

				destroy();

			}

			void Destroy () noexcept {

				destroy();

			}

			bool IsNull () const noexcept {

				return !engaged;

			}

			template <typename T>
			bool Is () const noexcept {

				return engaged && (active==info::template FindType<T>::Value);

			}

			template <typename T>
			T & Get () noexcept {

				return *get_ptr<T>();

			}

			template <typename T>
			const T & Get () const noexcept {

				return *get_ptr<T>();

			}

	};

}
<commit_msg>Variant Documentation<commit_after>/**
 *	\file
 */

#pragma once

#include <rleahylib/rleahylib.hpp>
#include <traits.hpp>
#include <cstddef>
#include <new>
#include <type_traits>
#include <utility>

namespace MCPP {

	/**
	 *	\cond
	 */

	namespace VariantImpl {

		template <typename...>
		class MaxAlignOfImpl {	};

		template <>
		class MaxAlignOfImpl<> {

			public:

				constexpr static Word Value=0;

		};

		template <typename T, typename... Args>
		class MaxAlignOfImpl<T,Args...> {

			private:

				constexpr static Word next=MaxAlignOfImpl<Args...>::Value;

			public:

				constexpr static Word Value=(alignof(T)>next) ? alignof(T) : next;

		};

		template <typename...>
		class MaxSizeOfImpl {	};

		template <>
		class MaxSizeOfImpl<> {

			public:

				constexpr static Word Value=0;

		};

		template <typename T, typename... Args>
		class MaxSizeOfImpl<T,Args...> {

			private:

				constexpr static Word next=MaxSizeOfImpl<Args...>::Value;

			public:

				constexpr static Word Value=(sizeof(T)>next) ? sizeof(T) : next;

		};

		template <Word, typename, typename...>
		class FindTypeImpl {	};

		template <Word i, typename T>
		class FindTypeImpl<i,T> {

			public:

				constexpr static Word Value=i;

		};

		template <Word i, typename T, typename Curr, typename... Args>
		class FindTypeImpl<i,T,Curr,Args...> {

			public:

				constexpr static Word Value=std::is_same<
					typename std::decay<T>::type,
					typename std::decay<Curr>::type
				>::value ? i : FindTypeImpl<i+1,T,Args...>::Value;

		};

		template <typename...>
		class NoThrowCopyableImpl {	};

		template <typename T, typename... Args>
		class NoThrowCopyableImpl<T,Args...> {

			public:

				constexpr static bool Value=std::is_nothrow_copy_constructible<T>::value ? NoThrowCopyableImpl<Args...>::Value : false;

		};

		template <>
		class NoThrowCopyableImpl<> {

			public:

				constexpr static bool Value=true;

		};

		template <typename...>
		class NoThrowMovableImpl {	};

		template <typename T, typename... Args>
		class NoThrowMovableImpl<T,Args...> {

			public:

				constexpr static bool Value=std::is_nothrow_move_constructible<T>::value ? NoThrowMovableImpl<Args...>::Value : false;

		};

		template <>
		class NoThrowMovableImpl<> {

			public:

				constexpr static bool Value=true;

		};

		template <typename... Args>
		class VariantInfo {

			public:

				template <Word i>
				class Types {

					public:

						typedef typename std::decay<typename GetType<i,Args...>::Type>::type Type;

				};

				template <typename T>
				class FindType {

					public:

						constexpr static Word Value=FindTypeImpl<0,T,Args...>::Value;

				};

				constexpr static Word MaxAlignOf=MaxAlignOfImpl<Args...>::Value;

				constexpr static Word MaxSizeOf=MaxSizeOfImpl<Args...>::Value;

				constexpr static bool NoThrowCopyable=NoThrowCopyableImpl<Args...>::Value;

				constexpr static bool NoThrowMovable=NoThrowMovableImpl<Args...>::Value;

		};

	}

	/**
	 *	\endcond
	 */

	/**
	 *	Thrown when an illegal operation
	 *	is undertaken on a Variant.
	 */
	class BadVariantOperation : public std::exception {

		public:

			/**
			 *	\cond
			 */

			__attribute__((noreturn))
			static void Raise () {

				throw BadVariantOperation();

			}

			/**
			 *	\endcond
			 */

	};

	/**
	 *	An object which may be imbued with
	 *	any one of a number of types.
	 *
	 *	This object does not use or allocate
	 *	heap memory for internal storage
	 *	of stored objects, rather it contains
	 *	an internal buffer with the necessary
	 *	size and alignment to contain any
	 *	of its possible types.
	 */
	template <typename... Args>
	class Variant {

		private:

			typedef VariantImpl::VariantInfo<Args...> info;

			bool engaged;
			Word active;
			alignas(
				max_align_t
				//info::MaxAlignOf
			) Byte buffer [info::MaxSizeOf];

			template <typename T>
			T * get_ptr () noexcept {

				return reinterpret_cast<T *>(
					reinterpret_cast<void *>(
						buffer
					)
				);

			}

			template <typename T>
			const T * get_ptr () const noexcept {

				return reinterpret_cast<const T *>(
					reinterpret_cast<const void *>(
						buffer
					)
				);

			}

			template <Word i>
			typename std::enable_if<
				i>=sizeof...(Args)
			>::type destroy_impl () const noexcept {	}

			template <Word i>
			typename std::enable_if<
				i<sizeof...(Args)
			>::type destroy_impl () noexcept {

				typedef typename info::template Types<i>::Type type;

				if (active==i) get_ptr<type>()->~type();
				else destroy_impl<i+1>();

			}

			void destroy () noexcept {

				if (engaged) {

					destroy_impl<0>();

					engaged=false;

				}

			}

			template <typename T>
			typename std::enable_if<
				!std::is_same<
					typename std::decay<T>::type,
					Variant
				>::value
			>::type construct (T && item) noexcept(
				std::is_nothrow_constructible<
					typename std::decay<T>::type,
					T
				>::value
			) {

				constexpr Word index=info::template FindType<T>::Value;

				static_assert(
					index!=sizeof...(Args),
					"Variant does not contain that type"
				);

				new (buffer) typename std::decay<T>::type (std::forward<T>(item));

				engaged=true;
				active=index;

			}

			template <Word i>
			typename std::enable_if<
				i>=sizeof...(Args)
			>::type copy_impl (const Variant &) const noexcept {	}

			template <Word i>
			typename std::enable_if<
				std::is_copy_constructible<typename info::template Types<i>::Type>::value
			>::type copy_impl_impl (const Variant & other) noexcept(
				std::is_nothrow_copy_constructible<typename info::template Types<i>::Type>::value
			) {

				typedef typename info::template Types<i>::Type type;

				new (buffer) type (*other.get_ptr<type>());

				engaged=true;
				active=i;

			}

			template <Word i>
			typename std::enable_if<
				!std::is_copy_constructible<typename info::template Types<i>::Type>::value
			>::type copy_impl_impl (const Variant &) {

				BadVariantOperation::Raise();

			}

			template <Word i>
			typename std::enable_if<
				i<sizeof...(Args)
			>::type copy_impl (const Variant & other) noexcept (
				info::NoThrowCopyable
			) {

				if (i==other.active) copy_impl_impl<i>(other);
				else copy_impl<i+1>(other);

			}

			template <Word i>
			typename std::enable_if<
				i>=sizeof...(Args)
			>::type move_impl (const Variant &) const noexcept {	}

			template <Word i>
			typename std::enable_if<
				std::is_move_constructible<typename info::template Types<i>::Type>::value
			>::type move_impl_impl (Variant && other) noexcept(
				std::is_nothrow_move_constructible<typename info::template Types<i>::Type>::value
			) {

				typedef typename info::template Types<i>::Type type;

				new (buffer) type (std::move(*other.get_ptr<type>()));

				engaged=true;
				active=i;

			}

			template <Word i>
			typename std::enable_if<
				!std::is_move_constructible<typename info::template Types<i>::Type>::value
			>::type move_impl_impl (const Variant &) {

				BadVariantOperation::Raise();

			}

			template <Word i>
			typename std::enable_if<
				i<sizeof...(Args)
			>::type move_impl (Variant && other) noexcept(
				info::NoThrowMovable
			) {

				if (i==other.active) move_impl_impl<i>(std::move(other));
				else move_impl<i+1>(std::move(other));

			}

			void construct (const Variant & other) noexcept(
				info::NoThrowCopyable
			) {

				if (other.engaged) copy_impl<0>(other);

			}

			void construct (Variant && other) noexcept(
				info::NoThrowMovable
			) {

				if (other.engaged) {

					move_impl<0>(std::move(other));

					other.destroy();

				}

			}

			template <typename T>
			void assign_impl (T && item) noexcept(
				info::NoThrowMovable && info::NoThrowCopyable
			) {

				destroy();

				construct(std::forward<T>(item));

			}

			template <typename T>
			typename std::enable_if<
				std::is_same<
					typename std::decay<T>::type,
					Variant
				>::value
			>::type assign (T && item) noexcept(
				info::NoThrowMovable && info::NoThrowCopyable
			) {

				if (reinterpret_cast<const void *>(&item)!=this) assign_impl(std::forward<T>(item));

			}

			template <typename T>
			typename std::enable_if<
				!std::is_same<
					typename std::decay<T>::type,
					Variant
				>::value
			>::type assign (T && item) noexcept(
				info::NoThrowMovable && info::NoThrowCopyable
			) {

				assign_impl(std::forward<T>(item));

			}

		public:

			/**
			 *	Creates an empty Variant.
			 */
			Variant () noexcept : engaged(false) {	}

			/**
			 *	Creates a variant by moving another
			 *	Variant.
			 *
			 *	\except BadVariantOperation
			 *		Thrown if \em other is currently
			 *		of a type which cannot be moved.
			 *
			 *	\param [in] other
			 *		The Variant to move.
			 */
			Variant (Variant && other) noexcept(
				info::NoThrowMovable
			) : engaged(false) {

				construct(std::move(other));

			}

			/**
			 *	Creates a variant by copying another
			 *	Variant.
			 *
			 *	\except BadVariantOperation
			 *		Thrown if \em other is currently
			 *		of a type which cannot be copied.
			 *
			 *	\param [in] other
			 *		The Variant to copy.
			 */
			Variant (const Variant & other) noexcept(
				info::NoThrowCopyable
			) : engaged(false) {

				construct(other);

			}

			/**
			 *	Creates a variant by imbuing it with a
			 *	certain object of a type which it may
			 *	contain.
			 *
			 *	\param [in] item
			 *		The object to create this Variant from.
			 */
			template <typename T>
			Variant (T && item) noexcept(
				info::NoThrowMovable && info::NoThrowCopyable
			) : engaged(false) {

				construct(std::forward<T>(item));

			}

			/**
			 *	Assigns an item or another Variant to
			 *	this object.
			 *
			 *	\except BadVariantOperation
			 *		Thrown if \em item is a Variant, and
			 *		the object within that Variant cannot
			 *		be copied or moved (as applicable).
			 *
			 *	\param [in] item
			 *		The item to assign to this Variant.
			 *
			 *	\return
			 *		A reference to this Variant.
			 */
			template <typename T>
			Variant & operator = (T && item) noexcept(
				info::NoThrowMovable && info::NoThrowCopyable
			) {

				assign(std::forward<T>(item));

				return *this;

			}

			template <typename T, typename... EmplaceArgs>
			typename std::enable_if<
				info::template FindType<T>::Value!=sizeof...(Args)
			>::type Construct (EmplaceArgs &&... args) noexcept(
				std::is_nothrow_constructible<
					T,
					EmplaceArgs...
				>::value
			) {

				destroy();

				new (buffer) T (std::forward<EmplaceArgs>(args)...);

				engaged=true;
				active=info::template FindType<T>::Value;

			}

			/**
			 *	Destroys this Variant and any object
			 *	contained within.
			 */
			~Variant () noexcept {

				destroy();

			}

			/**
			 *	Destroys the object within this Variant.
			 */
			void Destroy () noexcept {

				destroy();

			}

			/**
			 *	Determines whether or not this Variant
			 *	currently contains an object.
			 *
			 *	\return
			 *		\em true if this Variant does not
			 *		contain an object, \em false otherwise.
			 */
			bool IsNull () const noexcept {

				return !engaged;

			}

			/**
			 *	Determines whether this Variant currently
			 *	contains an object of type \em T.
			 *
			 *	\tparam T
			 *		The type-in-question.
			 *
			 *	\return
			 *		\em true if this Variant contains an
			 *		object of type \em T, \em false
			 *		otherwise.
			 */
			template <typename T>
			bool Is () const noexcept {

				return engaged && (active==info::template FindType<T>::Value);

			}

			/**
			 *	Returns the zero-relative index of the
			 *	type this Variant currently contains.
			 *
			 *	If this Variant is empty, the behaviour
			 *	of this function is undefined.
			 *
			 *	\return
			 *		The zero-relative index of the type
			 *		this Variant currently contains.
			 */
			Word Type () const noexcept {

				return active;

			}

			/**
			 *	Gets a reference to the object contained
			 *	within the variant.
			 *
			 *	If the Variant is empty, or does not contain
			 *	an object of type \em T, the behaviour of
			 *	this function is undefined.
			 *
			 *	\return
			 *		A reference to the object stored within
			 *		this Variant.
			 */
			template <typename T>
			T & Get () noexcept {

				return *get_ptr<T>();

			}

			/**
			 *	Gets a reference to the object contained
			 *	within the variant.
			 *
			 *	If the Variant is empty, or does not contain
			 *	an object of type \em T, the behaviour of
			 *	this function is undefined.
			 *
			 *	\return
			 *		A reference to the object stored within
			 *		this Variant.
			 */
			template <typename T>
			const T & Get () const noexcept {

				return *get_ptr<T>();

			}

	};

}
<|endoftext|>


<commit_before>#pragma once

#include "depthai-shared/common/ProcessorType.hpp"
#include "depthai-shared/common/optional.hpp"
#include "depthai-shared/properties/Properties.hpp"

namespace dai {

/**
 * Specify ScriptProperties options such as script uri, script name, ...
 */
struct ScriptProperties : PropertiesSerializable<Properties, ScriptProperties> {
    /**
     * Uri which points to actual script
     */
    std::string scriptUri = "";

    /**
     * Name of script
     */
    std::string scriptName = "<script>";

    /**
     * Which processor should execute the script
     */
    ProcessorType processor = ProcessorType::LEON_MSS;
};

DEPTHAI_SERIALIZE_EXT(ScriptProperties, scriptUri, scriptName, processor);

}  // namespace dai
<commit_msg>Change default CPU to CSS<commit_after>#pragma once

#include "depthai-shared/common/ProcessorType.hpp"
#include "depthai-shared/common/optional.hpp"
#include "depthai-shared/properties/Properties.hpp"

namespace dai {

/**
 * Specify ScriptProperties options such as script uri, script name, ...
 */
struct ScriptProperties : PropertiesSerializable<Properties, ScriptProperties> {
    /**
     * Uri which points to actual script
     */
    std::string scriptUri = "";

    /**
     * Name of script
     */
    std::string scriptName = "<script>";

    /**
     * Which processor should execute the script
     */
    ProcessorType processor = ProcessorType::LEON_CSS;
};

DEPTHAI_SERIALIZE_EXT(ScriptProperties, scriptUri, scriptName, processor);

}  // namespace dai
<|endoftext|>


<commit_before>/**
 * \file
 * \brief SdMmcCardSpiBased class header
 *
 * \author Copyright (C) 2018-2019 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * 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/.
 */

#ifndef INCLUDE_DISTORTOS_DEVICES_MEMORY_SDMMCCARDSPIBASED_HPP_
#define INCLUDE_DISTORTOS_DEVICES_MEMORY_SDMMCCARDSPIBASED_HPP_

#include "distortos/devices/communication/SpiDevice.hpp"

#include "distortos/devices/memory/BlockDevice.hpp"

namespace distortos
{

namespace devices
{

/**
 * SdMmcCardSpiBased class is a SD or MMC card connected via SPI.
 *
 * \ingroup devices
 */

class SdMmcCardSpiBased : public BlockDevice
{
public:

	/// type of card connected via SPI
	enum class Type : uint8_t
	{
		/// unknown type
		unknown,

		/// MMC card
		mmc,
		/// SD version 1.0 card
		sdVersion1,
		/// SD version 2.0 card
		sdVersion2,
	};

	/// size of block, bytes
	constexpr static size_t blockSize {512};

	/**
	 * \brief SdMmcCardSpiBased's constructor
	 *
	 * \param [in] spiMaster is a reference to SPI master to which this SD or MMC card is connected
	 * \param [in] slaveSelectPin is a reference to slave select pin of this SD or MMC card
	 * \param [in] clockFrequency is the desired clock frequency of SD or MMC card, Hz, default - 5 MHz
	 */

	constexpr SdMmcCardSpiBased(SpiMaster& spiMaster, OutputPin& slaveSelectPin,
			const uint32_t clockFrequency = 5000000) :
					spiDevice_{spiMaster, slaveSelectPin},
					blocksCount_{},
					auSize_{},
					clockFrequency_{clockFrequency},
					eraseTimeoutMs_{},
					readTimeoutMs_{},
					writeTimeoutMs_{},
					blockAddressing_{},
					type_{}
	{

	}

	/**
	 * \brief SdMmcCardSpiBased's destructor
	 */

	~SdMmcCardSpiBased() override;

	/**
	 * \brief Closes SD or MMC card connected via SPI.
	 *
	 * \warning This function must not be called from interrupt context!
	 *
	 * \return 0 on success, error code otherwise:
	 * - error codes returned by SpiDevice::close();
	 */

	int close() override;

	/**
	 * \brief Erases blocks on a SD or MMC card connected via SPI.
	 *
	 * \warning This function must not be called from interrupt context!
	 *
	 * \param [in] address is the address of range that will be erased, must be a multiple of block size
	 * \param [in] size is the size of erased range, bytes, must be a multiple of block size
	 *
	 * \return 0 on success, error code otherwise:
	 * - EBADF - the device is not opened;
	 * - EINVAL - \a address and/or \a size are not valid;
	 * - ENOSPC - selected range is greater than size of device;
	 * - error codes returned by executeCmd32();
	 * - error codes returned by executeCmd33();
	 * - error codes returned by executeCmd38();
	 * - error codes returned by SpiMasterProxy::configure();
	 */

	int erase(uint64_t address, uint64_t size) override;

	/**
	 * \return block size, bytes
	 */

	size_t getBlockSize() const override;

	/**
	 * \return size of SD or MMC card connected via SPI, bytes
	 */

	uint64_t getSize() const override;

	/**
	 * \brief Locks the device for exclusive use by current thread.
	 *
	 * When the object is locked, any call to any member function from other thread will be blocked until the object is
	 * unlocked. Locking is optional, but may be useful when more than one transaction must be done atomically.
	 *
	 * \note Locks are recursive.
	 *
	 * \warning This function must not be called from interrupt context!
	 *
	 * \return 0 on success, error code otherwise:
	 * - error codes returned by SpiDevice::lock();
	 */

	int lock() override;

	/**
	 * \brief Opens SD or MMC card connected via SPI.
	 *
	 * \warning This function must not be called from interrupt context!
	 *
	 * \return 0 on success, error code otherwise:
	 * - error codes returned by initialize();
	 * - error codes returned by SpiDevice::open();
	 */

	int open() override;

	/**
	 * \brief Reads data from SD or MMC card connected via SPI.
	 *
	 * \warning This function must not be called from interrupt context!
	 *
	 * \param [in] address is the address of data that will be read, must be a multiple of block size
	 * \param [out] buffer is the buffer into which the data will be read
	 * \param [in] size is the size of \a buffer, bytes, must be a multiple of block size
	 *
	 * \return 0 on success, error code otherwise:
	 * - EBADF - the device is not opened;
	 * - EINVAL - \a address and/or \a buffer and/or \a size are not valid;
	 * - EIO - error during communication with SD or MMC card;
	 * - ENOSPC - selected range is greater than size of device;
	 * - error codes returned by executeCmd12();
	 * - error codes returned by executeCmd17();
	 * - error codes returned by executeCmd18();
	 * - error codes returned by readDataBlock();
	 * - error codes returned by SpiMasterProxy::configure();
	 */

	int read(uint64_t address, void* buffer, size_t size) override;

	/**
	 * \brief Synchronizes state of SD or MMC card connected via SPI, ensuring all cached writes are finished.
	 *
	 * \return always 0
	 */

	int synchronize() override;

	/**
	 * \brief Unlocks the device which was previously locked by current thread.
	 *
	 * \note Locks are recursive.
	 *
	 * \warning This function must not be called from interrupt context!
	 *
	 * \return 0 on success, error code otherwise:
	 * - error codes returned by SpiDevice::unlock();
	 */

	int unlock() override;

	/**
	 * \brief Writes data to SD or MMC card connected via SPI.
	 *
	 * \warning This function must not be called from interrupt context!
	 *
	 * \param [in] address is the address of data that will be written, must be a multiple of block size
	 * \param [in] buffer is the buffer with data that will be written
	 * \param [in] size is the size of \a buffer, bytes, must be a multiple of block size
	 *
	 * \return 0 on success, error code otherwise:
	 * - EBADF - the device is not opened;
	 * - EINVAL - \a address and/or \a buffer and/or \a size are not valid;
	 * - EIO - error during communication with SD or MMC card;
	 * - ENOSPC - selected range is greater than size of device;
	 * - error codes returned by executeAcmd23();
	 * - error codes returned by executeCmd24();
	 * - error codes returned by executeCmd25();
	 * - error codes returned by waitWhileBusy();
	 * - error codes returned by writeDataBlock();
	 * - error codes returned by SpiMasterProxy::configure();
	 * - error codes returned by SpiMasterProxy::executeTransaction();
	 */

	int write(uint64_t address, const void* buffer, size_t size) override;

private:

	/**
	 * \brief Deinitializes SD or MMC card connected via SPI.
	 */

	void deinitialize();

	/**
	 * \brief Initializes SD or MMC card connected via SPI.
	 *
	 * Algorithm is based on ChaN's
	 * [How to Use MMC/SDC: Initialization Procedure for SPI Mode](http://elm-chan.org/docs/mmc/mmc_e.html#spiinit).
	 *
	 * \param [in] spiDeviceProxy is a reference to SpiDeviceProxy associated with this object
	 *
	 * \return 0 on success, error code otherwise:
	 * - EIO - error during communication with SD or MMC card;
	 * - ETIMEDOUT - timed-out while waiting for SD or MMC card to respond;
	 * - error codes returned by executeAcmd41();
	 * - error codes returned by executeCmd0();
	 * - error codes returned by executeCmd1();
	 * - error codes returned by executeCmd8();
	 * - error codes returned by executeCmd9();
	 * - error codes returned by executeCmd16();
	 * - error codes returned by executeCmd58();
	 * - error codes returned by SpiMasterProxy::configure();
	 * - error codes returned by SpiMasterProxy::executeTransaction();
	 */

	int initialize(const SpiDeviceProxy& spiDeviceProxy);

	/// internal SPI slave device
	SpiDevice spiDevice_;

	/// number of blocks available on SD or MMC card
	size_t blocksCount_;

	/// size of AU, bytes
	uint32_t auSize_;

	/// desired clock frequency of SD or MMC card, Hz
	uint32_t clockFrequency_;

	/// timeout of erase operation of single AU, milliseconds
	uint16_t eraseTimeoutMs_;

	/// timeout of read operation, milliseconds
	uint16_t readTimeoutMs_;

	/// timeout of write operation, milliseconds
	uint16_t writeTimeoutMs_;

	/// selects whether card uses byte (false) or block (true) addressing
	bool blockAddressing_;

	/// type of card connected via SPI
	Type type_;
};

}	// namespace devices

}	// namespace distortos

#endif	// INCLUDE_DISTORTOS_DEVICES_MEMORY_SDMMCCARDSPIBASED_HPP_
<commit_msg>Increase default clock for SdMmcCardSpiBased to 25 MHz<commit_after>/**
 * \file
 * \brief SdMmcCardSpiBased class header
 *
 * \author Copyright (C) 2018-2019 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * 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/.
 */

#ifndef INCLUDE_DISTORTOS_DEVICES_MEMORY_SDMMCCARDSPIBASED_HPP_
#define INCLUDE_DISTORTOS_DEVICES_MEMORY_SDMMCCARDSPIBASED_HPP_

#include "distortos/devices/communication/SpiDevice.hpp"

#include "distortos/devices/memory/BlockDevice.hpp"

namespace distortos
{

namespace devices
{

/**
 * SdMmcCardSpiBased class is a SD or MMC card connected via SPI.
 *
 * \ingroup devices
 */

class SdMmcCardSpiBased : public BlockDevice
{
public:

	/// type of card connected via SPI
	enum class Type : uint8_t
	{
		/// unknown type
		unknown,

		/// MMC card
		mmc,
		/// SD version 1.0 card
		sdVersion1,
		/// SD version 2.0 card
		sdVersion2,
	};

	/// size of block, bytes
	constexpr static size_t blockSize {512};

	/**
	 * \brief SdMmcCardSpiBased's constructor
	 *
	 * \param [in] spiMaster is a reference to SPI master to which this SD or MMC card is connected
	 * \param [in] slaveSelectPin is a reference to slave select pin of this SD or MMC card
	 * \param [in] clockFrequency is the desired clock frequency of SD or MMC card, Hz, default - 25 MHz
	 */

	constexpr SdMmcCardSpiBased(SpiMaster& spiMaster, OutputPin& slaveSelectPin,
			const uint32_t clockFrequency = 25000000) :
					spiDevice_{spiMaster, slaveSelectPin},
					blocksCount_{},
					auSize_{},
					clockFrequency_{clockFrequency},
					eraseTimeoutMs_{},
					readTimeoutMs_{},
					writeTimeoutMs_{},
					blockAddressing_{},
					type_{}
	{

	}

	/**
	 * \brief SdMmcCardSpiBased's destructor
	 */

	~SdMmcCardSpiBased() override;

	/**
	 * \brief Closes SD or MMC card connected via SPI.
	 *
	 * \warning This function must not be called from interrupt context!
	 *
	 * \return 0 on success, error code otherwise:
	 * - error codes returned by SpiDevice::close();
	 */

	int close() override;

	/**
	 * \brief Erases blocks on a SD or MMC card connected via SPI.
	 *
	 * \warning This function must not be called from interrupt context!
	 *
	 * \param [in] address is the address of range that will be erased, must be a multiple of block size
	 * \param [in] size is the size of erased range, bytes, must be a multiple of block size
	 *
	 * \return 0 on success, error code otherwise:
	 * - EBADF - the device is not opened;
	 * - EINVAL - \a address and/or \a size are not valid;
	 * - ENOSPC - selected range is greater than size of device;
	 * - error codes returned by executeCmd32();
	 * - error codes returned by executeCmd33();
	 * - error codes returned by executeCmd38();
	 * - error codes returned by SpiMasterProxy::configure();
	 */

	int erase(uint64_t address, uint64_t size) override;

	/**
	 * \return block size, bytes
	 */

	size_t getBlockSize() const override;

	/**
	 * \return size of SD or MMC card connected via SPI, bytes
	 */

	uint64_t getSize() const override;

	/**
	 * \brief Locks the device for exclusive use by current thread.
	 *
	 * When the object is locked, any call to any member function from other thread will be blocked until the object is
	 * unlocked. Locking is optional, but may be useful when more than one transaction must be done atomically.
	 *
	 * \note Locks are recursive.
	 *
	 * \warning This function must not be called from interrupt context!
	 *
	 * \return 0 on success, error code otherwise:
	 * - error codes returned by SpiDevice::lock();
	 */

	int lock() override;

	/**
	 * \brief Opens SD or MMC card connected via SPI.
	 *
	 * \warning This function must not be called from interrupt context!
	 *
	 * \return 0 on success, error code otherwise:
	 * - error codes returned by initialize();
	 * - error codes returned by SpiDevice::open();
	 */

	int open() override;

	/**
	 * \brief Reads data from SD or MMC card connected via SPI.
	 *
	 * \warning This function must not be called from interrupt context!
	 *
	 * \param [in] address is the address of data that will be read, must be a multiple of block size
	 * \param [out] buffer is the buffer into which the data will be read
	 * \param [in] size is the size of \a buffer, bytes, must be a multiple of block size
	 *
	 * \return 0 on success, error code otherwise:
	 * - EBADF - the device is not opened;
	 * - EINVAL - \a address and/or \a buffer and/or \a size are not valid;
	 * - EIO - error during communication with SD or MMC card;
	 * - ENOSPC - selected range is greater than size of device;
	 * - error codes returned by executeCmd12();
	 * - error codes returned by executeCmd17();
	 * - error codes returned by executeCmd18();
	 * - error codes returned by readDataBlock();
	 * - error codes returned by SpiMasterProxy::configure();
	 */

	int read(uint64_t address, void* buffer, size_t size) override;

	/**
	 * \brief Synchronizes state of SD or MMC card connected via SPI, ensuring all cached writes are finished.
	 *
	 * \return always 0
	 */

	int synchronize() override;

	/**
	 * \brief Unlocks the device which was previously locked by current thread.
	 *
	 * \note Locks are recursive.
	 *
	 * \warning This function must not be called from interrupt context!
	 *
	 * \return 0 on success, error code otherwise:
	 * - error codes returned by SpiDevice::unlock();
	 */

	int unlock() override;

	/**
	 * \brief Writes data to SD or MMC card connected via SPI.
	 *
	 * \warning This function must not be called from interrupt context!
	 *
	 * \param [in] address is the address of data that will be written, must be a multiple of block size
	 * \param [in] buffer is the buffer with data that will be written
	 * \param [in] size is the size of \a buffer, bytes, must be a multiple of block size
	 *
	 * \return 0 on success, error code otherwise:
	 * - EBADF - the device is not opened;
	 * - EINVAL - \a address and/or \a buffer and/or \a size are not valid;
	 * - EIO - error during communication with SD or MMC card;
	 * - ENOSPC - selected range is greater than size of device;
	 * - error codes returned by executeAcmd23();
	 * - error codes returned by executeCmd24();
	 * - error codes returned by executeCmd25();
	 * - error codes returned by waitWhileBusy();
	 * - error codes returned by writeDataBlock();
	 * - error codes returned by SpiMasterProxy::configure();
	 * - error codes returned by SpiMasterProxy::executeTransaction();
	 */

	int write(uint64_t address, const void* buffer, size_t size) override;

private:

	/**
	 * \brief Deinitializes SD or MMC card connected via SPI.
	 */

	void deinitialize();

	/**
	 * \brief Initializes SD or MMC card connected via SPI.
	 *
	 * Algorithm is based on ChaN's
	 * [How to Use MMC/SDC: Initialization Procedure for SPI Mode](http://elm-chan.org/docs/mmc/mmc_e.html#spiinit).
	 *
	 * \param [in] spiDeviceProxy is a reference to SpiDeviceProxy associated with this object
	 *
	 * \return 0 on success, error code otherwise:
	 * - EIO - error during communication with SD or MMC card;
	 * - ETIMEDOUT - timed-out while waiting for SD or MMC card to respond;
	 * - error codes returned by executeAcmd41();
	 * - error codes returned by executeCmd0();
	 * - error codes returned by executeCmd1();
	 * - error codes returned by executeCmd8();
	 * - error codes returned by executeCmd9();
	 * - error codes returned by executeCmd16();
	 * - error codes returned by executeCmd58();
	 * - error codes returned by SpiMasterProxy::configure();
	 * - error codes returned by SpiMasterProxy::executeTransaction();
	 */

	int initialize(const SpiDeviceProxy& spiDeviceProxy);

	/// internal SPI slave device
	SpiDevice spiDevice_;

	/// number of blocks available on SD or MMC card
	size_t blocksCount_;

	/// size of AU, bytes
	uint32_t auSize_;

	/// desired clock frequency of SD or MMC card, Hz
	uint32_t clockFrequency_;

	/// timeout of erase operation of single AU, milliseconds
	uint16_t eraseTimeoutMs_;

	/// timeout of read operation, milliseconds
	uint16_t readTimeoutMs_;

	/// timeout of write operation, milliseconds
	uint16_t writeTimeoutMs_;

	/// selects whether card uses byte (false) or block (true) addressing
	bool blockAddressing_;

	/// type of card connected via SPI
	Type type_;
};

}	// namespace devices

}	// namespace distortos

#endif	// INCLUDE_DISTORTOS_DEVICES_MEMORY_SDMMCCARDSPIBASED_HPP_
<|endoftext|>