<commit_before>//===-- MainThreadCheckerRuntime.cpp ----------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "MainThreadCheckerRuntime.h"

#include "lldb/Breakpoint/StoppointCallbackContext.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/Variable.h"
#include "lldb/Symbol/VariableList.h"
#include "lldb/Target/InstrumentationRuntimeStopInfo.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/StopInfo.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/RegularExpression.h"
#include "Plugins/Process/Utility/HistoryThread.h"

using namespace lldb;
using namespace lldb_private;

MainThreadCheckerRuntime::~MainThreadCheckerRuntime() {
  Deactivate();
}

lldb::InstrumentationRuntimeSP
MainThreadCheckerRuntime::CreateInstance(const lldb::ProcessSP &process_sp) {
  return InstrumentationRuntimeSP(new MainThreadCheckerRuntime(process_sp));
}

void MainThreadCheckerRuntime::Initialize() {
  PluginManager::RegisterPlugin(
      GetPluginNameStatic(), "MainThreadChecker instrumentation runtime plugin.",
      CreateInstance, GetTypeStatic);
}

void MainThreadCheckerRuntime::Terminate() {
  PluginManager::UnregisterPlugin(CreateInstance);
}

lldb_private::ConstString MainThreadCheckerRuntime::GetPluginNameStatic() {
  return ConstString("MainThreadChecker");
}

lldb::InstrumentationRuntimeType MainThreadCheckerRuntime::GetTypeStatic() {
  return eInstrumentationRuntimeTypeMainThreadChecker;
}

const RegularExpression &
MainThreadCheckerRuntime::GetPatternForRuntimeLibrary() {
  static RegularExpression regex(llvm::StringRef("libMainThreadChecker.dylib"));
  return regex;
}

bool MainThreadCheckerRuntime::CheckIfRuntimeIsValid(
    const lldb::ModuleSP module_sp) {
  static ConstString test_sym("__main_thread_checker_on_report");
  const Symbol *symbol =
      module_sp->FindFirstSymbolWithNameAndType(test_sym, lldb::eSymbolTypeAny);
  return symbol != nullptr;
}

StructuredData::ObjectSP
MainThreadCheckerRuntime::RetrieveReportData(ExecutionContextRef exe_ctx_ref) {
  ProcessSP process_sp = GetProcessSP();
  if (!process_sp)
    return StructuredData::ObjectSP();

  ThreadSP thread_sp = exe_ctx_ref.GetThreadSP();
  StackFrameSP frame_sp = thread_sp->GetSelectedFrame();
  ModuleSP runtime_module_sp = GetRuntimeModuleSP();
  Target &target = process_sp->GetTarget();

  if (!frame_sp)
    return StructuredData::ObjectSP();

  RegisterContextSP regctx_sp = frame_sp->GetRegisterContext();
  if (!regctx_sp)
    return StructuredData::ObjectSP();

  const RegisterInfo *reginfo = regctx_sp->GetRegisterInfoByName("arg1");
  if (!reginfo)
    return StructuredData::ObjectSP();

  uint64_t apiname_ptr = regctx_sp->ReadRegisterAsUnsigned(reginfo, 0);
  if (!apiname_ptr)
    return StructuredData::ObjectSP();

  std::string apiName = "";
  Status read_error;
  target.ReadCStringFromMemory(apiname_ptr, apiName, read_error);
  if (read_error.Fail())
    return StructuredData::ObjectSP();

  std::string className = "";
  std::string selector = "";
  if (apiName.substr(0, 2) == "-[") {
    size_t spacePos = apiName.find(" ");
    if (spacePos != std::string::npos) {
      className = apiName.substr(2, spacePos - 2);
      selector = apiName.substr(spacePos + 1, apiName.length() - spacePos - 2);
    }
  }

  // Gather the PCs of the user frames in the backtrace.
  StructuredData::Array *trace = new StructuredData::Array();
  auto trace_sp = StructuredData::ObjectSP(trace);
  StackFrameSP responsible_frame;
  for (unsigned I = 0; I < thread_sp->GetStackFrameCount(); ++I) {
    StackFrameSP frame = thread_sp->GetStackFrameAtIndex(I);
    Address addr = frame->GetFrameCodeAddress();
    if (addr.GetModule() == runtime_module_sp) // Skip PCs from the runtime.
      continue;

    // The first non-runtime frame is responsible for the bug.
    if (!responsible_frame)
      responsible_frame = frame;

    // First frame in stacktrace should point to a real PC, not return address.
    if (I != 0 && trace->GetSize() == 0) {
      addr.Slide(-1);
    }

    lldb::addr_t PC = addr.GetLoadAddress(&target);
    trace->AddItem(StructuredData::ObjectSP(new StructuredData::Integer(PC)));
  }

  auto *d = new StructuredData::Dictionary();
  auto dict_sp = StructuredData::ObjectSP(d);
  d->AddStringItem("instrumentation_class", "MainThreadChecker");
  d->AddStringItem("api_name", apiName);
  d->AddStringItem("class_name", className);
  d->AddStringItem("selector", selector);
  d->AddStringItem("description",
                   apiName + " must be called from main thread only");
  d->AddIntegerItem("tid", thread_sp->GetIndexID());
  d->AddItem("trace", trace_sp);
  return dict_sp;
}

bool MainThreadCheckerRuntime::NotifyBreakpointHit(
    void *baton, StoppointCallbackContext *context, user_id_t break_id,
    user_id_t break_loc_id) {
  assert(baton && "null baton");
  if (!baton)
    return false; //< false => resume execution.

  MainThreadCheckerRuntime *const instance =
      static_cast<MainThreadCheckerRuntime *>(baton);

  ProcessSP process_sp = instance->GetProcessSP();
  ThreadSP thread_sp = context->exe_ctx_ref.GetThreadSP();
  if (!process_sp || !thread_sp ||
      process_sp != context->exe_ctx_ref.GetProcessSP())
    return false;

  StructuredData::ObjectSP report =
      instance->RetrieveReportData(context->exe_ctx_ref);

  if (report) {
    std::string description = report->GetAsDictionary()
                                ->GetValueForKey("description")
                                ->GetAsString()
                                ->GetValue();
    thread_sp->SetStopInfo(
        InstrumentationRuntimeStopInfo::CreateStopReasonWithInstrumentationData(
            *thread_sp, description, report));
    return true;
  }

  return false;
}

void MainThreadCheckerRuntime::Activate() {
  if (IsActive())
    return;

  ProcessSP process_sp = GetProcessSP();
  if (!process_sp)
    return;

  ModuleSP runtime_module_sp = GetRuntimeModuleSP();

  ConstString symbol_name("__main_thread_checker_on_report");
  const Symbol *symbol = runtime_module_sp->FindFirstSymbolWithNameAndType(
      symbol_name, eSymbolTypeCode);

  if (symbol == nullptr)
    return;

  if (!symbol->ValueIsAddress() || !symbol->GetAddressRef().IsValid())
    return;

  Target &target = process_sp->GetTarget();
  addr_t symbol_address = symbol->GetAddressRef().GetOpcodeLoadAddress(&target);

  if (symbol_address == LLDB_INVALID_ADDRESS)
    return;

  Breakpoint *breakpoint =
      process_sp->GetTarget()
          .CreateBreakpoint(symbol_address, /*internal=*/true,
                            /*hardware=*/false)
          .get();
  breakpoint->SetCallback(MainThreadCheckerRuntime::NotifyBreakpointHit, this,
                          true);
  breakpoint->SetBreakpointKind("main-thread-checker-report");
  SetBreakpointID(breakpoint->GetID());

  SetActive(true);
}

void MainThreadCheckerRuntime::Deactivate() {
  SetActive(false);

  auto BID = GetBreakpointID();
  if (BID == LLDB_INVALID_BREAK_ID)
    return;

  if (ProcessSP process_sp = GetProcessSP()) {
    process_sp->GetTarget().RemoveBreakpointByID(BID);
    SetBreakpointID(LLDB_INVALID_BREAK_ID);
  }
}

lldb::ThreadCollectionSP
MainThreadCheckerRuntime::GetBacktracesFromExtendedStopInfo(
    StructuredData::ObjectSP info) {
  ThreadCollectionSP threads;
  threads.reset(new ThreadCollection());

  ProcessSP process_sp = GetProcessSP();

  if (info->GetObjectForDotSeparatedPath("instrumentation_class")
      ->GetStringValue() != "MainThreadChecker")
    return threads;

  std::vector<lldb::addr_t> PCs;
  auto trace = info->GetObjectForDotSeparatedPath("trace")->GetAsArray();
  trace->ForEach([&PCs](StructuredData::Object *PC) -> bool {
    PCs.push_back(PC->GetAsInteger()->GetValue());
    return true;
  });

  if (PCs.empty())
    return threads;

  StructuredData::ObjectSP thread_id_obj =
      info->GetObjectForDotSeparatedPath("tid");
  tid_t tid = thread_id_obj ? thread_id_obj->GetIntegerValue() : 0;

  uint32_t stop_id = 0;
  bool stop_id_is_valid = false;
  HistoryThread *history_thread =
      new HistoryThread(*process_sp, tid, PCs, stop_id, stop_id_is_valid);
  ThreadSP new_thread_sp(history_thread);

  // Save this in the Process' ExtendedThreadList so a strong pointer
  // retains the object
  process_sp->GetExtendedThreadList().AddThread(new_thread_sp);
  threads->AddThread(new_thread_sp);

  return threads;
}
<commit_msg>Main Thread Checker: If we're in Swift, translate the Obj-C name to Swift name.<commit_after>//===-- MainThreadCheckerRuntime.cpp ----------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "MainThreadCheckerRuntime.h"

#include "lldb/Breakpoint/StoppointCallbackContext.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/Variable.h"
#include "lldb/Symbol/VariableList.h"
#include "lldb/Target/InstrumentationRuntimeStopInfo.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/StopInfo.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/RegularExpression.h"
#include "Plugins/Process/Utility/HistoryThread.h"
#include "swift/AST/ASTContext.h"
#include "swift/AST/NameLookup.h"
#include "swift/ClangImporter/ClangImporter.h"

using namespace lldb;
using namespace lldb_private;

MainThreadCheckerRuntime::~MainThreadCheckerRuntime() {
  Deactivate();
}

lldb::InstrumentationRuntimeSP
MainThreadCheckerRuntime::CreateInstance(const lldb::ProcessSP &process_sp) {
  return InstrumentationRuntimeSP(new MainThreadCheckerRuntime(process_sp));
}

void MainThreadCheckerRuntime::Initialize() {
  PluginManager::RegisterPlugin(
      GetPluginNameStatic(), "MainThreadChecker instrumentation runtime plugin.",
      CreateInstance, GetTypeStatic);
}

void MainThreadCheckerRuntime::Terminate() {
  PluginManager::UnregisterPlugin(CreateInstance);
}

lldb_private::ConstString MainThreadCheckerRuntime::GetPluginNameStatic() {
  return ConstString("MainThreadChecker");
}

lldb::InstrumentationRuntimeType MainThreadCheckerRuntime::GetTypeStatic() {
  return eInstrumentationRuntimeTypeMainThreadChecker;
}

const RegularExpression &
MainThreadCheckerRuntime::GetPatternForRuntimeLibrary() {
  static RegularExpression regex(llvm::StringRef("libMainThreadChecker.dylib"));
  return regex;
}

bool MainThreadCheckerRuntime::CheckIfRuntimeIsValid(
    const lldb::ModuleSP module_sp) {
  static ConstString test_sym("__main_thread_checker_on_report");
  const Symbol *symbol =
      module_sp->FindFirstSymbolWithNameAndType(test_sym, lldb::eSymbolTypeAny);
  return symbol != nullptr;
}

static std::string TranslateObjCNameToSwiftName(std::string className,
                                                std::string selector,
                                                StackFrameSP swiftFrame) {
  if (className.empty() || selector.empty())
    return "";
  ModuleSP swiftModule = swiftFrame->GetFrameCodeAddress().GetModule();
  if (!swiftModule)
    return "";
  SwiftASTContext *ctx = llvm::dyn_cast_or_null<SwiftASTContext>(
      swiftModule->GetTypeSystemForLanguage(lldb::eLanguageTypeSwift));
  if (!ctx)
    return "";
  swift::ClangImporter *imp = ctx->GetClangImporter();
  if (!imp)
    return "";

  size_t numArguments = llvm::StringRef(selector).count(':');
  llvm::SmallVector<llvm::StringRef, 4> parts;
  llvm::StringRef(selector).split(parts, ":", /*MaxSplit*/ -1,
      /*KeepEmpty*/ false);

  llvm::SmallVector<swift::Identifier, 2> selectorIdentifiers;
  for (auto i = 0; i < parts.size(); i++) {
    selectorIdentifiers.push_back(ctx->GetIdentifier(parts[i]));
  }

  class MyConsumer : public swift::VisibleDeclConsumer {
  public:
    swift::ObjCSelector selectorToLookup;
    swift::DeclName result;

    MyConsumer(swift::ObjCSelector selector) : selectorToLookup(selector) {}

    virtual void foundDecl(swift::ValueDecl *VD,
                           swift::DeclVisibilityKind Reason) {
      if (result)
        return; // Take the first result.
      if (swift::ClassDecl *cls = clang::dyn_cast<swift::ClassDecl>(VD)) {
        auto funcs = cls->lookupDirect(selectorToLookup, true);
        if (funcs.size() > 0) {
          result = funcs.front()->getFullName();
        }
      }
    }
  };

  MyConsumer consumer(swift::ObjCSelector(*ctx->GetASTContext(), numArguments,
                                          selectorIdentifiers));
  // FIXME(mracek): Switch to a new API that translates the Clang class name
  // to Swift class name, once this API exists. Now we assume they are the same.
  imp->lookupValue(ctx->GetIdentifier(className), consumer);

  if (!consumer.result)
    return "";
  llvm::SmallString<32> scratchSpace;
  return className + "." + consumer.result.getString(scratchSpace).str();
}

StructuredData::ObjectSP
MainThreadCheckerRuntime::RetrieveReportData(ExecutionContextRef exe_ctx_ref) {
  ProcessSP process_sp = GetProcessSP();
  if (!process_sp)
    return StructuredData::ObjectSP();

  ThreadSP thread_sp = exe_ctx_ref.GetThreadSP();
  StackFrameSP frame_sp = thread_sp->GetSelectedFrame();
  ModuleSP runtime_module_sp = GetRuntimeModuleSP();
  Target &target = process_sp->GetTarget();

  if (!frame_sp)
    return StructuredData::ObjectSP();

  RegisterContextSP regctx_sp = frame_sp->GetRegisterContext();
  if (!regctx_sp)
    return StructuredData::ObjectSP();

  const RegisterInfo *reginfo = regctx_sp->GetRegisterInfoByName("arg1");
  if (!reginfo)
    return StructuredData::ObjectSP();

  uint64_t apiname_ptr = regctx_sp->ReadRegisterAsUnsigned(reginfo, 0);
  if (!apiname_ptr)
    return StructuredData::ObjectSP();

  std::string apiName = "";
  Status read_error;
  target.ReadCStringFromMemory(apiname_ptr, apiName, read_error);
  if (read_error.Fail())
    return StructuredData::ObjectSP();

  std::string className = "";
  std::string selector = "";
  if (apiName.substr(0, 2) == "-[") {
    size_t spacePos = apiName.find(" ");
    if (spacePos != std::string::npos) {
      className = apiName.substr(2, spacePos - 2);
      selector = apiName.substr(spacePos + 1, apiName.length() - spacePos - 2);
    }
  }

  // Gather the PCs of the user frames in the backtrace.
  StructuredData::Array *trace = new StructuredData::Array();
  auto trace_sp = StructuredData::ObjectSP(trace);
  StackFrameSP responsible_frame;
  for (unsigned I = 0; I < thread_sp->GetStackFrameCount(); ++I) {
    StackFrameSP frame = thread_sp->GetStackFrameAtIndex(I);
    Address addr = frame->GetFrameCodeAddress();
    if (addr.GetModule() == runtime_module_sp) // Skip PCs from the runtime.
      continue;

    // The first non-runtime frame is responsible for the bug.
    if (!responsible_frame)
      responsible_frame = frame;

    // First frame in stacktrace should point to a real PC, not return address.
    if (I != 0 && trace->GetSize() == 0) {
      addr.Slide(-1);
    }

    lldb::addr_t PC = addr.GetLoadAddress(&target);
    trace->AddItem(StructuredData::ObjectSP(new StructuredData::Integer(PC)));
  }

  if (responsible_frame) {
    if (responsible_frame->GetLanguage() == eLanguageTypeSwift) {
      std::string swiftApiName =
          TranslateObjCNameToSwiftName(className, selector, responsible_frame);
      if (swiftApiName != "")
        apiName = swiftApiName;
    }
  }

  auto *d = new StructuredData::Dictionary();
  auto dict_sp = StructuredData::ObjectSP(d);
  d->AddStringItem("instrumentation_class", "MainThreadChecker");
  d->AddStringItem("api_name", apiName);
  d->AddStringItem("class_name", className);
  d->AddStringItem("selector", selector);
  d->AddStringItem("description",
                   apiName + " must be called from main thread only");
  d->AddIntegerItem("tid", thread_sp->GetIndexID());
  d->AddItem("trace", trace_sp);
  return dict_sp;
}

bool MainThreadCheckerRuntime::NotifyBreakpointHit(
    void *baton, StoppointCallbackContext *context, user_id_t break_id,
    user_id_t break_loc_id) {
  assert(baton && "null baton");
  if (!baton)
    return false; //< false => resume execution.

  MainThreadCheckerRuntime *const instance =
      static_cast<MainThreadCheckerRuntime *>(baton);

  ProcessSP process_sp = instance->GetProcessSP();
  ThreadSP thread_sp = context->exe_ctx_ref.GetThreadSP();
  if (!process_sp || !thread_sp ||
      process_sp != context->exe_ctx_ref.GetProcessSP())
    return false;

  StructuredData::ObjectSP report =
      instance->RetrieveReportData(context->exe_ctx_ref);

  if (report) {
    std::string description = report->GetAsDictionary()
                                ->GetValueForKey("description")
                                ->GetAsString()
                                ->GetValue();
    thread_sp->SetStopInfo(
        InstrumentationRuntimeStopInfo::CreateStopReasonWithInstrumentationData(
            *thread_sp, description, report));
    return true;
  }

  return false;
}

void MainThreadCheckerRuntime::Activate() {
  if (IsActive())
    return;

  ProcessSP process_sp = GetProcessSP();
  if (!process_sp)
    return;

  ModuleSP runtime_module_sp = GetRuntimeModuleSP();

  ConstString symbol_name("__main_thread_checker_on_report");
  const Symbol *symbol = runtime_module_sp->FindFirstSymbolWithNameAndType(
      symbol_name, eSymbolTypeCode);

  if (symbol == nullptr)
    return;

  if (!symbol->ValueIsAddress() || !symbol->GetAddressRef().IsValid())
    return;

  Target &target = process_sp->GetTarget();
  addr_t symbol_address = symbol->GetAddressRef().GetOpcodeLoadAddress(&target);

  if (symbol_address == LLDB_INVALID_ADDRESS)
    return;

  Breakpoint *breakpoint =
      process_sp->GetTarget()
          .CreateBreakpoint(symbol_address, /*internal=*/true,
                            /*hardware=*/false)
          .get();
  breakpoint->SetCallback(MainThreadCheckerRuntime::NotifyBreakpointHit, this,
                          true);
  breakpoint->SetBreakpointKind("main-thread-checker-report");
  SetBreakpointID(breakpoint->GetID());

  SetActive(true);
}

void MainThreadCheckerRuntime::Deactivate() {
  SetActive(false);

  auto BID = GetBreakpointID();
  if (BID == LLDB_INVALID_BREAK_ID)
    return;

  if (ProcessSP process_sp = GetProcessSP()) {
    process_sp->GetTarget().RemoveBreakpointByID(BID);
    SetBreakpointID(LLDB_INVALID_BREAK_ID);
  }
}

lldb::ThreadCollectionSP
MainThreadCheckerRuntime::GetBacktracesFromExtendedStopInfo(
    StructuredData::ObjectSP info) {
  ThreadCollectionSP threads;
  threads.reset(new ThreadCollection());

  ProcessSP process_sp = GetProcessSP();

  if (info->GetObjectForDotSeparatedPath("instrumentation_class")
      ->GetStringValue() != "MainThreadChecker")
    return threads;

  std::vector<lldb::addr_t> PCs;
  auto trace = info->GetObjectForDotSeparatedPath("trace")->GetAsArray();
  trace->ForEach([&PCs](StructuredData::Object *PC) -> bool {
    PCs.push_back(PC->GetAsInteger()->GetValue());
    return true;
  });

  if (PCs.empty())
    return threads;

  StructuredData::ObjectSP thread_id_obj =
      info->GetObjectForDotSeparatedPath("tid");
  tid_t tid = thread_id_obj ? thread_id_obj->GetIntegerValue() : 0;

  uint32_t stop_id = 0;
  bool stop_id_is_valid = false;
  HistoryThread *history_thread =
      new HistoryThread(*process_sp, tid, PCs, stop_id, stop_id_is_valid);
  ThreadSP new_thread_sp(history_thread);

  // Save this in the Process' ExtendedThreadList so a strong pointer
  // retains the object
  process_sp->GetExtendedThreadList().AddThread(new_thread_sp);
  threads->AddThread(new_thread_sp);

  return threads;
}
<|endoftext|>


<commit_before>#ifndef DEBRUIJN_BIT_BLOCK_ITERATOR_HPP_
#define DEBRUIJN_BIT_BLOCK_ITERATOR_HPP_

#include "clotho/utility/bit_block_iterator_def.hpp"
#include "clotho/utility/bit_masks.hpp"

namespace clotho {
namespace utility {
namespace tag {

struct debruijn_iterator_tag {};

}   // namespace tag
}   // namespace utility
}   // namespace clotho

namespace clotho {
namespace utility {

template < class Block >
class bit_block_iterator < Block, clotho::utility::tag::debruijn_iterator_tag, typename std::enable_if< std::is_integral< Block >::value >::type > {
public:
    typedef bit_block_iterator< Block, clotho::utility::tag::debruijn_iterator_tag, void > self_type;
    typedef Block block_type;

    static const unsigned int bits_per_block = sizeof( block_type ) * 8;

    bit_block_iterator( block_type b = (block_type)0) :
        m_val(b),
        m_lsb(0)
    {
        next();
    }

    bit_block_iterator( const self_type & rhs ) :
        m_val( rhs.m_val )
        , m_lsb( rhs.m_lsb )
    {
    }

    bit_block_iterator & operator++() {
        // remove least significant bit
        m_val ^= (m_val & (-m_val));
        next();
        return *this;
    }

    bit_block_iterator operator++(int) {
        bit_block_iterator res(*this);
        this->operator++();
        return res;
    }

    inline bool    done() const {
        return !(m_val);
    }

    unsigned int operator*() const {
        if( !m_val ) {
            return (unsigned int) (-1);
        }
        return m_lsb;
    }

    bool operator==( const self_type & rhs ) const {
        return (this->m_val == rhs.m_val);
    }

    bool operator!=(const self_type & rhs ) const {
        return (this->m_val != rhs.m_val );
    }

    void reset( block_type b ) {
        m_val = b;
        next();
    }

    virtual ~bit_block_iterator() {}

protected:
    inline void next() {
        if( m_val ) {
            unsigned int lsb = (unsigned int)m_val;
            if( lsb ) {
                m_lsb = DEBRUIJNBIT_HASH_LOOKUP( (lsb & (-lsb)) );
            } else {
                lsb = (unsigned int)( m_val >> 32 );
                m_lsb = DEBRUIJNBIT_HASH_LOOKUP( (lsb & (-lsb)) );
                lsb += 32;
            }
        }
    }
    block_type m_val, m_lsb;
};

}   // namespace utility
}   // namespace clotho
#endif  // DEBRUIJN_BIT_BLOCK_ITERATOR_HPP_
<commit_msg>Formatting<commit_after>#ifndef DEBRUIJN_BIT_BLOCK_ITERATOR_HPP_
#define DEBRUIJN_BIT_BLOCK_ITERATOR_HPP_

#include "clotho/utility/bit_block_iterator_def.hpp"
#include "clotho/utility/bit_masks.hpp"

namespace clotho {
namespace utility {
namespace tag {

struct debruijn_iterator_tag {};

}   // namespace tag
}   // namespace utility
}   // namespace clotho

namespace clotho {
namespace utility {

template < class Block >
class bit_block_iterator < Block, clotho::utility::tag::debruijn_iterator_tag, typename std::enable_if< std::is_integral< Block >::value >::type > {
public:
    typedef bit_block_iterator< Block, clotho::utility::tag::debruijn_iterator_tag, void > self_type;
    typedef Block block_type;

    static const unsigned int bits_per_block = sizeof( block_type ) * 8;

    bit_block_iterator( block_type b = (block_type)0) :
        m_val(b),
        m_lsb(0) {
        next();
    }

    bit_block_iterator( const self_type & rhs ) :
        m_val( rhs.m_val )
        , m_lsb( rhs.m_lsb ) {
    }

    bit_block_iterator & operator++() {
        // remove least significant bit
        m_val ^= (m_val & (-m_val));
        next();
        return *this;
    }

    bit_block_iterator operator++(int) {
        bit_block_iterator res(*this);
        this->operator++();
        return res;
    }

    inline bool    done() const {
        return !(m_val);
    }

    unsigned int operator*() const {
        if( !m_val ) {
            return (unsigned int) (-1);
        }
        return m_lsb;
    }

    bool operator==( const self_type & rhs ) const {
        return (this->m_val == rhs.m_val);
    }

    bool operator!=(const self_type & rhs ) const {
        return (this->m_val != rhs.m_val );
    }

    void reset( block_type b ) {
        m_val = b;
        next();
    }

    virtual ~bit_block_iterator() {}

protected:
    inline void next() {
        if( m_val ) {
            unsigned int lsb = (unsigned int)m_val;
            if( lsb ) {
                m_lsb = DEBRUIJNBIT_HASH_LOOKUP( (lsb & (-lsb)) );
            } else {
                lsb = (unsigned int)( m_val >> 32 );
                m_lsb = DEBRUIJNBIT_HASH_LOOKUP( (lsb & (-lsb)) );
                lsb += 32;
            }
        }
    }
    block_type m_val, m_lsb;
};

}   // namespace utility
}   // namespace clotho
#endif  // DEBRUIJN_BIT_BLOCK_ITERATOR_HPP_
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: sddll.cxx,v $
 *
 *  $Revision: 1.9 $
 *
 *  last change: $Author: pjunck $ $Date: 2004-11-03 08:54:36 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _EEITEM_HXX //autogen
#include <svx/eeitem.hxx>
#endif

#include <svx/editeng.hxx>

#ifndef _SVDOBJ_HXX //autogen
#include <svx/svdobj.hxx>
#endif
#ifndef INCLUDED_SVTOOLS_MODULEOPTIONS_HXX
#include <svtools/moduleoptions.hxx>
#endif
#ifndef _FM_FMOBJFAC_HXX
#include <svx/fmobjfac.hxx>
#endif
#ifndef _SVX_SIIMPORT_HXX
#include <svx/siimport.hxx>
#endif
#ifndef _SVDFIELD_HXX
#include <svx/svdfield.hxx>
#endif
#ifndef _OBJFAC3D_HXX
#include <svx/objfac3d.hxx>
#endif

#pragma hdrstop

#include "sddll.hxx"
#ifndef SD_DRAW_DOC_SHELL_HXX
#include "DrawDocShell.hxx"
#endif
#ifndef SD_GRAPHIC_DOC_SHELL_HXX
#include "GraphicDocShell.hxx"
#endif
#include "sdresid.hxx"
#include "sdobjfac.hxx"
#include "cfgids.hxx"
#include "strmname.h"
#include "SdShapeTypes.hxx"

#include <svx/SvxShapeTypes.hxx>
#include <sfx2/docfilt.hxx>
#include <sfx2/docfile.hxx>
#include <sfx2/fcontnr.hxx>
#include <tools/urlobj.hxx>
#include <svx/impgrf.hxx>
#include <svtools/FilterConfigItem.hxx>

#ifndef _COM_SUN_STAR_UTIL_XARCHIVER_HPP_
#include <com/sun/star/util/XArchiver.hpp>
#endif

#ifndef _COMPHELPER_PROCESSFACTORY_HXX_
#include <comphelper/processfactory.hxx>
#endif

using namespace ::rtl;
using namespace ::com::sun::star;

/*************************************************************************
|*
|* Init
|*
\************************************************************************/

void SdDLL::Init()
{
    if ( SD_MOD() )
        return;

    SfxObjectFactory* pDrawFact = NULL;
    SfxObjectFactory* pImpressFact = NULL;

    if (SvtModuleOptions().IsImpress())
        pImpressFact = &::sd::DrawDocShell::Factory();

    if (SvtModuleOptions().IsDraw())
        pDrawFact = &::sd::GraphicDocShell::Factory();

    // the SdModule must be created
     SdModule** ppShlPtr = (SdModule**) GetAppData(SHL_DRAW);
    (*ppShlPtr) = new SdModule( pImpressFact, pDrawFact);

    if (SvtModuleOptions().IsImpress())
    {
        // Register the Impress shape types in order to make the shapes accessible.
        ::accessibility::RegisterImpressShapeTypes ();
        ::sd::DrawDocShell::Factory().SetDocumentServiceName( String( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.presentation.PresentationDocument" ) ) );
        ::sd::DrawDocShell::Factory().RegisterMenuBar( SdResId( RID_DRAW_DEFAULTMENU ) );
        ::sd::DrawDocShell::Factory().RegisterAccel( SdResId( RID_DRAW_DEFAULTACCEL ) );
    }

    if (SvtModuleOptions().IsDraw())
    {
        ::sd::GraphicDocShell::Factory().SetDocumentServiceName( String( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.drawing.DrawingDocument" ) ) );
        ::sd::GraphicDocShell::Factory().RegisterMenuBar( SdResId( RID_GRAPHIC_DEFAULTMENU ) );
        ::sd::GraphicDocShell::Factory().RegisterAccel( SdResId( RID_GRAPHIC_DEFAULTACCEL ) );
    }

    // register your view-factories here
    RegisterFactorys();

    // register your shell-interfaces here
    RegisterInterfaces();

    // register your controllers here
    RegisterControllers();

    // SvDraw-Felder registrieren
    SdrRegisterFieldClasses();

    // 3D-Objekt-Factory eintragen
    E3dObjFactory();

    // ::com::sun::star::form::component::Form-Objekt-Factory eintragen
    FmFormObjFactory();

    // factory for dummy import of old si-controls in 3.1 documents
//BFS02    SiImportFactory();

    // Objekt-Factory eintragen
    SdrObjFactory::InsertMakeUserDataHdl(LINK(&aSdObjectFactory, SdObjectFactory, MakeUserData));
}

/*************************************************************************
|*
|* Exit
|*
\************************************************************************/

void SdDLL::Exit()
{
    // called directly befor unloading the DLL
    // do whatever you want, Sd-DLL is accessible

    // Objekt-Factory austragen
    SdrObjFactory::RemoveMakeUserDataHdl(LINK(&aSdObjectFactory, SdObjectFactory, MakeUserData));

    // the SdModule must be destroyed
    SdModule** ppShlPtr = (SdModule**) GetAppData(SHL_DRAW);
    delete (*ppShlPtr);
    (*ppShlPtr) = NULL;
}

/*
ULONG SdDLL::DetectFilter(SfxMedium& rMedium, const SfxFilter** ppFilter,
                          SfxFilterFlags nMust, SfxFilterFlags nDont)
{
    ULONG nReturn = ERRCODE_ABORT;  // Erkennung fehlgeschlagen, Filter ungueltig
    BOOL bStorage = FALSE;

    if( *ppFilter && (*ppFilter)->GetFilterFlags() & SFX_FILTER_PACKED )
    {
        uno::Reference< lang::XMultiServiceFactory > xSMgr( ::comphelper::getProcessServiceFactory() );
        uno::Reference< util::XArchiver > xPacker( xSMgr->createInstance( OUString::createFromAscii( "com.sun.star.util.Archiver" ) ), uno::UNO_QUERY );
        if( xPacker.is() )
        {
            // extract extra data
            OUString aPath( rMedium.GetOrigURL() );
            OUString aExtraData( xPacker->getExtraData( aPath ) );
            const OUString aSig1= OUString::createFromAscii( "private:" );
            String aTmp;
            aTmp += sal_Unicode( '?' );
            aTmp += String::CreateFromAscii("simpress");
            const OUString aSig2( aTmp );
            INT32 nIndex1 = aExtraData.indexOf( aSig1 );
            INT32 nIndex2 = aExtraData.indexOf( aSig2 );
            if( nIndex1 == 0 && nIndex2 != -1 )
                return ERRCODE_NONE;
        }
    }
    else if (rMedium.GetError() == SVSTREAM_OK)
    {
        if ( rMedium.IsStorage() )
        {
            bStorage = TRUE;
            SotStorageRef xStorage = rMedium.GetStorage();
            if ( !xStorage.Is() )
                return ULONG_MAX;

            if( SvtModuleOptions().IsImpress() )
            {
                // Erkennung ueber contained streams (PowerPoint 97-Filter)
                String aStreamName = UniString::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "PowerPoint Document" ) );
                if ( xStorage->IsContained( aStreamName ) && xStorage->IsStream( aStreamName ) )
                {
                    String aFileName(rMedium.GetName());
                    aFileName.ToUpperAscii();

                    if( aFileName.SearchAscii( ".POT" ) == STRING_NOTFOUND )
                        *ppFilter = SfxFilter::GetFilterByName( pFilterPowerPoint97);
                    else
                        *ppFilter = SfxFilter::GetFilterByName( pFilterPowerPoint97Template );

                    return ERRCODE_NONE;
                }
            }

            const SfxFilter* pFilter = *ppFilter;
            if ( *ppFilter )
            {
                if ( (*ppFilter)->GetFormat() == xStorage->GetFormat() )
                    pFilter = *ppFilter;
            }

             if( !pFilter && SvtModuleOptions().IsImpress() )
            {
                SfxFilterMatcher aMatcher( String::CreateFromAscii("simpress") );
                pFilter = aMatcher.GetFilter4ClipBoardId( xStorage->GetFormat() );
                if ( pFilter )
                    *ppFilter = pFilter;
            }

            if( !pFilter && SvtModuleOptions().IsDraw() )
            {
                SfxFilterMatcher aMatcher( String::CreateFromAscii("sdraw") );
                pFilter = aMatcher.GetFilter4ClipBoardId( xStorage->GetFormat() );
                if ( pFilter )
                    *ppFilter = pFilter;
            }

            if ( pFilter &&
                ( pFilter->GetFilterFlags() & nMust ) == nMust &&
                ( pFilter->GetFilterFlags() & nDont ) == 0 )
            {
                *ppFilter = pFilter;
                nReturn = ERRCODE_NONE;
            }
            else
            {
                *ppFilter = NULL;
                nReturn = ERRCODE_NONE;
            }
        }

        String aFileName( rMedium.GetName() );
        aFileName.ToUpperAscii();

        if ( nReturn == ERRCODE_ABORT )
        {
            if( bStorage )         // aber keine Clipboard-Id #55337#
            {
                *ppFilter = NULL;
            }
            else
            {
                // Vektorgraphik?
                SvStream* pStm = rMedium.GetInStream();

                if( !pStm )
                    nReturn = ERRCODE_IO_GENERAL;
                else
                {
                    pStm->Seek( STREAM_SEEK_TO_BEGIN );

                    const String        aFileName( rMedium.GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) );
                    GraphicDescriptor   aDesc( *pStm, &aFileName );
                    GraphicFilter*      pGrfFilter = GetGrfFilter();

                    if( !aDesc.Detect( FALSE ) )
                    {
                        if( SvtModuleOptions().IsImpress() )
                        {
                            *ppFilter = NULL;
                            nReturn = ERRCODE_ABORT;
                            INetURLObject aURL( aFileName );
                            if( aURL.getExtension().EqualsIgnoreCaseAscii( "cgm" ) )
                            {
                                sal_uInt8 n8;
                                pStm->Seek( STREAM_SEEK_TO_BEGIN );
                                *pStm >> n8;
                                if ( ( n8 & 0xf0 ) == 0 )       // we are supporting binary cgm format only, so
                                {                               // this is a small test to exclude cgm text
                                    const String aName = UniString::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "CGM - Computer Graphics Metafile" ) );
                                    SfxFilterMatcher aMatch( String::CreateFromAscii("simpress") );
                                    *ppFilter = aMatch.GetFilter4FilterName( aName );
                                    nReturn = ERRCODE_NONE;
                                }
                            }
                        }
                    }
                    else
                    {
                        if( SvtModuleOptions().IsDraw() )
                        {
                            String aShortName( aDesc.GetImportFormatShortName( aDesc.GetFileFormat() ) );
                            const String aName( pGrfFilter->GetImportFormatTypeName( pGrfFilter->GetImportFormatNumberForShortName( aShortName ) ) );

                            if ( *ppFilter && aShortName.EqualsIgnoreCaseAscii( "PCD" ) )    // there is a multiple pcd selection possible
                            {
                                sal_Int32 nBase = 2;    // default Base0
                                String aFilterTypeName( (*ppFilter)->GetRealTypeName() );
                                if ( aFilterTypeName.CompareToAscii( "pcd_Photo_CD_Base4" ) == COMPARE_EQUAL )
                                    nBase = 1;
                                else if ( aFilterTypeName.CompareToAscii( "pcd_Photo_CD_Base16" ) == COMPARE_EQUAL )
                                    nBase = 0;
                                String aFilterConfigPath( RTL_CONSTASCII_USTRINGPARAM( "Office.Common/Filter/Graphic/Import/PCD" ) );
                                FilterConfigItem aFilterConfigItem( aFilterConfigPath );
                                aFilterConfigItem.WriteInt32( String( RTL_CONSTASCII_USTRINGPARAM( "Resolution" ) ), nBase );
                            }

                            SfxFilterMatcher aMatch( String::CreateFromAscii("draw") );
                            *ppFilter = aMatch.GetFilter4FilterName( aName );
                            nReturn = ERRCODE_NONE;
                        }
                        else
                        {
                            nReturn = ERRCODE_ABORT;
                            *ppFilter = NULL;
                        }
                    }
                }
            }
        }
    }
    else
    {
        nReturn = rMedium.GetError();
    }

    return nReturn;
} */
<commit_msg>INTEGRATION: CWS ineturl1 (1.7.220); FILE MERGED 2004/12/01 16:42:05 cmc 1.7.220.3: RESYNC: (1.8-1.9); FILE MERGED 2004/10/27 12:39:31 cmc 1.7.220.2: RESYNC: (1.7-1.8); FILE MERGED 2004/10/01 10:26:38 cmc 1.7.220.1: #i34006# modify INetURLObject to use rtl::OUString and rtl::OUStringBuffer<commit_after>/*************************************************************************
 *
 *  $RCSfile: sddll.cxx,v $
 *
 *  $Revision: 1.10 $
 *
 *  last change: $Author: hr $ $Date: 2004-12-13 12:32:38 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _EEITEM_HXX //autogen
#include <svx/eeitem.hxx>
#endif

#include <svx/editeng.hxx>

#ifndef _SVDOBJ_HXX //autogen
#include <svx/svdobj.hxx>
#endif
#ifndef INCLUDED_SVTOOLS_MODULEOPTIONS_HXX
#include <svtools/moduleoptions.hxx>
#endif
#ifndef _FM_FMOBJFAC_HXX
#include <svx/fmobjfac.hxx>
#endif
#ifndef _SVX_SIIMPORT_HXX
#include <svx/siimport.hxx>
#endif
#ifndef _SVDFIELD_HXX
#include <svx/svdfield.hxx>
#endif
#ifndef _OBJFAC3D_HXX
#include <svx/objfac3d.hxx>
#endif

#pragma hdrstop

#include "sddll.hxx"
#ifndef SD_DRAW_DOC_SHELL_HXX
#include "DrawDocShell.hxx"
#endif
#ifndef SD_GRAPHIC_DOC_SHELL_HXX
#include "GraphicDocShell.hxx"
#endif
#include "sdresid.hxx"
#include "sdobjfac.hxx"
#include "cfgids.hxx"
#include "strmname.h"
#include "SdShapeTypes.hxx"

#include <svx/SvxShapeTypes.hxx>
#include <sfx2/docfilt.hxx>
#include <sfx2/docfile.hxx>
#include <sfx2/fcontnr.hxx>
#include <tools/urlobj.hxx>
#include <svx/impgrf.hxx>
#include <svtools/FilterConfigItem.hxx>

#ifndef _COM_SUN_STAR_UTIL_XARCHIVER_HPP_
#include <com/sun/star/util/XArchiver.hpp>
#endif

#ifndef _COMPHELPER_PROCESSFACTORY_HXX_
#include <comphelper/processfactory.hxx>
#endif

using namespace ::rtl;
using namespace ::com::sun::star;

/*************************************************************************
|*
|* Init
|*
\************************************************************************/

void SdDLL::Init()
{
    if ( SD_MOD() )
        return;

    SfxObjectFactory* pDrawFact = NULL;
    SfxObjectFactory* pImpressFact = NULL;

    if (SvtModuleOptions().IsImpress())
        pImpressFact = &::sd::DrawDocShell::Factory();

    if (SvtModuleOptions().IsDraw())
        pDrawFact = &::sd::GraphicDocShell::Factory();

    // the SdModule must be created
     SdModule** ppShlPtr = (SdModule**) GetAppData(SHL_DRAW);
    (*ppShlPtr) = new SdModule( pImpressFact, pDrawFact);

    if (SvtModuleOptions().IsImpress())
    {
        // Register the Impress shape types in order to make the shapes accessible.
        ::accessibility::RegisterImpressShapeTypes ();
        ::sd::DrawDocShell::Factory().SetDocumentServiceName( String( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.presentation.PresentationDocument" ) ) );
        ::sd::DrawDocShell::Factory().RegisterMenuBar( SdResId( RID_DRAW_DEFAULTMENU ) );
        ::sd::DrawDocShell::Factory().RegisterAccel( SdResId( RID_DRAW_DEFAULTACCEL ) );
    }

    if (SvtModuleOptions().IsDraw())
    {
        ::sd::GraphicDocShell::Factory().SetDocumentServiceName( String( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.drawing.DrawingDocument" ) ) );
        ::sd::GraphicDocShell::Factory().RegisterMenuBar( SdResId( RID_GRAPHIC_DEFAULTMENU ) );
        ::sd::GraphicDocShell::Factory().RegisterAccel( SdResId( RID_GRAPHIC_DEFAULTACCEL ) );
    }

    // register your view-factories here
    RegisterFactorys();

    // register your shell-interfaces here
    RegisterInterfaces();

    // register your controllers here
    RegisterControllers();

    // SvDraw-Felder registrieren
    SdrRegisterFieldClasses();

    // 3D-Objekt-Factory eintragen
    E3dObjFactory();

    // ::com::sun::star::form::component::Form-Objekt-Factory eintragen
    FmFormObjFactory();

    // factory for dummy import of old si-controls in 3.1 documents
//BFS02    SiImportFactory();

    // Objekt-Factory eintragen
    SdrObjFactory::InsertMakeUserDataHdl(LINK(&aSdObjectFactory, SdObjectFactory, MakeUserData));
}

/*************************************************************************
|*
|* Exit
|*
\************************************************************************/

void SdDLL::Exit()
{
    // called directly befor unloading the DLL
    // do whatever you want, Sd-DLL is accessible

    // Objekt-Factory austragen
    SdrObjFactory::RemoveMakeUserDataHdl(LINK(&aSdObjectFactory, SdObjectFactory, MakeUserData));

    // the SdModule must be destroyed
    SdModule** ppShlPtr = (SdModule**) GetAppData(SHL_DRAW);
    delete (*ppShlPtr);
    (*ppShlPtr) = NULL;
}

/*
ULONG SdDLL::DetectFilter(SfxMedium& rMedium, const SfxFilter** ppFilter,
                          SfxFilterFlags nMust, SfxFilterFlags nDont)
{
    ULONG nReturn = ERRCODE_ABORT;  // Erkennung fehlgeschlagen, Filter ungueltig
    BOOL bStorage = FALSE;

    if( *ppFilter && (*ppFilter)->GetFilterFlags() & SFX_FILTER_PACKED )
    {
        uno::Reference< lang::XMultiServiceFactory > xSMgr( ::comphelper::getProcessServiceFactory() );
        uno::Reference< util::XArchiver > xPacker( xSMgr->createInstance( OUString::createFromAscii( "com.sun.star.util.Archiver" ) ), uno::UNO_QUERY );
        if( xPacker.is() )
        {
            // extract extra data
            OUString aPath( rMedium.GetOrigURL() );
            OUString aExtraData( xPacker->getExtraData( aPath ) );
            const OUString aSig1= OUString::createFromAscii( "private:" );
            String aTmp;
            aTmp += sal_Unicode( '?' );
            aTmp += String::CreateFromAscii("simpress");
            const OUString aSig2( aTmp );
            INT32 nIndex1 = aExtraData.indexOf( aSig1 );
            INT32 nIndex2 = aExtraData.indexOf( aSig2 );
            if( nIndex1 == 0 && nIndex2 != -1 )
                return ERRCODE_NONE;
        }
    }
    else if (rMedium.GetError() == SVSTREAM_OK)
    {
        if ( rMedium.IsStorage() )
        {
            bStorage = TRUE;
            SotStorageRef xStorage = rMedium.GetStorage();
            if ( !xStorage.Is() )
                return ULONG_MAX;

            if( SvtModuleOptions().IsImpress() )
            {
                // Erkennung ueber contained streams (PowerPoint 97-Filter)
                String aStreamName = UniString::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "PowerPoint Document" ) );
                if ( xStorage->IsContained( aStreamName ) && xStorage->IsStream( aStreamName ) )
                {
                    String aFileName(rMedium.GetName());
                    aFileName.ToUpperAscii();

                    if( aFileName.SearchAscii( ".POT" ) == STRING_NOTFOUND )
                        *ppFilter = SfxFilter::GetFilterByName( pFilterPowerPoint97);
                    else
                        *ppFilter = SfxFilter::GetFilterByName( pFilterPowerPoint97Template );

                    return ERRCODE_NONE;
                }
            }

            const SfxFilter* pFilter = *ppFilter;
            if ( *ppFilter )
            {
                if ( (*ppFilter)->GetFormat() == xStorage->GetFormat() )
                    pFilter = *ppFilter;
            }

             if( !pFilter && SvtModuleOptions().IsImpress() )
            {
                SfxFilterMatcher aMatcher( String::CreateFromAscii("simpress") );
                pFilter = aMatcher.GetFilter4ClipBoardId( xStorage->GetFormat() );
                if ( pFilter )
                    *ppFilter = pFilter;
            }

            if( !pFilter && SvtModuleOptions().IsDraw() )
            {
                SfxFilterMatcher aMatcher( String::CreateFromAscii("sdraw") );
                pFilter = aMatcher.GetFilter4ClipBoardId( xStorage->GetFormat() );
                if ( pFilter )
                    *ppFilter = pFilter;
            }

            if ( pFilter &&
                ( pFilter->GetFilterFlags() & nMust ) == nMust &&
                ( pFilter->GetFilterFlags() & nDont ) == 0 )
            {
                *ppFilter = pFilter;
                nReturn = ERRCODE_NONE;
            }
            else
            {
                *ppFilter = NULL;
                nReturn = ERRCODE_NONE;
            }
        }

        String aFileName( rMedium.GetName() );
        aFileName.ToUpperAscii();

        if ( nReturn == ERRCODE_ABORT )
        {
            if( bStorage )         // aber keine Clipboard-Id #55337#
            {
                *ppFilter = NULL;
            }
            else
            {
                // Vektorgraphik?
                SvStream* pStm = rMedium.GetInStream();

                if( !pStm )
                    nReturn = ERRCODE_IO_GENERAL;
                else
                {
                    pStm->Seek( STREAM_SEEK_TO_BEGIN );

                    const String        aFileName( rMedium.GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) );
                    GraphicDescriptor   aDesc( *pStm, &aFileName );
                    GraphicFilter*      pGrfFilter = GetGrfFilter();

                    if( !aDesc.Detect( FALSE ) )
                    {
                        if( SvtModuleOptions().IsImpress() )
                        {
                            *ppFilter = NULL;
                            nReturn = ERRCODE_ABORT;
                            INetURLObject aURL( aFileName );
                            if( aURL.getExtension().equalsIgnoreAsciiCaseAscii( "cgm" ) )
                            {
                                sal_uInt8 n8;
                                pStm->Seek( STREAM_SEEK_TO_BEGIN );
                                *pStm >> n8;
                                if ( ( n8 & 0xf0 ) == 0 )       // we are supporting binary cgm format only, so
                                {                               // this is a small test to exclude cgm text
                                    const String aName = UniString::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "CGM - Computer Graphics Metafile" ) );
                                    SfxFilterMatcher aMatch( String::CreateFromAscii("simpress") );
                                    *ppFilter = aMatch.GetFilter4FilterName( aName );
                                    nReturn = ERRCODE_NONE;
                                }
                            }
                        }
                    }
                    else
                    {
                        if( SvtModuleOptions().IsDraw() )
                        {
                            String aShortName( aDesc.GetImportFormatShortName( aDesc.GetFileFormat() ) );
                            const String aName( pGrfFilter->GetImportFormatTypeName( pGrfFilter->GetImportFormatNumberForShortName( aShortName ) ) );

                            if ( *ppFilter && aShortName.EqualsIgnoreCaseAscii( "PCD" ) )    // there is a multiple pcd selection possible
                            {
                                sal_Int32 nBase = 2;    // default Base0
                                String aFilterTypeName( (*ppFilter)->GetRealTypeName() );
                                if ( aFilterTypeName.CompareToAscii( "pcd_Photo_CD_Base4" ) == COMPARE_EQUAL )
                                    nBase = 1;
                                else if ( aFilterTypeName.CompareToAscii( "pcd_Photo_CD_Base16" ) == COMPARE_EQUAL )
                                    nBase = 0;
                                String aFilterConfigPath( RTL_CONSTASCII_USTRINGPARAM( "Office.Common/Filter/Graphic/Import/PCD" ) );
                                FilterConfigItem aFilterConfigItem( aFilterConfigPath );
                                aFilterConfigItem.WriteInt32( String( RTL_CONSTASCII_USTRINGPARAM( "Resolution" ) ), nBase );
                            }

                            SfxFilterMatcher aMatch( String::CreateFromAscii("draw") );
                            *ppFilter = aMatch.GetFilter4FilterName( aName );
                            nReturn = ERRCODE_NONE;
                        }
                        else
                        {
                            nReturn = ERRCODE_ABORT;
                            *ppFilter = NULL;
                        }
                    }
                }
            }
        }
    }
    else
    {
        nReturn = rMedium.GetError();
    }

    return nReturn;
} */
<|endoftext|>


<commit_before>/**
 * \file
 * \brief SerialPort class header
 *
 * \author Copyright (C) 2016 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_COMMUNICATION_SERIALPORT_HPP_
#define INCLUDE_DISTORTOS_DEVICES_COMMUNICATION_SERIALPORT_HPP_

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

#include "distortos/internal/devices/UartBase.hpp"

#include "distortos/Mutex.hpp"

namespace distortos
{

class Semaphore;

namespace internal
{

class UartLowLevel;

}

namespace devices
{

/**
 * SerialPort class is a serial port with an interface similar to standard files
 *
 * \ingroup devices
 */

class SerialPort : private internal::UartBase
{
public:

	/// thread-safe, lock-free circular buffer for one-producer and one-consumer
	class CircularBuffer
	{
	public:

		/**
		 * \brief CircularBuffer's constructor
		 *
		 * \param [in] buffer is a buffer for data
		 * \param [in] size is the size of \a buffer, bytes, should be even, must be greater than or equal to 4
		 */

		constexpr CircularBuffer(void* const buffer, const size_t size) :
				buffer_{static_cast<uint8_t*>(buffer)},
				size_{size},
				readPosition_{},
				writePosition_{}
		{

		}

		/**
		 * \brief Clears circular buffer
		 */

		void clear()
		{
			readPosition_ = 0;
			writePosition_ = 0;
		}

		/**
		 * \return First contiguous block (as a pair with pointer and size) available for reading
		 */

		std::pair<const uint8_t*, size_t> getReadBlock() const;

		/**
		 * \return total size of circular buffer, bytes
		 */

		size_t getSize() const
		{
			return size_;
		}

		/**
		 * \return First contiguous block (as a pair with pointer and size) available for writing
		 */

		std::pair<uint8_t*, size_t> getWriteBlock() const;

		/**
		 * \brief Increases read position by given value
		 *
		 * \param [in] value is the value which will be added to read position, must come from previous call to
		 * getReadBlock()
		 */

		void increaseReadPosition(const size_t value)
		{
			readPosition_ += value;
			readPosition_ %= size_;
		}

		/**
		 * \brief Increases write position by given value
		 *
		 * \param [in] value is the value which will be added to write position, must come from previous call to
		 * getWriteBlock()
		 */

		void increaseWritePosition(const size_t value)
		{
			writePosition_ += value;
			writePosition_ %= size_;
		}

		/**
		 * \return true if circular buffer is empty, false otherwise
		 */

		bool isEmpty() const
		{
			return writePosition_ == readPosition_;
		}

		/**
		 * \return true if circular buffer is full, false otherwise
		 */

		bool isFull() const
		{
			return readPosition_ == (writePosition_ + 2) % size_;
		}

	private:

		/// pointer to beginning of buffer
		uint8_t* buffer_;

		/// size of \a buffer_, bytes
		size_t size_;

		/// current read position
		volatile size_t readPosition_;

		/// current write position
		volatile size_t writePosition_;
	};

	/**
	 * \brief SerialPort's constructor
	 *
	 * \param [in] uart is a reference to low-level implementation of internal::UartLowLevel interface
	 * \param [in] readBuffer is a buffer for read operations
	 * \param [in] readBufferSize is the size of \a readBuffer, bytes, should be even, must be greater than or equal to
	 * 4
	 * \param [in] writeBuffer is a buffer to write operations
	 * \param [in] writeBufferSize is the size of \a writeBuffer, bytes, should be even, must be greater than or equal
	 * to 4
	 */

	constexpr SerialPort(internal::UartLowLevel& uart, void* const readBuffer, const size_t readBufferSize,
			void* const writeBuffer, const size_t writeBufferSize) :
					readMutex_{Mutex::Type::normal, Mutex::Protocol::priorityInheritance},
					writeMutex_{Mutex::Type::normal, Mutex::Protocol::priorityInheritance},
					readBuffer_{readBuffer, (readBufferSize / 2) * 2},
					writeBuffer_{writeBuffer, (writeBufferSize / 2) * 2},
					readSemaphore_{},
					transmitSemaphore_{},
					writeSemaphore_{},
					writeLimit_{},
					uart_{uart},
					baudRate_{},
					characterLength_{},
					parity_{},
					_2StopBits_{},
					openCount_{},
					transmitInProgress_{},
					writeInProgress_{}
	{

	}

	/**
	 * \brief SerialPort's destructor
	 *
	 * Does nothing if all users already closed this device. If they did not, performs forced close of device.
	 */

	~SerialPort() override;

	/**
	 * \brief Closes SerialPort
	 *
	 * Does nothing if any user still has this device opened. Otherwise all transfers and low-level driver are stopped.
	 * If any write transfer is still in progress, this function will wait for physical end of transmission before
	 * shutting the device down.
	 *
	 * If the function is interrupted by a signal, the device is not closed - the user should try to close it again.
	 *
	 * \return 0 on success, error code otherwise:
	 * - EBADF - the device is already completely closed;
	 * - EINTR - the wait was interrupted by an unmasked, caught signal;
	 * - error codes returned by internal::UartLowLevel::stop();
	 */

	int close();

	/**
	 * \brief Opens SerialPort
	 *
	 * Does nothing if any user already has this device opened. Otherwise low-level driver and buffered reads are
	 * started.
	 *
	 * \param [in] baudRate is the desired baud rate, bps
	 * \param [in] characterLength selects character length, bits
	 * \param [in] parity selects parity
	 * \param [in] _2StopBits selects whether 1 (false) or 2 (true) stop bits are used
	 *
	 * \return 0 on success, error code otherwise:
	 * - EINVAL - provided arguments don't match current configuration of already opened device;
	 * - EMFILE - this device is already opened too many times;
	 * - ENOBUFS - read and/or write buffers are too small;
	 * - error codes returned by internal::UartLowLevel::start();
	 * - error codes returned by internal::UartLowLevel::startRead();
	 */

	int open(uint32_t baudRate, uint8_t characterLength, devices::UartParity parity, bool _2StopBits);

	/**
	 * \brief Reads data from SerialPort
	 *
	 * Similar to POSIX read() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/read.html#
	 *
	 * This function will block until at least one character can be read.
	 *
	 * \param [out] buffer is the buffer to which the data will be written
	 * \param [in] size is the size of \a buffer, bytes, must be even if selected character length is greater than 8
	 * bits
	 *
	 * \return pair with return code (0 on success, error code otherwise) and number of read bytes (valid even when
	 * error code is returned);
	 * error codes:
	 * - EBADF - the device is not opened;
	 * - EINTR - the wait was interrupted by an unmasked, caught signal;
	 * - EINVAL - \a buffer and/or \a size are invalid;
	 * - error codes returned by internal::UartLowLevel::startRead();
	 */

	std::pair<int, size_t> read(void* buffer, size_t size);

	/**
	 * \brief Writes data to SerialPort
	 *
	 * Similar to POSIX write() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/write.html#
	 *
	 * This function will block until all character are written.
	 *
	 * \param [in] buffer is the buffer with data that will be transmitted
	 * \param [in] size is the size of \a buffer, bytes, must be even if selected character length is greater than 8
	 * bits
	 *
	 * \return pair with return code (0 on success, error code otherwise) and number of written bytes (valid even when
	 * error code is returned);
	 * error codes:
	 * - EBADF - the device is not opened;
	 * - EINTR - the wait was interrupted by an unmasked, caught signal;
	 * - EINVAL - \a buffer and/or \a size are invalid;
	 * - error codes returned by internal::UartLowLevel::startWrite();
	 */

	std::pair<int, size_t> write(const void* buffer, size_t size);

private:

	/**
	 * \brief "Read complete" event
	 *
	 * Called by low-level UART driver when whole read buffer is filled.
	 *
	 * Updates position of read circular buffer and notifies any thread waiting for this event. If the read circular
	 * buffer is not full, next read operation is started.
	 *
	 * \param [in] bytesRead is the number of bytes read by low-level UART driver (and written to read buffer)
	 */

	void readCompleteEvent(size_t bytesRead) override;

	/**
	 * \brief "Receive error" event
	 *
	 * Called by low-level UART driver when the last character was received with an error. This character is written to
	 * the read buffer before this function is called.
	 *
	 * Does nothing.
	 *
	 * \param [in] errorSet is the set of error bits
	 */

	void receiveErrorEvent(ErrorSet errorSet) override;

	/**
	 * \brief Wrapper for internal::UartLowLevel::startRead()
	 *
	 * Starts read operation with size that is the smallest of: size of first available write block, half the size of
	 * read circular buffer and value of \a limit.
	 *
	 * \param [in] limit is the size limit of started read operation, bytes
	 *
	 * \return values returned by internal::UartLowLevel::startRead()
	 */

	int startReadWrapper(size_t limit);

	/**
	 * \brief Wrapper for internal::UartLowLevel::startWrite()
	 *
	 * Does nothing if write is already in progress or if write circular buffer is empty. Otherwise sets "transmit in
	 * progress" and "write in progress" flags, starts write operation with size that is the smallest of: size of first
	 * available read block, half the size of write circular buffer and current size limit of write operations (only if
	 * it's not equal to 0).
	 *
	 * \return 0 on success, error code otherwise:
	 * - error codes returned by internal::UartLowLevel::startWrite();
	 */

	int startWriteWrapper();

	/**
	 * \brief Wrapper for internal::UartLowLevel::stopWrite()
	 *
	 * Stops write operation, updates position of write circular buffer, updates size limit of write operations and
	 * clears "write in progress" flag.
	 *
	 * \return values returned by internal::UartLowLevel::stopWrite();
	 */

	size_t stopWriteWrapper();

	/**
	 * \brief "Transmit complete" event
	 *
	 * Called by low-level UART driver when the transmission is physically finished.
	 *
	 * Notifies any thread waiting for this event and clears "transmit in progress" flag.
	 */

	void transmitCompleteEvent() override;

	/**
	 * \brief "Write complete" event
	 *
	 * Called by low-level UART driver when whole write buffer was transfered - the transmission may still be in
	 * progress.
	 *
	 * Updates position of write circular buffer, updates size limit of write operations, clears "write in progress"
	 * flag and notifies any thread waiting for this event. Next write operation is started if there's anything in the
	 * write circular buffer.
	 *
	 * \param [in] bytesWritten is the number of bytes written by low-level UART driver (and read from write buffer)
	 */

	void writeCompleteEvent(size_t bytesWritten) override;

	/// mutex used to serialize access to read(), close() and open()
	Mutex readMutex_;

	/// mutex used to serialize access to write(), close() and open()
	Mutex writeMutex_;

	/// circular buffer for read operations
	CircularBuffer readBuffer_;

	/// circular buffer for write operations
	CircularBuffer writeBuffer_;

	/// pointer to semaphore used for "read complete" event notifications
	Semaphore* volatile readSemaphore_;

	/// pointer to semaphore used for "transmit complete" event notifications
	Semaphore* volatile transmitSemaphore_;

	/// pointer to semaphore used for "write complete" event notifications
	Semaphore* volatile writeSemaphore_;

	/// size limit of write operations, 0 if no limiting is needed, bytes
	volatile size_t writeLimit_;

	/// reference to low-level implementation of internal::UartLowLevel interface
	internal::UartLowLevel& uart_;

	/// current baud rate, bps
	uint32_t baudRate_;

	/// current character length, bits
	uint8_t characterLength_;

	/// current parity
	devices::UartParity parity_;

	/// current configuration of stop bits: 1 (false) or 2 (true)
	bool _2StopBits_;

	/// number of times this device was opened but not yet closed
	uint8_t openCount_;

	/// "transmit in progress" flag
	volatile bool transmitInProgress_;

	/// "write in progress" flag
	volatile bool writeInProgress_;
};

}	// namespace devices

}	// namespace distortos

#endif	// INCLUDE_DISTORTOS_DEVICES_COMMUNICATION_SERIALPORT_HPP_
<commit_msg>Add getCapacity() for CircularBuffer in SerialPort<commit_after>/**
 * \file
 * \brief SerialPort class header
 *
 * \author Copyright (C) 2016 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_COMMUNICATION_SERIALPORT_HPP_
#define INCLUDE_DISTORTOS_DEVICES_COMMUNICATION_SERIALPORT_HPP_

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

#include "distortos/internal/devices/UartBase.hpp"

#include "distortos/Mutex.hpp"

namespace distortos
{

class Semaphore;

namespace internal
{

class UartLowLevel;

}

namespace devices
{

/**
 * SerialPort class is a serial port with an interface similar to standard files
 *
 * \ingroup devices
 */

class SerialPort : private internal::UartBase
{
public:

	/// thread-safe, lock-free circular buffer for one-producer and one-consumer
	class CircularBuffer
	{
	public:

		/**
		 * \brief CircularBuffer's constructor
		 *
		 * \param [in] buffer is a buffer for data
		 * \param [in] size is the size of \a buffer, bytes, should be even, must be greater than or equal to 4
		 */

		constexpr CircularBuffer(void* const buffer, const size_t size) :
				buffer_{static_cast<uint8_t*>(buffer)},
				size_{size},
				readPosition_{},
				writePosition_{}
		{

		}

		/**
		 * \brief Clears circular buffer
		 */

		void clear()
		{
			readPosition_ = 0;
			writePosition_ = 0;
		}

		/**
		 * \return total capacity of circular buffer, bytes
		 */

		size_t getCapacity() const
		{
			return size_ >= 2 ? size_ - 2 : 0;
		}

		/**
		 * \return First contiguous block (as a pair with pointer and size) available for reading
		 */

		std::pair<const uint8_t*, size_t> getReadBlock() const;

		/**
		 * \return total size of circular buffer, bytes
		 */

		size_t getSize() const
		{
			return size_;
		}

		/**
		 * \return First contiguous block (as a pair with pointer and size) available for writing
		 */

		std::pair<uint8_t*, size_t> getWriteBlock() const;

		/**
		 * \brief Increases read position by given value
		 *
		 * \param [in] value is the value which will be added to read position, must come from previous call to
		 * getReadBlock()
		 */

		void increaseReadPosition(const size_t value)
		{
			readPosition_ += value;
			readPosition_ %= size_;
		}

		/**
		 * \brief Increases write position by given value
		 *
		 * \param [in] value is the value which will be added to write position, must come from previous call to
		 * getWriteBlock()
		 */

		void increaseWritePosition(const size_t value)
		{
			writePosition_ += value;
			writePosition_ %= size_;
		}

		/**
		 * \return true if circular buffer is empty, false otherwise
		 */

		bool isEmpty() const
		{
			return writePosition_ == readPosition_;
		}

		/**
		 * \return true if circular buffer is full, false otherwise
		 */

		bool isFull() const
		{
			return readPosition_ == (writePosition_ + 2) % size_;
		}

	private:

		/// pointer to beginning of buffer
		uint8_t* buffer_;

		/// size of \a buffer_, bytes
		size_t size_;

		/// current read position
		volatile size_t readPosition_;

		/// current write position
		volatile size_t writePosition_;
	};

	/**
	 * \brief SerialPort's constructor
	 *
	 * \param [in] uart is a reference to low-level implementation of internal::UartLowLevel interface
	 * \param [in] readBuffer is a buffer for read operations
	 * \param [in] readBufferSize is the size of \a readBuffer, bytes, should be even, must be greater than or equal to
	 * 4
	 * \param [in] writeBuffer is a buffer to write operations
	 * \param [in] writeBufferSize is the size of \a writeBuffer, bytes, should be even, must be greater than or equal
	 * to 4
	 */

	constexpr SerialPort(internal::UartLowLevel& uart, void* const readBuffer, const size_t readBufferSize,
			void* const writeBuffer, const size_t writeBufferSize) :
					readMutex_{Mutex::Type::normal, Mutex::Protocol::priorityInheritance},
					writeMutex_{Mutex::Type::normal, Mutex::Protocol::priorityInheritance},
					readBuffer_{readBuffer, (readBufferSize / 2) * 2},
					writeBuffer_{writeBuffer, (writeBufferSize / 2) * 2},
					readSemaphore_{},
					transmitSemaphore_{},
					writeSemaphore_{},
					writeLimit_{},
					uart_{uart},
					baudRate_{},
					characterLength_{},
					parity_{},
					_2StopBits_{},
					openCount_{},
					transmitInProgress_{},
					writeInProgress_{}
	{

	}

	/**
	 * \brief SerialPort's destructor
	 *
	 * Does nothing if all users already closed this device. If they did not, performs forced close of device.
	 */

	~SerialPort() override;

	/**
	 * \brief Closes SerialPort
	 *
	 * Does nothing if any user still has this device opened. Otherwise all transfers and low-level driver are stopped.
	 * If any write transfer is still in progress, this function will wait for physical end of transmission before
	 * shutting the device down.
	 *
	 * If the function is interrupted by a signal, the device is not closed - the user should try to close it again.
	 *
	 * \return 0 on success, error code otherwise:
	 * - EBADF - the device is already completely closed;
	 * - EINTR - the wait was interrupted by an unmasked, caught signal;
	 * - error codes returned by internal::UartLowLevel::stop();
	 */

	int close();

	/**
	 * \brief Opens SerialPort
	 *
	 * Does nothing if any user already has this device opened. Otherwise low-level driver and buffered reads are
	 * started.
	 *
	 * \param [in] baudRate is the desired baud rate, bps
	 * \param [in] characterLength selects character length, bits
	 * \param [in] parity selects parity
	 * \param [in] _2StopBits selects whether 1 (false) or 2 (true) stop bits are used
	 *
	 * \return 0 on success, error code otherwise:
	 * - EINVAL - provided arguments don't match current configuration of already opened device;
	 * - EMFILE - this device is already opened too many times;
	 * - ENOBUFS - read and/or write buffers are too small;
	 * - error codes returned by internal::UartLowLevel::start();
	 * - error codes returned by internal::UartLowLevel::startRead();
	 */

	int open(uint32_t baudRate, uint8_t characterLength, devices::UartParity parity, bool _2StopBits);

	/**
	 * \brief Reads data from SerialPort
	 *
	 * Similar to POSIX read() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/read.html#
	 *
	 * This function will block until at least one character can be read.
	 *
	 * \param [out] buffer is the buffer to which the data will be written
	 * \param [in] size is the size of \a buffer, bytes, must be even if selected character length is greater than 8
	 * bits
	 *
	 * \return pair with return code (0 on success, error code otherwise) and number of read bytes (valid even when
	 * error code is returned);
	 * error codes:
	 * - EBADF - the device is not opened;
	 * - EINTR - the wait was interrupted by an unmasked, caught signal;
	 * - EINVAL - \a buffer and/or \a size are invalid;
	 * - error codes returned by internal::UartLowLevel::startRead();
	 */

	std::pair<int, size_t> read(void* buffer, size_t size);

	/**
	 * \brief Writes data to SerialPort
	 *
	 * Similar to POSIX write() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/write.html#
	 *
	 * This function will block until all character are written.
	 *
	 * \param [in] buffer is the buffer with data that will be transmitted
	 * \param [in] size is the size of \a buffer, bytes, must be even if selected character length is greater than 8
	 * bits
	 *
	 * \return pair with return code (0 on success, error code otherwise) and number of written bytes (valid even when
	 * error code is returned);
	 * error codes:
	 * - EBADF - the device is not opened;
	 * - EINTR - the wait was interrupted by an unmasked, caught signal;
	 * - EINVAL - \a buffer and/or \a size are invalid;
	 * - error codes returned by internal::UartLowLevel::startWrite();
	 */

	std::pair<int, size_t> write(const void* buffer, size_t size);

private:

	/**
	 * \brief "Read complete" event
	 *
	 * Called by low-level UART driver when whole read buffer is filled.
	 *
	 * Updates position of read circular buffer and notifies any thread waiting for this event. If the read circular
	 * buffer is not full, next read operation is started.
	 *
	 * \param [in] bytesRead is the number of bytes read by low-level UART driver (and written to read buffer)
	 */

	void readCompleteEvent(size_t bytesRead) override;

	/**
	 * \brief "Receive error" event
	 *
	 * Called by low-level UART driver when the last character was received with an error. This character is written to
	 * the read buffer before this function is called.
	 *
	 * Does nothing.
	 *
	 * \param [in] errorSet is the set of error bits
	 */

	void receiveErrorEvent(ErrorSet errorSet) override;

	/**
	 * \brief Wrapper for internal::UartLowLevel::startRead()
	 *
	 * Starts read operation with size that is the smallest of: size of first available write block, half the size of
	 * read circular buffer and value of \a limit.
	 *
	 * \param [in] limit is the size limit of started read operation, bytes
	 *
	 * \return values returned by internal::UartLowLevel::startRead()
	 */

	int startReadWrapper(size_t limit);

	/**
	 * \brief Wrapper for internal::UartLowLevel::startWrite()
	 *
	 * Does nothing if write is already in progress or if write circular buffer is empty. Otherwise sets "transmit in
	 * progress" and "write in progress" flags, starts write operation with size that is the smallest of: size of first
	 * available read block, half the size of write circular buffer and current size limit of write operations (only if
	 * it's not equal to 0).
	 *
	 * \return 0 on success, error code otherwise:
	 * - error codes returned by internal::UartLowLevel::startWrite();
	 */

	int startWriteWrapper();

	/**
	 * \brief Wrapper for internal::UartLowLevel::stopWrite()
	 *
	 * Stops write operation, updates position of write circular buffer, updates size limit of write operations and
	 * clears "write in progress" flag.
	 *
	 * \return values returned by internal::UartLowLevel::stopWrite();
	 */

	size_t stopWriteWrapper();

	/**
	 * \brief "Transmit complete" event
	 *
	 * Called by low-level UART driver when the transmission is physically finished.
	 *
	 * Notifies any thread waiting for this event and clears "transmit in progress" flag.
	 */

	void transmitCompleteEvent() override;

	/**
	 * \brief "Write complete" event
	 *
	 * Called by low-level UART driver when whole write buffer was transfered - the transmission may still be in
	 * progress.
	 *
	 * Updates position of write circular buffer, updates size limit of write operations, clears "write in progress"
	 * flag and notifies any thread waiting for this event. Next write operation is started if there's anything in the
	 * write circular buffer.
	 *
	 * \param [in] bytesWritten is the number of bytes written by low-level UART driver (and read from write buffer)
	 */

	void writeCompleteEvent(size_t bytesWritten) override;

	/// mutex used to serialize access to read(), close() and open()
	Mutex readMutex_;

	/// mutex used to serialize access to write(), close() and open()
	Mutex writeMutex_;

	/// circular buffer for read operations
	CircularBuffer readBuffer_;

	/// circular buffer for write operations
	CircularBuffer writeBuffer_;

	/// pointer to semaphore used for "read complete" event notifications
	Semaphore* volatile readSemaphore_;

	/// pointer to semaphore used for "transmit complete" event notifications
	Semaphore* volatile transmitSemaphore_;

	/// pointer to semaphore used for "write complete" event notifications
	Semaphore* volatile writeSemaphore_;

	/// size limit of write operations, 0 if no limiting is needed, bytes
	volatile size_t writeLimit_;

	/// reference to low-level implementation of internal::UartLowLevel interface
	internal::UartLowLevel& uart_;

	/// current baud rate, bps
	uint32_t baudRate_;

	/// current character length, bits
	uint8_t characterLength_;

	/// current parity
	devices::UartParity parity_;

	/// current configuration of stop bits: 1 (false) or 2 (true)
	bool _2StopBits_;

	/// number of times this device was opened but not yet closed
	uint8_t openCount_;

	/// "transmit in progress" flag
	volatile bool transmitInProgress_;

	/// "write in progress" flag
	volatile bool writeInProgress_;
};

}	// namespace devices

}	// namespace distortos

#endif	// INCLUDE_DISTORTOS_DEVICES_COMMUNICATION_SERIALPORT_HPP_
<|endoftext|>


<commit_before>#ifndef SOFA_COMPONENT_CONSTRAINT_UNILATERALINTERACTIONCONSTRAINT_INL
#define SOFA_COMPONENT_CONSTRAINT_UNILATERALINTERACTIONCONSTRAINT_INL

#include <sofa/component/constraint/UnilateralInteractionConstraint.h>
#include <sofa/defaulttype/Vec.h>
#include <sofa/helper/gl/template.h>
namespace sofa
{

namespace component
{

namespace constraint
{

template<class DataTypes>
void UnilateralInteractionConstraint<DataTypes>::addContact(double mu, Deriv norm, Coord P, Coord Q, Real contactDistance, int m1, int m2, Coord Pfree, Coord Qfree, long id)
{
    // compute dt and delta
    Real delta = dot(P-Q, norm) - contactDistance;
    Real deltaFree = dot(Pfree-Qfree, norm) - contactDistance;
    Real dt;
    int i = contacts.size();
    contacts.resize(i+1);
    Contact& c = contacts[i];

// for visu
    c.P = P;
    c.Q = Q;
    c.Pfree = Pfree;
    c.Qfree = Qfree;
//
    c.m1 = m1;
    c.m2 = m2;
    c.norm = norm;
    c.delta = delta;
    c.t = Deriv(norm.z(), norm.x(), norm.y());
    c.s = cross(norm,c.t);
    c.s = c.s / c.s.norm();
    c.t = cross((-norm), c.s);
    c.mu = mu;
    c.contactId = id;

    if (rabs(delta - deltaFree) > 0.001 * delta)
    {
        dt = delta / (delta - deltaFree);
        if (dt > 0.0 && dt < 1.0  )
        {
            sofa::defaulttype::Vector3 Qt, Pt;
            Qt = Q*(1-dt) + Qfree*dt;
            Pt = P*(1-dt) + Pfree*dt;
            c.dfree = deltaFree;// dot(Pfree-Pt, c.norm) - dot(Qfree-Qt, c.norm);
            c.dfree_t = dot(Pfree-Pt, c.t) - dot(Qfree-Qt, c.t);
            c.dfree_s = dot(Pfree-Pt, c.s) - dot(Qfree-Qt, c.s);
            //printf("\n ! dt = %f, c.dfree = %f, deltaFree=%f, delta = %f", dt, c.dfree, deltaFree, delta);
        }
        else
        {
            if (deltaFree < 0.0)
            {
                dt=0.0;
                c.dfree = deltaFree; // dot(Pfree-P, c.norm) - dot(Qfree-Q, c.norm);
                //printf("\n dt = %f, c.dfree = %f, deltaFree=%f, delta = %f", dt, c.dfree, deltaFree, delta);
                c.dfree_t = dot(Pfree-P, c.t) - dot(Qfree-Q, c.t);
                c.dfree_s = dot(Pfree-P, c.s) - dot(Qfree-Q, c.s);
            }
            else
            {
                dt=1.0;
                c.dfree = deltaFree;
                c.dfree_t = 0;
                c.dfree_s = 0;
            }
        }
    }
    else
    {
        dt = 0;
        c.dfree = deltaFree;
        c.dfree_t = 0;
        c.dfree_s = 0;
        //printf("\n dt = %f, c.dfree = %f, deltaFree=%f, delta = %f", dt, c.dfree, deltaFree, delta);
    }
}

template<class DataTypes>
void UnilateralInteractionConstraint<DataTypes>::applyConstraint(unsigned int &contactId, double &mu)
{
    assert(this->object1);
    assert(this->object2);

    VecConst& c1 = *this->object1->getC();
    VecConst& c2 = *this->object2->getC();

    for (unsigned int i=0; i<contacts.size(); i++)
    {
        Contact& c = contacts[i];

        mu = c.mu;
        c.id = contactId++;

        SparseVecDeriv svd1;
        SparseVecDeriv svd2;

        this->object1->setConstraintId(c.id);
        svd1.push_back(SparseDeriv(c.m1, -c.norm));
        c1.push_back(svd1);

        this->object2->setConstraintId(c.id);
        svd2.push_back(SparseDeriv(c.m2, c.norm));
        c2.push_back(svd2);

        if (c.mu > 0.0)
        {
            contactId += 2;
            this->object1->setConstraintId(c.id+1);
            svd1[0] = SparseDeriv(c.m1, -c.t);
            c1.push_back(svd1);

            this->object1->setConstraintId(c.id+2);
            svd1[0] = SparseDeriv(c.m1, -c.s);
            c1.push_back(svd1);

            this->object2->setConstraintId(c.id+1);
            svd2[0] = SparseDeriv(c.m2, c.t);
            c2.push_back(svd2);

            this->object2->setConstraintId(c.id+2);
            svd2[0] = SparseDeriv(c.m2, c.s);
            c2.push_back(svd2);
        }
    }
}

template<class DataTypes>
void UnilateralInteractionConstraint<DataTypes>::getConstraintValue(double* v)
{
    for (unsigned int i=0; i<contacts.size(); i++)
    {
        Contact& c = contacts[i]; // get each contact detected
        v[c.id] = c.dfree;
        if (c.mu > 0.0)
        {
            v[c.id+1] = c.dfree_t; // dfree_t & dfree_s are added to v to compute the friction
            v[c.id+2] = c.dfree_s;
        }
    }
}

template<class DataTypes>
void UnilateralInteractionConstraint<DataTypes>::getConstraintId(long* id, unsigned int &offset)
{
    if (!yetIntegrated)
    {
        for (unsigned int i=0; i<contacts.size(); i++)
        {
            Contact& c = contacts[i];
            id[offset++] = -c.contactId;
        }

        yetIntegrated = true;
    }
    else
    {
        for (unsigned int i=0; i<contacts.size(); i++)
        {
            Contact& c = contacts[i];
            id[offset++] = c.contactId;
        }
    }
}

template<class DataTypes>
void UnilateralInteractionConstraint<DataTypes>::getConstraintType(bool* type, unsigned int &offset)
{
    for (unsigned int i=0; i<contacts.size()*3; i++)
        type[offset++] = false;
}

template<class DataTypes>
void UnilateralInteractionConstraint<DataTypes>::draw()
{
    if (!getContext()->getShowInteractionForceFields()) return;

    glDisable(GL_LIGHTING);
    glBegin(GL_LINES);
    glColor4f(1,0,0,1);
    for (unsigned int i=0; i<contacts.size(); i++)
    {
        glLineWidth(1);
        glColor4f(1,0,0,1);
        const Contact& c = contacts[i];
        helper::gl::glVertexT(c.P);
        helper::gl::glVertexT(c.Q);

        if (c.dfree < 0)
        {
            glLineWidth(5);
            glColor4f(0,1,0,1);
            helper::gl::glVertexT(c.Pfree);
            helper::gl::glVertexT(c.Qfree);
        }
    }
    glEnd();
}

} // namespace constraint

} // namespace component

} // namespace sofa

#endif
<commit_msg>r2281/sofa-dev : FIX: methods in MechanicalGetConstraintValueVisitor and MechanicalApplyContactForceVisitor where not called anymore due to the new Node class (tree::GNode* MUST be changed to Node* in all callbacks otherwise they are silently ignored...) TODO: Check other classes deriving from MechanicalVisitor. Also change handling of friction parameter mu to be able to control it in MasterContactSolver.<commit_after>#ifndef SOFA_COMPONENT_CONSTRAINT_UNILATERALINTERACTIONCONSTRAINT_INL
#define SOFA_COMPONENT_CONSTRAINT_UNILATERALINTERACTIONCONSTRAINT_INL

#include <sofa/component/constraint/UnilateralInteractionConstraint.h>
#include <sofa/defaulttype/Vec.h>
#include <sofa/helper/gl/template.h>
namespace sofa
{

namespace component
{

namespace constraint
{

template<class DataTypes>
void UnilateralInteractionConstraint<DataTypes>::addContact(double mu, Deriv norm, Coord P, Coord Q, Real contactDistance, int m1, int m2, Coord Pfree, Coord Qfree, long id)
{
    // compute dt and delta
    Real delta = dot(P-Q, norm) - contactDistance;
    Real deltaFree = dot(Pfree-Qfree, norm) - contactDistance;
    Real dt;
    int i = contacts.size();
    contacts.resize(i+1);
    Contact& c = contacts[i];

// for visu
    c.P = P;
    c.Q = Q;
    c.Pfree = Pfree;
    c.Qfree = Qfree;
//
    c.m1 = m1;
    c.m2 = m2;
    c.norm = norm;
    c.delta = delta;
    c.t = Deriv(norm.z(), norm.x(), norm.y());
    c.s = cross(norm,c.t);
    c.s = c.s / c.s.norm();
    c.t = cross((-norm), c.s);
    c.mu = mu;
    c.contactId = id;

    if (rabs(delta - deltaFree) > 0.001 * delta)
    {
        dt = delta / (delta - deltaFree);
        if (dt > 0.0 && dt < 1.0  )
        {
            sofa::defaulttype::Vector3 Qt, Pt;
            Qt = Q*(1-dt) + Qfree*dt;
            Pt = P*(1-dt) + Pfree*dt;
            c.dfree = deltaFree;// dot(Pfree-Pt, c.norm) - dot(Qfree-Qt, c.norm);
            c.dfree_t = dot(Pfree-Pt, c.t) - dot(Qfree-Qt, c.t);
            c.dfree_s = dot(Pfree-Pt, c.s) - dot(Qfree-Qt, c.s);
            //printf("\n ! dt = %f, c.dfree = %f, deltaFree=%f, delta = %f", dt, c.dfree, deltaFree, delta);
        }
        else
        {
            if (deltaFree < 0.0)
            {
                dt=0.0;
                c.dfree = deltaFree; // dot(Pfree-P, c.norm) - dot(Qfree-Q, c.norm);
                //printf("\n dt = %f, c.dfree = %f, deltaFree=%f, delta = %f", dt, c.dfree, deltaFree, delta);
                c.dfree_t = dot(Pfree-P, c.t) - dot(Qfree-Q, c.t);
                c.dfree_s = dot(Pfree-P, c.s) - dot(Qfree-Q, c.s);
            }
            else
            {
                dt=1.0;
                c.dfree = deltaFree;
                c.dfree_t = 0;
                c.dfree_s = 0;
            }
        }
    }
    else
    {
        dt = 0;
        c.dfree = deltaFree;
        c.dfree_t = 0;
        c.dfree_s = 0;
        //printf("\n dt = %f, c.dfree = %f, deltaFree=%f, delta = %f", dt, c.dfree, deltaFree, delta);
    }
}

template<class DataTypes>
void UnilateralInteractionConstraint<DataTypes>::applyConstraint(unsigned int &contactId, double &mu)
{
    assert(this->object1);
    assert(this->object2);

    VecConst& c1 = *this->object1->getC();
    VecConst& c2 = *this->object2->getC();

    for (unsigned int i=0; i<contacts.size(); i++)
    {
        Contact& c = contacts[i];

        //mu = c.mu;
        c.mu = mu;
        c.id = contactId++;

        SparseVecDeriv svd1;
        SparseVecDeriv svd2;

        this->object1->setConstraintId(c.id);
        svd1.push_back(SparseDeriv(c.m1, -c.norm));
        c1.push_back(svd1);

        this->object2->setConstraintId(c.id);
        svd2.push_back(SparseDeriv(c.m2, c.norm));
        c2.push_back(svd2);

        if (c.mu > 0.0)
        {
            contactId += 2;
            this->object1->setConstraintId(c.id+1);
            svd1[0] = SparseDeriv(c.m1, -c.t);
            c1.push_back(svd1);

            this->object1->setConstraintId(c.id+2);
            svd1[0] = SparseDeriv(c.m1, -c.s);
            c1.push_back(svd1);

            this->object2->setConstraintId(c.id+1);
            svd2[0] = SparseDeriv(c.m2, c.t);
            c2.push_back(svd2);

            this->object2->setConstraintId(c.id+2);
            svd2[0] = SparseDeriv(c.m2, c.s);
            c2.push_back(svd2);
        }
    }
}

template<class DataTypes>
void UnilateralInteractionConstraint<DataTypes>::getConstraintValue(double* v)
{
    for (unsigned int i=0; i<contacts.size(); i++)
    {
        Contact& c = contacts[i]; // get each contact detected
        v[c.id] = c.dfree;
        std::cout << "constraint value "<<c.id<<" = "<<c.dfree<<std::endl;
        if (c.mu > 0.0)
        {
            v[c.id+1] = c.dfree_t; // dfree_t & dfree_s are added to v to compute the friction
            v[c.id+2] = c.dfree_s;
        }
    }
}

template<class DataTypes>
void UnilateralInteractionConstraint<DataTypes>::getConstraintId(long* id, unsigned int &offset)
{
    if (!yetIntegrated)
    {
        for (unsigned int i=0; i<contacts.size(); i++)
        {
            Contact& c = contacts[i];
            id[offset++] = -c.contactId;
        }

        yetIntegrated = true;
    }
    else
    {
        for (unsigned int i=0; i<contacts.size(); i++)
        {
            Contact& c = contacts[i];
            id[offset++] = c.contactId;
        }
    }
}

template<class DataTypes>
void UnilateralInteractionConstraint<DataTypes>::getConstraintType(bool* type, unsigned int &offset)
{
    for (unsigned int i=0; i<contacts.size()*3; i++)
        type[offset++] = false;
}

template<class DataTypes>
void UnilateralInteractionConstraint<DataTypes>::draw()
{
    if (!getContext()->getShowInteractionForceFields()) return;

    glDisable(GL_LIGHTING);
    glBegin(GL_LINES);
    glColor4f(1,0,0,1);
    for (unsigned int i=0; i<contacts.size(); i++)
    {
        glLineWidth(1);
        glColor4f(1,0,0,1);
        const Contact& c = contacts[i];
        helper::gl::glVertexT(c.P);
        helper::gl::glVertexT(c.Q);

        if (c.dfree < 0)
        {
            glLineWidth(5);
            glColor4f(0,1,0,1);
            helper::gl::glVertexT(c.Pfree);
            helper::gl::glVertexT(c.Qfree);
        }
    }
    glEnd();
}

} // namespace constraint

} // namespace component

} // namespace sofa

#endif
<|endoftext|>