<commit_before>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "content/browser/browser_thread_impl.h"

#include <string>

#include "base/atomicops.h"
#include "base/bind.h"
#include "base/compiler_specific.h"
#include "base/lazy_instance.h"
#include "base/message_loop.h"
#include "base/message_loop_proxy.h"
#include "base/threading/sequenced_worker_pool.h"
#include "base/threading/thread_restrictions.h"
#include "content/public/browser/browser_thread_delegate.h"

namespace content {

namespace {

// Friendly names for the well-known threads.
static const char* g_browser_thread_names[BrowserThread::ID_COUNT] = {
  "",  // UI (name assembled in browser_main.cc).
  "Chrome_DBThread",  // DB
  "Chrome_WebKitThread",  // WEBKIT_DEPRECATED
  "Chrome_FileThread",  // FILE
  "Chrome_FileUserBlockingThread",  // FILE_USER_BLOCKING
  "Chrome_ProcessLauncherThread",  // PROCESS_LAUNCHER
  "Chrome_CacheThread",  // CACHE
  "Chrome_IOThread",  // IO
};

struct BrowserThreadGlobals {
  BrowserThreadGlobals()
      : blocking_pool(new base::SequencedWorkerPool(3, "BrowserBlocking")) {
    memset(threads, 0, BrowserThread::ID_COUNT * sizeof(threads[0]));
    memset(thread_delegates, 0,
           BrowserThread::ID_COUNT * sizeof(thread_delegates[0]));
  }

  // This lock protects |threads|. Do not read or modify that array
  // without holding this lock. Do not block while holding this lock.
  base::Lock lock;

  // This array is protected by |lock|. The threads are not owned by this
  // array. Typically, the threads are owned on the UI thread by
  // content::BrowserMainLoop. BrowserThreadImpl objects remove themselves from
  // this array upon destruction.
  BrowserThreadImpl* threads[BrowserThread::ID_COUNT];

  // Only atomic operations are used on this array. The delegates are not owned
  // by this array, rather by whoever calls BrowserThread::SetDelegate.
  BrowserThreadDelegate* thread_delegates[BrowserThread::ID_COUNT];

  const scoped_refptr<base::SequencedWorkerPool> blocking_pool;
};

base::LazyInstance<BrowserThreadGlobals>::Leaky
    g_globals = LAZY_INSTANCE_INITIALIZER;

}  // namespace

BrowserThreadImpl::BrowserThreadImpl(ID identifier)
    : Thread(g_browser_thread_names[identifier]),
      identifier_(identifier) {
  Initialize();
}

BrowserThreadImpl::BrowserThreadImpl(ID identifier,
                                     MessageLoop* message_loop)
    : Thread(message_loop->thread_name().c_str()),
      identifier_(identifier) {
  set_message_loop(message_loop);
  Initialize();
}

// static
void BrowserThreadImpl::ShutdownThreadPool() {
  BrowserThreadGlobals& globals = g_globals.Get();
  globals.blocking_pool->Shutdown();
}

void BrowserThreadImpl::Init() {
  BrowserThreadGlobals& globals = g_globals.Get();

  using base::subtle::AtomicWord;
  AtomicWord* storage =
      reinterpret_cast<AtomicWord*>(&globals.thread_delegates[identifier_]);
  AtomicWord stored_pointer = base::subtle::NoBarrier_Load(storage);
  BrowserThreadDelegate* delegate =
      reinterpret_cast<BrowserThreadDelegate*>(stored_pointer);
  if (delegate)
    delegate->Init();
}

void BrowserThreadImpl::CleanUp() {
  BrowserThreadGlobals& globals = g_globals.Get();

  using base::subtle::AtomicWord;
  AtomicWord* storage =
      reinterpret_cast<AtomicWord*>(&globals.thread_delegates[identifier_]);
  AtomicWord stored_pointer = base::subtle::NoBarrier_Load(storage);
  BrowserThreadDelegate* delegate =
      reinterpret_cast<BrowserThreadDelegate*>(stored_pointer);

  if (delegate)
    delegate->CleanUp();
}

void BrowserThreadImpl::Initialize() {
  BrowserThreadGlobals& globals = g_globals.Get();

  base::AutoLock lock(globals.lock);
  DCHECK(identifier_ >= 0 && identifier_ < ID_COUNT);
  DCHECK(globals.threads[identifier_] == NULL);
  globals.threads[identifier_] = this;
}

BrowserThreadImpl::~BrowserThreadImpl() {
  // All Thread subclasses must call Stop() in the destructor. This is
  // doubly important here as various bits of code check they are on
  // the right BrowserThread.
  Stop();

  BrowserThreadGlobals& globals = g_globals.Get();
  base::AutoLock lock(globals.lock);
  globals.threads[identifier_] = NULL;
#ifndef NDEBUG
  // Double check that the threads are ordered correctly in the enumeration.
  for (int i = identifier_ + 1; i < ID_COUNT; ++i) {
    DCHECK(!globals.threads[i]) <<
        "Threads must be listed in the reverse order that they die";
  }
#endif
}

// static
bool BrowserThreadImpl::PostTaskHelper(
    BrowserThread::ID identifier,
    const tracked_objects::Location& from_here,
    const base::Closure& task,
    base::TimeDelta delay,
    bool nestable) {
  DCHECK(identifier >= 0 && identifier < ID_COUNT);
  // Optimization: to avoid unnecessary locks, we listed the ID enumeration in
  // order of lifetime.  So no need to lock if we know that the other thread
  // outlives this one.
  // Note: since the array is so small, ok to loop instead of creating a map,
  // which would require a lock because std::map isn't thread safe, defeating
  // the whole purpose of this optimization.
  BrowserThread::ID current_thread;
  bool guaranteed_to_outlive_target_thread =
      GetCurrentThreadIdentifier(&current_thread) &&
      current_thread <= identifier;

  BrowserThreadGlobals& globals = g_globals.Get();
  if (!guaranteed_to_outlive_target_thread)
    globals.lock.Acquire();

  MessageLoop* message_loop = globals.threads[identifier] ?
      globals.threads[identifier]->message_loop() : NULL;
  if (message_loop) {
    if (nestable) {
      message_loop->PostDelayedTask(from_here, task, delay);
    } else {
      message_loop->PostNonNestableDelayedTask(from_here, task, delay);
    }
  }

  if (!guaranteed_to_outlive_target_thread)
    globals.lock.Release();

  return !!message_loop;
}

// An implementation of MessageLoopProxy to be used in conjunction
// with BrowserThread.
class BrowserThreadMessageLoopProxy : public base::MessageLoopProxy {
 public:
  explicit BrowserThreadMessageLoopProxy(BrowserThread::ID identifier)
      : id_(identifier) {
  }

  // MessageLoopProxy implementation.
  virtual bool PostDelayedTask(
      const tracked_objects::Location& from_here,
      const base::Closure& task, int64 delay_ms) OVERRIDE {
    return BrowserThread::PostDelayedTask(id_, from_here, task, delay_ms);
  }
  virtual bool PostDelayedTask(
      const tracked_objects::Location& from_here,
      const base::Closure& task, base::TimeDelta delay) OVERRIDE {
    return BrowserThread::PostDelayedTask(id_, from_here, task, delay);
  }

  virtual bool PostNonNestableDelayedTask(
      const tracked_objects::Location& from_here,
      const base::Closure& task,
      int64 delay_ms) OVERRIDE {
    return BrowserThread::PostNonNestableDelayedTask(id_, from_here, task,
                                                     delay_ms);
  }
  virtual bool PostNonNestableDelayedTask(
      const tracked_objects::Location& from_here,
      const base::Closure& task,
      base::TimeDelta delay) OVERRIDE {
    return BrowserThread::PostNonNestableDelayedTask(id_, from_here, task,
                                                     delay);
  }

  virtual bool RunsTasksOnCurrentThread() const OVERRIDE {
    return BrowserThread::CurrentlyOn(id_);
  }

 private:
  BrowserThread::ID id_;
  DISALLOW_COPY_AND_ASSIGN(BrowserThreadMessageLoopProxy);
};

// static
bool BrowserThread::PostBlockingPoolTask(
    const tracked_objects::Location& from_here,
    const base::Closure& task) {
  return g_globals.Get().blocking_pool->PostWorkerTask(from_here, task);
}

// static
bool BrowserThread::PostBlockingPoolSequencedTask(
    const std::string& sequence_token_name,
    const tracked_objects::Location& from_here,
    const base::Closure& task) {
  return g_globals.Get().blocking_pool->PostNamedSequencedWorkerTask(
      sequence_token_name, from_here, task);
}

// static
base::SequencedWorkerPool* BrowserThread::GetBlockingPool() {
  return g_globals.Get().blocking_pool;
}

// static
bool BrowserThread::IsWellKnownThread(ID identifier) {
  BrowserThreadGlobals& globals = g_globals.Get();
  base::AutoLock lock(globals.lock);
  return (identifier >= 0 && identifier < ID_COUNT &&
          globals.threads[identifier]);
}

// static
bool BrowserThread::CurrentlyOn(ID identifier) {
  // We shouldn't use MessageLoop::current() since it uses LazyInstance which
  // may be deleted by ~AtExitManager when a WorkerPool thread calls this
  // function.
  // http://crbug.com/63678
  base::ThreadRestrictions::ScopedAllowSingleton allow_singleton;
  BrowserThreadGlobals& globals = g_globals.Get();
  base::AutoLock lock(globals.lock);
  DCHECK(identifier >= 0 && identifier < ID_COUNT);
  return globals.threads[identifier] &&
         globals.threads[identifier]->message_loop() ==
             MessageLoop::current();
}

// static
bool BrowserThread::IsMessageLoopValid(ID identifier) {
  BrowserThreadGlobals& globals = g_globals.Get();
  base::AutoLock lock(globals.lock);
  DCHECK(identifier >= 0 && identifier < ID_COUNT);
  return globals.threads[identifier] &&
         globals.threads[identifier]->message_loop();
}

// static
bool BrowserThread::PostTask(ID identifier,
                             const tracked_objects::Location& from_here,
                             const base::Closure& task) {
  return BrowserThreadImpl::PostTaskHelper(
      identifier, from_here, task, base::TimeDelta(), true);
}

// static
bool BrowserThread::PostDelayedTask(ID identifier,
                                    const tracked_objects::Location& from_here,
                                    const base::Closure& task,
                                    int64 delay_ms) {
  return BrowserThreadImpl::PostTaskHelper(
      identifier,
      from_here,
      task,
      base::TimeDelta::FromMilliseconds(delay_ms),
      true);
}

// static
bool BrowserThread::PostDelayedTask(ID identifier,
                                    const tracked_objects::Location& from_here,
                                    const base::Closure& task,
                                    base::TimeDelta delay) {
  return BrowserThreadImpl::PostTaskHelper(
      identifier, from_here, task, delay, true);
}

// static
bool BrowserThread::PostNonNestableTask(
    ID identifier,
    const tracked_objects::Location& from_here,
    const base::Closure& task) {
  return BrowserThreadImpl::PostTaskHelper(
      identifier, from_here, task, base::TimeDelta(), false);
}

// static
bool BrowserThread::PostNonNestableDelayedTask(
    ID identifier,
    const tracked_objects::Location& from_here,
    const base::Closure& task,
    int64 delay_ms) {
  return BrowserThreadImpl::PostTaskHelper(
      identifier,
      from_here,
      task,
      base::TimeDelta::FromMilliseconds(delay_ms),
      false);
}

// static
bool BrowserThread::PostNonNestableDelayedTask(
    ID identifier,
    const tracked_objects::Location& from_here,
    const base::Closure& task,
    base::TimeDelta delay) {
  return BrowserThreadImpl::PostTaskHelper(
      identifier, from_here, task, delay, false);
}

// static
bool BrowserThread::PostTaskAndReply(
    ID identifier,
    const tracked_objects::Location& from_here,
    const base::Closure& task,
    const base::Closure& reply) {
  return GetMessageLoopProxyForThread(identifier)->PostTaskAndReply(from_here,
                                                                    task,
                                                                    reply);
}

// static
bool BrowserThread::GetCurrentThreadIdentifier(ID* identifier) {
  // We shouldn't use MessageLoop::current() since it uses LazyInstance which
  // may be deleted by ~AtExitManager when a WorkerPool thread calls this
  // function.
  // http://crbug.com/63678
  base::ThreadRestrictions::ScopedAllowSingleton allow_singleton;
  MessageLoop* cur_message_loop = MessageLoop::current();
  BrowserThreadGlobals& globals = g_globals.Get();
  for (int i = 0; i < ID_COUNT; ++i) {
    if (globals.threads[i] &&
        globals.threads[i]->message_loop() == cur_message_loop) {
      *identifier = globals.threads[i]->identifier_;
      return true;
    }
  }

  return false;
}

// static
scoped_refptr<base::MessageLoopProxy>
BrowserThread::GetMessageLoopProxyForThread(ID identifier) {
  scoped_refptr<base::MessageLoopProxy> proxy(
      new BrowserThreadMessageLoopProxy(identifier));
  return proxy;
}

// static
MessageLoop* BrowserThread::UnsafeGetMessageLoopForThread(ID identifier) {
  BrowserThreadGlobals& globals = g_globals.Get();
  base::AutoLock lock(globals.lock);
  base::Thread* thread = globals.threads[identifier];
  DCHECK(thread);
  MessageLoop* loop = thread->message_loop();
  return loop;
}

// static
void BrowserThread::SetDelegate(ID identifier,
                                BrowserThreadDelegate* delegate) {
  using base::subtle::AtomicWord;
  BrowserThreadGlobals& globals = g_globals.Get();
  AtomicWord* storage = reinterpret_cast<AtomicWord*>(
      &globals.thread_delegates[identifier]);
  AtomicWord old_pointer = base::subtle::NoBarrier_AtomicExchange(
      storage, reinterpret_cast<AtomicWord>(delegate));

  // This catches registration when previously registered.
  DCHECK(!delegate || !old_pointer);
}

}  // namespace content
<commit_msg>Avoid creating BrowserThreadGlobals when we don't need to.<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "content/browser/browser_thread_impl.h"

#include <string>

#include "base/atomicops.h"
#include "base/bind.h"
#include "base/compiler_specific.h"
#include "base/lazy_instance.h"
#include "base/message_loop.h"
#include "base/message_loop_proxy.h"
#include "base/threading/sequenced_worker_pool.h"
#include "base/threading/thread_restrictions.h"
#include "content/public/browser/browser_thread_delegate.h"

namespace content {

namespace {

// Friendly names for the well-known threads.
static const char* g_browser_thread_names[BrowserThread::ID_COUNT] = {
  "",  // UI (name assembled in browser_main.cc).
  "Chrome_DBThread",  // DB
  "Chrome_WebKitThread",  // WEBKIT_DEPRECATED
  "Chrome_FileThread",  // FILE
  "Chrome_FileUserBlockingThread",  // FILE_USER_BLOCKING
  "Chrome_ProcessLauncherThread",  // PROCESS_LAUNCHER
  "Chrome_CacheThread",  // CACHE
  "Chrome_IOThread",  // IO
};

struct BrowserThreadGlobals {
  BrowserThreadGlobals()
      : blocking_pool(new base::SequencedWorkerPool(3, "BrowserBlocking")) {
    memset(threads, 0, BrowserThread::ID_COUNT * sizeof(threads[0]));
    memset(thread_delegates, 0,
           BrowserThread::ID_COUNT * sizeof(thread_delegates[0]));
  }

  // This lock protects |threads|. Do not read or modify that array
  // without holding this lock. Do not block while holding this lock.
  base::Lock lock;

  // This array is protected by |lock|. The threads are not owned by this
  // array. Typically, the threads are owned on the UI thread by
  // content::BrowserMainLoop. BrowserThreadImpl objects remove themselves from
  // this array upon destruction.
  BrowserThreadImpl* threads[BrowserThread::ID_COUNT];

  // Only atomic operations are used on this array. The delegates are not owned
  // by this array, rather by whoever calls BrowserThread::SetDelegate.
  BrowserThreadDelegate* thread_delegates[BrowserThread::ID_COUNT];

  const scoped_refptr<base::SequencedWorkerPool> blocking_pool;
};

base::LazyInstance<BrowserThreadGlobals>::Leaky
    g_globals = LAZY_INSTANCE_INITIALIZER;

}  // namespace

BrowserThreadImpl::BrowserThreadImpl(ID identifier)
    : Thread(g_browser_thread_names[identifier]),
      identifier_(identifier) {
  Initialize();
}

BrowserThreadImpl::BrowserThreadImpl(ID identifier,
                                     MessageLoop* message_loop)
    : Thread(message_loop->thread_name().c_str()),
      identifier_(identifier) {
  set_message_loop(message_loop);
  Initialize();
}

// static
void BrowserThreadImpl::ShutdownThreadPool() {
  BrowserThreadGlobals& globals = g_globals.Get();
  globals.blocking_pool->Shutdown();
}

void BrowserThreadImpl::Init() {
  BrowserThreadGlobals& globals = g_globals.Get();

  using base::subtle::AtomicWord;
  AtomicWord* storage =
      reinterpret_cast<AtomicWord*>(&globals.thread_delegates[identifier_]);
  AtomicWord stored_pointer = base::subtle::NoBarrier_Load(storage);
  BrowserThreadDelegate* delegate =
      reinterpret_cast<BrowserThreadDelegate*>(stored_pointer);
  if (delegate)
    delegate->Init();
}

void BrowserThreadImpl::CleanUp() {
  BrowserThreadGlobals& globals = g_globals.Get();

  using base::subtle::AtomicWord;
  AtomicWord* storage =
      reinterpret_cast<AtomicWord*>(&globals.thread_delegates[identifier_]);
  AtomicWord stored_pointer = base::subtle::NoBarrier_Load(storage);
  BrowserThreadDelegate* delegate =
      reinterpret_cast<BrowserThreadDelegate*>(stored_pointer);

  if (delegate)
    delegate->CleanUp();
}

void BrowserThreadImpl::Initialize() {
  BrowserThreadGlobals& globals = g_globals.Get();

  base::AutoLock lock(globals.lock);
  DCHECK(identifier_ >= 0 && identifier_ < ID_COUNT);
  DCHECK(globals.threads[identifier_] == NULL);
  globals.threads[identifier_] = this;
}

BrowserThreadImpl::~BrowserThreadImpl() {
  // All Thread subclasses must call Stop() in the destructor. This is
  // doubly important here as various bits of code check they are on
  // the right BrowserThread.
  Stop();

  BrowserThreadGlobals& globals = g_globals.Get();
  base::AutoLock lock(globals.lock);
  globals.threads[identifier_] = NULL;
#ifndef NDEBUG
  // Double check that the threads are ordered correctly in the enumeration.
  for (int i = identifier_ + 1; i < ID_COUNT; ++i) {
    DCHECK(!globals.threads[i]) <<
        "Threads must be listed in the reverse order that they die";
  }
#endif
}

// static
bool BrowserThreadImpl::PostTaskHelper(
    BrowserThread::ID identifier,
    const tracked_objects::Location& from_here,
    const base::Closure& task,
    base::TimeDelta delay,
    bool nestable) {
  DCHECK(identifier >= 0 && identifier < ID_COUNT);
  // Optimization: to avoid unnecessary locks, we listed the ID enumeration in
  // order of lifetime.  So no need to lock if we know that the other thread
  // outlives this one.
  // Note: since the array is so small, ok to loop instead of creating a map,
  // which would require a lock because std::map isn't thread safe, defeating
  // the whole purpose of this optimization.
  BrowserThread::ID current_thread;
  bool guaranteed_to_outlive_target_thread =
      GetCurrentThreadIdentifier(&current_thread) &&
      current_thread <= identifier;

  BrowserThreadGlobals& globals = g_globals.Get();
  if (!guaranteed_to_outlive_target_thread)
    globals.lock.Acquire();

  MessageLoop* message_loop = globals.threads[identifier] ?
      globals.threads[identifier]->message_loop() : NULL;
  if (message_loop) {
    if (nestable) {
      message_loop->PostDelayedTask(from_here, task, delay);
    } else {
      message_loop->PostNonNestableDelayedTask(from_here, task, delay);
    }
  }

  if (!guaranteed_to_outlive_target_thread)
    globals.lock.Release();

  return !!message_loop;
}

// An implementation of MessageLoopProxy to be used in conjunction
// with BrowserThread.
class BrowserThreadMessageLoopProxy : public base::MessageLoopProxy {
 public:
  explicit BrowserThreadMessageLoopProxy(BrowserThread::ID identifier)
      : id_(identifier) {
  }

  // MessageLoopProxy implementation.
  virtual bool PostDelayedTask(
      const tracked_objects::Location& from_here,
      const base::Closure& task, int64 delay_ms) OVERRIDE {
    return BrowserThread::PostDelayedTask(id_, from_here, task, delay_ms);
  }
  virtual bool PostDelayedTask(
      const tracked_objects::Location& from_here,
      const base::Closure& task, base::TimeDelta delay) OVERRIDE {
    return BrowserThread::PostDelayedTask(id_, from_here, task, delay);
  }

  virtual bool PostNonNestableDelayedTask(
      const tracked_objects::Location& from_here,
      const base::Closure& task,
      int64 delay_ms) OVERRIDE {
    return BrowserThread::PostNonNestableDelayedTask(id_, from_here, task,
                                                     delay_ms);
  }
  virtual bool PostNonNestableDelayedTask(
      const tracked_objects::Location& from_here,
      const base::Closure& task,
      base::TimeDelta delay) OVERRIDE {
    return BrowserThread::PostNonNestableDelayedTask(id_, from_here, task,
                                                     delay);
  }

  virtual bool RunsTasksOnCurrentThread() const OVERRIDE {
    return BrowserThread::CurrentlyOn(id_);
  }

 private:
  BrowserThread::ID id_;
  DISALLOW_COPY_AND_ASSIGN(BrowserThreadMessageLoopProxy);
};

// static
bool BrowserThread::PostBlockingPoolTask(
    const tracked_objects::Location& from_here,
    const base::Closure& task) {
  return g_globals.Get().blocking_pool->PostWorkerTask(from_here, task);
}

// static
bool BrowserThread::PostBlockingPoolSequencedTask(
    const std::string& sequence_token_name,
    const tracked_objects::Location& from_here,
    const base::Closure& task) {
  return g_globals.Get().blocking_pool->PostNamedSequencedWorkerTask(
      sequence_token_name, from_here, task);
}

// static
base::SequencedWorkerPool* BrowserThread::GetBlockingPool() {
  return g_globals.Get().blocking_pool;
}

// static
bool BrowserThread::IsWellKnownThread(ID identifier) {
  if (g_globals == NULL)
    return false;

  BrowserThreadGlobals& globals = g_globals.Get();
  base::AutoLock lock(globals.lock);
  return (identifier >= 0 && identifier < ID_COUNT &&
          globals.threads[identifier]);
}

// static
bool BrowserThread::CurrentlyOn(ID identifier) {
  // We shouldn't use MessageLoop::current() since it uses LazyInstance which
  // may be deleted by ~AtExitManager when a WorkerPool thread calls this
  // function.
  // http://crbug.com/63678
  base::ThreadRestrictions::ScopedAllowSingleton allow_singleton;
  BrowserThreadGlobals& globals = g_globals.Get();
  base::AutoLock lock(globals.lock);
  DCHECK(identifier >= 0 && identifier < ID_COUNT);
  return globals.threads[identifier] &&
         globals.threads[identifier]->message_loop() ==
             MessageLoop::current();
}

// static
bool BrowserThread::IsMessageLoopValid(ID identifier) {
  if (g_globals == NULL)
    return false;

  BrowserThreadGlobals& globals = g_globals.Get();
  base::AutoLock lock(globals.lock);
  DCHECK(identifier >= 0 && identifier < ID_COUNT);
  return globals.threads[identifier] &&
         globals.threads[identifier]->message_loop();
}

// static
bool BrowserThread::PostTask(ID identifier,
                             const tracked_objects::Location& from_here,
                             const base::Closure& task) {
  return BrowserThreadImpl::PostTaskHelper(
      identifier, from_here, task, base::TimeDelta(), true);
}

// static
bool BrowserThread::PostDelayedTask(ID identifier,
                                    const tracked_objects::Location& from_here,
                                    const base::Closure& task,
                                    int64 delay_ms) {
  return BrowserThreadImpl::PostTaskHelper(
      identifier,
      from_here,
      task,
      base::TimeDelta::FromMilliseconds(delay_ms),
      true);
}

// static
bool BrowserThread::PostDelayedTask(ID identifier,
                                    const tracked_objects::Location& from_here,
                                    const base::Closure& task,
                                    base::TimeDelta delay) {
  return BrowserThreadImpl::PostTaskHelper(
      identifier, from_here, task, delay, true);
}

// static
bool BrowserThread::PostNonNestableTask(
    ID identifier,
    const tracked_objects::Location& from_here,
    const base::Closure& task) {
  return BrowserThreadImpl::PostTaskHelper(
      identifier, from_here, task, base::TimeDelta(), false);
}

// static
bool BrowserThread::PostNonNestableDelayedTask(
    ID identifier,
    const tracked_objects::Location& from_here,
    const base::Closure& task,
    int64 delay_ms) {
  return BrowserThreadImpl::PostTaskHelper(
      identifier,
      from_here,
      task,
      base::TimeDelta::FromMilliseconds(delay_ms),
      false);
}

// static
bool BrowserThread::PostNonNestableDelayedTask(
    ID identifier,
    const tracked_objects::Location& from_here,
    const base::Closure& task,
    base::TimeDelta delay) {
  return BrowserThreadImpl::PostTaskHelper(
      identifier, from_here, task, delay, false);
}

// static
bool BrowserThread::PostTaskAndReply(
    ID identifier,
    const tracked_objects::Location& from_here,
    const base::Closure& task,
    const base::Closure& reply) {
  return GetMessageLoopProxyForThread(identifier)->PostTaskAndReply(from_here,
                                                                    task,
                                                                    reply);
}

// static
bool BrowserThread::GetCurrentThreadIdentifier(ID* identifier) {
  if (g_globals == NULL)
    return false;

  // We shouldn't use MessageLoop::current() since it uses LazyInstance which
  // may be deleted by ~AtExitManager when a WorkerPool thread calls this
  // function.
  // http://crbug.com/63678
  base::ThreadRestrictions::ScopedAllowSingleton allow_singleton;
  MessageLoop* cur_message_loop = MessageLoop::current();
  BrowserThreadGlobals& globals = g_globals.Get();
  for (int i = 0; i < ID_COUNT; ++i) {
    if (globals.threads[i] &&
        globals.threads[i]->message_loop() == cur_message_loop) {
      *identifier = globals.threads[i]->identifier_;
      return true;
    }
  }

  return false;
}

// static
scoped_refptr<base::MessageLoopProxy>
BrowserThread::GetMessageLoopProxyForThread(ID identifier) {
  scoped_refptr<base::MessageLoopProxy> proxy(
      new BrowserThreadMessageLoopProxy(identifier));
  return proxy;
}

// static
MessageLoop* BrowserThread::UnsafeGetMessageLoopForThread(ID identifier) {
  if (g_globals == NULL)
    return NULL;

  BrowserThreadGlobals& globals = g_globals.Get();
  base::AutoLock lock(globals.lock);
  base::Thread* thread = globals.threads[identifier];
  DCHECK(thread);
  MessageLoop* loop = thread->message_loop();
  return loop;
}

// static
void BrowserThread::SetDelegate(ID identifier,
                                BrowserThreadDelegate* delegate) {
  using base::subtle::AtomicWord;
  BrowserThreadGlobals& globals = g_globals.Get();
  AtomicWord* storage = reinterpret_cast<AtomicWord*>(
      &globals.thread_delegates[identifier]);
  AtomicWord old_pointer = base::subtle::NoBarrier_AtomicExchange(
      storage, reinterpret_cast<AtomicWord>(delegate));

  // This catches registration when previously registered.
  DCHECK(!delegate || !old_pointer);
}

}  // namespace content
<|endoftext|>


<commit_before>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Written (W) 1999-2009 Soeren Sonnenburg
 * Written (W) 1999-2008 Gunnar Raetsch
 * Written (W) 2006-2007 Mikio L. Braun
 * Written (W) 2008 Jochen Garcke
 * Written (W) 2011 Sergey Lisitsyn
 * Copyright (C) 1999-2009 Fraunhofer Institute FIRST and Max-Planck-Society
 */

#include <shogun/lib/config.h>

#ifdef HAVE_LAPACK
#include <shogun/mathematics/lapack.h>
#include <shogun/lib/common.h>
#include <shogun/base/Parallel.h>
#include <pthread.h>
#include <shogun/io/SGIO.h>

using namespace shogun;

#if defined(HAVE_MKL) || defined(HAVE_ACML)
#define DSYEV dsyev
#define DGESVD dgesvd
#define DPOSV dposv
#define DPOTRF dpotrf
#define DPOTRI dpotri
#define DGETRI dgetri
#define DGETRF dgetrf
#define DGEQRF dgeqrf
#define DORGQR dorgqr
#define DSYEVR dsyevr
#define DPOTRS dpotrs
#define DGETRS dgetrs
#define DSYGVX dsygvx
#else
#define DSYEV dsyev_
#define DGESVD dgesvd_
#define DPOSV dposv_
#define DPOTRF dpotrf_
#define DPOTRI dpotri_
#define DGETRI dgetri_
#define DGETRF dgetrf_
#define DGEQRF dgeqrf_
#define DORGQR dorgqr_
#define DSYEVR dsyevr_
#define DGETRS dgetrs_
#define DPOTRS dpotrs_
#define DSYGVX dsygvx_
#endif

#ifndef HAVE_ATLAS
int clapack_dpotrf(const CBLAS_ORDER Order, const CBLAS_UPLO Uplo,
		const int N, double *A, const int LDA)
{
	char uplo = 'U';
	int info = 0;
	if (Order==CblasRowMajor)
	{//A is symmetric, we switch Uplo to get result for CblasRowMajor
		if (Uplo==CblasUpper)
			uplo='L';
	}
	else if (Uplo==CblasLower)
	{
		uplo='L';
	}
#ifdef HAVE_ACML
	DPOTRF(uplo, N, A, LDA, &info);
#else
	int n=N;
	int lda=LDA;
	DPOTRF(&uplo, &n, A, &lda, &info);
#endif
	return info;
}
#undef DPOTRF

int clapack_dpotri(const CBLAS_ORDER Order, const CBLAS_UPLO Uplo,
		const int N, double *A, const int LDA)
{
	char uplo = 'U';
	int info = 0;
	if (Order==CblasRowMajor)
	{//A is symmetric, we switch Uplo to get result for CblasRowMajor
		if (Uplo==CblasUpper)
			uplo='L';
	}
	else if (Uplo==CblasLower)
	{
		uplo='L';
	}
#ifdef HAVE_ACML
	DPOTRI(uplo, N, A, LDA, &info);
#else
	int n=N;
	int lda=LDA;
	DPOTRI(&uplo, &n, A, &lda, &info);
#endif
	return info;
}
#undef DPOTRI

/* DPOSV computes the solution to a real system of linear equations
 * A * X = B,
 * where A is an N-by-N symmetric positive definite matrix and X and B
 * are N-by-NRHS matrices
 */
int clapack_dposv(const CBLAS_ORDER Order, const CBLAS_UPLO Uplo,
		const int N, const int NRHS, double *A, const int lda,
		double *B, const int ldb)
{
	char uplo = 'U';
	int info=0;
	if (Order==CblasRowMajor)
	{//A is symmetric, we switch Uplo to achieve CblasColMajor
		if (Uplo==CblasUpper)
			uplo='L';
	}
	else if (Uplo==CblasLower)
	{
		uplo='L';
	}
#ifdef HAVE_ACML
	DPOSV(uplo,N,NRHS,A,lda,B,ldb,&info);
#else
	int n=N;
	int nrhs=NRHS;
	int LDA=lda;
	int LDB=ldb;
	DPOSV(&uplo, &n, &nrhs, A, &LDA, B, &LDB, &info);
#endif
	return info;
}
#undef DPOSV

int clapack_dgetrf(const CBLAS_ORDER Order, const int M, const int N,
                   double *A, const int lda, int *ipiv)
{
	// no rowmajor?
	int info=0;
#ifdef HAVE_ACML
	DGETRF(M,N,A,lda,ipiv,&info);
#else
	int m=M;
	int n=N;
	int LDA=lda;
	DGETRF(&m,&n,A,&LDA,ipiv,&info);
#endif
	return info;
}
#undef DGETRF

// order not supported (yet?)
int clapack_dgetri(const CBLAS_ORDER Order, const int N, double *A,
                   const int lda, int* ipiv)
{
	int info=0;
#ifdef HAVE_ACML
	DGETRI(N,A,lda,ipiv,&info);
#else
	double* work;
	int n=N;
	int LDA=lda;
	int lwork = -1;
	double work1 = 0;
	DGETRI(&n,A,&LDA,ipiv,&work1,&lwork,&info);
	lwork = (int) work1;
	work = SG_MALLOC(double, lwork);
	DGETRI(&n,A,&LDA,ipiv,work,&lwork,&info);
	SG_FREE(work);
#endif
	return info;
}
#undef DGETRI

// order not supported (yet?)
int clapack_dgetrs(const CBLAS_ORDER Order, const CBLAS_TRANSPOSE Transpose,
                   const int N, const int NRHS, double *A, const int lda,
                   int *ipiv, double *B, const int ldb)
{
	int info = 0;
	char trans = 'N';
	if (Transpose==CblasTrans)
	{
		trans = 'T';
	}
#ifdef HAVE_ACML
	DGETRS(trans,N,NRHS,A,lda,ipiv,B,ldb,info);
#else
	int n=N;
	int nrhs=NRHS;
	int LDA=lda;
	int LDB=ldb;
	DGETRS(&trans,&n,&nrhs,A,&LDA,ipiv,B,&LDB,&info);
#endif
	return info;
}
#undef DGETRS

// order not supported (yet?)
int clapack_dpotrs(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo,
                   const int N, const int NRHS, double *A, const int lda,
                   double *B, const int ldb)
{
	int info=0;
	char uplo = 'U';
	if (Uplo==CblasLower)
	{
		uplo = 'L';
	}
#ifdef HAVE_ACML
	DPOTRS(uplo,N,NRHS,A,lda,B,ldb,info);
#else
	int n=N;
	int nrhs=NRHS;
	int LDA=lda;
	int LDB=ldb;
	DPOTRS(&uplo,&n,&nrhs,A,&LDA,B,&LDB,&info);
#endif
	return info;
}
#undef DPOTRS
#endif //HAVE_ATLAS

namespace shogun
{

void wrap_dsyev(char jobz, char uplo, int n, double *a, int lda, double *w, int *info)
{
#ifdef HAVE_ACML
	DSYEV(jobz, uplo, n, a, lda, w, info);
#else
	int lwork=-1;
	double work1;
	DSYEV(&jobz, &uplo, &n, a, &lda, w, &work1, &lwork, info);
	ASSERT(*info==0);
	ASSERT(work1>0);
	lwork=(int) work1;
	double* work=SG_MALLOC(double, lwork);
	DSYEV(&jobz, &uplo, &n, a, &lda, w, work, &lwork, info);
	SG_FREE(work);
#endif
}
#undef DSYEV

void wrap_dgesvd(char jobu, char jobvt, int m, int n, double *a, int lda, double *sing,
		double *u, int ldu, double *vt, int ldvt, int *info)
{
#ifdef HAVE_ACML
	DGESVD(jobu, jobvt, m, n, a, lda, sing, u, ldu, vt, ldvt, info);
#else
	double work1 = 0;
	int lworka = -1;
	DGESVD(&jobu, &jobvt, &m, &n, a, &lda, sing, u, &ldu, vt, &ldvt, &work1, &lworka, info);
	ASSERT(*info==0);
	lworka = (int) work1;
	double* worka = SG_MALLOC(double, lworka);
	DGESVD(&jobu, &jobvt, &m, &n, a, &lda, sing, u, &ldu, vt, &ldvt, worka, &lworka, info);
	SG_FREE(worka);
#endif
}
#undef DGESVD

void wrap_dgeqrf(int m, int n, double *a, int lda, double *tau, int *info)
{
#ifdef HAVE_ACML
	DGEQRF(m, n, a, lda, tau, info);
#else
	int lwork = -1;
	double work1 = 0;
	DGEQRF(&m, &n, a, &lda, tau, &work1, &lwork, info);
	ASSERT(*info==0);
	lwork = (int)work1;
	ASSERT(lwork>0)
	double* work = SG_MALLOC(double, lwork);
	DGEQRF(&m, &n, a, &lda, tau, work, &lwork, info);
	SG_FREE(work);
#endif
}
#undef DGEQRF

void wrap_dorgqr(int m, int n, int k, double *a, int lda, double *tau, int *info)
{
#ifdef HAVE_ACML
	DORGQR(m, n, k, a, lda, tau, info);
#else
	int lwork = -1;
	double work1 = 0;
	DORGQR(&m, &n, &k, a, &lda, tau, &work1, &lwork, info);
	ASSERT(*info==0);
	lwork = (int)work1;
	ASSERT(lwork>0);
	double* work = SG_MALLOC(double, lwork);
	DORGQR(&m, &n, &k, a, &lda, tau, work, &lwork, info);
	SG_FREE(work);
#endif
}
#undef DORGQR

void wrap_dsyevr(char jobz, char uplo, int n, double *a, int lda, int il, int iu,
                 double *eigenvalues, double *eigenvectors, int *info)
{
	int m;
	double vl,vu;
	double abstol = 0.0;
	char I = 'I';
	int* isuppz = SG_MALLOC(int, n);
#ifdef HAVE_ACML
	DSYEVR(jobz,I,uplo,n,a,lda,vl,vu,il,iu,abstol,m,
	       eigenvalues,eigenvectors,n,isuppz,info);
#else
	int lwork = -1;
	int liwork = -1;
	double work1 = 0;
	int work2 = 0;
	DSYEVR(&jobz,&I,&uplo,&n,a,&lda,&vl,&vu,&il,&iu,&abstol,
               &m,eigenvalues,eigenvectors,&n,isuppz,
               &work1,&lwork,&work2,&liwork,info);
	ASSERT(*info==0);
	lwork = (int)work1;
	liwork = work2;
	double* work = SG_MALLOC(double, lwork);
	int* iwork = SG_MALLOC(int, liwork);
	DSYEVR(&jobz,&I,&uplo,&n,a,&lda,&vl,&vu,&il,&iu,&abstol,
               &m,eigenvalues,eigenvectors,&n,isuppz,
               work,&lwork,iwork,&liwork,info);
	ASSERT(*info==0);
	SG_FREE(work);
	SG_FREE(iwork);
	SG_FREE(isuppz);
#endif
}
#undef DSYEVR

void wrap_dsygvx(int itype, char jobz, char uplo, int n, double *a, int lda, double *b,
                 int ldb, int il, int iu, double *eigenvalues, double *eigenvectors, int *info)
{
	int m;
	double abstol = 0.0;
	double vl,vu;
	int* ifail = SG_MALLOC(int, n);
	char I = 'I';
#ifdef HAVE_ACML
	DSYGVX(itype,jobz,I,uplo,n,a,lda,b,ldb,vl,vu,
               il,iu,abstol,m,eigenvalues,
               eigenvectors,n,ifail,info);
#else
	int lwork = -1;
	double work1 = 0;
	int* iwork = SG_MALLOC(int, 5*n);
	DSYGVX(&itype,&jobz,&I,&uplo,&n,a,&lda,b,&ldb,&vl,&vu,
               &il,&iu,&abstol,&m,eigenvalues,eigenvectors,
               &n,&work1,&lwork,iwork,ifail,info);
	lwork = (int)work1;
	double* work = SG_MALLOC(double, lwork);
	DSYGVX(&itype,&jobz,&I,&uplo,&n,a,&lda,b,&ldb,&vl,&vu,
               &il,&iu,&abstol,&m,eigenvalues,eigenvectors,
               &n,work,&lwork,iwork,ifail,info);
	SG_FREE(work);
	SG_FREE(iwork);
	SG_FREE(ifail);
#endif
}
#undef DSYGVX
}
#endif //HAVE_LAPACK
<commit_msg>Made lapack use mallocs instead of SG_MALLOCs<commit_after>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Written (W) 1999-2009 Soeren Sonnenburg
 * Written (W) 1999-2008 Gunnar Raetsch
 * Written (W) 2006-2007 Mikio L. Braun
 * Written (W) 2008 Jochen Garcke
 * Written (W) 2011 Sergey Lisitsyn
 * Copyright (C) 1999-2009 Fraunhofer Institute FIRST and Max-Planck-Society
 */

#include <shogun/lib/config.h>

#ifdef HAVE_LAPACK
#include <shogun/mathematics/lapack.h>
#include <shogun/lib/common.h>
#include <shogun/base/Parallel.h>
#include <pthread.h>
#include <shogun/io/SGIO.h>

using namespace shogun;

#if defined(HAVE_MKL) || defined(HAVE_ACML)
#define DSYEV dsyev
#define DGESVD dgesvd
#define DPOSV dposv
#define DPOTRF dpotrf
#define DPOTRI dpotri
#define DGETRI dgetri
#define DGETRF dgetrf
#define DGEQRF dgeqrf
#define DORGQR dorgqr
#define DSYEVR dsyevr
#define DPOTRS dpotrs
#define DGETRS dgetrs
#define DSYGVX dsygvx
#else
#define DSYEV dsyev_
#define DGESVD dgesvd_
#define DPOSV dposv_
#define DPOTRF dpotrf_
#define DPOTRI dpotri_
#define DGETRI dgetri_
#define DGETRF dgetrf_
#define DGEQRF dgeqrf_
#define DORGQR dorgqr_
#define DSYEVR dsyevr_
#define DGETRS dgetrs_
#define DPOTRS dpotrs_
#define DSYGVX dsygvx_
#endif

#ifndef HAVE_ATLAS
int clapack_dpotrf(const CBLAS_ORDER Order, const CBLAS_UPLO Uplo,
		const int N, double *A, const int LDA)
{
	char uplo = 'U';
	int info = 0;
	if (Order==CblasRowMajor)
	{//A is symmetric, we switch Uplo to get result for CblasRowMajor
		if (Uplo==CblasUpper)
			uplo='L';
	}
	else if (Uplo==CblasLower)
	{
		uplo='L';
	}
#ifdef HAVE_ACML
	DPOTRF(uplo, N, A, LDA, &info);
#else
	int n=N;
	int lda=LDA;
	DPOTRF(&uplo, &n, A, &lda, &info);
#endif
	return info;
}
#undef DPOTRF

int clapack_dpotri(const CBLAS_ORDER Order, const CBLAS_UPLO Uplo,
		const int N, double *A, const int LDA)
{
	char uplo = 'U';
	int info = 0;
	if (Order==CblasRowMajor)
	{//A is symmetric, we switch Uplo to get result for CblasRowMajor
		if (Uplo==CblasUpper)
			uplo='L';
	}
	else if (Uplo==CblasLower)
	{
		uplo='L';
	}
#ifdef HAVE_ACML
	DPOTRI(uplo, N, A, LDA, &info);
#else
	int n=N;
	int lda=LDA;
	DPOTRI(&uplo, &n, A, &lda, &info);
#endif
	return info;
}
#undef DPOTRI

/* DPOSV computes the solution to a real system of linear equations
 * A * X = B,
 * where A is an N-by-N symmetric positive definite matrix and X and B
 * are N-by-NRHS matrices
 */
int clapack_dposv(const CBLAS_ORDER Order, const CBLAS_UPLO Uplo,
		const int N, const int NRHS, double *A, const int lda,
		double *B, const int ldb)
{
	char uplo = 'U';
	int info=0;
	if (Order==CblasRowMajor)
	{//A is symmetric, we switch Uplo to achieve CblasColMajor
		if (Uplo==CblasUpper)
			uplo='L';
	}
	else if (Uplo==CblasLower)
	{
		uplo='L';
	}
#ifdef HAVE_ACML
	DPOSV(uplo,N,NRHS,A,lda,B,ldb,&info);
#else
	int n=N;
	int nrhs=NRHS;
	int LDA=lda;
	int LDB=ldb;
	DPOSV(&uplo, &n, &nrhs, A, &LDA, B, &LDB, &info);
#endif
	return info;
}
#undef DPOSV

int clapack_dgetrf(const CBLAS_ORDER Order, const int M, const int N,
                   double *A, const int lda, int *ipiv)
{
	// no rowmajor?
	int info=0;
#ifdef HAVE_ACML
	DGETRF(M,N,A,lda,ipiv,&info);
#else
	int m=M;
	int n=N;
	int LDA=lda;
	DGETRF(&m,&n,A,&LDA,ipiv,&info);
#endif
	return info;
}
#undef DGETRF

// order not supported (yet?)
int clapack_dgetri(const CBLAS_ORDER Order, const int N, double *A,
                   const int lda, int* ipiv)
{
	int info=0;
#ifdef HAVE_ACML
	DGETRI(N,A,lda,ipiv,&info);
#else
	double* work;
	int n=N;
	int LDA=lda;
	int lwork = -1;
	double work1 = 0;
	DGETRI(&n,A,&LDA,ipiv,&work1,&lwork,&info);
	lwork = (int) work1;
	work = (double*)malloc(sizeof(double)*lwork);
	DGETRI(&n,A,&LDA,ipiv,work,&lwork,&info);
	free(work);
#endif
	return info;
}
#undef DGETRI

// order not supported (yet?)
int clapack_dgetrs(const CBLAS_ORDER Order, const CBLAS_TRANSPOSE Transpose,
                   const int N, const int NRHS, double *A, const int lda,
                   int *ipiv, double *B, const int ldb)
{
	int info = 0;
	char trans = 'N';
	if (Transpose==CblasTrans)
	{
		trans = 'T';
	}
#ifdef HAVE_ACML
	DGETRS(trans,N,NRHS,A,lda,ipiv,B,ldb,info);
#else
	int n=N;
	int nrhs=NRHS;
	int LDA=lda;
	int LDB=ldb;
	DGETRS(&trans,&n,&nrhs,A,&LDA,ipiv,B,&LDB,&info);
#endif
	return info;
}
#undef DGETRS

// order not supported (yet?)
int clapack_dpotrs(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo,
                   const int N, const int NRHS, double *A, const int lda,
                   double *B, const int ldb)
{
	int info=0;
	char uplo = 'U';
	if (Uplo==CblasLower)
	{
		uplo = 'L';
	}
#ifdef HAVE_ACML
	DPOTRS(uplo,N,NRHS,A,lda,B,ldb,info);
#else
	int n=N;
	int nrhs=NRHS;
	int LDA=lda;
	int LDB=ldb;
	DPOTRS(&uplo,&n,&nrhs,A,&LDA,B,&LDB,&info);
#endif
	return info;
}
#undef DPOTRS
#endif //HAVE_ATLAS

namespace shogun
{

void wrap_dsyev(char jobz, char uplo, int n, double *a, int lda, double *w, int *info)
{
#ifdef HAVE_ACML
	DSYEV(jobz, uplo, n, a, lda, w, info);
#else
	int lwork=-1;
	double work1;
	DSYEV(&jobz, &uplo, &n, a, &lda, w, &work1, &lwork, info);
	ASSERT(*info==0);
	ASSERT(work1>0);
	lwork=(int) work1;
	double* work=(double*)malloc(sizeof(double)*lwork);
	DSYEV(&jobz, &uplo, &n, a, &lda, w, work, &lwork, info);
	free(work);
#endif
}
#undef DSYEV

void wrap_dgesvd(char jobu, char jobvt, int m, int n, double *a, int lda, double *sing,
		double *u, int ldu, double *vt, int ldvt, int *info)
{
#ifdef HAVE_ACML
	DGESVD(jobu, jobvt, m, n, a, lda, sing, u, ldu, vt, ldvt, info);
#else
	double work1 = 0;
	int lworka = -1;
	DGESVD(&jobu, &jobvt, &m, &n, a, &lda, sing, u, &ldu, vt, &ldvt, &work1, &lworka, info);
	ASSERT(*info==0);
	lworka = (int) work1;
	double* worka = (double*)malloc(sizeof(double)*lworka);
	DGESVD(&jobu, &jobvt, &m, &n, a, &lda, sing, u, &ldu, vt, &ldvt, worka, &lworka, info);
	free(worka);
#endif
}
#undef DGESVD

void wrap_dgeqrf(int m, int n, double *a, int lda, double *tau, int *info)
{
#ifdef HAVE_ACML
	DGEQRF(m, n, a, lda, tau, info);
#else
	int lwork = -1;
	double work1 = 0;
	DGEQRF(&m, &n, a, &lda, tau, &work1, &lwork, info);
	ASSERT(*info==0);
	lwork = (int)work1;
	ASSERT(lwork>0)
	double* work = (double*)malloc(sizeof(double)*lwork);
	DGEQRF(&m, &n, a, &lda, tau, work, &lwork, info);
	free(work);
#endif
}
#undef DGEQRF

void wrap_dorgqr(int m, int n, int k, double *a, int lda, double *tau, int *info)
{
#ifdef HAVE_ACML
	DORGQR(m, n, k, a, lda, tau, info);
#else
	int lwork = -1;
	double work1 = 0;
	DORGQR(&m, &n, &k, a, &lda, tau, &work1, &lwork, info);
	ASSERT(*info==0);
	lwork = (int)work1;
	ASSERT(lwork>0);
	double* work = (double*)malloc(sizeof(double)*lwork);
	DORGQR(&m, &n, &k, a, &lda, tau, work, &lwork, info);
	free(work);
#endif
}
#undef DORGQR

void wrap_dsyevr(char jobz, char uplo, int n, double *a, int lda, int il, int iu,
                 double *eigenvalues, double *eigenvectors, int *info)
{
	int m;
	double vl,vu;
	double abstol = 0.0;
	char I = 'I';
	int* isuppz = (int*)malloc(sizeof(int)*n);
#ifdef HAVE_ACML
	DSYEVR(jobz,I,uplo,n,a,lda,vl,vu,il,iu,abstol,m,
	       eigenvalues,eigenvectors,n,isuppz,info);
#else
	int lwork = -1;
	int liwork = -1;
	double work1 = 0;
	int work2 = 0;
	DSYEVR(&jobz,&I,&uplo,&n,a,&lda,&vl,&vu,&il,&iu,&abstol,
               &m,eigenvalues,eigenvectors,&n,isuppz,
               &work1,&lwork,&work2,&liwork,info);
	ASSERT(*info==0);
	lwork = (int)work1;
	liwork = work2;
	double* work = (double*)malloc(sizeof(double)*lwork);
	int* iwork = (int*)malloc(sizeof(int)*liwork);
	DSYEVR(&jobz,&I,&uplo,&n,a,&lda,&vl,&vu,&il,&iu,&abstol,
               &m,eigenvalues,eigenvectors,&n,isuppz,
               work,&lwork,iwork,&liwork,info);
	ASSERT(*info==0);
	free(work);
	free(iwork);
	free(isuppz);
#endif
}
#undef DSYEVR

void wrap_dsygvx(int itype, char jobz, char uplo, int n, double *a, int lda, double *b,
                 int ldb, int il, int iu, double *eigenvalues, double *eigenvectors, int *info)
{
	int m;
	double abstol = 0.0;
	double vl,vu;
	int* ifail = (int*)malloc(sizeof(int)*n);
	char I = 'I';
#ifdef HAVE_ACML
	DSYGVX(itype,jobz,I,uplo,n,a,lda,b,ldb,vl,vu,
               il,iu,abstol,m,eigenvalues,
               eigenvectors,n,ifail,info);
#else
	int lwork = -1;
	double work1 = 0;
	int* iwork = (int*)malloc(sizeof(int)*5*n);
	DSYGVX(&itype,&jobz,&I,&uplo,&n,a,&lda,b,&ldb,&vl,&vu,
               &il,&iu,&abstol,&m,eigenvalues,eigenvectors,
               &n,&work1,&lwork,iwork,ifail,info);
	lwork = (int)work1;
	double* work = (double*)malloc(sizeof(double)*lwork);
	DSYGVX(&itype,&jobz,&I,&uplo,&n,a,&lda,b,&ldb,&vl,&vu,
               &il,&iu,&abstol,&m,eigenvalues,eigenvectors,
               &n,work,&lwork,iwork,ifail,info);
	free(work);
	free(iwork);
	free(ifail);
#endif
}
#undef DSYGVX
}
#endif //HAVE_LAPACK
<|endoftext|>


<commit_before><commit_msg>Turned off Shadow DOM by default.<commit_after><|endoftext|>


<commit_before>//
//  main.cpp
//  raytracer
//
//  Created by a on 06/08/15.
//  Copyright (c) 2015 Martin Mi. All rights reserved.
//

#include <iostream>

int main(int argc, const char * argv[])
{

	// insert code here...
	std::cout << "Hello, World!\n";
    return 0;
}

<commit_msg>ppm image output<commit_after>//
//  main.cpp
//  raytracer
//
//  Created by a on 06/08/15.
//  Copyright (c) 2015 Martin Mi. All rights reserved.
//

#include <iostream>
#include <fstream>

//! Type for usage as dimensions/coordinates
typedef std::uint_fast16_t dim_t;

int main(int argc, const char * argv[]) {
	// code adapted from http://rosettacode.org/wiki/Bitmap/Write_a_PPM_file#C
	dim_t size_x = 320, size_y = 240;
	std::string out_file = "out.ppm";

	std::ofstream out(out_file, std::ios::binary);

	// Print the header
	out << "P6\n" << size_x << " " << size_y << "\n255\n";

	for (dim_t y = 0; y < size_y; ++y) {
		for (dim_t x = 0; x < size_x; ++x) {
			static char color[3];
			color[0] = x % 256; // red
			color[1] = y % 256; // green
			color[2] = (x * y) % 256; // blue
			out.write(&color[0], 3);
		}
	}

	out.close();

    return 0;
}
<|endoftext|>


<commit_before>
#include "pin.H"
#include "Triton.h"

static std::string replaceEq(std::string str, std::string from, std::string to)
{
  size_t start_pos = str.find(from);
  if(start_pos == std::string::npos)
      return NULL;
  str.replace(start_pos, from.length(), to);
  return str;
}

static std::string formulaReconstruction(UINT64 id)
{
  int value;
  std::size_t found;
  std::stringstream formula;

  std::stringstream from;
  std::stringstream to;

  formula.str(symbolicEngine->getElementFromId(id)->getSource());
  while (formula.str().find("#") != std::string::npos){

    from.str("");
    to.str("");

    found = formula.str().find("#") + 1;
    std::string subs = formula.str().substr(found, std::string::npos);
    value = atoi(subs.c_str());
    from << "#" << value;
    to.str(symbolicEngine->getElementFromId(value)->getSource());

    formula.str(replaceEq(formula.str(), from.str(), to.str()));
  }

  return formula.str();
}

SolverEngine::SolverEngine(SymbolicEngine *symEngine)
{
  this->symEngine = symEngine;
}

SolverEngine::~SolverEngine()
{
}

VOID SolverEngine::solveFromID(UINT64 id)
{
  std::stringstream formula;

  std::cout << 1 << std::endl;

  formula.str(formulaReconstruction(symEngine->symbolicReg[ID_ZF]));

  this->formula << this->symEngine->getSmt2LibVarsDecl();
  this->formula << formula.str();

  this->ctx = new z3::context();

  Z3_ast ast = Z3_parse_smtlib2_string(*this->ctx, this->formula.str().c_str(), 0, 0, 0, 0, 0, 0);
  z3::expr eq(*this->ctx, ast);
  this->solver = new z3::solver(*this->ctx);
  this->solver->add(eq);
  this->solver->check();
}

VOID SolverEngine::displayModel()
{
  z3::model m = this->solver->get_model();
  std::cout << "----- Model -----" << std::endl << m << std::endl << "-----------------" << std::endl;
}

z3::model SolverEngine::getModel()
{
  return this->solver->get_model();
}

std::string SolverEngine::getFormula()
{
  return this->formula.str();
}

<commit_msg>Use const replaceEq<commit_after>
#include "pin.H"
#include "Triton.h"

static std::string replaceEq(std::string str, const std::string from, const std::string to)
{
  size_t start_pos = str.find(from);
  if(start_pos == std::string::npos)
      return NULL;
  str.replace(start_pos, from.length(), to);
  return str;
}

static std::string formulaReconstruction(UINT64 id)
{
  int value;
  std::size_t found;
  std::stringstream formula;

  std::stringstream from;
  std::stringstream to;

  formula.str(symbolicEngine->getElementFromId(id)->getSource());
  while (formula.str().find("#") != std::string::npos){

    from.str("");
    to.str("");

    found = formula.str().find("#") + 1;
    std::string subs = formula.str().substr(found, std::string::npos);
    value = atoi(subs.c_str());
    from << "#" << value;
    to.str(symbolicEngine->getElementFromId(value)->getSource());

    formula.str(replaceEq(formula.str(), from.str(), to.str()));
  }

  return formula.str();
}

SolverEngine::SolverEngine(SymbolicEngine *symEngine)
{
  this->symEngine = symEngine;
}

SolverEngine::~SolverEngine()
{
}

VOID SolverEngine::solveFromID(UINT64 id)
{
  std::stringstream formula;

  std::cout << 1 << std::endl;

  formula.str(formulaReconstruction(symEngine->symbolicReg[ID_ZF]));

  this->formula << this->symEngine->getSmt2LibVarsDecl();
  this->formula << formula.str();

  this->ctx = new z3::context();

  Z3_ast ast = Z3_parse_smtlib2_string(*this->ctx, this->formula.str().c_str(), 0, 0, 0, 0, 0, 0);
  z3::expr eq(*this->ctx, ast);
  this->solver = new z3::solver(*this->ctx);
  this->solver->add(eq);
  this->solver->check();
}

VOID SolverEngine::displayModel()
{
  z3::model m = this->solver->get_model();
  std::cout << "----- Model -----" << std::endl << m << std::endl << "-----------------" << std::endl;
}

z3::model SolverEngine::getModel()
{
  return this->solver->get_model();
}

std::string SolverEngine::getFormula()
{
  return this->formula.str();
}

<|endoftext|>


<commit_before>#include "core/numeric.h"
#include "lsearch_cgdescent.h"

using namespace nano;

bool lsearch_cgdescent_t::updateU(const solver_state_t& state0, step_t& a, step_t& b, solver_state_t& c)
{
        assert(0 < m_theta && m_theta < 1);

        for (int i = 0; i < max_iterations(); ++ i)
        {
                if (evaluate(state0, (1 - m_theta) * a.t + m_theta * b.t, a, b, c))
                {
                        return true;
                }
                else if (!c.has_descent())
                {
                        b = c;
                        return false;
                }
                else if (c.has_approx_armijo(state0, m_epsilon))
                {
                        a = c;
                }
                else
                {
                        b = c;
                }
        }

        return false;
}

bool lsearch_cgdescent_t::update(const solver_state_t& state0, step_t& a, step_t& b, solver_state_t& c)
{
        if (c.t <= a.t || c.t >= b.t)
        {
                return false;
        }
        else if (!c.has_descent())
        {
                b = c;
                return false;
        }
        else if (c.has_approx_armijo(state0, m_epsilon))
        {
                a = c;
                return false;
        }
        else
        {
                b = c;
                return updateU(state0, a, b, c);
        }
}

bool lsearch_cgdescent_t::secant2(const solver_state_t& state0, step_t& a, step_t& b, solver_state_t& c)
{
        const auto a0 = a, b0 = b;
        const auto tc = secant(a0, b0);

        if (evaluate(state0, tc, a, b, c))
        {
                return true;
        }
        else if (update(state0, a, b, c))
        {
                return true;
        }
        else if (std::fabs(tc - a.t) < epsilon0<scalar_t>())
        {
                return  evaluate(state0, secant(a0, a), a, b, c) ||
                        update(state0, a, b, c);
        }
        else if (std::fabs(tc - b.t) < epsilon0<scalar_t>())
        {
                return  evaluate(state0, secant(b0, b), a, b, c) ||
                        update(state0, a, b, c);
        }
        else
        {
                return false;
        }
}

bool lsearch_cgdescent_t::bracket(const solver_state_t& state0, step_t& a, step_t& b, solver_state_t& c)
{
        assert(m_ro > 1);

        auto last_a = a;
        for (int i = 0; i < max_iterations(); ++ i)
        {
                if (!c.has_descent())
                {
                        a = last_a;
                        b = c;
                        return false;
                }
                else if (!c.has_approx_armijo(state0, m_epsilon))
                {
                        a = state0;
                        b = c;
                        return updateU(state0, a, b, c);
                }
                else
                {
                        last_a = c;
                        if (evaluate(state0, m_ro * c.t, a, b, c))
                        {
                                return true;
                        }
                }
        }

        return false;
}

bool lsearch_cgdescent_t::evaluate(const solver_state_t& state0, const scalar_t t, solver_state_t& c)
{
        // check overflow
        if (!c.update(state0, t))
        {
                return true;
        }

        // check Armijo+Wolfe conditions or the approximate versions
        const auto done =
                (!m_approx && c.has_armijo(state0, c1()) && c.has_wolfe(state0, c2())) ||
                (m_approx && c.has_approx_armijo(state0, m_epsilon) && c.has_approx_wolfe(state0, c1(), c2()));

        if (done && !m_approx)
        {
                // decide if to switch permanently to the approximate Wolfe conditions
                m_approx = std::fabs(c.f - state0.f) <= m_omega * m_sumC;
        }

        return done;
}

bool lsearch_cgdescent_t::evaluate(const solver_state_t& state0, const scalar_t t, const step_t& a, const step_t& b,
        solver_state_t& c)
{
        if (evaluate(state0, t, c))
        {
                return true;
        }

        // check if the search interval is too small
        if (std::fabs(b.t - a.t) < epsilon0<scalar_t>())
        {
                return true;
        }

        // go on on updating the search interval
        return false;
}

bool lsearch_cgdescent_t::get(const solver_state_t& state0, const scalar_t t0, solver_state_t& state)
{
        // estimate an upper bound of the function value
        // (to be used for the approximate Wolfe condition)
        m_sumQ = 1 + m_sumQ * m_delta;
        m_sumC = m_sumC + (std::fabs(state0.f) - m_sumC) / m_sumQ;
        m_epsilon = m_epsilon0 * m_sumC;

        // evaluate the initial step length
        auto& c = state;
        if (evaluate(state0, t0, c))
        {
                return true;
        }

        // bracket the initial step size
        step_t a = state0, b = c;
        if (bracket(state0, a, b, c))
        {
                return true;
        }

        // iteratively update the search interval [a, b]
        for (int i = 0; i < max_iterations(); ++ i)
        {
                // secant interpolation
                const auto prev_width = b.t - a.t;
                if (secant2(state0, a, b, c))
                {
                        return true;
                }

                // update search interval
                if (b.t - a.t > m_gamma * prev_width)
                {
                        if (    evaluate(state0, (a.t + b.t) / 2, a, b, c) ||
                                update(state0, a, b, c))
                        {
                                return true;
                        }
                }
        }

        return false;
}
<commit_msg>actually the secant interpolation can produce NANs with CG_DESCENT<commit_after>#include "core/numeric.h"
#include "lsearch_cgdescent.h"

using namespace nano;

bool lsearch_cgdescent_t::updateU(const solver_state_t& state0, step_t& a, step_t& b, solver_state_t& c)
{
        assert(0 < m_theta && m_theta < 1);

        for (int i = 0; i < max_iterations(); ++ i)
        {
                if (evaluate(state0, (1 - m_theta) * a.t + m_theta * b.t, a, b, c))
                {
                        return true;
                }
                else if (!c.has_descent())
                {
                        b = c;
                        return false;
                }
                else if (c.has_approx_armijo(state0, m_epsilon))
                {
                        a = c;
                }
                else
                {
                        b = c;
                }
        }

        return false;
}

bool lsearch_cgdescent_t::update(const solver_state_t& state0, step_t& a, step_t& b, solver_state_t& c)
{
        if (c.t <= a.t || c.t >= b.t)
        {
                return false;
        }
        else if (!c.has_descent())
        {
                b = c;
                return false;
        }
        else if (c.has_approx_armijo(state0, m_epsilon))
        {
                a = c;
                return false;
        }
        else
        {
                b = c;
                return updateU(state0, a, b, c);
        }
}

bool lsearch_cgdescent_t::secant2(const solver_state_t& state0, step_t& a, step_t& b, solver_state_t& c)
{
        const auto a0 = a, b0 = b;
        const auto tc = interpolate(a0, b0);

        if (evaluate(state0, tc, a, b, c))
        {
                return true;
        }
        else if (update(state0, a, b, c))
        {
                return true;
        }
        else if (std::fabs(tc - a.t) < epsilon0<scalar_t>())
        {
                return  evaluate(state0, interpolate(a0, a), a, b, c) ||
                        update(state0, a, b, c);
        }
        else if (std::fabs(tc - b.t) < epsilon0<scalar_t>())
        {
                return  evaluate(state0, interpolate(b0, b), a, b, c) ||
                        update(state0, a, b, c);
        }
        else
        {
                return false;
        }
}

bool lsearch_cgdescent_t::bracket(const solver_state_t& state0, step_t& a, step_t& b, solver_state_t& c)
{
        assert(m_ro > 1);

        auto last_a = a;
        for (int i = 0; i < max_iterations(); ++ i)
        {
                if (!c.has_descent())
                {
                        a = last_a;
                        b = c;
                        return false;
                }
                else if (!c.has_approx_armijo(state0, m_epsilon))
                {
                        a = state0;
                        b = c;
                        return updateU(state0, a, b, c);
                }
                else
                {
                        last_a = c;
                        if (evaluate(state0, m_ro * c.t, a, b, c))
                        {
                                return true;
                        }
                }
        }

        return false;
}

bool lsearch_cgdescent_t::evaluate(const solver_state_t& state0, const scalar_t t, solver_state_t& c)
{
        // check overflow
        if (!c.update(state0, t))
        {
                return true;
        }

        // check Armijo+Wolfe conditions or the approximate versions
        const auto done =
                (!m_approx && c.has_armijo(state0, c1()) && c.has_wolfe(state0, c2())) ||
                (m_approx && c.has_approx_armijo(state0, m_epsilon) && c.has_approx_wolfe(state0, c1(), c2()));

        if (done && !m_approx)
        {
                // decide if to switch permanently to the approximate Wolfe conditions
                m_approx = std::fabs(c.f - state0.f) <= m_omega * m_sumC;
        }

        return done;
}

bool lsearch_cgdescent_t::evaluate(const solver_state_t& state0, const scalar_t t, const step_t& a, const step_t& b,
        solver_state_t& c)
{
        if (evaluate(state0, t, c))
        {
                return true;
        }

        // check if the search interval is too small
        if (std::fabs(b.t - a.t) < epsilon0<scalar_t>())
        {
                return true;
        }

        // go on on updating the search interval
        return false;
}

bool lsearch_cgdescent_t::get(const solver_state_t& state0, const scalar_t t0, solver_state_t& state)
{
        // estimate an upper bound of the function value
        // (to be used for the approximate Wolfe condition)
        m_sumQ = 1 + m_sumQ * m_delta;
        m_sumC = m_sumC + (std::fabs(state0.f) - m_sumC) / m_sumQ;
        m_epsilon = m_epsilon0 * m_sumC;

        // evaluate the initial step length
        auto& c = state;
        if (evaluate(state0, t0, c))
        {
                return true;
        }

        // bracket the initial step size
        step_t a = state0, b = c;
        if (bracket(state0, a, b, c))
        {
                return true;
        }

        // iteratively update the search interval [a, b]
        for (int i = 0; i < max_iterations(); ++ i)
        {
                // secant interpolation
                const auto prev_width = b.t - a.t;
                if (secant2(state0, a, b, c))
                {
                        return true;
                }

                // update search interval
                if (b.t - a.t > m_gamma * prev_width)
                {
                        if (    evaluate(state0, (a.t + b.t) / 2, a, b, c) ||
                                update(state0, a, b, c))
                        {
                                return true;
                        }
                }
        }

        return false;
}
<|endoftext|>


<commit_before>/*
    Kopete , The KDE Instant Messenger
    Copyright (c) 2001-2002 by Duncan Mac-Vicar Prett <duncan@kde.org>

    Viva Chile Mierda!
    Started at Wed Dec 26 03:12:10 CLST 2001, Santiago de Chile

    Kopete    (c) 2002-2005 by the Kopete developers  <kopete-devel@kde.org>

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

#include <kcmdlineargs.h>
#include <kaboutdata.h>
#include "kopeteapplication.h"

#include <dcopclient.h>
#include "kopeteiface.h"
#include "kimifaceimpl.h"

#define KOPETE_VERSION "0.10.91"

static const char description[] =
	I18N_NOOP( "Kopete, the KDE Instant Messenger" );

static KCmdLineOptions options[] =
{
	{ "noplugins",              I18N_NOOP( "Do not load plugins. This option overrides all other options." ), 0 },
	{ "noconnect",              I18N_NOOP( "Disable auto-connection" ), 0 },
	{ "autoconnect <accounts>", I18N_NOOP( "Auto-connect the specified accounts. Use a comma-separated list\n"
		"to auto-connect multiple accounts." ), 0 },
	{ "disable <plugins>",      I18N_NOOP( "Do not load the specified plugin. Use a comma-separated list\n"
		"to disable multiple plugins." ), 0 },
	{ "load-plugins <plugins>", I18N_NOOP( "Load only the specified plugins. Use a comma-separated list\n"
		"to load multiple plugins. This option has no effect when\n"
		"--noplugins is set and overrides all other plugin related\n"
		"command line options." ), 0 },
//	{ "url <url>",              I18N_NOOP( "Load the given Kopete URL" ), 0 },
//	{ "!+[plugin]",            I18N_NOOP( "Load specified plugins" ), 0 },
	{ "!+[URL]",                 I18N_NOOP("URLs to pass to kopete / emoticon themes to install"), 0},
	KCmdLineLastOption
};

int main( int argc, char *argv[] )
{
	KAboutData aboutData( "kopete", I18N_NOOP("Kopete"),
		KOPETE_VERSION, description, KAboutData::License_GPL,
		I18N_NOOP("(c) 2001-2004, Duncan Mac-Vicar Prett\n(c) 2002-2005, Kopete Development Team"), "kopete-devel@kde.org", "http://kopete.kde.org");

	aboutData.addAuthor ( "Duncan Mac-Vicar Prett", I18N_NOOP("Original author, Developer"), "duncan@kde.org", "http://www.mac-vicar.org/~duncan" );
	aboutData.addAuthor ( "Andre Duffeck", I18N_NOOP("Developer, Yahoo plugin maintainer"), "andre@duffeck.de" );
	aboutData.addAuthor ( "Till Gerken", I18N_NOOP("Developer, Jabber plugin maintainer"), "till@tantalo.net");
	aboutData.addAuthor ( "Olivier Goffart", I18N_NOOP("Developer, MSN plugin maintainer"), "ogoffart @ kde.org");
	aboutData.addAuthor ( "Andy Goossens", I18N_NOOP("Developer"), "andygoossens@telenet.be" );
	aboutData.addAuthor ( "Michel Hermier", I18N_NOOP("IRC plugin maintainer"), "michel.hermier@wanadoo.fr" );
	aboutData.addAuthor ( "Chris Howells", I18N_NOOP("Developer, Connection status plugin author"), "howells@kde.org", "http://chrishowells.co.uk");
	aboutData.addAuthor ( "Grzegorz Jaskiewicz", I18N_NOOP("Developer, Gadu plugin maintainer"), "gj@pointblue.com.pl" );
	aboutData.addAuthor ( "Jason Keirstead", I18N_NOOP("Developer"), "jason@keirstead.org", "http://www.keirstead.org");
	aboutData.addAuthor ( "Chetan Reddy", I18N_NOOP("Developer, Yahoo"), "chetan13@gmail.com" );
	aboutData.addAuthor ( "Matt Rogers", I18N_NOOP("Developer, AIM and ICQ plugin maintainer"), "mattr@kde.org" );
	aboutData.addAuthor ( "Richard Smith", I18N_NOOP("Developer, UI maintainer"), "kde@metafoo.co.uk" );
	aboutData.addAuthor ( "Will Stephenson", I18N_NOOP("Developer, GroupWise maintainer"), "lists@stevello.free-online.co.uk" );
	aboutData.addAuthor ( "Michaël Larouche", I18N_NOOP("Developer, MSN"), "michael.larouche@kdemail.net", "http://mlarouche.blogspot.com" );

	aboutData.addCredit ( "Luciash d' Being", I18N_NOOP("Kopete's icon author") );
	aboutData.addCredit ( "Steve Cable", I18N_NOOP("Sounds") );
	aboutData.addCredit ( "Justin Karneges", I18N_NOOP("Iris Jabber Backend Library") );
	aboutData.addCredit ( "Tom Linsky", I18N_NOOP("OscarSocket author"), "twl6@po.cwru.edu" );
	aboutData.addCredit ( "Olaf Lueg", I18N_NOOP("Kmerlin MSN code") );

	aboutData.addCredit ( "Nick Betcher", I18N_NOOP("Former developer, project co-founder"), "nbetcher@kde.org");
	aboutData.addCredit ( "Ryan Cumming", I18N_NOOP("Former developer"), "ryan@kde.org" );
	aboutData.addCredit ( "Stefan Gehn", I18N_NOOP("Former developer"), "metz@gehn.net", "http://metz.gehn.net" );
	aboutData.addCredit ( "Martijn Klingens", I18N_NOOP("Former developer"), "klingens@kde.org" );
	aboutData.addCredit ( "Andres Krapf", I18N_NOOP("Former developer"), "dae@chez.com" );
	aboutData.addCredit ( "Carsten Pfeiffer", I18N_NOOP("Misc bugfixes and enhancements"), "pfeiffer@kde.org" );
	aboutData.addCredit ( "Zack Rusin", I18N_NOOP("Former developer, original Gadu plugin author"), "zack@kde.org" );
	aboutData.addCredit ( "Richard Stellingwerff", I18N_NOOP("Former developer"), "remenic@linuxfromscratch.org");
	aboutData.addCredit ( "Daniel Stone", I18N_NOOP("Former developer, Jabber plugin author"), "daniel@fooishbar.org", "http://fooishbar.org");
	aboutData.addCredit ( "Chris TenHarmsel", I18N_NOOP("Former developer, Oscar plugin"), "tenharmsel@users.sourceforge.net");
	aboutData.addCredit ( "Hendrik vom Lehn", I18N_NOOP("Former developer"), "hennevl@hennevl.de", "http://www.hennevl.de");
	aboutData.addCredit ( "Gav Wood", I18N_NOOP("Former developer and WinPopup maintainer"), "gav@indigoarchive.net" );

	aboutData.setTranslator( I18N_NOOP("_: NAME OF TRANSLATORS\nYour names"),
		I18N_NOOP("_: EMAIL OF TRANSLATORS\nYour emails") );

	KCmdLineArgs::init( argc, argv, &aboutData );
	KCmdLineArgs::addCmdLineOptions( options ); // Add our own options.
	KUniqueApplication::addCmdLineOptions();

	KopeteApplication kopete;
	new KIMIfaceImpl();
	kapp->dcopClient()->registerAs( "kopete", false );
	kapp->dcopClient()->setDefaultObject( (new KopeteIface())->objId() ); // Has to be called before exec

	kopete.exec();
}
// vim: set noet ts=4 sts=4 sw=4:
<commit_msg>make use of kopeteversion.h<commit_after>/*
    Kopete , The KDE Instant Messenger
    Copyright (c) 2001-2002 by Duncan Mac-Vicar Prett <duncan@kde.org>

    Viva Chile Mierda!
    Started at Wed Dec 26 03:12:10 CLST 2001, Santiago de Chile

    Kopete    (c) 2002-2005 by the Kopete developers  <kopete-devel@kde.org>

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

#include <kcmdlineargs.h>
#include <kaboutdata.h>
#include "kopeteapplication.h"

#include <dcopclient.h>
#include "kopeteiface.h"
#include "kimifaceimpl.h"
#include "kopeteversion.h"

static const char description[] =
	I18N_NOOP( "Kopete, the KDE Instant Messenger" );

static KCmdLineOptions options[] =
{
	{ "noplugins",              I18N_NOOP( "Do not load plugins. This option overrides all other options." ), 0 },
	{ "noconnect",              I18N_NOOP( "Disable auto-connection" ), 0 },
	{ "autoconnect <accounts>", I18N_NOOP( "Auto-connect the specified accounts. Use a comma-separated list\n"
		"to auto-connect multiple accounts." ), 0 },
	{ "disable <plugins>",      I18N_NOOP( "Do not load the specified plugin. Use a comma-separated list\n"
		"to disable multiple plugins." ), 0 },
	{ "load-plugins <plugins>", I18N_NOOP( "Load only the specified plugins. Use a comma-separated list\n"
		"to load multiple plugins. This option has no effect when\n"
		"--noplugins is set and overrides all other plugin related\n"
		"command line options." ), 0 },
//	{ "url <url>",              I18N_NOOP( "Load the given Kopete URL" ), 0 },
//	{ "!+[plugin]",            I18N_NOOP( "Load specified plugins" ), 0 },
	{ "!+[URL]",                 I18N_NOOP("URLs to pass to kopete / emoticon themes to install"), 0},
	KCmdLineLastOption
};

int main( int argc, char *argv[] )
{
	KAboutData aboutData( "kopete", I18N_NOOP("Kopete"),
		KOPETE_VERSION_STRING, description, KAboutData::License_GPL,
		I18N_NOOP("(c) 2001-2004, Duncan Mac-Vicar Prett\n(c) 2002-2005, Kopete Development Team"), "kopete-devel@kde.org", "http://kopete.kde.org");

	aboutData.addAuthor ( "Duncan Mac-Vicar Prett", I18N_NOOP("Original author, Developer"), "duncan@kde.org", "http://www.mac-vicar.org/~duncan" );
	aboutData.addAuthor ( "Andre Duffeck", I18N_NOOP("Developer, Yahoo plugin maintainer"), "andre@duffeck.de" );
	aboutData.addAuthor ( "Till Gerken", I18N_NOOP("Developer, Jabber plugin maintainer"), "till@tantalo.net");
	aboutData.addAuthor ( "Olivier Goffart", I18N_NOOP("Developer, MSN plugin maintainer"), "ogoffart @ kde.org");
	aboutData.addAuthor ( "Andy Goossens", I18N_NOOP("Developer"), "andygoossens@telenet.be" );
	aboutData.addAuthor ( "Michel Hermier", I18N_NOOP("IRC plugin maintainer"), "michel.hermier@wanadoo.fr" );
	aboutData.addAuthor ( "Chris Howells", I18N_NOOP("Developer, Connection status plugin author"), "howells@kde.org", "http://chrishowells.co.uk");
	aboutData.addAuthor ( "Grzegorz Jaskiewicz", I18N_NOOP("Developer, Gadu plugin maintainer"), "gj@pointblue.com.pl" );
	aboutData.addAuthor ( "Jason Keirstead", I18N_NOOP("Developer"), "jason@keirstead.org", "http://www.keirstead.org");
	aboutData.addAuthor ( "Chetan Reddy", I18N_NOOP("Developer, Yahoo"), "chetan13@gmail.com" );
	aboutData.addAuthor ( "Matt Rogers", I18N_NOOP("Developer, AIM and ICQ plugin maintainer"), "mattr@kde.org" );
	aboutData.addAuthor ( "Richard Smith", I18N_NOOP("Developer, UI maintainer"), "kde@metafoo.co.uk" );
	aboutData.addAuthor ( "Will Stephenson", I18N_NOOP("Developer, GroupWise maintainer"), "lists@stevello.free-online.co.uk" );
	aboutData.addAuthor ( "Michaël Larouche", I18N_NOOP("Developer, MSN"), "michael.larouche@kdemail.net", "http://mlarouche.blogspot.com" );

	aboutData.addCredit ( "Luciash d' Being", I18N_NOOP("Kopete's icon author") );
	aboutData.addCredit ( "Steve Cable", I18N_NOOP("Sounds") );
	aboutData.addCredit ( "Justin Karneges", I18N_NOOP("Iris Jabber Backend Library") );
	aboutData.addCredit ( "Tom Linsky", I18N_NOOP("OscarSocket author"), "twl6@po.cwru.edu" );
	aboutData.addCredit ( "Olaf Lueg", I18N_NOOP("Kmerlin MSN code") );

	aboutData.addCredit ( "Nick Betcher", I18N_NOOP("Former developer, project co-founder"), "nbetcher@kde.org");
	aboutData.addCredit ( "Ryan Cumming", I18N_NOOP("Former developer"), "ryan@kde.org" );
	aboutData.addCredit ( "Stefan Gehn", I18N_NOOP("Former developer"), "metz@gehn.net", "http://metz.gehn.net" );
	aboutData.addCredit ( "Martijn Klingens", I18N_NOOP("Former developer"), "klingens@kde.org" );
	aboutData.addCredit ( "Andres Krapf", I18N_NOOP("Former developer"), "dae@chez.com" );
	aboutData.addCredit ( "Carsten Pfeiffer", I18N_NOOP("Misc bugfixes and enhancements"), "pfeiffer@kde.org" );
	aboutData.addCredit ( "Zack Rusin", I18N_NOOP("Former developer, original Gadu plugin author"), "zack@kde.org" );
	aboutData.addCredit ( "Richard Stellingwerff", I18N_NOOP("Former developer"), "remenic@linuxfromscratch.org");
	aboutData.addCredit ( "Daniel Stone", I18N_NOOP("Former developer, Jabber plugin author"), "daniel@fooishbar.org", "http://fooishbar.org");
	aboutData.addCredit ( "Chris TenHarmsel", I18N_NOOP("Former developer, Oscar plugin"), "tenharmsel@users.sourceforge.net");
	aboutData.addCredit ( "Hendrik vom Lehn", I18N_NOOP("Former developer"), "hennevl@hennevl.de", "http://www.hennevl.de");
	aboutData.addCredit ( "Gav Wood", I18N_NOOP("Former developer and WinPopup maintainer"), "gav@indigoarchive.net" );

	aboutData.setTranslator( I18N_NOOP("_: NAME OF TRANSLATORS\nYour names"),
		I18N_NOOP("_: EMAIL OF TRANSLATORS\nYour emails") );

	KCmdLineArgs::init( argc, argv, &aboutData );
	KCmdLineArgs::addCmdLineOptions( options ); // Add our own options.
	KUniqueApplication::addCmdLineOptions();

	KopeteApplication kopete;
	new KIMIfaceImpl();
	kapp->dcopClient()->registerAs( "kopete", false );
	kapp->dcopClient()->setDefaultObject( (new KopeteIface())->objId() ); // Has to be called before exec

	kopete.exec();
}
// vim: set noet ts=4 sts=4 sw=4:
<|endoftext|>


<commit_before>#include <boost/assert.hpp>
#include <boost/assign/list_of.hpp>
#include <boost/assign/list_inserter.hpp>
#include <boost/assign/std/vector.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/foreach.hpp>

#include "../main.h"
#include "../script.h"
#include "../wallet.h"

using namespace std;

// Test routines internal to script.cpp:
extern uint256 SignatureHash(CScript scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType);
extern bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn, int& nSigOps,
                         int nHashType, bool fStrictOpEval);

BOOST_AUTO_TEST_SUITE(script_op_eval_tests)

BOOST_AUTO_TEST_CASE(script_op_eval1)
{
    // OP_EVAL looks like this:
    // scriptSig:    <sig> <sig...> <serialized_script>
    // scriptPubKey: DUP HASH160 <hash> EQUALVERIFY EVAL

    // Test SignSignature() (and therefore the version of Solver() that signs transactions)
    CBasicKeyStore keystore;
    CKey key[4];
    for (int i = 0; i < 4; i++)
    {
        key[i].MakeNewKey();
        keystore.AddKey(key[i]);
    }

    // 8 Scripts: checking all combinations of
    // different keys, straight/EVAL, pubkey/pubkeyhash
    CScript standardScripts[4];
    standardScripts[0] << key[0].GetPubKey() << OP_CHECKSIG;
    standardScripts[1].SetBitcoinAddress(key[1].GetPubKey());
    standardScripts[2] << key[1].GetPubKey() << OP_CHECKSIG;
    standardScripts[3].SetBitcoinAddress(key[2].GetPubKey());
    CScript evalScripts[4];
    uint160 sigScriptHashes[4];
    for (int i = 0; i < 4; i++)
    {
        sigScriptHashes[i] = Hash160(standardScripts[i]);
        keystore.AddCScript(sigScriptHashes[i], standardScripts[i]);
        evalScripts[i] << OP_DUP << OP_HASH160 << sigScriptHashes[i] << OP_EQUALVERIFY << OP_EVAL;
    }

    CTransaction txFrom;  // Funding transaction:
    txFrom.vout.resize(8);
    for (int i = 0; i < 4; i++)
    {
        txFrom.vout[i].scriptPubKey = evalScripts[i];
        txFrom.vout[i+4].scriptPubKey = standardScripts[i];
    }
    BOOST_CHECK(txFrom.IsStandard());

    CTransaction txTo[8]; // Spending transactions
    for (int i = 0; i < 8; i++)
    {
        txTo[i].vin.resize(1);
        txTo[i].vout.resize(1);
        txTo[i].vin[0].prevout.n = i;
        txTo[i].vin[0].prevout.hash = txFrom.GetHash();
        txTo[i].vout[0].nValue = 1;
        BOOST_CHECK_MESSAGE(IsMine(keystore, txFrom.vout[i].scriptPubKey), strprintf("IsMine %d", i));
    }
    for (int i = 0; i < 8; i++)
    {
        BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0), strprintf("SignSignature %d", i));
    }
    // All of the above should be OK, and the txTos have valid signatures
    // Check to make sure signature verification fails if we use the wrong ScriptSig:
    for (int i = 0; i < 8; i++)
        for (int j = 0; j < 8; j++)
        {
            CScript sigSave = txTo[i].vin[0].scriptSig;
            txTo[i].vin[0].scriptSig = txTo[j].vin[0].scriptSig;
            int nUnused = 0;
            bool sigOK = VerifySignature(txFrom, txTo[i], 0, nUnused);
            if (i == j)
                BOOST_CHECK_MESSAGE(sigOK, strprintf("VerifySignature %d %d", i, j));
            else
                BOOST_CHECK_MESSAGE(!sigOK, strprintf("VerifySignature %d %d", i, j));
            txTo[i].vin[0].scriptSig = sigSave;
        }
}

BOOST_AUTO_TEST_CASE(script_op_eval2)
{
    // Test OP_EVAL edge cases

    CScript recurse;
    recurse << OP_DUP << OP_EVAL;

    uint160 recurseHash = Hash160(recurse);

    CScript fund;
    fund << OP_DUP << OP_HASH160 << recurseHash << OP_EQUALVERIFY << OP_EVAL;

    CTransaction txFrom;  // Funding transaction:
    txFrom.vout.resize(1);
    txFrom.vout[0].scriptPubKey = fund;

    BOOST_CHECK(txFrom.IsStandard()); // Looks like a standard transaction until you try to spend it

    CTransaction txTo;
    txTo.vin.resize(1);
    txTo.vout.resize(1);
    txTo.vin[0].prevout.n = 0;
    txTo.vin[0].prevout.hash = txFrom.GetHash();
    txTo.vin[0].scriptSig = CScript() << static_cast<std::vector<unsigned char> >(recurse);
    txTo.vout[0].nValue = 1;

    int nUnused = 0;
    BOOST_CHECK(!VerifyScript(txTo.vin[0].scriptSig, txFrom.vout[0].scriptPubKey, txTo, 0, nUnused, 0, true));
    BOOST_CHECK(!VerifySignature(txFrom, txTo, 0, nUnused, true));
}

BOOST_AUTO_TEST_CASE(script_op_eval3)
{
    // Test the CScript::Set* methods
    CBasicKeyStore keystore;
    CKey key[4];
    std::vector<CKey> keys;
    for (int i = 0; i < 4; i++)
    {
        key[i].MakeNewKey();
        keystore.AddKey(key[i]);
        keys.push_back(key[i]);
    }

    CScript inner[4];
    inner[0].SetBitcoinAddress(key[0].GetPubKey());
    inner[1].SetMultisig(2, std::vector<CKey>(keys.begin(), keys.begin()+2));
    inner[2].SetMultisig(1, std::vector<CKey>(keys.begin(), keys.begin()+2));
    inner[3].SetMultisig(2, std::vector<CKey>(keys.begin(), keys.begin()+3));

    CScript outer[4];
    for (int i = 0; i < 4; i++)
    {
        outer[i].SetEval(inner[i]);
        keystore.AddCScript(Hash160(inner[i]), inner[i]);
    }

    CTransaction txFrom;  // Funding transaction:
    txFrom.vout.resize(4);
    for (int i = 0; i < 4; i++)
    {
        txFrom.vout[i].scriptPubKey = outer[i];
    }
    BOOST_CHECK(txFrom.IsStandard());

    CTransaction txTo[4]; // Spending transactions
    for (int i = 0; i < 4; i++)
    {
        txTo[i].vin.resize(1);
        txTo[i].vout.resize(1);
        txTo[i].vin[0].prevout.n = i;
        txTo[i].vin[0].prevout.hash = txFrom.GetHash();
        txTo[i].vout[0].nValue = 1;
        txTo[i].vout[0].scriptPubKey = inner[i];
        BOOST_CHECK_MESSAGE(IsMine(keystore, txFrom.vout[i].scriptPubKey), strprintf("IsMine %d", i));
    }
    for (int i = 0; i < 4; i++)
    {
        BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0), strprintf("SignSignature %d", i));
        BOOST_CHECK_MESSAGE(txTo[i].IsStandard(), strprintf("txTo[%d].IsStandard", i));
    }
}

BOOST_AUTO_TEST_CASE(script_op_eval_backcompat1)
{
    // Check backwards-incompatibility-testing code
    CScript returnsEleven;
    returnsEleven << OP_11;

    // This should validate on new clients, but will
    // be invalid on old clients (that interpret OP_EVAL as a no-op)
    //  ... except there's a special rule that makes new clients reject
    // it.
    CScript fund;
    fund << OP_EVAL << OP_11 << OP_EQUAL;

    CTransaction txFrom;  // Funding transaction:
    txFrom.vout.resize(1);
    txFrom.vout[0].scriptPubKey = fund;

    CTransaction txTo;
    txTo.vin.resize(1);
    txTo.vout.resize(1);
    txTo.vin[0].prevout.n = 0;
    txTo.vin[0].prevout.hash = txFrom.GetHash();
    txTo.vin[0].scriptSig = CScript() << static_cast<std::vector<unsigned char> >(returnsEleven);
    txTo.vout[0].nValue = 1;

    int nUnused = 0;
    BOOST_CHECK(!VerifyScript(txTo.vin[0].scriptSig, txFrom.vout[0].scriptPubKey, txTo, 0, nUnused, 0, true));
    BOOST_CHECK(!VerifySignature(txFrom, txTo, 0, nUnused, true));
}

BOOST_AUTO_TEST_CASE(script_op_eval_switchover)
{
    // Test OP_EVAL switchover code
    CScript notValid;
    notValid << OP_11 << OP_12 << OP_EQUALVERIFY;

    // This will be valid under old rules, invalid under new:
    CScript fund;
    fund << OP_EVAL;

    CTransaction txFrom;  // Funding transaction:
    txFrom.vout.resize(1);
    txFrom.vout[0].scriptPubKey = fund;

    CTransaction txTo;
    txTo.vin.resize(1);
    txTo.vout.resize(1);
    txTo.vin[0].prevout.n = 0;
    txTo.vin[0].prevout.hash = txFrom.GetHash();
    txTo.vin[0].scriptSig = CScript() << static_cast<std::vector<unsigned char> >(notValid);
    txTo.vout[0].nValue = 1;

    int nUnused = 0;
    BOOST_CHECK(VerifyScript(txTo.vin[0].scriptSig, txFrom.vout[0].scriptPubKey, txTo, 0, nUnused, 0, false));

    // Under strict op_eval switchover, it should be considered invalid:
    BOOST_CHECK(!VerifyScript(txTo.vin[0].scriptSig, txFrom.vout[0].scriptPubKey, txTo, 0, nUnused, 0, true));
}

BOOST_AUTO_TEST_SUITE_END()
<commit_msg>Fixed OP_EVAL recursion unit test, checks for both infinite and exactly-3-deep recursion<commit_after>#include <boost/assert.hpp>
#include <boost/assign/list_of.hpp>
#include <boost/assign/list_inserter.hpp>
#include <boost/assign/std/vector.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/foreach.hpp>

#include "../main.h"
#include "../script.h"
#include "../wallet.h"

using namespace std;

// Test routines internal to script.cpp:
extern uint256 SignatureHash(CScript scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType);
extern bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn, int& nSigOps,
                         int nHashType, bool fStrictOpEval);

BOOST_AUTO_TEST_SUITE(script_op_eval_tests)

BOOST_AUTO_TEST_CASE(script_op_eval1)
{
    // OP_EVAL looks like this:
    // scriptSig:    <sig> <sig...> <serialized_script>
    // scriptPubKey: DUP HASH160 <hash> EQUALVERIFY EVAL

    // Test SignSignature() (and therefore the version of Solver() that signs transactions)
    CBasicKeyStore keystore;
    CKey key[4];
    for (int i = 0; i < 4; i++)
    {
        key[i].MakeNewKey();
        keystore.AddKey(key[i]);
    }

    // 8 Scripts: checking all combinations of
    // different keys, straight/EVAL, pubkey/pubkeyhash
    CScript standardScripts[4];
    standardScripts[0] << key[0].GetPubKey() << OP_CHECKSIG;
    standardScripts[1].SetBitcoinAddress(key[1].GetPubKey());
    standardScripts[2] << key[1].GetPubKey() << OP_CHECKSIG;
    standardScripts[3].SetBitcoinAddress(key[2].GetPubKey());
    CScript evalScripts[4];
    uint160 sigScriptHashes[4];
    for (int i = 0; i < 4; i++)
    {
        sigScriptHashes[i] = Hash160(standardScripts[i]);
        keystore.AddCScript(sigScriptHashes[i], standardScripts[i]);
        evalScripts[i] << OP_DUP << OP_HASH160 << sigScriptHashes[i] << OP_EQUALVERIFY << OP_EVAL;
    }

    CTransaction txFrom;  // Funding transaction:
    txFrom.vout.resize(8);
    for (int i = 0; i < 4; i++)
    {
        txFrom.vout[i].scriptPubKey = evalScripts[i];
        txFrom.vout[i+4].scriptPubKey = standardScripts[i];
    }
    BOOST_CHECK(txFrom.IsStandard());

    CTransaction txTo[8]; // Spending transactions
    for (int i = 0; i < 8; i++)
    {
        txTo[i].vin.resize(1);
        txTo[i].vout.resize(1);
        txTo[i].vin[0].prevout.n = i;
        txTo[i].vin[0].prevout.hash = txFrom.GetHash();
        txTo[i].vout[0].nValue = 1;
        BOOST_CHECK_MESSAGE(IsMine(keystore, txFrom.vout[i].scriptPubKey), strprintf("IsMine %d", i));
    }
    for (int i = 0; i < 8; i++)
    {
        BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0), strprintf("SignSignature %d", i));
    }
    // All of the above should be OK, and the txTos have valid signatures
    // Check to make sure signature verification fails if we use the wrong ScriptSig:
    for (int i = 0; i < 8; i++)
        for (int j = 0; j < 8; j++)
        {
            CScript sigSave = txTo[i].vin[0].scriptSig;
            txTo[i].vin[0].scriptSig = txTo[j].vin[0].scriptSig;
            int nUnused = 0;
            bool sigOK = VerifySignature(txFrom, txTo[i], 0, nUnused);
            if (i == j)
                BOOST_CHECK_MESSAGE(sigOK, strprintf("VerifySignature %d %d", i, j));
            else
                BOOST_CHECK_MESSAGE(!sigOK, strprintf("VerifySignature %d %d", i, j));
            txTo[i].vin[0].scriptSig = sigSave;
        }
}

BOOST_AUTO_TEST_CASE(script_op_eval2)
{
    // Test OP_EVAL edge cases

    // Make sure infinite recursion fails to validate:
    CScript infiniteRecurse;
    infiniteRecurse << OP_DUP << OP_EVAL;

    uint160 infiniteRecurseHash = Hash160(infiniteRecurse);

    CScript fund1;
    fund1 << OP_DUP << OP_HASH160 << infiniteRecurseHash << OP_EQUALVERIFY << OP_EVAL;

    CTransaction txFrom1;  // Funding transaction:
    txFrom1.vout.resize(1);
    txFrom1.vout[0].scriptPubKey = fund1;

    BOOST_CHECK(txFrom1.IsStandard()); // Looks like a standard transaction until you try to spend it

    std::vector<unsigned char> infiniteRecurseSerialized(infiniteRecurse);

    CTransaction txTo1;
    txTo1.vin.resize(1);
    txTo1.vout.resize(1);
    txTo1.vin[0].prevout.n = 0;
    txTo1.vin[0].prevout.hash = txFrom1.GetHash();
    txTo1.vin[0].scriptSig = CScript() << infiniteRecurseSerialized << infiniteRecurseSerialized;
    txTo1.vout[0].nValue = 1;

    int nUnused1 = 0;
    BOOST_CHECK(!VerifyScript(txTo1.vin[0].scriptSig, txFrom1.vout[0].scriptPubKey, txTo1, 0, nUnused1, 0, true));
    BOOST_CHECK(!VerifySignature(txFrom1, txTo1, 0, nUnused1, true));

    // Make sure 3-level-deep recursion fails to validate:
    CScript recurse3;
    recurse3 << OP_EVAL;

    uint160 recurse3Hash = Hash160(recurse3);

    CScript fund2;
    fund2 << OP_DUP << OP_HASH160 << recurse3Hash << OP_EQUALVERIFY << OP_EVAL;

    CTransaction txFrom2;  // Funding transaction:
    txFrom2.vout.resize(1);
    txFrom2.vout[0].scriptPubKey = fund2;

    BOOST_CHECK(txFrom2.IsStandard()); // Looks like a standard transaction until you try to spend it

    std::vector<unsigned char> recurse3Serialized(recurse3);
    CScript op1Script = CScript() << OP_1;
    std::vector<unsigned char> op1Serialized(op1Script);

    CTransaction txTo2;
    txTo2.vin.resize(1);
    txTo2.vout.resize(1);
    txTo2.vin[0].prevout.n = 0;
    txTo2.vin[0].prevout.hash = txFrom2.GetHash();
    txTo2.vin[0].scriptSig = CScript() << op1Serialized << recurse3Serialized << recurse3Serialized;
    txTo2.vout[0].nValue = 1;

    int nUnused2 = 0;
    BOOST_CHECK(!VerifyScript(txTo2.vin[0].scriptSig, txFrom2.vout[0].scriptPubKey, txTo2, 0, nUnused2, 0, true));
    BOOST_CHECK(!VerifySignature(txFrom2, txTo2, 0, nUnused2, true));
}

BOOST_AUTO_TEST_CASE(script_op_eval3)
{
    // Test the CScript::Set* methods
    CBasicKeyStore keystore;
    CKey key[4];
    std::vector<CKey> keys;
    for (int i = 0; i < 4; i++)
    {
        key[i].MakeNewKey();
        keystore.AddKey(key[i]);
        keys.push_back(key[i]);
    }

    CScript inner[4];
    inner[0].SetBitcoinAddress(key[0].GetPubKey());
    inner[1].SetMultisig(2, std::vector<CKey>(keys.begin(), keys.begin()+2));
    inner[2].SetMultisig(1, std::vector<CKey>(keys.begin(), keys.begin()+2));
    inner[3].SetMultisig(2, std::vector<CKey>(keys.begin(), keys.begin()+3));

    CScript outer[4];
    for (int i = 0; i < 4; i++)
    {
        outer[i].SetEval(inner[i]);
        keystore.AddCScript(Hash160(inner[i]), inner[i]);
    }

    CTransaction txFrom;  // Funding transaction:
    txFrom.vout.resize(4);
    for (int i = 0; i < 4; i++)
    {
        txFrom.vout[i].scriptPubKey = outer[i];
    }
    BOOST_CHECK(txFrom.IsStandard());

    CTransaction txTo[4]; // Spending transactions
    for (int i = 0; i < 4; i++)
    {
        txTo[i].vin.resize(1);
        txTo[i].vout.resize(1);
        txTo[i].vin[0].prevout.n = i;
        txTo[i].vin[0].prevout.hash = txFrom.GetHash();
        txTo[i].vout[0].nValue = 1;
        txTo[i].vout[0].scriptPubKey = inner[i];
        BOOST_CHECK_MESSAGE(IsMine(keystore, txFrom.vout[i].scriptPubKey), strprintf("IsMine %d", i));
    }
    for (int i = 0; i < 4; i++)
    {
        BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0), strprintf("SignSignature %d", i));
        BOOST_CHECK_MESSAGE(txTo[i].IsStandard(), strprintf("txTo[%d].IsStandard", i));
    }
}

BOOST_AUTO_TEST_CASE(script_op_eval_backcompat1)
{
    // Check backwards-incompatibility-testing code
    CScript returnsEleven;
    returnsEleven << OP_11;

    // This should validate on new clients, but will
    // be invalid on old clients (that interpret OP_EVAL as a no-op)
    //  ... except there's a special rule that makes new clients reject
    // it.
    CScript fund;
    fund << OP_EVAL << OP_11 << OP_EQUAL;

    CTransaction txFrom;  // Funding transaction:
    txFrom.vout.resize(1);
    txFrom.vout[0].scriptPubKey = fund;

    CTransaction txTo;
    txTo.vin.resize(1);
    txTo.vout.resize(1);
    txTo.vin[0].prevout.n = 0;
    txTo.vin[0].prevout.hash = txFrom.GetHash();
    txTo.vin[0].scriptSig = CScript() << static_cast<std::vector<unsigned char> >(returnsEleven);
    txTo.vout[0].nValue = 1;

    int nUnused = 0;
    BOOST_CHECK(!VerifyScript(txTo.vin[0].scriptSig, txFrom.vout[0].scriptPubKey, txTo, 0, nUnused, 0, true));
    BOOST_CHECK(!VerifySignature(txFrom, txTo, 0, nUnused, true));
}

BOOST_AUTO_TEST_CASE(script_op_eval_switchover)
{
    // Test OP_EVAL switchover code
    CScript notValid;
    notValid << OP_11 << OP_12 << OP_EQUALVERIFY;

    // This will be valid under old rules, invalid under new:
    CScript fund;
    fund << OP_EVAL;

    CTransaction txFrom;  // Funding transaction:
    txFrom.vout.resize(1);
    txFrom.vout[0].scriptPubKey = fund;

    CTransaction txTo;
    txTo.vin.resize(1);
    txTo.vout.resize(1);
    txTo.vin[0].prevout.n = 0;
    txTo.vin[0].prevout.hash = txFrom.GetHash();
    txTo.vin[0].scriptSig = CScript() << static_cast<std::vector<unsigned char> >(notValid);
    txTo.vout[0].nValue = 1;

    int nUnused = 0;
    BOOST_CHECK(VerifyScript(txTo.vin[0].scriptSig, txFrom.vout[0].scriptPubKey, txTo, 0, nUnused, 0, false));

    // Under strict op_eval switchover, it should be considered invalid:
    BOOST_CHECK(!VerifyScript(txTo.vin[0].scriptSig, txFrom.vout[0].scriptPubKey, txTo, 0, nUnused, 0, true));
}

BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>


<commit_before>#include <stdio.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <iostream>
#include <sstream>
#include <stdlib.h>
#include <ctime>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>

#include </usr/local/curl/include/curl/curl.h>
//正则
#include <boost/regex.hpp>
#define MAX_BUF     65536
struct i2c_rdwr_ioctl_data rdwrdata;
using namespace std;
using namespace boost;
//正则匹配字段
regex expression("^seid:(.*)
open_hum:(.*)
end_hum:(.*)
open_time:(.*)
end_time:(.*)
pri:(.*)
time:");
char wr_buf[MAX_BUF+1];
int  wr_index;

//写入数据
size_t write_data( void *buffer, size_t size, size_t nmemb, void *userp ){
	int segsize = size * nmemb;

	if ( wr_index + segsize > MAX_BUF ) {
		*(int *)userp = 1;
		return 0;
	}
	memcpy( (void *)&wr_buf[wr_index], buffer, (size_t)segsize );
	wr_index += segsize;
	wr_buf[wr_index] = 0;
	return segsize;
}

int main(int argc, char *argv[]) {
	int i, j=0, err, fd;
	int h, t, b;
	//模数/数模转换模块上各模块的地址位
	char wordaddr;
	char *rdbuf1;
	char *rdbuf2;
	int bytenum;
	//湿度
	string humdata;
	//温度
	string tempdata;
	//光强
	string beamdata;
	//水泵开始状态，1为开启，0为关闭
	string wp;
	string time_now;

	CURL *curl;
	CURLcode ret;

	cmatch what;
	int  wr_error;
	//打开i2c设备文件
	fd = open("/dev/i2c-1",O_RDWR);
	//轮询
	while(1){
		wr_error = 0;
		wr_index = 0;
		if(j == 2){
			curl = curl_easy_init();
			if (!curl) {
				printf("couldn't init curl\n");
				return 0;
			}
			//curl获取接口数据，设置的参数，seid=001为指定设备号
			curl_easy_setopt( curl, CURLOPT_URL, "http://ipws.sinaapp.com/senddata/send.php?seid=001" );
			curl_easy_setopt( curl, CURLOPT_WRITEDATA, (void *)&wr_error );
			curl_easy_setopt( curl, CURLOPT_WRITEFUNCTION, write_data );
			ret = curl_easy_perform( curl );
			if ( ret == 0 ){
				if(regex_match(wr_buf, what, expression)){}
			}
			curl_easy_cleanup( curl );
		}
		//判断启动数据
	    if(argc < 1){
	        printf("please input as:");
	        printf("./rat24 [read byte addr] [read num of byte]\n");
	        return -1;
	    }
		wordaddr = j;
		bytenum = 4;

	    rdwrdata.msgs = (struct i2c_msg *)malloc(2*sizeof(struct i2c_msg));
	    if(!rdwrdata.msgs){
	        printf("rdwrdata.msgs malloc failed!\n");
	        return -1;
	    }

	    rdbuf1 = ( char *)malloc(sizeof(char));
	    //通关传感器获取到的数据，存放地址
	    rdbuf2 = ( char *)malloc(bytenum*sizeof(char));
	    //内存
	    if((!rdbuf1) || (!rdbuf2)){
	        printf("rdbuf malloc failed!\n");
	        return -1;
	    }
  		//写入模数/数模转换模块设备地址
	    rdwrdata.nmsgs = 2;

	    (rdwrdata.msgs[0]).addr = 0x48;
	    (rdwrdata.msgs[0]).len = 1;
	    (rdwrdata.msgs[0]).flags = 0;
	    (rdwrdata.msgs[0]).buf = (__u8*)rdbuf1;
	    (rdwrdata.msgs[0]).buf[0] = wordaddr;

	    (rdwrdata.msgs[1]).addr = 0x48;
	    (rdwrdata.msgs[1]).len = bytenum;
	    (rdwrdata.msgs[1]).flags = I2C_M_RD;
	    (rdwrdata.msgs[1]).buf = (__u8*)rdbuf2;

	    if(fd < 0){
	        printf("i2c device open failed!\n");
	        return -1;
	    }

	    err = ioctl(fd, I2C_SLAVE_FORCE, 0x50);
	    if(err < 0){
	        printf("ioctl failed\n");
	        return -1;
	    }

	    err = ioctl(fd, I2C_RDWR, &rdwrdata);
	    if(err < 0){
	        printf("ioctl msgs error, error number:%d\n", err);
	        return -1;
	    }
	    //当前时间
		time_t now_time;
		now_time = time(NULL);
		stringstream ss;
		ss<<now_time;
		ss>>time_now;

	    for(i = 2; i < bytenum; i++) {}
	    //湿度数据
	    if((rdbuf2[2]==rdbuf2[3])&&(wordaddr==2)){
			h=rdbuf2[2];
			//int转string
			stringstream ss;
			ss<<h;
			ss>>humdata;
			if(((what[3]<=humdata)&&what[6]=="0")||(what[4]<=time_now&&time_now<=what[5])&&(what[6]=="2")){
			    system("sh /home/work/control/on.sh");
			    wp="1";
			}else if(humdata<=what[2]&&what[6]=="0"||(what[5]<=time_now)&&(what[6]=="2")){
			    system("sh /home/work/control/off.sh");
			    wp="0";
			}else if((((what[4]<=time_now&&time_now<=what[5])&&what[3]<=humdata)||what[3]<=humdata)&&what[6]=="1"){
			    system("sh /home/work/control/on.sh");
				wp="1";
			}else if((humdata<=what[2]||what[5]<=time_now)&&what[6]=="1"){
			    system("sh /home/work/control/off.sh");
				wp="0";
			}
			//打印出当前湿度数据
		    cout<<"hum:"+humdata<<endl;

		}
		//光强数据
	    if((rdbuf2[2]==rdbuf2[3])&&(wordaddr==0)){
		    b=rdbuf2[2];
		    stringstream ss;
			ss<>beamdata;
			//打印出当前光强数据
			cout<<"beam:"+beamdata<<endl;
		}
		//温度数据
	    if((rdbuf2[2]==rdbuf2[3])&&(wordaddr==1)){
		    t=rdbuf2[2];
		    stringstream ss;
            ss<<t;
            ss>>tempdata;
            //打印出当前温度数据
            cout<<"temp:"+tempdata<<endl;
	    }
		j++;
		//最后一步将当前温湿度光强，水泵状态上传到云数据库
		if(j==3){
			j=0;
			//生成post参数
			string s = "curl -d 'seid=001&hum=";
			s += humdata;
			s += "&temp=";
			s += tempdata;
			s += "&wp=";
			s += wp;
			s += "&beam=";
			s += beamdata;
			s += "&time=";
			s += time_now;
			//数据库接口地址
			s += "' 'http://ipws.sinaapp.com/getdata/put.php'";
			system(s.c_str());
		}
    }
    //关闭i2c设备
	close(fd);
	return 0;
}
<commit_msg>Revert "init arm control"<commit_after><|endoftext|>