<commit_before>/*
 * Copyright (C) 2008-2013 The Communi Project
 *
 * This test is free, and not covered by the LGPL license. There is no
 * restriction applied to their modification, redistribution, using and so on.
 * You can study them, modify them, use them in your own program - either
 * completely or partially.
 */

#include "ircuser.h"
#include <QtTest/QtTest>
#include <QtCore/QRegExp>
#ifdef Q_OS_LINUX
#include "ircuser_p.h"
#endif // Q_OS_LINUX

class tst_IrcUser : public QObject
{
    Q_OBJECT

private slots:
    void testDefaults();
    void testSignals();
    void testDebug();
};

void tst_IrcUser::testDefaults()
{
    IrcUser user;
    QVERIFY(user.title().isEmpty());
    QVERIFY(user.name().isEmpty());
    QVERIFY(user.prefix().isEmpty());
    QVERIFY(user.mode().isEmpty());
    QVERIFY(!user.channel());
}

void tst_IrcUser::testSignals()
{
    IrcUser user;
    QSignalSpy titleSpy(&user, SIGNAL(titleChanged(QString)));
    QSignalSpy nameSpy(&user, SIGNAL(nameChanged(QString)));
    QSignalSpy prefixSpy(&user, SIGNAL(prefixChanged(QString)));
    QSignalSpy modeSpy(&user, SIGNAL(modeChanged(QString)));
    QVERIFY(titleSpy.isValid());
    QVERIFY(nameSpy.isValid());
    QVERIFY(prefixSpy.isValid());
    QVERIFY(modeSpy.isValid());
}

void tst_IrcUser::testDebug()
{
    QString str;
    QDebug dbg(&str);

    dbg << static_cast<IrcUser*>(0);
    QCOMPARE(str.trimmed(), QString::fromLatin1("IrcUser(0x0)"));
    str.clear();

    IrcUser user;
    dbg << &user;
    QVERIFY(QRegExp("IrcUser\\(0x[0-9A-Fa-f]+\\) ").exactMatch(str));
    str.clear();

    user.setObjectName("obj");
    dbg << &user;
    QVERIFY(QRegExp("IrcUser\\(0x[0-9A-Fa-f]+, name=obj\\) ").exactMatch(str));
    str.clear();

#ifdef Q_OS_LINUX
    // others have problems with symbols (win) or private headers (osx frameworks)
    IrcUserPrivate::get(&user)->setName("usr");
    dbg << &user;
    QVERIFY(QRegExp("IrcUser\\(0x[0-9A-Fa-f]+, name=obj, user=usr\\) ").exactMatch(str));
    str.clear();
#endif // Q_OS_LINUX
}

QTEST_MAIN(tst_IrcUser)

#include "tst_ircuser.moc"
<commit_msg>tst_IrcUser: test away/servop defaults & signals<commit_after>/*
 * Copyright (C) 2008-2013 The Communi Project
 *
 * This test is free, and not covered by the LGPL license. There is no
 * restriction applied to their modification, redistribution, using and so on.
 * You can study them, modify them, use them in your own program - either
 * completely or partially.
 */

#include "ircuser.h"
#include <QtTest/QtTest>
#include <QtCore/QRegExp>
#ifdef Q_OS_LINUX
#include "ircuser_p.h"
#endif // Q_OS_LINUX

class tst_IrcUser : public QObject
{
    Q_OBJECT

private slots:
    void testDefaults();
    void testSignals();
    void testDebug();
};

void tst_IrcUser::testDefaults()
{
    IrcUser user;
    QVERIFY(user.title().isEmpty());
    QVERIFY(user.name().isEmpty());
    QVERIFY(user.prefix().isEmpty());
    QVERIFY(user.mode().isEmpty());
    QVERIFY(!user.isServOp());
    QVERIFY(!user.isAway());
    QVERIFY(!user.channel());
}

void tst_IrcUser::testSignals()
{
    IrcUser user;
    QSignalSpy titleSpy(&user, SIGNAL(titleChanged(QString)));
    QSignalSpy nameSpy(&user, SIGNAL(nameChanged(QString)));
    QSignalSpy prefixSpy(&user, SIGNAL(prefixChanged(QString)));
    QSignalSpy modeSpy(&user, SIGNAL(modeChanged(QString)));
    QSignalSpy servOpSpy(&user, SIGNAL(servOpChanged(bool)));
    QSignalSpy awaySpy(&user, SIGNAL(awayChanged(bool)));
    QVERIFY(titleSpy.isValid());
    QVERIFY(nameSpy.isValid());
    QVERIFY(prefixSpy.isValid());
    QVERIFY(modeSpy.isValid());
    QVERIFY(servOpSpy.isValid());
    QVERIFY(awaySpy.isValid());
}

void tst_IrcUser::testDebug()
{
    QString str;
    QDebug dbg(&str);

    dbg << static_cast<IrcUser*>(0);
    QCOMPARE(str.trimmed(), QString::fromLatin1("IrcUser(0x0)"));
    str.clear();

    IrcUser user;
    dbg << &user;
    QVERIFY(QRegExp("IrcUser\\(0x[0-9A-Fa-f]+\\) ").exactMatch(str));
    str.clear();

    user.setObjectName("obj");
    dbg << &user;
    QVERIFY(QRegExp("IrcUser\\(0x[0-9A-Fa-f]+, name=obj\\) ").exactMatch(str));
    str.clear();

#ifdef Q_OS_LINUX
    // others have problems with symbols (win) or private headers (osx frameworks)
    IrcUserPrivate::get(&user)->setName("usr");
    dbg << &user;
    QVERIFY(QRegExp("IrcUser\\(0x[0-9A-Fa-f]+, name=obj, user=usr\\) ").exactMatch(str));
    str.clear();
#endif // Q_OS_LINUX
}

QTEST_MAIN(tst_IrcUser)

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


<commit_before>//===---------------------------- cxa_guard.cpp ---------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "__cxxabi_config.h"

#include "abort_message.h"
#include "include/atomic_support.h"
#include <__threading_support>

#include <stdint.h>
#include <string.h>

/*
    This implementation must be careful to not call code external to this file
    which will turn around and try to call __cxa_guard_acquire reentrantly.
    For this reason, the headers of this file are as restricted as possible.
    Previous implementations of this code for __APPLE__ have used
    std::__libcpp_mutex_lock and the abort_message utility without problem. This
    implementation also uses std::__libcpp_condvar_wait which has tested
    to not be a problem.
*/

namespace __cxxabiv1
{

namespace
{

enum InitializationResult {
  INIT_COMPLETE,
  INIT_NOT_COMPLETE,
};

#ifdef __arm__
// A 32-bit, 4-byte-aligned static data value. The least significant 2 bits must
// be statically initialized to 0.
typedef uint32_t guard_type;
#else
typedef uint64_t guard_type;
#endif

#if !defined(_LIBCXXABI_HAS_NO_THREADS) && defined(__APPLE__) &&               \
    !defined(__arm__)
// This is a special-case pthread dependency for Mac. We can't pull this
// out into libcxx's threading API (__threading_support) because not all
// supported Mac environments provide this function (in pthread.h). To
// make it possible to build/use libcxx in those environments, we have to
// keep this pthread dependency local to libcxxabi. If there is some
// convenient way to detect precisely when pthread_mach_thread_np is
// available in a given Mac environment, it might still be possible to
// bury this dependency in __threading_support.
#ifndef _LIBCPP_HAS_THREAD_API_PTHREAD
#error "How do I pthread_mach_thread_np()?"
#endif
#define LIBCXXABI_HAS_DEADLOCK_DETECTION
#define LOCK_ID_FOR_THREAD() pthread_mach_thread_np(std::__libcpp_thread_get_current_id())
typedef uint32_t lock_type;
#else
#define LOCK_ID_FOR_THREAD() true
typedef bool lock_type;
#endif

enum class OnRelease : char { UNLOCK, UNLOCK_AND_BROADCAST };

struct GlobalMutexGuard {
  explicit GlobalMutexGuard(const char* calling_func, OnRelease on_release)
      : calling_func(calling_func), on_release(on_release) {
#ifndef _LIBCXXABI_HAS_NO_THREADS
    if (std::__libcpp_mutex_lock(&guard_mut))
      abort_message("%s failed to acquire mutex", calling_func);
#endif
  }

  ~GlobalMutexGuard() {
#ifndef _LIBCXXABI_HAS_NO_THREADS
    if (std::__libcpp_mutex_unlock(&guard_mut))
      abort_message("%s failed to release mutex", calling_func);
    if (on_release == OnRelease::UNLOCK_AND_BROADCAST) {
      if (std::__libcpp_condvar_broadcast(&guard_cv))
        abort_message("%s failed to broadcast condition variable",
                      calling_func);
    }
#endif
  }

  void wait_for_signal() {
#ifndef _LIBCXXABI_HAS_NO_THREADS
    if (std::__libcpp_condvar_wait(&guard_cv, &guard_mut))
      abort_message("%s condition variable wait failed", calling_func);
#endif
  }

private:
  GlobalMutexGuard(GlobalMutexGuard const&) = delete;
  GlobalMutexGuard& operator=(GlobalMutexGuard const&) = delete;

  const char* const calling_func;
  OnRelease on_release;

#ifndef _LIBCXXABI_HAS_NO_THREADS
  static std::__libcpp_mutex_t guard_mut;
  static std::__libcpp_condvar_t guard_cv;
#endif
};

#ifndef _LIBCXXABI_HAS_NO_THREADS
std::__libcpp_mutex_t GlobalMutexGuard::guard_mut = _LIBCPP_MUTEX_INITIALIZER;
std::__libcpp_condvar_t GlobalMutexGuard::guard_cv =
    _LIBCPP_CONDVAR_INITIALIZER;
#endif

struct GuardObject;

/// GuardValue - An abstraction for accessing the various fields and bits of
///   the guard object.
struct GuardValue {
private:
  explicit GuardValue(guard_type v) : value(v) {}
  friend struct GuardObject;

public:
  /// Functions returning the values used to represent the uninitialized,
  /// initialized, and initialization pending states.
  static GuardValue ZERO();
  static GuardValue INIT_COMPLETE();
  static GuardValue INIT_PENDING();

  /// Returns true if the guard value represents that the initialization is
  /// complete.
  bool is_initialization_complete() const;

  /// Returns true if the guard value represents that the initialization is
  /// currently pending.
  bool is_initialization_pending() const;

  /// Returns the lock value for the current guard value.
  lock_type get_lock_value() const;

private:
  // Returns a guard object corresponding to the specified lock value.
  static guard_type guard_value_from_lock(lock_type l);

  // Returns the lock value represented by the specified guard object.
  static lock_type lock_value_from_guard(guard_type g);

private:
  guard_type value;
};

/// GuardObject - Manages correctly reading and writing to the guard object.
struct GuardObject {
  explicit GuardObject(guard_type *g) : guard(g) {}

  /// Load the current value from the guard object.
  GuardValue load() const;

  /// Store the specified value in the guard object.
  void store(GuardValue new_val);

  /// Store the specified value in the guard object and return the previous value.
  GuardValue exchange(GuardValue new_val);

  /// Perform a atomic compare and exchange operation. Return true if
  // desired is written to the guard object.
  bool compare_exchange(GuardValue *expected, GuardValue desired);

private:
  GuardObject(const GuardObject&) = delete;
  GuardObject& operator=(const GuardObject&) = delete;

  guard_type *guard;
};

}  // unnamed namespace

extern "C"
{

_LIBCXXABI_FUNC_VIS int __cxa_guard_acquire(guard_type* raw_guard_object) {
  GlobalMutexGuard gmutex("__cxa_guard_acquire", OnRelease::UNLOCK);
  GuardObject guard(raw_guard_object);
  GuardValue current_value = guard.load();

  if (current_value.is_initialization_complete())
    return INIT_COMPLETE;

  const GuardValue LOCK_ID = GuardValue::INIT_PENDING();
#ifdef LIBCXXABI_HAS_DEADLOCK_DETECTION
   if (current_value.is_initialization_pending() &&
       current_value.get_lock_value() == LOCK_ID.get_lock_value()) {
    abort_message("__cxa_guard_acquire detected deadlock");
  }
#endif
  while (current_value.is_initialization_pending()) {
      gmutex.wait_for_signal();
      current_value = guard.load();
  }
  if (current_value.is_initialization_complete())
    return INIT_COMPLETE;

  guard.store(LOCK_ID);
  return INIT_NOT_COMPLETE;
}

_LIBCXXABI_FUNC_VIS void __cxa_guard_release(guard_type *raw_guard_object) {
  GlobalMutexGuard gmutex("__cxa_guard_release",
                          OnRelease::UNLOCK_AND_BROADCAST);
  GuardObject guard(raw_guard_object);
  guard.store(GuardValue::ZERO());
  guard.store(GuardValue::INIT_COMPLETE());
}

_LIBCXXABI_FUNC_VIS void __cxa_guard_abort(guard_type *raw_guard_object) {
  GlobalMutexGuard gmutex("__cxa_guard_abort", OnRelease::UNLOCK);
  GuardObject guard(raw_guard_object);
  guard.store(GuardValue::ZERO());
}
}  // extern "C"

//===----------------------------------------------------------------------===//
//                        GuardObject Definitions
//===----------------------------------------------------------------------===//

GuardValue GuardObject::load() const {
  return GuardValue(std::__libcpp_atomic_load(guard));
}

void GuardObject::store(GuardValue new_val) {
  std::__libcpp_atomic_store(guard, new_val.value);
}

GuardValue GuardObject::exchange(GuardValue new_val) {
  return GuardValue(
      std::__libcpp_atomic_exchange(guard, new_val.value, std::_AO_Acq_Rel));
}

bool GuardObject::compare_exchange(GuardValue* expected,
                                   GuardValue desired) {
  return std::__libcpp_atomic_compare_exchange(guard, &expected->value, desired.value,
                                               std::_AO_Acq_Rel, std::_AO_Acquire);
}

//===----------------------------------------------------------------------===//
//                        GuardValue Definitions
//===----------------------------------------------------------------------===//

GuardValue GuardValue::ZERO() { return GuardValue(0); }

GuardValue GuardValue::INIT_COMPLETE() {
  guard_type value = {0};
#ifdef __arm__
  value |= 1;
#else
  char* init_bit = (char*)&value;
  *init_bit = 1;
#endif
  return GuardValue(value);
}

GuardValue GuardValue::INIT_PENDING() {
  return GuardValue(guard_value_from_lock(LOCK_ID_FOR_THREAD()));
}

bool GuardValue::is_initialization_complete() const {
#ifdef __arm__
  return value & 1;
#else
  const char* init_bit = (const char*)&value;
  return *init_bit;
#endif
}

bool GuardValue::is_initialization_pending() const {
  return lock_value_from_guard(value) != 0;
}

lock_type GuardValue::get_lock_value() const {
  return lock_value_from_guard(value);
}

// Create a guard object with the lock set to the specified value.
guard_type GuardValue::guard_value_from_lock(lock_type l) {
#if defined(__APPLE__) && !defined(__arm__)
#if __LITTLE_ENDIAN__
  return static_cast<guard_type>(l) << 32;
#else
  return static_cast<guard_type>(l);
#endif
#else  // defined(__APPLE__) && !defined(__arm__)
  guard_type f = {0};
  memcpy(static_cast<char*>(static_cast<void*>(&f)) + 1, &l, sizeof(lock_type));
  return f;
#endif // defined(__APPLE__) && !defined(__arm__)
}

lock_type GuardValue::lock_value_from_guard(guard_type g) {
#if defined(__APPLE__) && !defined(__arm__)
#if __LITTLE_ENDIAN__
  return static_cast<lock_type>(g >> 32);
#else
  return static_cast<lock_type>(g);
#endif
#else  // defined(__APPLE__) && !defined(__arm__)
  uint8_t guard_bytes[sizeof(guard_type)];
  memcpy(&guard_bytes, &g, sizeof(guard_type));
  return guard_bytes[1] != 0;
#endif // defined(__APPLE__) && !defined(__arm__)
}

}  // __cxxabiv1
<commit_msg>Remove unneeded write in __cxa_guard_release.<commit_after>//===---------------------------- cxa_guard.cpp ---------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "__cxxabi_config.h"

#include "abort_message.h"
#include "include/atomic_support.h"
#include <__threading_support>

#include <stdint.h>
#include <string.h>

/*
    This implementation must be careful to not call code external to this file
    which will turn around and try to call __cxa_guard_acquire reentrantly.
    For this reason, the headers of this file are as restricted as possible.
    Previous implementations of this code for __APPLE__ have used
    std::__libcpp_mutex_lock and the abort_message utility without problem. This
    implementation also uses std::__libcpp_condvar_wait which has tested
    to not be a problem.
*/

namespace __cxxabiv1
{

namespace
{

enum InitializationResult {
  INIT_COMPLETE,
  INIT_NOT_COMPLETE,
};

#ifdef __arm__
// A 32-bit, 4-byte-aligned static data value. The least significant 2 bits must
// be statically initialized to 0.
typedef uint32_t guard_type;
#else
typedef uint64_t guard_type;
#endif

#if !defined(_LIBCXXABI_HAS_NO_THREADS) && defined(__APPLE__) &&               \
    !defined(__arm__)
// This is a special-case pthread dependency for Mac. We can't pull this
// out into libcxx's threading API (__threading_support) because not all
// supported Mac environments provide this function (in pthread.h). To
// make it possible to build/use libcxx in those environments, we have to
// keep this pthread dependency local to libcxxabi. If there is some
// convenient way to detect precisely when pthread_mach_thread_np is
// available in a given Mac environment, it might still be possible to
// bury this dependency in __threading_support.
#ifndef _LIBCPP_HAS_THREAD_API_PTHREAD
#error "How do I pthread_mach_thread_np()?"
#endif
#define LIBCXXABI_HAS_DEADLOCK_DETECTION
#define LOCK_ID_FOR_THREAD() pthread_mach_thread_np(std::__libcpp_thread_get_current_id())
typedef uint32_t lock_type;
#else
#define LOCK_ID_FOR_THREAD() true
typedef bool lock_type;
#endif

enum class OnRelease : char { UNLOCK, UNLOCK_AND_BROADCAST };

struct GlobalMutexGuard {
  explicit GlobalMutexGuard(const char* calling_func, OnRelease on_release)
      : calling_func(calling_func), on_release(on_release) {
#ifndef _LIBCXXABI_HAS_NO_THREADS
    if (std::__libcpp_mutex_lock(&guard_mut))
      abort_message("%s failed to acquire mutex", calling_func);
#endif
  }

  ~GlobalMutexGuard() {
#ifndef _LIBCXXABI_HAS_NO_THREADS
    if (std::__libcpp_mutex_unlock(&guard_mut))
      abort_message("%s failed to release mutex", calling_func);
    if (on_release == OnRelease::UNLOCK_AND_BROADCAST) {
      if (std::__libcpp_condvar_broadcast(&guard_cv))
        abort_message("%s failed to broadcast condition variable",
                      calling_func);
    }
#endif
  }

  void wait_for_signal() {
#ifndef _LIBCXXABI_HAS_NO_THREADS
    if (std::__libcpp_condvar_wait(&guard_cv, &guard_mut))
      abort_message("%s condition variable wait failed", calling_func);
#endif
  }

private:
  GlobalMutexGuard(GlobalMutexGuard const&) = delete;
  GlobalMutexGuard& operator=(GlobalMutexGuard const&) = delete;

  const char* const calling_func;
  OnRelease on_release;

#ifndef _LIBCXXABI_HAS_NO_THREADS
  static std::__libcpp_mutex_t guard_mut;
  static std::__libcpp_condvar_t guard_cv;
#endif
};

#ifndef _LIBCXXABI_HAS_NO_THREADS
std::__libcpp_mutex_t GlobalMutexGuard::guard_mut = _LIBCPP_MUTEX_INITIALIZER;
std::__libcpp_condvar_t GlobalMutexGuard::guard_cv =
    _LIBCPP_CONDVAR_INITIALIZER;
#endif

struct GuardObject;

/// GuardValue - An abstraction for accessing the various fields and bits of
///   the guard object.
struct GuardValue {
private:
  explicit GuardValue(guard_type v) : value(v) {}
  friend struct GuardObject;

public:
  /// Functions returning the values used to represent the uninitialized,
  /// initialized, and initialization pending states.
  static GuardValue ZERO();
  static GuardValue INIT_COMPLETE();
  static GuardValue INIT_PENDING();

  /// Returns true if the guard value represents that the initialization is
  /// complete.
  bool is_initialization_complete() const;

  /// Returns true if the guard value represents that the initialization is
  /// currently pending.
  bool is_initialization_pending() const;

  /// Returns the lock value for the current guard value.
  lock_type get_lock_value() const;

private:
  // Returns a guard object corresponding to the specified lock value.
  static guard_type guard_value_from_lock(lock_type l);

  // Returns the lock value represented by the specified guard object.
  static lock_type lock_value_from_guard(guard_type g);

private:
  guard_type value;
};

/// GuardObject - Manages correctly reading and writing to the guard object.
struct GuardObject {
  explicit GuardObject(guard_type *g) : guard(g) {}

  /// Load the current value from the guard object.
  GuardValue load() const;

  /// Store the specified value in the guard object.
  void store(GuardValue new_val);

  /// Store the specified value in the guard object and return the previous value.
  GuardValue exchange(GuardValue new_val);

  /// Perform a atomic compare and exchange operation. Return true if
  // desired is written to the guard object.
  bool compare_exchange(GuardValue *expected, GuardValue desired);

private:
  GuardObject(const GuardObject&) = delete;
  GuardObject& operator=(const GuardObject&) = delete;

  guard_type *guard;
};

}  // unnamed namespace

extern "C"
{

_LIBCXXABI_FUNC_VIS int __cxa_guard_acquire(guard_type* raw_guard_object) {
  GlobalMutexGuard gmutex("__cxa_guard_acquire", OnRelease::UNLOCK);
  GuardObject guard(raw_guard_object);
  GuardValue current_value = guard.load();

  if (current_value.is_initialization_complete())
    return INIT_COMPLETE;

  const GuardValue LOCK_ID = GuardValue::INIT_PENDING();
#ifdef LIBCXXABI_HAS_DEADLOCK_DETECTION
   if (current_value.is_initialization_pending() &&
       current_value.get_lock_value() == LOCK_ID.get_lock_value()) {
    abort_message("__cxa_guard_acquire detected deadlock");
  }
#endif
  while (current_value.is_initialization_pending()) {
      gmutex.wait_for_signal();
      current_value = guard.load();
  }
  if (current_value.is_initialization_complete())
    return INIT_COMPLETE;

  guard.store(LOCK_ID);
  return INIT_NOT_COMPLETE;
}

_LIBCXXABI_FUNC_VIS void __cxa_guard_release(guard_type *raw_guard_object) {
  GlobalMutexGuard gmutex("__cxa_guard_release",
                          OnRelease::UNLOCK_AND_BROADCAST);
  GuardObject guard(raw_guard_object);
  guard.store(GuardValue::INIT_COMPLETE());
}

_LIBCXXABI_FUNC_VIS void __cxa_guard_abort(guard_type *raw_guard_object) {
  GlobalMutexGuard gmutex("__cxa_guard_abort", OnRelease::UNLOCK);
  GuardObject guard(raw_guard_object);
  guard.store(GuardValue::ZERO());
}
}  // extern "C"

//===----------------------------------------------------------------------===//
//                        GuardObject Definitions
//===----------------------------------------------------------------------===//

GuardValue GuardObject::load() const {
  return GuardValue(std::__libcpp_atomic_load(guard));
}

void GuardObject::store(GuardValue new_val) {
  std::__libcpp_atomic_store(guard, new_val.value);
}

GuardValue GuardObject::exchange(GuardValue new_val) {
  return GuardValue(
      std::__libcpp_atomic_exchange(guard, new_val.value, std::_AO_Acq_Rel));
}

bool GuardObject::compare_exchange(GuardValue* expected,
                                   GuardValue desired) {
  return std::__libcpp_atomic_compare_exchange(guard, &expected->value, desired.value,
                                               std::_AO_Acq_Rel, std::_AO_Acquire);
}

//===----------------------------------------------------------------------===//
//                        GuardValue Definitions
//===----------------------------------------------------------------------===//

GuardValue GuardValue::ZERO() { return GuardValue(0); }

GuardValue GuardValue::INIT_COMPLETE() {
  guard_type value = {0};
#ifdef __arm__
  value |= 1;
#else
  char* init_bit = (char*)&value;
  *init_bit = 1;
#endif
  return GuardValue(value);
}

GuardValue GuardValue::INIT_PENDING() {
  return GuardValue(guard_value_from_lock(LOCK_ID_FOR_THREAD()));
}

bool GuardValue::is_initialization_complete() const {
#ifdef __arm__
  return value & 1;
#else
  const char* init_bit = (const char*)&value;
  return *init_bit;
#endif
}

bool GuardValue::is_initialization_pending() const {
  return lock_value_from_guard(value) != 0;
}

lock_type GuardValue::get_lock_value() const {
  return lock_value_from_guard(value);
}

// Create a guard object with the lock set to the specified value.
guard_type GuardValue::guard_value_from_lock(lock_type l) {
#if defined(__APPLE__) && !defined(__arm__)
#if __LITTLE_ENDIAN__
  return static_cast<guard_type>(l) << 32;
#else
  return static_cast<guard_type>(l);
#endif
#else  // defined(__APPLE__) && !defined(__arm__)
  guard_type f = {0};
  memcpy(static_cast<char*>(static_cast<void*>(&f)) + 1, &l, sizeof(lock_type));
  return f;
#endif // defined(__APPLE__) && !defined(__arm__)
}

lock_type GuardValue::lock_value_from_guard(guard_type g) {
#if defined(__APPLE__) && !defined(__arm__)
#if __LITTLE_ENDIAN__
  return static_cast<lock_type>(g >> 32);
#else
  return static_cast<lock_type>(g);
#endif
#else  // defined(__APPLE__) && !defined(__arm__)
  uint8_t guard_bytes[sizeof(guard_type)];
  memcpy(&guard_bytes, &g, sizeof(guard_type));
  return guard_bytes[1] != 0;
#endif // defined(__APPLE__) && !defined(__arm__)
}

}  // __cxxabiv1
<|endoftext|>


<commit_before>// $Id$

// The libMesh Finite Element Library.
// Copyright (C) 2002-2008 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner

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

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

// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

// C++ includes
#include <cmath> // for std::abs

// Local Includes
#include "numeric_vector.h"
#include "distributed_vector.h"
#include "laspack_vector.h"
#include "petsc_vector.h"
#include "trilinos_epetra_vector.h"
#include "shell_matrix.h"

namespace libMesh
{

//------------------------------------------------------------------
// NumericVector methods

// Full specialization for Real datatypes
template <typename T>
AutoPtr<NumericVector<T> >
NumericVector<T>::build(const SolverPackage solver_package)
{
  // Build the appropriate vector
  switch (solver_package)
    {

#ifdef LIBMESH_HAVE_LASPACK
    case LASPACK_SOLVERS:
      {
	AutoPtr<NumericVector<T> > ap(new LaspackVector<T>);
	return ap;
      }
#endif

#ifdef LIBMESH_HAVE_PETSC
    case PETSC_SOLVERS:
      {
	AutoPtr<NumericVector<T> > ap(new PetscVector<T>);
	return ap;
      }
#endif

#ifdef LIBMESH_HAVE_TRILINOS
    case TRILINOS_SOLVERS:
      {
	AutoPtr<NumericVector<T> > ap(new EpetraVector<T>);
	return ap;
      }
#endif

    default:
      AutoPtr<NumericVector<T> > ap(new DistributedVector<T>);
      return ap;
    }

  AutoPtr<NumericVector<T> > ap(NULL);
  return ap;
}

template <typename T>
int NumericVector<T>::compare (const NumericVector<T> &other_vector,
			       const Real threshold) const
{
  libmesh_assert (this->initialized());
  libmesh_assert (other_vector.initialized());
  libmesh_assert (this->first_local_index() == other_vector.first_local_index());
  libmesh_assert (this->last_local_index()  == other_vector.last_local_index());

  int first_different_i = std::numeric_limits<int>::max();
  unsigned int i = first_local_index();

  do
    {
      if ( std::abs( (*this)(i) - other_vector(i) ) > threshold )
	first_different_i = i;
      else
	i++;
    }
  while (first_different_i==std::numeric_limits<int>::max()
         && i<last_local_index());

  // Find the correct first differing index in parallel
  Parallel::min(first_different_i);

  if (first_different_i == std::numeric_limits<int>::max())
    return -1;

  return first_different_i;
}

template <typename T>
int NumericVector<T>::local_relative_compare (const NumericVector<T> &other_vector,
			                      const Real threshold) const
{
  libmesh_assert (this->initialized());
  libmesh_assert (other_vector.initialized());
  libmesh_assert (this->first_local_index() == other_vector.first_local_index());
  libmesh_assert (this->last_local_index()  == other_vector.last_local_index());

  int first_different_i = std::numeric_limits<int>::max();
  unsigned int i = first_local_index();

  do
    {
      if ( std::abs( (*this)(i) - other_vector(i) ) > threshold *
           std::max(std::abs((*this)(i)), std::abs(other_vector(i))))
	first_different_i = i;
      else
	i++;
    }
  while (first_different_i==std::numeric_limits<int>::max()
         && i<last_local_index());

  // Find the correct first differing index in parallel
  Parallel::min(first_different_i);

  if (first_different_i == std::numeric_limits<int>::max())
    return -1;

  return first_different_i;
}

template <typename T>
int NumericVector<T>::global_relative_compare (const NumericVector<T> &other_vector,
			                       const Real threshold) const
{
  libmesh_assert (this->initialized());
  libmesh_assert (other_vector.initialized());
  libmesh_assert (this->first_local_index() == other_vector.first_local_index());
  libmesh_assert (this->last_local_index()  == other_vector.last_local_index());

  int first_different_i = std::numeric_limits<int>::max();
  unsigned int i = first_local_index();

  const Real my_norm = this->linfty_norm();
  const Real other_norm = other_vector.linfty_norm();
  const Real abs_threshold = std::max(my_norm, other_norm) * threshold;

  do
    {
      if ( std::abs( (*this)(i) - other_vector(i) ) > abs_threshold )
	first_different_i = i;
      else
	i++;
    }
  while (first_different_i==std::numeric_limits<int>::max()
         && i<last_local_index());

  // Find the correct first differing index in parallel
  Parallel::min(first_different_i);

  if (first_different_i == std::numeric_limits<int>::max())
    return -1;

  return first_different_i;
}

/*
// Full specialization for float datatypes (DistributedVector wants this)

template <>
int NumericVector<float>::compare (const NumericVector<float> &other_vector,
				   const Real threshold) const
{
  libmesh_assert (this->initialized());
  libmesh_assert (other_vector.initialized());
  libmesh_assert (this->first_local_index() == other_vector.first_local_index());
  libmesh_assert (this->last_local_index()  == other_vector.last_local_index());

  int rvalue     = -1;
  unsigned int i = first_local_index();

  do
    {
      if ( std::abs( (*this)(i) - other_vector(i) ) > threshold )
	rvalue = i;
      else
	i++;
    }
  while (rvalue==-1 && i<last_local_index());

  return rvalue;
}

// Full specialization for double datatypes
template <>
int NumericVector<double>::compare (const NumericVector<double> &other_vector,
				    const Real threshold) const
{
  libmesh_assert (this->initialized());
  libmesh_assert (other_vector.initialized());
  libmesh_assert (this->first_local_index() == other_vector.first_local_index());
  libmesh_assert (this->last_local_index()  == other_vector.last_local_index());

  int rvalue     = -1;
  unsigned int i = first_local_index();

  do
    {
      if ( std::abs( (*this)(i) - other_vector(i) ) > threshold )
	rvalue = i;
      else
	i++;
    }
  while (rvalue==-1 && i<last_local_index());

  return rvalue;
}

#ifdef TRIPLE_PRECISION
// Full specialization for long double datatypes
template <>
int NumericVector<long double>::compare (const NumericVector<long double> &other_vector,
				         const Real threshold) const
{
  libmesh_assert (this->initialized());
  libmesh_assert (other_vector.initialized());
  libmesh_assert (this->first_local_index() == other_vector.first_local_index());
  libmesh_assert (this->last_local_index()  == other_vector.last_local_index());

  int rvalue     = -1;
  unsigned int i = first_local_index();

  do
    {
      if ( std::abs( (*this)(i) - other_vector(i) ) > threshold )
	rvalue = i;
      else
	i++;
    }
  while (rvalue==-1 && i<last_local_index());

  return rvalue;
}
#endif

// Full specialization for Complex datatypes
template <>
int NumericVector<Complex>::compare (const NumericVector<Complex> &other_vector,
				     const Real threshold) const
{
  libmesh_assert (this->initialized());
  libmesh_assert (other_vector.initialized());
  libmesh_assert (this->first_local_index() == other_vector.first_local_index());
  libmesh_assert (this->last_local_index()  == other_vector.last_local_index());

  int rvalue     = -1;
  unsigned int i = first_local_index();

  do
    {
      if (( std::abs( (*this)(i).real() - other_vector(i).real() ) > threshold ) ||
	  ( std::abs( (*this)(i).imag() - other_vector(i).imag() ) > threshold ))
	rvalue = i;
      else
	i++;
    }
  while (rvalue==-1 && i<this->last_local_index());

  return rvalue;
}
*/

template <class T>
Real NumericVector<T>::subset_l1_norm (const std::set<unsigned int> & indices) const
{
  const NumericVector<T> & v = *this;

  std::set<unsigned int>::iterator it = indices.begin();
  const std::set<unsigned int>::iterator it_end = indices.end();

  Real norm = 0;

  for(; it!=it_end; ++it)
    norm += std::abs(v(*it));

  Parallel::sum(norm);

  return norm;
}

template <class T>
Real NumericVector<T>::subset_l2_norm (const std::set<unsigned int> & indices) const
{
  const NumericVector<T> & v = *this;

  std::set<unsigned int>::iterator it = indices.begin();
  const std::set<unsigned int>::iterator it_end = indices.end();

  Real norm = 0;

  for(; it!=it_end; ++it)
    norm += libmesh_norm(v(*it));

  Parallel::sum(norm);

  return std::sqrt(norm);
}

template <class T>
Real NumericVector<T>::subset_linfty_norm (const std::set<unsigned int> & indices) const
{
  const NumericVector<T> & v = *this;

  std::set<unsigned int>::iterator it = indices.begin();
  const std::set<unsigned int>::iterator it_end = indices.end();

  Real norm = 0;

  for(; it!=it_end; ++it)
    {
      Real value = std::abs(v(*it));
      if(value > norm)
        norm = value;
    }

  Parallel::max(norm);

  return norm;
}

template <typename T>
void NumericVector<T>::add_vector (const NumericVector<T>& v,
				   const ShellMatrix<T>& a)
{
  a.vector_mult_add(*this,v);
}

//------------------------------------------------------------------
// Explicit instantiations
template class NumericVector<Number>;

} // namespace libMesh
<commit_msg>Use const_iterators in a const function with a const std::set. IBM xlC complained about this, frankly I agree with it.  Not sure why other compilers didn't complain.<commit_after>// $Id$

// The libMesh Finite Element Library.
// Copyright (C) 2002-2008 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner

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

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

// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

// C++ includes
#include <cmath> // for std::abs

// Local Includes
#include "numeric_vector.h"
#include "distributed_vector.h"
#include "laspack_vector.h"
#include "petsc_vector.h"
#include "trilinos_epetra_vector.h"
#include "shell_matrix.h"

namespace libMesh
{

//------------------------------------------------------------------
// NumericVector methods

// Full specialization for Real datatypes
template <typename T>
AutoPtr<NumericVector<T> >
NumericVector<T>::build(const SolverPackage solver_package)
{
  // Build the appropriate vector
  switch (solver_package)
    {

#ifdef LIBMESH_HAVE_LASPACK
    case LASPACK_SOLVERS:
      {
	AutoPtr<NumericVector<T> > ap(new LaspackVector<T>);
	return ap;
      }
#endif

#ifdef LIBMESH_HAVE_PETSC
    case PETSC_SOLVERS:
      {
	AutoPtr<NumericVector<T> > ap(new PetscVector<T>);
	return ap;
      }
#endif

#ifdef LIBMESH_HAVE_TRILINOS
    case TRILINOS_SOLVERS:
      {
	AutoPtr<NumericVector<T> > ap(new EpetraVector<T>);
	return ap;
      }
#endif

    default:
      AutoPtr<NumericVector<T> > ap(new DistributedVector<T>);
      return ap;
    }

  AutoPtr<NumericVector<T> > ap(NULL);
  return ap;
}

template <typename T>
int NumericVector<T>::compare (const NumericVector<T> &other_vector,
			       const Real threshold) const
{
  libmesh_assert (this->initialized());
  libmesh_assert (other_vector.initialized());
  libmesh_assert (this->first_local_index() == other_vector.first_local_index());
  libmesh_assert (this->last_local_index()  == other_vector.last_local_index());

  int first_different_i = std::numeric_limits<int>::max();
  unsigned int i = first_local_index();

  do
    {
      if ( std::abs( (*this)(i) - other_vector(i) ) > threshold )
	first_different_i = i;
      else
	i++;
    }
  while (first_different_i==std::numeric_limits<int>::max()
         && i<last_local_index());

  // Find the correct first differing index in parallel
  Parallel::min(first_different_i);

  if (first_different_i == std::numeric_limits<int>::max())
    return -1;

  return first_different_i;
}

template <typename T>
int NumericVector<T>::local_relative_compare (const NumericVector<T> &other_vector,
			                      const Real threshold) const
{
  libmesh_assert (this->initialized());
  libmesh_assert (other_vector.initialized());
  libmesh_assert (this->first_local_index() == other_vector.first_local_index());
  libmesh_assert (this->last_local_index()  == other_vector.last_local_index());

  int first_different_i = std::numeric_limits<int>::max();
  unsigned int i = first_local_index();

  do
    {
      if ( std::abs( (*this)(i) - other_vector(i) ) > threshold *
           std::max(std::abs((*this)(i)), std::abs(other_vector(i))))
	first_different_i = i;
      else
	i++;
    }
  while (first_different_i==std::numeric_limits<int>::max()
         && i<last_local_index());

  // Find the correct first differing index in parallel
  Parallel::min(first_different_i);

  if (first_different_i == std::numeric_limits<int>::max())
    return -1;

  return first_different_i;
}

template <typename T>
int NumericVector<T>::global_relative_compare (const NumericVector<T> &other_vector,
			                       const Real threshold) const
{
  libmesh_assert (this->initialized());
  libmesh_assert (other_vector.initialized());
  libmesh_assert (this->first_local_index() == other_vector.first_local_index());
  libmesh_assert (this->last_local_index()  == other_vector.last_local_index());

  int first_different_i = std::numeric_limits<int>::max();
  unsigned int i = first_local_index();

  const Real my_norm = this->linfty_norm();
  const Real other_norm = other_vector.linfty_norm();
  const Real abs_threshold = std::max(my_norm, other_norm) * threshold;

  do
    {
      if ( std::abs( (*this)(i) - other_vector(i) ) > abs_threshold )
	first_different_i = i;
      else
	i++;
    }
  while (first_different_i==std::numeric_limits<int>::max()
         && i<last_local_index());

  // Find the correct first differing index in parallel
  Parallel::min(first_different_i);

  if (first_different_i == std::numeric_limits<int>::max())
    return -1;

  return first_different_i;
}

/*
// Full specialization for float datatypes (DistributedVector wants this)

template <>
int NumericVector<float>::compare (const NumericVector<float> &other_vector,
				   const Real threshold) const
{
  libmesh_assert (this->initialized());
  libmesh_assert (other_vector.initialized());
  libmesh_assert (this->first_local_index() == other_vector.first_local_index());
  libmesh_assert (this->last_local_index()  == other_vector.last_local_index());

  int rvalue     = -1;
  unsigned int i = first_local_index();

  do
    {
      if ( std::abs( (*this)(i) - other_vector(i) ) > threshold )
	rvalue = i;
      else
	i++;
    }
  while (rvalue==-1 && i<last_local_index());

  return rvalue;
}

// Full specialization for double datatypes
template <>
int NumericVector<double>::compare (const NumericVector<double> &other_vector,
				    const Real threshold) const
{
  libmesh_assert (this->initialized());
  libmesh_assert (other_vector.initialized());
  libmesh_assert (this->first_local_index() == other_vector.first_local_index());
  libmesh_assert (this->last_local_index()  == other_vector.last_local_index());

  int rvalue     = -1;
  unsigned int i = first_local_index();

  do
    {
      if ( std::abs( (*this)(i) - other_vector(i) ) > threshold )
	rvalue = i;
      else
	i++;
    }
  while (rvalue==-1 && i<last_local_index());

  return rvalue;
}

#ifdef TRIPLE_PRECISION
// Full specialization for long double datatypes
template <>
int NumericVector<long double>::compare (const NumericVector<long double> &other_vector,
				         const Real threshold) const
{
  libmesh_assert (this->initialized());
  libmesh_assert (other_vector.initialized());
  libmesh_assert (this->first_local_index() == other_vector.first_local_index());
  libmesh_assert (this->last_local_index()  == other_vector.last_local_index());

  int rvalue     = -1;
  unsigned int i = first_local_index();

  do
    {
      if ( std::abs( (*this)(i) - other_vector(i) ) > threshold )
	rvalue = i;
      else
	i++;
    }
  while (rvalue==-1 && i<last_local_index());

  return rvalue;
}
#endif

// Full specialization for Complex datatypes
template <>
int NumericVector<Complex>::compare (const NumericVector<Complex> &other_vector,
				     const Real threshold) const
{
  libmesh_assert (this->initialized());
  libmesh_assert (other_vector.initialized());
  libmesh_assert (this->first_local_index() == other_vector.first_local_index());
  libmesh_assert (this->last_local_index()  == other_vector.last_local_index());

  int rvalue     = -1;
  unsigned int i = first_local_index();

  do
    {
      if (( std::abs( (*this)(i).real() - other_vector(i).real() ) > threshold ) ||
	  ( std::abs( (*this)(i).imag() - other_vector(i).imag() ) > threshold ))
	rvalue = i;
      else
	i++;
    }
  while (rvalue==-1 && i<this->last_local_index());

  return rvalue;
}
*/

template <class T>
Real NumericVector<T>::subset_l1_norm (const std::set<unsigned int> & indices) const
{
  const NumericVector<T> & v = *this;

  std::set<unsigned int>::const_iterator it = indices.begin();
  const std::set<unsigned int>::const_iterator it_end = indices.end();

  Real norm = 0;

  for(; it!=it_end; ++it)
    norm += std::abs(v(*it));

  Parallel::sum(norm);

  return norm;
}

template <class T>
Real NumericVector<T>::subset_l2_norm (const std::set<unsigned int> & indices) const
{
  const NumericVector<T> & v = *this;

  std::set<unsigned int>::const_iterator it = indices.begin();
  const std::set<unsigned int>::const_iterator it_end = indices.end();

  Real norm = 0;

  for(; it!=it_end; ++it)
    norm += libmesh_norm(v(*it));

  Parallel::sum(norm);

  return std::sqrt(norm);
}

template <class T>
Real NumericVector<T>::subset_linfty_norm (const std::set<unsigned int> & indices) const
{
  const NumericVector<T> & v = *this;

  std::set<unsigned int>::const_iterator it = indices.begin();
  const std::set<unsigned int>::const_iterator it_end = indices.end();

  Real norm = 0;

  for(; it!=it_end; ++it)
    {
      Real value = std::abs(v(*it));
      if(value > norm)
        norm = value;
    }

  Parallel::max(norm);

  return norm;
}

template <typename T>
void NumericVector<T>::add_vector (const NumericVector<T>& v,
				   const ShellMatrix<T>& a)
{
  a.vector_mult_add(*this,v);
}

//------------------------------------------------------------------
// Explicit instantiations
template class NumericVector<Number>;

} // namespace libMesh
<|endoftext|>


<commit_before>//=======================================================================
// Copyright (c) 2014 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#include <iostream>
#include <memory>

#include "dbn/dbn.hpp"
#include "dbn/layer.hpp"
#include "dbn/conf.hpp"
#include "dbn/labels.hpp"
#include "dbn/test.hpp"

#include "mnist/mnist_reader.hpp"

namespace {

template<typename Container>
void binarize_each(Container& values){
    for(auto& vec : values){
        for(auto& v : vec){
            v = v > 10.0 ? 1.0 : 0.0;
        }
    }
}

template<typename DBN, typename P>
void test_all(DBN& dbn, std::vector<vector<double>>& training_images, const std::vector<uint8_t>& training_labels, P&& predictor){
    auto test_images = mnist::read_test_images<std::vector, vector, double>();
    auto test_labels = mnist::read_test_labels<std::vector>();

    if(test_images.empty() || test_labels.empty()){
        std::cout << "Impossible to read test set" << std::endl;
        return;
    }

    std::cout << "Start testing" << std::endl;

    std::cout << "Training Set" << std::endl;
    auto error_rate = dbn::test_set(dbn, training_images, training_labels, predictor);
    std::cout << "\tError rate (normal): " << 100.0 * error_rate << std::endl;

    std::cout << "Test Set" << std::endl;
    error_rate =  dbn::test_set(dbn, test_images, test_labels, predictor);
    std::cout << "\tError rate (normal): " << 100.0 * error_rate << std::endl;
}

} //end of anonymous namespace

int main(int argc, char* argv[]){
    auto simple = false;
    auto load = false;

    for(int i = 1; i < argc; ++i){
        std::string command(argv[i]);

        if(command == "simple"){
            simple = true;
        }

        if(command == "load"){
            load = true;
        }
    }

    auto training_images = mnist::read_training_images<std::vector, vector, double>();
    auto training_labels = mnist::read_training_labels<std::vector>();

    if(training_images.empty() || training_labels.empty()){
        return 1;
    }

    binarize_each(training_images);

    if(simple){
        typedef dbn::dbn<
            dbn::layer<dbn::conf<true, 50, true>, 28 * 28, 50>,
            dbn::layer<dbn::conf<true, 50, false>, 50, 50>,
            dbn::layer<dbn::conf<true, 50, false>, 60, 100>> dbn_simple_t;

        auto dbn = std::make_shared<dbn_simple_t>();

        dbn->train_with_labels(training_images, training_labels, 10, 5);

        test_all(dbn, training_images, training_labels, dbn::label_predictor());
    } else {
        typedef dbn::dbn<
            dbn::layer<dbn::conf<true, 100, true, true>, 28 * 28, 30>,
            //dbn::layer<dbn::conf<true, 100, false, true>, 300, 300>,
            dbn::layer<dbn::conf<true, 100, false, true>, 30, 30>,
            dbn::layer<dbn::conf<true, 100, false, true, true, dbn::Type::SIGMOID, dbn::Type::EXP>, 30, 10>> dbn_t;

        auto labels = dbn::make_fake(training_labels);

        auto dbn = make_unique<dbn_t>();

        dbn->display();

        if(load){
            std::cout << "Load from file" << std::endl;

            std::ifstream is("dbn.dat", std::ifstream::binary);
            dbn->load(is);
        } else {
            std::cout << "Start pretraining" << std::endl;
            dbn->pretrain(training_images, 5);

            std::cout << "Start fine-tuning" << std::endl;
            dbn->fine_tune(training_images, labels, 5, 1000);

            std::ofstream os("dbn.dat", std::ofstream::binary);
            dbn->store(os);
        }

        test_all(dbn, training_images, training_labels, dbn::predictor());
    }

    return 0;
}
<commit_msg>Tests<commit_after>//=======================================================================
// Copyright (c) 2014 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#include <iostream>
#include <memory>

#include "dbn/dbn.hpp"
#include "dbn/layer.hpp"
#include "dbn/conf.hpp"
#include "dbn/labels.hpp"
#include "dbn/test.hpp"

#include "mnist/mnist_reader.hpp"

namespace {

template<typename Container>
void binarize_each(Container& values){
    for(auto& vec : values){
        for(auto& v : vec){
            v = v > 10.0 ? 1.0 : 0.0;
        }
    }
}

template<typename DBN, typename P>
void test_all(DBN& dbn, std::vector<vector<double>>& training_images, const std::vector<uint8_t>& training_labels, P&& predictor){
    auto test_images = mnist::read_test_images<std::vector, vector, double>();
    auto test_labels = mnist::read_test_labels<std::vector>();

    if(test_images.empty() || test_labels.empty()){
        std::cout << "Impossible to read test set" << std::endl;
        return;
    }

    std::cout << "Start testing" << std::endl;

    std::cout << "Training Set" << std::endl;
    auto error_rate = dbn::test_set(dbn, training_images, training_labels, predictor);
    std::cout << "\tError rate (normal): " << 100.0 * error_rate << std::endl;

    std::cout << "Test Set" << std::endl;
    error_rate =  dbn::test_set(dbn, test_images, test_labels, predictor);
    std::cout << "\tError rate (normal): " << 100.0 * error_rate << std::endl;
}

} //end of anonymous namespace

int main(int argc, char* argv[]){
    auto simple = false;
    auto load = false;

    for(int i = 1; i < argc; ++i){
        std::string command(argv[i]);

        if(command == "simple"){
            simple = true;
        }

        if(command == "load"){
            load = true;
        }
    }

    auto training_images = mnist::read_training_images<std::vector, vector, double>();
    auto training_labels = mnist::read_training_labels<std::vector>();

    if(training_images.empty() || training_labels.empty()){
        return 1;
    }

    binarize_each(training_images);

    if(simple){
        typedef dbn::dbn<
            dbn::layer<dbn::conf<true, 50, true>, 28 * 28, 100>,
            dbn::layer<dbn::conf<true, 50, false>, 100, 100>,
            dbn::layer<dbn::conf<true, 50, false>, 110, 200>> dbn_simple_t;

        auto dbn = std::make_shared<dbn_simple_t>();

        dbn->train_with_labels(training_images, training_labels, 10, 5);

        test_all(dbn, training_images, training_labels, dbn::label_predictor());
    } else {
        typedef dbn::dbn<
            dbn::layer<dbn::conf<true, 100, true, true>, 28 * 28, 30>,
            //dbn::layer<dbn::conf<true, 100, false, true>, 300, 300>,
            dbn::layer<dbn::conf<true, 100, false, true>, 30, 30>,
            dbn::layer<dbn::conf<true, 100, false, true, true, dbn::Type::SIGMOID, dbn::Type::EXP>, 30, 10>> dbn_t;

        auto labels = dbn::make_fake(training_labels);

        auto dbn = make_unique<dbn_t>();

        dbn->display();

        if(load){
            std::cout << "Load from file" << std::endl;

            std::ifstream is("dbn.dat", std::ifstream::binary);
            dbn->load(is);
        } else {
            std::cout << "Start pretraining" << std::endl;
            dbn->pretrain(training_images, 5);

            std::cout << "Start fine-tuning" << std::endl;
            dbn->fine_tune(training_images, labels, 5, 1000);

            std::ofstream os("dbn.dat", std::ofstream::binary);
            dbn->store(os);
        }

        test_all(dbn, training_images, training_labels, dbn::predictor());
    }

    return 0;
}
<|endoftext|>


<commit_before><commit_msg>Small changes to demo<commit_after><|endoftext|>


<commit_before>//functor_overload header
//Copyright (c) 2014 mmYYmmdd

#if !defined MMYYMMDD_FUNCTOR_OVERLOAD_INCLUDED
#define MMYYMMDD_FUNCTOR_OVERLOAD_INCLUDED

#include <type_traits>

namespace mymd {
	namespace detail_fo	{

		template <typename>
		struct noCondition	{
			static constexpr bool value = true;
		};

		template <template <typename> class C = noCondition, bool B = true>
		struct cond	{ };
		//-----------------------------------------------------
		template <typename...>
		struct types  { };

		template <typename T, typename>
		struct arg  {
			using apply = std::enable_if<true, T>;
		};

		template <template <typename> class C, bool B, typename V>
		struct arg<cond<C, B>, V>  {
			using apply = std::enable_if<B == C<V>::value, V>;
		};
		//-----------------------------------------------------
		struct no_action	{
			constexpr no_action() { }
			template <typename... V>
			void operator ()(V&&...) const {}
		};
		//-----------------------------------------------------
		template <typename F, typename... A>
		class bolt  {
			F fn;
			template <typename T, typename U>	//workaround for VC
			using apply = typename arg<T, U>::apply;
		protected:
			template <typename... V>
			auto invoke(types<V...>, typename arg<A, V>::apply::type&&... a) const
				->decltype(fn(std::declval<typename apply<A, V>::type>()...))
			{  return fn(std::forward<typename apply<A, V>::type>(a) ...);  }
		public:
			constexpr bolt(const F& f) : fn(f)  {  }
		};
		//----------------------------------------------

	}	//namespace detail_fo

	//user interfaces are ,
	//  mymd::gen< >( )  ,  mymd::cond< >  ,  operator +

	using detail_fo::cond;

	template <typename T1, typename T2>
	struct bolts : private T1, private T2  {
        using T1::operator ();
        using T2::operator ();
		constexpr bolts(const T1& t1, const T2& t2) : T1(t1), T2(t2) { }
	};

	template <typename F, typename... A>
	struct bolts<detail_fo::bolt<F, A...>, void> : private detail_fo::bolt<F, A...>  {
        protected: using detail_fo::bolt<F, A...>::invoke;
    public:
		constexpr bolts(const detail_fo::bolt<F, A...>& t) : detail_fo::bolt<F, A...>(t) { }
		template <typename... V>
		auto operator()(V&&... v) const->decltype(invoke(detail_fo::types<V...>{}, std::declval<V>()...))
		{  return invoke(detail_fo::types<V...>{}, std::forward<V>(v)...);  }
	};

	template <typename T1, typename T2, typename U1, typename U2>
	auto operator +(bolts<T1, T2> const& b, bolts<U1, U2> const& c)
		->bolts<bolts<T1, T2>, bolts<U1, U2>>
	{
		return bolts<bolts<T1, T2>, bolts<U1, U2>>(b, c);
	}

	template <typename... A, typename F>
	auto gen(const F& f) ->bolts<detail_fo::bolt<F, A...>, void>
	{
		return bolts<detail_fo::bolt<F, A...>, void>(detail_fo::bolt<F, A...>(f));
	}

	//no action
	template <typename... A>
	auto gen() ->bolts<detail_fo::bolt<detail_fo::no_action, A...>, void>
	{
		return bolts<detail_fo::bolt<detail_fo::no_action, A...>, void>
			(detail_fo::bolt<detail_fo::no_action, A...>(detail_fo::no_action{}));
	}

	//----------------------------------
	//template <typename T>
	//using is_xxx = mymd::is_some_rr<std::is_yyyy, std::is_zzzz>::apply<T>;
	//using is_xxx = mymd::is_every_rr<std::is_yyyy, std::is_zzzz>::apply<T>;

	template <template <typename> class first, template <typename> class... tail>
	struct is_some_rr	{
		template <typename T>
		struct apply	{
			using T2 = typename std::remove_reference<T>::type;
			static constexpr bool value = first<T2>::value || is_some_rr<tail...>::template apply<T>::value;
		};
	};

	template <template <typename> class first>
	struct is_some_rr<first>	{
		template <typename T>
		struct apply	{
			using T2 = typename std::remove_reference<T>::type;
			static constexpr bool value = first<T2>::value;
		};
	};

	template <template <typename> class first, template <typename> class... tail>
	struct is_every_rr	{
		template <typename T>
		struct apply	{
			using T2 = typename std::remove_reference<T>::type;
			static constexpr bool value = first<T2>::value && is_every_rr<tail...>::template apply<T>::value;
		};
	};

	template <template <typename> class first>
	struct is_every_rr<first>	{
		template <typename T>
		struct apply	{
			using T2 = typename std::remove_reference<T>::type;
			static constexpr bool value = first<T2>::value;
		};
	};
}

#endif
<commit_msg>型名 gen_t と plus_t を追加<commit_after>//functor_overload header
//Copyright (c) 2014 mmYYmmdd

#if !defined MMYYMMDD_FUNCTOR_OVERLOAD_INCLUDED
#define MMYYMMDD_FUNCTOR_OVERLOAD_INCLUDED

#include <type_traits>

namespace mymd {
	namespace detail_fo	{

		template <typename>
		struct noCondition	{
			static constexpr bool value = true;
		};

		template <template <typename> class C = noCondition, bool B = true>
		struct cond	{ };
		//-----------------------------------------------------
		template <typename...>
		struct types  { };

		template <typename...>	struct reverse_imple;

		template <typename... result, typename first, typename... tail>
		struct reverse_imple<types<result...>, first, tail...> : reverse_imple<types<first, result...>, tail...>
		{	};

		template <typename... result>
		struct reverse_imple<types<result...>>		{
			using type = types<result...>;
		};

		template <typename... T>
		using reverse = typename reverse_imple<types<>, T...>::type;
		//-----------------------------------------------------
		template <typename T, typename>
		struct arg  {
			using apply = std::enable_if<true, T>;
		};

		template <template <typename> class C, bool B, typename V>
		struct arg<cond<C, B>, V>  {
			using apply = std::enable_if<B == C<V>::value, V>;
		};
		//-----------------------------------------------------
		struct no_action	{
			constexpr no_action() { }
			template <typename... V>
			void operator ()(V&&...) const {}
		};
		//-----------------------------------------------------
		template <typename F, typename... A>
		class bolt  {
			F fn;
			template <typename T, typename U>	//workaround for VC
			using apply = typename arg<T, U>::apply;
		protected:
			template <typename... V>
			auto invoke(types<V...>, typename arg<A, V>::apply::type&&... a) const
				->decltype(fn(std::declval<typename apply<A, V>::type>()...))
			{  return fn(std::forward<typename apply<A, V>::type>(a) ...);  }
		public:
			constexpr bolt(const F& f) : fn(f)  {  }
		};
		//----------------------------------------------

		template <typename T1, typename T2>
		struct bolts : private T1, private T2  {
			using T1::operator ();
			using T2::operator ();
			constexpr bolts(const T1& t1, const T2& t2) : T1(t1), T2(t2) { }
		};

		template <typename F, typename... A>
		struct bolts<bolt<F, A...>, void> : private bolt<F, A...>  {
			protected: using bolt<F, A...>::invoke;
		public:
			constexpr bolts(const F& t) : bolt<F, A...>(t) { }
			template <typename... V>
			auto operator()(V&&... v) const->decltype(invoke(types<V...>{}, std::declval<V>()...))
			{  return invoke(types<V...>{}, std::forward<V>(v)...);  }
		};

		template <typename T1, typename T2, typename U1, typename U2>
		auto operator +(bolts<T1, T2> const& b, bolts<U1, U2> const& c)
			->bolts<bolts<T1, T2>, bolts<U1, U2>>
		{
			return bolts<bolts<T1, T2>, bolts<U1, U2>>(b, c);
		}

		template <typename F, typename... A>
		using gen_t = bolts<bolt<typename std::conditional<std::is_same<F, void>::value, no_action, F>::type, A...>, void>;

		template <typename>	struct plus_t_imple;

		template <typename first, typename... tail>
		struct plus_t_imple<types<first, tail...>>	{
			using type = decltype(std::declval<typename plus_t_imple<types<tail...>>::type>() + std::declval<first>());
		};

		template <typename first>
		struct plus_t_imple<types<first>>	{
			using type = first;
		};

		template <typename... T>
		using plus_t = typename plus_t_imple<reverse<T...>>::type;

	}	//namespace detail_fo

	//********************************************************************
	//  user interfaces are ,
	//  mymd::gen< >( )  ,  mymd::cond< >  ,  operator +
	//********************************************************************
	using detail_fo::cond;		//  condition for type
	using detail_fo::bolts;		//  functor type
	using detail_fo::gen_t;		//  functor type generated by 'gen'
	using detail_fo::plus_t;	//  functor type generated by operator +

	template <typename... A, typename F>
	auto gen(const F& f) ->gen_t<F, A...>
	{
		return gen_t<F, A...>(f);
	}

	//no action
	template <typename... A>
	auto gen() ->gen_t<void, A...>
	{
		return gen_t<void, A...>(detail_fo::no_action{});
	}

	//----------------------------------
	//template <typename T>
	//using is_xxx = mymd::is_some_rr<std::is_yyyy, std::is_zzzz>::apply<T>;
	//using is_xxx = mymd::is_every_rr<std::is_yyyy, std::is_zzzz>::apply<T>;

	template <template <typename> class first, template <typename> class... tail>
	struct is_some_rr	{
		template <typename T>
		struct apply	{
			using T2 = typename std::remove_reference<T>::type;
			static constexpr bool value = first<T2>::value || is_some_rr<tail...>::template apply<T>::value;
		};
	};

	template <template <typename> class first>
	struct is_some_rr<first>	{
		template <typename T>
		struct apply	{
			using T2 = typename std::remove_reference<T>::type;
			static constexpr bool value = first<T2>::value;
		};
	};

	template <template <typename> class first, template <typename> class... tail>
	struct is_every_rr	{
		template <typename T>
		struct apply	{
			using T2 = typename std::remove_reference<T>::type;
			static constexpr bool value = first<T2>::value && is_every_rr<tail...>::template apply<T>::value;
		};
	};

	template <template <typename> class first>
	struct is_every_rr<first>	{
		template <typename T>
		struct apply	{
			using T2 = typename std::remove_reference<T>::type;
			static constexpr bool value = first<T2>::value;
		};
	};
}

#endif
<|endoftext|>


<commit_before>// demo.cpp : ̨Ӧóڵ㡣
//

#include "stdafx.h"

/*void callback_connection(const boost::system::error_code& err, client::CMessage::Ptr msg)
{
	if (!err)
		std::cout << "something is work fine" << err.value() << std::endl;
}

int _tmain(int argc, _TCHAR* argv[])
{
	try
	{
		std::cout << "Hello World" << std::endl;

		std::string host = "localhost";
        std::string port = "11211";

		boost::asio::io_service io_service;

		boost::shared_ptr<client::CConnection> connection(new client::CConnection(io_service));

		connection->Connect(host, port, boost::bind(&callback_connection, _1, _2));

		boost::shared_ptr<boost::thread> thread(new boost::thread(boost::bind(&boost::asio::io_service::run, &io_service)));

		thread->join();
	}
	catch (...)
	{
	}

	return EXIT_SUCCESS;
}*/
int times = 0;
client::CClient cli;

void OnSendComplete(const boost::system::error_code &err, client::CMessage::Ptr msg)
{
	std::cout << "ErrorCode" << err.value() << std::endl;
	if (err.value() == boost::asio::error::not_connected)
	{
		cli.Reset();
		return;
	}
	std::cout << "OnSendComplete" << std::endl;
	std::cout << "OnSendComplete times \"" << times++ << "\"" <<std::endl;
}

void OnReceive(const boost::system::error_code &err, client::StatusCode sc, client::CMessage::Ptr msg)
{
	std::cout << "the error code is " << err.value() << std::endl;
	std::cout << "the times is \"" << times++ << "\"" << std::endl;

	if (!err && sc == client::SC_ReadBody/*&& msg->body()[0]*/)
	{
		boost::shared_ptr<client::CMessage> request(new client::CMessage());
		char str[client::CMessage::max_body_length];

		msg->ReadBegin();
		strncpy(str, msg->ReadString(), sizeof(str));
		std::cout << "string: "<< str << std::endl;
		char b = msg->ReadByte();
		bool result = (b != -1) ? b : false;
		std::cout << "bool:"<< result << std::endl;
		int l = msg->ReadLong();
		std::cout << "long:" << l << std::endl;
		float f = msg->ReadFloat();
		std::cout << "float:" << f << std::endl;
		msg->ReadEnd();

		request->WriteBegin();
		request->WriteString(str);
		request->WriteByte(result);
		request->WriteLong(l);
		request->WriteEnd();
		cli.PostSend(request, boost::bind(&OnSendComplete, _1, _2));
	}
}

int _tmain(int argc, _TCHAR* argv[])
{
	try
	{
		printf ( "Hello, Boost !!!\n" );

		std::string host = "localhost";
		std::string port = "60000";

		cli.Init( host, port, boost::bind(&OnReceive, _1, _2, _3), 1, 4);

		while (true)
		{
			getchar();
			char line[8] = "demo";

			boost::shared_ptr<client::CMessage> msg(new client::CMessage());

			msg->WriteBegin();
			msg->WriteString(line);
			msg->WriteByte(true);
			msg->WriteLong(10);
			msg->WriteFloat(12.0);
			msg->WriteString(line);
			msg->WriteEnd();

			cli.PostSend(msg, boost::bind(&OnSendComplete, _1, _2));
			Sleep( 10 );
		}

	}
	catch ( std::exception& e )
	{
		std::cout << "Exception :" << e.what() << std::endl;
	}
	return EXIT_SUCCESS;
}<commit_msg>update demo<commit_after>// demo.cpp : ̨Ӧóڵ㡣
//

#include "stdafx.h"

/*void callback_connection(const boost::system::error_code& err, client::CMessage::Ptr msg)
{
	if (!err)
		std::cout << "something is work fine" << err.value() << std::endl;
}

int _tmain(int argc, _TCHAR* argv[])
{
	try
	{
		std::cout << "Hello World" << std::endl;

		std::string host = "localhost";
        std::string port = "11211";

		boost::asio::io_service io_service;

		boost::shared_ptr<client::CConnection> connection(new client::CConnection(io_service));

		connection->Connect(host, port, boost::bind(&callback_connection, _1, _2));

		boost::shared_ptr<boost::thread> thread(new boost::thread(boost::bind(&boost::asio::io_service::run, &io_service)));

		thread->join();
	}
	catch (...)
	{
	}

	return EXIT_SUCCESS;
}*/
int times = 0;
client::CClient cli;

void OnSendComplete(const boost::system::error_code &err, client::CMessage::Ptr msg)
{
	std::cout << "ErrorCode" << err.value() << std::endl;
	if (err.value() == boost::asio::error::not_connected)
	{
		cli.Reset();
		return;
	}
	std::cout << "OnSendComplete" << std::endl;
	std::cout << "OnSendComplete times \"" << times++ << "\"" <<std::endl;
}

void OnReceive(const boost::system::error_code &err, client::StatusCode sc, client::CMessage::Ptr msg)
{
	std::cout << "the error code is " << err.value() << std::endl;
	std::cout << "the times is \"" << times++ << "\"" << std::endl;

	if (!err && sc == client::SC_ReadBody/*&& msg->body()[0]*/)
	{
		boost::shared_ptr<client::CMessage> request(new client::CMessage());
		char str[client::CMessage::max_body_length];

		msg->ReadBegin();
		strncpy(str, msg->ReadString(), sizeof(str));
		std::cout << "string: "<< str << std::endl;
		char b = msg->ReadByte();
		bool result = (b != -1) ? b : false;
		std::cout << "bool:"<< result << std::endl;
		int l = msg->ReadLong();
		std::cout << "long:" << l << std::endl;
		float f = msg->ReadFloat();
		std::cout << "float:" << f << std::endl;
		msg->ReadEnd();

		request->WriteBegin();
		request->WriteString(str);
		request->WriteByte(result);
		request->WriteLong(l);
		request->WriteFloat(f);
		request->WriteString(str);
		request->WriteEnd();
		cli.PostSend(request, boost::bind(&OnSendComplete, _1, _2));
	}
}

int _tmain(int argc, _TCHAR* argv[])
{
	try
	{
		printf ( "Hello, Boost !!!\n" );

		std::string host = "192.168.199.125";
		std::string port = "81";

		cli.Init( host, port, boost::bind(&OnReceive, _1, _2, _3), 1, 1);

		while (true)
		{
			getchar();
			char line[8] = "demo";

			boost::shared_ptr<client::CMessage> msg(new client::CMessage());

			msg->WriteBegin();
			msg->WriteString(line);
			msg->WriteByte(true);
			msg->WriteLong(10);
			msg->WriteFloat(12.0);
			msg->WriteString(line);
			msg->WriteEnd();

			cli.PostSend(msg, boost::bind(&OnSendComplete, _1, _2));
			Sleep( 10 );
		}

	}
	catch ( std::exception& e )
	{
		std::cout << "Exception :" << e.what() << std::endl;
	}
	return EXIT_SUCCESS;
}<|endoftext|>


<commit_before>/*____________________________________________________________________________

  MusicBrainz -- The Internet music metadatabase

  Portions Copyright (C) 2000 Relatable

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

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

   You should have received a copy of the GNU Lesser General Public
   License along with this library; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

  $Id$
____________________________________________________________________________*/

/***************************************************************************
sigclient.cpp  -  description
-------------------
copyright            : (C) 2000 by Relatable
written by           : Isaac Richards
email                : ijr@relatable.com
***************************************************************************/

#ifdef WIN32
#pragma warning(disable:4786)
#endif

#include "sigclient.h"
#include "comhttpsocket.h"

#include "sigxdr.h"

namespace SigClientVars
{
    static const char cGetGUID = 'N';
    static const char cDisconnect = 'E';

    static const int nGUIDSize = 16;
    static const int nTimeout = 15;
    static const int nVersion = 1;
    static const int nHeaderSize = sizeof(char) + sizeof(int);
}

using namespace std;

SigClient::SigClient()
{
    m_pSocket = new MBCOMHTTPSocket;
    m_nNumFailures = 0;
}

SigClient::~SigClient()
{
    if (m_pSocket->IsConnected())
        this->Disconnect();
    if (m_pSocket != NULL)
        delete m_pSocket;
}

int SigClient::GetSignature(AudioSig *sig, string &strGUID,
                            string strCollectionID)
{
    int nConRes = this->Connect(m_strIP, m_nPort);
    if (nConRes != 0)
        return -1;

    SigXDR converter;

    int nOffSet = sizeof(char) + sizeof(int);
    int nGUIDLen = strCollectionID.size() * sizeof(char) + sizeof(char);
    int iSigEncodeSize = sizeof(int) + 35 * sizeof(int32) + nGUIDLen;
    int nTotalSize = nOffSet + iSigEncodeSize;

    char* pBuffer = new char[nTotalSize + 1];
    memset(pBuffer, 0, nTotalSize);
    memcpy(&pBuffer[0], &SigClientVars::cGetGUID, sizeof(char));
    memcpy(&pBuffer[1], &iSigEncodeSize, sizeof(int));

    memcpy(&pBuffer[nOffSet], &SigClientVars::nVersion, sizeof(int));
    nOffSet += sizeof(int);

    iSigEncodeSize -= (nGUIDLen + sizeof(int));

    char *sigencode = converter.FromSig(sig);
    memcpy(&pBuffer[nOffSet], sigencode, iSigEncodeSize);

    memcpy(&pBuffer[nOffSet + iSigEncodeSize], strCollectionID.c_str(),
           nGUIDLen - sizeof(char));
    pBuffer[nOffSet + iSigEncodeSize + nGUIDLen - sizeof(char)] = '\0';

    int nBytes = 0;
    int ret = m_pSocket->Write(pBuffer, nTotalSize, &nBytes);

    memset(pBuffer, 0, nTotalSize);
    int iGUIDSize = 16 * sizeof(int32);

    ret = m_pSocket->NBRead(pBuffer, iGUIDSize, &nBytes,
                            SigClientVars::nTimeout);

    if ((ret != -1) && (nBytes == iGUIDSize)) {
        ret = 0;
        strGUID = converter.ToStrGUID(pBuffer, nBytes);
    }
    else {
	ret = -1;
        strGUID = "";
    }
    this->Disconnect();

    delete [] pBuffer;
    delete [] sigencode;

    return ret;
}

int SigClient::Connect(string& strIP, int nPort)
{
    if (m_nNumFailures > 5)
        return -1;  // server probably down.

    if (m_proxyAddr.empty())
        m_pSocket->SetProxy(NULL);
    else {
        char *proxyurl = new char[m_proxyAddr.size() + 128];
        sprintf(proxyurl, "http://%s:%d", m_proxyAddr.c_str(), m_proxyPort);
        m_pSocket->SetProxy(proxyurl);
        delete [] proxyurl;
    }

    char *url = new char[strIP.size() + 128]; // ample space..
    sprintf(url, "http://%s/cgi-bin/gateway/gateway?%d", strIP.c_str(), nPort);
    //sprintf(url, "http://209.249.187.200/cgi-bin/gateway?%d", nPort);
    int nErr = m_pSocket->Connect(url);

    delete [] url;

    if (nErr == -1)
    {
        m_nNumFailures++;
        return -1;
    }
    m_nNumFailures = 0;
    return 0;
}

int SigClient::Disconnect()
{
    if (m_pSocket->IsConnected())
    {
        char cBuffer[sizeof(char) + sizeof(int)];
        memset(cBuffer, 0, sizeof(char) + sizeof(int));
        cBuffer[0] = SigClientVars::cDisconnect;

        int nBytes = 0;
        m_pSocket->Write(cBuffer, sizeof(char) + sizeof(int),
                         &nBytes);
        m_pSocket->Disconnect();
    }

    return 0;
}
<commit_msg>- fix the proxy stuff<commit_after>/*____________________________________________________________________________

  MusicBrainz -- The Internet music metadatabase

  Portions Copyright (C) 2000 Relatable

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

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

   You should have received a copy of the GNU Lesser General Public
   License along with this library; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

  $Id$
____________________________________________________________________________*/

/***************************************************************************
sigclient.cpp  -  description
-------------------
copyright            : (C) 2000 by Relatable
written by           : Isaac Richards
email                : ijr@relatable.com
***************************************************************************/

#ifdef WIN32
#pragma warning(disable:4786)
#endif

#include "sigclient.h"
#include "comhttpsocket.h"

#include "sigxdr.h"

namespace SigClientVars
{
    static const char cGetGUID = 'N';
    static const char cDisconnect = 'E';

    static const int nGUIDSize = 16;
    static const int nTimeout = 15;
    static const int nVersion = 1;
    static const int nHeaderSize = sizeof(char) + sizeof(int);
}

using namespace std;

SigClient::SigClient()
{
    m_pSocket = new MBCOMHTTPSocket;
    m_nNumFailures = 0;
}

SigClient::~SigClient()
{
    if (m_pSocket->IsConnected())
        this->Disconnect();
    if (m_pSocket != NULL)
        delete m_pSocket;
}

int SigClient::GetSignature(AudioSig *sig, string &strGUID,
                            string strCollectionID)
{
    int nConRes = this->Connect(m_strIP, m_nPort);
    if (nConRes != 0)
        return -1;

    SigXDR converter;

    int nOffSet = sizeof(char) + sizeof(int);
    int nGUIDLen = strCollectionID.size() * sizeof(char) + sizeof(char);
    int iSigEncodeSize = sizeof(int) + 35 * sizeof(int32) + nGUIDLen;
    int nTotalSize = nOffSet + iSigEncodeSize;

    char* pBuffer = new char[nTotalSize + 1];
    memset(pBuffer, 0, nTotalSize);
    memcpy(&pBuffer[0], &SigClientVars::cGetGUID, sizeof(char));
    memcpy(&pBuffer[1], &iSigEncodeSize, sizeof(int));

    memcpy(&pBuffer[nOffSet], &SigClientVars::nVersion, sizeof(int));
    nOffSet += sizeof(int);

    iSigEncodeSize -= (nGUIDLen + sizeof(int));

    char *sigencode = converter.FromSig(sig);
    memcpy(&pBuffer[nOffSet], sigencode, iSigEncodeSize);

    memcpy(&pBuffer[nOffSet + iSigEncodeSize], strCollectionID.c_str(),
           nGUIDLen - sizeof(char));
    pBuffer[nOffSet + iSigEncodeSize + nGUIDLen - sizeof(char)] = '\0';

    int nBytes = 0;
    int ret = m_pSocket->Write(pBuffer, nTotalSize, &nBytes);

    memset(pBuffer, 0, nTotalSize);
    int iGUIDSize = 16 * sizeof(int32);

    ret = m_pSocket->NBRead(pBuffer, iGUIDSize, &nBytes,
                            SigClientVars::nTimeout);

    if ((ret != -1) && (nBytes == iGUIDSize)) {
        ret = 0;
        strGUID = converter.ToStrGUID(pBuffer, nBytes);
    }
    else {
	ret = -1;
        strGUID = "";
    }
    this->Disconnect();

    delete [] pBuffer;
    delete [] sigencode;

    return ret;
}

int SigClient::Connect(string& strIP, int nPort)
{
    if (m_nNumFailures > 5)
        return -1;  // server probably down.

    if (m_proxyAddr.empty())
        m_pSocket->SetProxy(NULL);
    else {
        char *proxyurl = new char[m_proxyAddr.size() + 128];
        sprintf(proxyurl, "%s:%d", m_proxyAddr.c_str(), m_proxyPort);
        m_pSocket->SetProxy(proxyurl);
        delete [] proxyurl;
    }

    char *url = new char[strIP.size() + 128]; // ample space..
    sprintf(url, "http://%s/cgi-bin/gateway/gateway?%d", strIP.c_str(), nPort);
    //sprintf(url, "http://209.249.187.200/cgi-bin/gateway?%d", nPort);
    int nErr = m_pSocket->Connect(url);

    delete [] url;

    if (nErr == -1)
    {
        m_nNumFailures++;
        return -1;
    }
    m_nNumFailures = 0;
    return 0;
}

int SigClient::Disconnect()
{
    if (m_pSocket->IsConnected())
    {
        char cBuffer[sizeof(char) + sizeof(int)];
        memset(cBuffer, 0, sizeof(char) + sizeof(int));
        cBuffer[0] = SigClientVars::cDisconnect;

        int nBytes = 0;
        m_pSocket->Write(cBuffer, sizeof(char) + sizeof(int),
                         &nBytes);
        m_pSocket->Disconnect();
    }

    return 0;
}
<|endoftext|>