<commit_before>/*
 * Copyright 2017-2018 Leonid Yuriev <leo@yuriev.ru>
 * and other libmdbx authors: please see AUTHORS file.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted only as authorized by the OpenLDAP
 * Public License.
 *
 * A copy of this license is available in the file LICENSE in the
 * top-level directory of the distribution or, alternatively, at
 * <http://www.OpenLDAP.org/license.html>.
 */

#include "test.h"
#include <float.h>
#if defined(HAVE_IEEE754_H) || __has_include(<ieee754.h>)
#include <ieee754.h>
#endif

std::string format(const char *fmt, ...) {
  va_list ap, ones;
  va_start(ap, fmt);
  va_copy(ones, ap);
#ifdef _MSC_VER
  int needed = _vscprintf(fmt, ap);
#else
  int needed = vsnprintf(nullptr, 0, fmt, ap);
#endif
  assert(needed >= 0);
  va_end(ap);
  std::string result;
  result.reserve((size_t)needed + 1);
  result.resize((size_t)needed, '\0');
  int actual = vsnprintf((char *)result.data(), result.capacity(), fmt, ones);
  assert(actual == needed);
  (void)actual;
  va_end(ones);
  return result;
}

std::string data2hex(const void *ptr, size_t bytes, simple_checksum &checksum) {
  std::string result;
  if (bytes > 0) {
    const uint8_t *data = (const uint8_t *)ptr;
    checksum.push(data, bytes);
    result.reserve(bytes * 2);
    const uint8_t *const end = data + bytes;
    do {
      char h = *data >> 4;
      char l = *data & 15;
      result.push_back((l < 10) ? l + '0' : l - 10 + 'a');
      result.push_back((h < 10) ? h + '0' : h - 10 + 'a');
    } while (++data < end);
  }
  assert(result.size() == bytes * 2);
  return result;
}

bool hex2data(const char *hex_begin, const char *hex_end, void *ptr,
              size_t bytes, simple_checksum &checksum) {
  if (bytes * 2 != (size_t)(hex_end - hex_begin))
    return false;

  uint8_t *data = (uint8_t *)ptr;
  for (const char *hex = hex_begin; hex != hex_end; hex += 2, ++data) {
    unsigned l = hex[0], h = hex[1];

    if (l >= '0' && l <= '9')
      l = l - '0';
    else if (l >= 'A' && l <= 'F')
      l = l - 'A' + 10;
    else if (l >= 'a' && l <= 'f')
      l = l - 'a' + 10;
    else
      return false;

    if (h >= '0' && h <= '9')
      h = h - '0';
    else if (h >= 'A' && h <= 'F')
      h = h - 'A' + 10;
    else if (h >= 'a' && h <= 'f')
      h = h - 'a' + 10;
    else
      return false;

    uint32_t c = l + (h << 4);
    checksum.push(c);
    *data = (uint8_t)c;
  }
  return true;
}

//-----------------------------------------------------------------------------

/* TODO: replace my 'libmera' fomr t1ha. */
uint64_t entropy_ticks(void) {
#if defined(__GNUC__) || defined(__clang__)
#if defined(__ia64__)
  uint64_t ticks;
  __asm __volatile("mov %0=ar.itc" : "=r"(ticks));
  return ticks;
#elif defined(__hppa__)
  uint64_t ticks;
  __asm __volatile("mfctl 16, %0" : "=r"(ticks));
  return ticks;
#elif defined(__s390__)
  uint64_t ticks;
  __asm __volatile("stck 0(%0)" : : "a"(&(ticks)) : "memory", "cc");
  return ticks;
#elif defined(__alpha__)
  uint64_t ticks;
  __asm __volatile("rpcc %0" : "=r"(ticks));
  return ticks;
#elif defined(__sparc_v9__)
  uint64_t ticks;
  __asm __volatile("rd %%tick, %0" : "=r"(ticks));
  return ticks;
#elif defined(__powerpc64__) || defined(__ppc64__)
  uint64_t ticks;
  __asm __volatile("mfspr %0, 268" : "=r"(ticks));
  return ticks;
#elif defined(__ppc__) || defined(__powerpc__)
  unsigned tbl, tbu;

  /* LY: Here not a problem if a high-part (tbu)
   * would been updated during reading. */
  __asm __volatile("mftb %0" : "=r"(tbl));
  __asm __volatile("mftbu %0" : "=r"(tbu));

  return (((uin64_t)tbu0) << 32) | tbl;
#endif /* arch selector */
#endif /* __GNUC__ || __clang__ */

#if defined(__e2k__) || defined(__ia32__)
  return __rdtsc();
#elif defined(_WIN32) || defined(_WIN64) || defined(_WINDOWS)
  LARGE_INTEGER PerformanceCount;
  if (QueryPerformanceCounter(&PerformanceCount))
    return PerformanceCount.QuadPart;
  return GetTickCount64();
#else
  struct timespec ts;
#if defined(CLOCK_MONOTONIC_COARSE)
  clockid_t clock = CLOCK_MONOTONIC_COARSE;
#elif defined(CLOCK_MONOTONIC_RAW)
  clockid_t clock = CLOCK_MONOTONIC_RAW;
#else
  clockid_t clock = CLOCK_MONOTONIC;
#endif
  int rc = clock_gettime(clock, &ts);
  if (unlikely(rc))
    failure_perror("clock_gettime()", rc);

  return (((uint64_t)ts.tv_sec) << 32) + ts.tv_nsec;
#endif
}

//-----------------------------------------------------------------------------

static __inline uint64_t bleach64(uint64_t dirty) {
  return mul_64x64_high(bswap64(dirty), UINT64_C(17048867929148541611));
}

static __inline uint32_t bleach32(uint32_t dirty) {
  return (uint32_t)((bswap32(dirty) * UINT64_C(2175734609)) >> 32);
}

uint64_t prng64_careless(uint64_t &state) {
  state = state * UINT64_C(6364136223846793005) + 1;
  return state;
}

uint64_t prng64_white(uint64_t &state) {
  state = state * UINT64_C(6364136223846793005) + UINT64_C(1442695040888963407);
  return bleach64(state);
}

uint32_t prng32(uint64_t &state) {
  return (uint32_t)(prng64_careless(state) >> 32);
}

void prng_fill(uint64_t &state, void *ptr, size_t bytes) {
  while (bytes >= 4) {
    *((uint32_t *)ptr) = prng32(state);
    ptr = (uint32_t *)ptr + 1;
    bytes -= 4;
  }

  switch (bytes & 3) {
  case 3: {
    uint32_t u32 = prng32(state);
    memcpy(ptr, &u32, 3);
  } break;
  case 2:
    *((uint16_t *)ptr) = (uint16_t)prng32(state);
    break;
  case 1:
    *((uint8_t *)ptr) = (uint8_t)prng32(state);
    break;
  case 0:
    break;
  }
}

static __thread uint64_t prng_state;

void prng_seed(uint64_t seed) { prng_state = bleach64(seed); }

uint32_t prng32(void) { return prng32(prng_state); }

uint64_t prng64(void) { return prng64_white(prng_state); }

void prng_fill(void *ptr, size_t bytes) { prng_fill(prng_state, ptr, bytes); }

uint64_t entropy_white() { return bleach64(entropy_ticks()); }

double double_from_lower(uint64_t salt) {
#ifdef IEEE754_DOUBLE_BIAS
  ieee754_double r;
  r.ieee.negative = 0;
  r.ieee.exponent = IEEE754_DOUBLE_BIAS;
  r.ieee.mantissa0 = (unsigned)(salt >> 32);
  r.ieee.mantissa1 = (unsigned)salt;
  return r.d;
#else
  const uint64_t top = (UINT64_C(1) << DBL_MANT_DIG) - 1;
  const double scale = 1.0 / (double)top;
  return (salt & top) * scale;
#endif
}

double double_from_upper(uint64_t salt) {
#ifdef IEEE754_DOUBLE_BIAS
  ieee754_double r;
  r.ieee.negative = 0;
  r.ieee.exponent = IEEE754_DOUBLE_BIAS;
  salt >>= 64 - DBL_MANT_DIG;
  r.ieee.mantissa0 = (unsigned)(salt >> 32);
  r.ieee.mantissa1 = (unsigned)salt;
  return r.d;
#else
  const uint64_t top = (UINT64_C(1) << DBL_MANT_DIG) - 1;
  const double scale = 1.0 / (double)top;
  return (salt >> (64 - DBL_MANT_DIG)) * scale;
#endif
}

bool flipcoin() { return bleach32((uint32_t)entropy_ticks()) & 1; }

bool jitter(unsigned probability_percent) {
  const uint32_t top = UINT32_MAX - UINT32_MAX % 100;
  uint32_t dice, edge = (top) / 100 * probability_percent;
  do
    dice = bleach32((uint32_t)entropy_ticks());
  while (dice >= top);
  return dice < edge;
}

void jitter_delay(bool extra) {
  unsigned dice = entropy_white() & 3;
  if (dice == 0) {
    log_trace("== jitter.no-delay");
  } else {
    log_trace(">> jitter.delay: dice %u", dice);
    do {
      cpu_relax();
      memory_barrier();
      cpu_relax();
      if (dice > 1) {
        osal_yield();
        cpu_relax();
        if (dice > 2) {
          unsigned us = entropy_white() &
                        (extra ? 0xfffff /* 1.05 s */ : 0x3ff /* 1 ms */);
          log_trace("== jitter.delay: %0.6f", us / 1000000.0);
          osal_udelay(us);
        }
      }
    } while (flipcoin());
    log_trace("<< jitter.delay: dice %u", dice);
  }
}
<commit_msg>mdbx-tests: fix entropy_ticks() for multiarch.<commit_after>/*
 * Copyright 2017-2018 Leonid Yuriev <leo@yuriev.ru>
 * and other libmdbx authors: please see AUTHORS file.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted only as authorized by the OpenLDAP
 * Public License.
 *
 * A copy of this license is available in the file LICENSE in the
 * top-level directory of the distribution or, alternatively, at
 * <http://www.OpenLDAP.org/license.html>.
 */

#include "test.h"
#include <float.h>
#if defined(HAVE_IEEE754_H) || __has_include(<ieee754.h>)
#include <ieee754.h>
#endif

std::string format(const char *fmt, ...) {
  va_list ap, ones;
  va_start(ap, fmt);
  va_copy(ones, ap);
#ifdef _MSC_VER
  int needed = _vscprintf(fmt, ap);
#else
  int needed = vsnprintf(nullptr, 0, fmt, ap);
#endif
  assert(needed >= 0);
  va_end(ap);
  std::string result;
  result.reserve((size_t)needed + 1);
  result.resize((size_t)needed, '\0');
  int actual = vsnprintf((char *)result.data(), result.capacity(), fmt, ones);
  assert(actual == needed);
  (void)actual;
  va_end(ones);
  return result;
}

std::string data2hex(const void *ptr, size_t bytes, simple_checksum &checksum) {
  std::string result;
  if (bytes > 0) {
    const uint8_t *data = (const uint8_t *)ptr;
    checksum.push(data, bytes);
    result.reserve(bytes * 2);
    const uint8_t *const end = data + bytes;
    do {
      char h = *data >> 4;
      char l = *data & 15;
      result.push_back((l < 10) ? l + '0' : l - 10 + 'a');
      result.push_back((h < 10) ? h + '0' : h - 10 + 'a');
    } while (++data < end);
  }
  assert(result.size() == bytes * 2);
  return result;
}

bool hex2data(const char *hex_begin, const char *hex_end, void *ptr,
              size_t bytes, simple_checksum &checksum) {
  if (bytes * 2 != (size_t)(hex_end - hex_begin))
    return false;

  uint8_t *data = (uint8_t *)ptr;
  for (const char *hex = hex_begin; hex != hex_end; hex += 2, ++data) {
    unsigned l = hex[0], h = hex[1];

    if (l >= '0' && l <= '9')
      l = l - '0';
    else if (l >= 'A' && l <= 'F')
      l = l - 'A' + 10;
    else if (l >= 'a' && l <= 'f')
      l = l - 'a' + 10;
    else
      return false;

    if (h >= '0' && h <= '9')
      h = h - '0';
    else if (h >= 'A' && h <= 'F')
      h = h - 'A' + 10;
    else if (h >= 'a' && h <= 'f')
      h = h - 'a' + 10;
    else
      return false;

    uint32_t c = l + (h << 4);
    checksum.push(c);
    *data = (uint8_t)c;
  }
  return true;
}

//-----------------------------------------------------------------------------

/* TODO: replace my 'libmera' fomr t1ha. */
uint64_t entropy_ticks(void) {
#if defined(EMSCRIPTEN)
  return (uint64_t)emscripten_get_now();
#endif /* EMSCRIPTEN */

#if defined(__APPLE__) || defined(__MACH__)
  return mach_absolute_time();
#endif /* defined(__APPLE__) || defined(__MACH__) */

#if defined(__sun__) || defined(__sun)
  return gethrtime();
#endif /* __sun__ */

#if defined(__GNUC__) || defined(__clang__)

#if defined(__ia64__)
  uint64_t ticks;
  __asm __volatile("mov %0=ar.itc" : "=r"(ticks));
  return ticks;
#elif defined(__hppa__)
  uint64_t ticks;
  __asm __volatile("mfctl 16, %0" : "=r"(ticks));
  return ticks;
#elif defined(__s390__)
  uint64_t ticks;
  __asm __volatile("stck 0(%0)" : : "a"(&(ticks)) : "memory", "cc");
  return ticks;
#elif defined(__alpha__)
  uint64_t ticks;
  __asm __volatile("rpcc %0" : "=r"(ticks));
  return ticks;
#elif defined(__sparc__) || defined(__sparc) || defined(__sparc64__) ||        \
    defined(__sparc64) || defined(__sparc_v8plus__) ||                         \
    defined(__sparc_v8plus) || defined(__sparc_v8plusa__) ||                   \
    defined(__sparc_v8plusa) || defined(__sparc_v9__) || defined(__sparc_v9)

  union {
    uint64_t u64;
    struct {
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
      uint32_t h, l;
#else
      uint32_t l, h;
#endif
    } u32;
  } cycles;

#if defined(__sparc_v8plus__) || defined(__sparc_v8plusa__) ||                 \
    defined(__sparc_v9__) || defined(__sparc_v8plus) ||                        \
    defined(__sparc_v8plusa) || defined(__sparc_v9)

#if UINTPTR_MAX > 0xffffFFFFul || ULONG_MAX > 0xffffFFFFul ||                  \
    defined(__sparc64__) || defined(__sparc64)
  __asm __volatile("rd %%tick, %0" : "=r"(cycles.u64));
#else
  __asm __volatile("rd %%tick, %1; srlx %1, 32, %0"
                   : "=r"(cycles.u32.h), "=r"(cycles.u32.l));
#endif /* __sparc64__ */

#else
  __asm __volatile(".byte 0x83, 0x41, 0x00, 0x00; mov %%g1, %0"
                   : "=r"(cycles.u64)
                   :
                   : "%g1");
#endif /* __sparc8plus__ || __sparc_v9__ */
  return cycles.u64;

#elif (defined(__powerpc64__) || defined(__ppc64__) || defined(__ppc64) ||     \
       defined(__powerpc64))
  uint64_t ticks;
  __asm __volatile("mfspr %0, 268" : "=r"(ticks));
  return ticks;
#elif (defined(__powerpc__) || defined(__ppc__) || defined(__powerpc) ||       \
       defined(__ppc))
#if UINTPTR_MAX > 0xffffFFFFul || ULONG_MAX > 0xffffFFFFul
  uint64_t ticks;
  __asm __volatile("mftb  %0" : "=r"(ticks));
  *now = ticks;
#else
  uint64_t ticks;
  uint32_t low, high_before, high_after;
  __asm __volatile("mftbu %0; mftb  %1; mftbu %2"
                   : "=r"(high_before), "=r"(low), "=r"(high_after));
  ticks = (uint64_t)high_after << 32;
  ticks |= low & /* zeroes if high part has changed */
           ~(high_before - high_after);
#endif
#elif defined(__aarch64__) || (defined(__ARM_ARCH) && __ARM_ARCH > 7)
  uint64_t virtual_timer;
  __asm __volatile("mrs %0, cntvct_el0" : "=r"(virtual_timer));
  return virtual_timer;
#elif defined(__ARM_ARCH) && __ARM_ARCH > 5 && __ARM_ARCH < 8
  unsigned long pmccntr;
  __asm __volatile("mrc p15, 0, %0, c9, c13, 0" : "=r"(pmccntr));
  return pmccntr;
#elif defined(__mips__) || defined(__mips) || defined(_R4000)
  unsigned count;
  __asm __volatile("rdhwr %0, $2" : "=r"(count));
  return count;
#endif /* arch selector */
#endif /* __GNUC__ || __clang__ */

#if defined(__e2k__) || defined(__ia32__)
  return __rdtsc();
#elif defined(_M_ARM)
  return __rdpmccntr64();
#elif defined(_WIN32) || defined(_WIN64) || defined(_WINDOWS)
  LARGE_INTEGER PerformanceCount;
  if (QueryPerformanceCounter(&PerformanceCount))
    return PerformanceCount.QuadPart;
  return GetTickCount64();
#else
  struct timespec ts;
#if defined(CLOCK_MONOTONIC_COARSE)
  clockid_t clock = CLOCK_MONOTONIC_COARSE;
#elif defined(CLOCK_MONOTONIC_RAW)
  clockid_t clock = CLOCK_MONOTONIC_RAW;
#else
  clockid_t clock = CLOCK_MONOTONIC;
#endif
  int rc = clock_gettime(clock, &ts);
  if (unlikely(rc))
    failure_perror("clock_gettime()", rc);

  return (((uint64_t)ts.tv_sec) << 32) + ts.tv_nsec;
#endif
}

//-----------------------------------------------------------------------------

static __inline uint64_t bleach64(uint64_t dirty) {
  return mul_64x64_high(bswap64(dirty), UINT64_C(17048867929148541611));
}

static __inline uint32_t bleach32(uint32_t dirty) {
  return (uint32_t)((bswap32(dirty) * UINT64_C(2175734609)) >> 32);
}

uint64_t prng64_careless(uint64_t &state) {
  state = state * UINT64_C(6364136223846793005) + 1;
  return state;
}

uint64_t prng64_white(uint64_t &state) {
  state = state * UINT64_C(6364136223846793005) + UINT64_C(1442695040888963407);
  return bleach64(state);
}

uint32_t prng32(uint64_t &state) {
  return (uint32_t)(prng64_careless(state) >> 32);
}

void prng_fill(uint64_t &state, void *ptr, size_t bytes) {
  while (bytes >= 4) {
    *((uint32_t *)ptr) = prng32(state);
    ptr = (uint32_t *)ptr + 1;
    bytes -= 4;
  }

  switch (bytes & 3) {
  case 3: {
    uint32_t u32 = prng32(state);
    memcpy(ptr, &u32, 3);
  } break;
  case 2:
    *((uint16_t *)ptr) = (uint16_t)prng32(state);
    break;
  case 1:
    *((uint8_t *)ptr) = (uint8_t)prng32(state);
    break;
  case 0:
    break;
  }
}

static __thread uint64_t prng_state;

void prng_seed(uint64_t seed) { prng_state = bleach64(seed); }

uint32_t prng32(void) { return prng32(prng_state); }

uint64_t prng64(void) { return prng64_white(prng_state); }

void prng_fill(void *ptr, size_t bytes) { prng_fill(prng_state, ptr, bytes); }

uint64_t entropy_white() { return bleach64(entropy_ticks()); }

double double_from_lower(uint64_t salt) {
#ifdef IEEE754_DOUBLE_BIAS
  ieee754_double r;
  r.ieee.negative = 0;
  r.ieee.exponent = IEEE754_DOUBLE_BIAS;
  r.ieee.mantissa0 = (unsigned)(salt >> 32);
  r.ieee.mantissa1 = (unsigned)salt;
  return r.d;
#else
  const uint64_t top = (UINT64_C(1) << DBL_MANT_DIG) - 1;
  const double scale = 1.0 / (double)top;
  return (salt & top) * scale;
#endif
}

double double_from_upper(uint64_t salt) {
#ifdef IEEE754_DOUBLE_BIAS
  ieee754_double r;
  r.ieee.negative = 0;
  r.ieee.exponent = IEEE754_DOUBLE_BIAS;
  salt >>= 64 - DBL_MANT_DIG;
  r.ieee.mantissa0 = (unsigned)(salt >> 32);
  r.ieee.mantissa1 = (unsigned)salt;
  return r.d;
#else
  const uint64_t top = (UINT64_C(1) << DBL_MANT_DIG) - 1;
  const double scale = 1.0 / (double)top;
  return (salt >> (64 - DBL_MANT_DIG)) * scale;
#endif
}

bool flipcoin() { return bleach32((uint32_t)entropy_ticks()) & 1; }

bool jitter(unsigned probability_percent) {
  const uint32_t top = UINT32_MAX - UINT32_MAX % 100;
  uint32_t dice, edge = (top) / 100 * probability_percent;
  do
    dice = bleach32((uint32_t)entropy_ticks());
  while (dice >= top);
  return dice < edge;
}

void jitter_delay(bool extra) {
  unsigned dice = entropy_white() & 3;
  if (dice == 0) {
    log_trace("== jitter.no-delay");
  } else {
    log_trace(">> jitter.delay: dice %u", dice);
    do {
      cpu_relax();
      memory_barrier();
      cpu_relax();
      if (dice > 1) {
        osal_yield();
        cpu_relax();
        if (dice > 2) {
          unsigned us = entropy_white() &
                        (extra ? 0xfffff /* 1.05 s */ : 0x3ff /* 1 ms */);
          log_trace("== jitter.delay: %0.6f", us / 1000000.0);
          osal_udelay(us);
        }
      }
    } while (flipcoin());
    log_trace("<< jitter.delay: dice %u", dice);
  }
}
<|endoftext|>


<commit_before>#include <node.h>
#include <v8.h>
#include <nan.h>

#ifdef _WIN32
#include "notificationstate-query.h"
#endif

using namespace v8;

void GetNotificationState(const v8::FunctionCallbackInfo<Value>& args) {
  Isolate* isolate = Isolate::GetCurrent();
  HandleScope scope(isolate);
  int returnValue = -1;

  #ifdef _WIN32
    returnValue = queryUserNotificationState();
  #endif

  args.GetReturnValue().Set(Int32::New(isolate, returnValue));
}

NAN_MODULE_INIT(Init) {
  Nan::Set(target, Nan::New<String>("getNotificationState").ToLocalChecked(),
    Nan::GetFunction(Nan::New<FunctionTemplate>(GetNotificationState)).ToLocalChecked());
}

NODE_MODULE(quiethours, Init)
<commit_msg>fix: Better Node 12 compilation, part 234<commit_after>#include <node.h>
#include <v8.h>
#include <nan.h>

#ifdef _WIN32
#include "notificationstate-query.h"
#endif

using namespace v8;

NAN_METHOD(GetNotificationState) {
  Isolate* isolate = Isolate::GetCurrent();
  HandleScope scope(isolate);
  int returnValue = -1;

  #ifdef TARGET_OS_MAC
    returnValue = queryUserNotificationState();
  #endif

  info.GetReturnValue().Set(Int32::New(isolate, returnValue));
}

NAN_MODULE_INIT(Init) {
  Nan::SetMethod(target, "getNotificationState", GetNotificationState);
}

NODE_MODULE(quiethours, Init)
<|endoftext|>


<commit_before>/*
 This file is part of cpp-ethereum.

 cpp-ethereum is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 cpp-ethereum 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 General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
 */
/** @file RLPXHandshake.cpp
 * @author Alex Leverington <nessence@gmail.com>
 * @date 2015
 */

#include "Host.h"
#include "Session.h"
#include "Peer.h"
#include "RLPxHandshake.h"
using namespace std;
using namespace dev;
using namespace dev::p2p;
using namespace CryptoPP;

void RLPXHandshake::writeAuth()
{
	clog(NetP2PConnect) << "p2p.connect.egress sending auth to " << m_socket->remoteEndpoint();
	m_auth.resize(Signature::size + h256::size + Public::size + h256::size + 1);
	bytesRef sig(&m_auth[0], Signature::size);
	bytesRef hepubk(&m_auth[Signature::size], h256::size);
	bytesRef pubk(&m_auth[Signature::size + h256::size], Public::size);
	bytesRef nonce(&m_auth[Signature::size + h256::size + Public::size], h256::size);

	// E(remote-pubk, S(ecdhe-random, ecdh-shared-secret^nonce) || H(ecdhe-random-pubk) || pubk || nonce || 0x0)
	Secret staticShared;
	crypto::ecdh::agree(m_host->m_alias.sec(), m_remote, staticShared);
	sign(m_ecdhe.seckey(), staticShared ^ m_nonce).ref().copyTo(sig);
	sha3(m_ecdhe.pubkey().ref(), hepubk);
	m_host->m_alias.pub().ref().copyTo(pubk);
	m_nonce.ref().copyTo(nonce);
	m_auth[m_auth.size() - 1] = 0x0;
	encryptECIES(m_remote, &m_auth, m_authCipher);

	auto self(shared_from_this());
	ba::async_write(m_socket->ref(), ba::buffer(m_authCipher), [this, self](boost::system::error_code ec, std::size_t)
	{
		transition(ec);
	});
}

void RLPXHandshake::writeAck()
{
	clog(NetP2PConnect) << "p2p.connect.ingress sending ack to " << m_socket->remoteEndpoint();
	m_ack.resize(Public::size + h256::size + 1);
	bytesRef epubk(&m_ack[0], Public::size);
	bytesRef nonce(&m_ack[Public::size], h256::size);
	m_ecdhe.pubkey().ref().copyTo(epubk);
	m_nonce.ref().copyTo(nonce);
	m_ack[m_ack.size() - 1] = 0x0;
	encryptECIES(m_remote, &m_ack, m_ackCipher);

	auto self(shared_from_this());
	ba::async_write(m_socket->ref(), ba::buffer(m_ackCipher), [this, self](boost::system::error_code ec, std::size_t)
	{
		transition(ec);
	});
}

void RLPXHandshake::readAuth()
{
	clog(NetP2PConnect) << "p2p.connect.ingress recving auth from " << m_socket->remoteEndpoint();
	m_authCipher.resize(307);
	auto self(shared_from_this());
	ba::async_read(m_socket->ref(), ba::buffer(m_authCipher, 307), [this, self](boost::system::error_code ec, std::size_t)
	{
		if (ec)
			transition(ec);
		else if (decryptECIES(m_host->m_alias.sec(), bytesConstRef(&m_authCipher), m_auth))
		{
			bytesConstRef sig(&m_auth[0], Signature::size);
			bytesConstRef hepubk(&m_auth[Signature::size], h256::size);
			bytesConstRef pubk(&m_auth[Signature::size + h256::size], Public::size);
			bytesConstRef nonce(&m_auth[Signature::size + h256::size + Public::size], h256::size);
			pubk.copyTo(m_remote.ref());
			nonce.copyTo(m_remoteNonce.ref());

			Secret sharedSecret;
			crypto::ecdh::agree(m_host->m_alias.sec(), m_remote, sharedSecret);
			m_remoteEphemeral = recover(*(Signature*)sig.data(), sharedSecret ^ m_remoteNonce);

			if (sha3(m_remoteEphemeral) != *(h256*)hepubk.data())
				clog(NetP2PConnect) << "p2p.connect.ingress auth failed (invalid: hash mismatch) for" << m_socket->remoteEndpoint();

			transition();
		}
		else
		{
			clog(NetP2PConnect) << "p2p.connect.ingress recving auth decrypt failed for" << m_socket->remoteEndpoint();
			m_nextState = Error;
			transition();
		}
	});
}

void RLPXHandshake::readAck()
{
	clog(NetP2PConnect) << "p2p.connect.egress recving ack from " << m_socket->remoteEndpoint();
	m_ackCipher.resize(210);
	auto self(shared_from_this());
	ba::async_read(m_socket->ref(), ba::buffer(m_ackCipher, 210), [this, self](boost::system::error_code ec, std::size_t)
	{
		if (ec)
			transition(ec);
		else if (decryptECIES(m_host->m_alias.sec(), bytesConstRef(&m_ackCipher), m_ack))
		{
			bytesConstRef(&m_ack).cropped(0, Public::size).copyTo(m_remoteEphemeral.ref());
			bytesConstRef(&m_ack).cropped(Public::size, h256::size).copyTo(m_remoteNonce.ref());
			transition();
		}
		else
		{
			clog(NetP2PConnect) << "p2p.connect.egress recving ack decrypt failed for " << m_socket->remoteEndpoint();
			m_nextState = Error;
			transition();
		}
	});
}

void RLPXHandshake::error()
{
	m_idleTimer.cancel();

	auto connected = m_socket->isConnected();
	if (connected && !m_socket->remoteEndpoint().address().is_unspecified())
		clog(NetP2PConnect) << "Disconnecting " << m_socket->remoteEndpoint() << " (Handshake Failed)";
	else
		clog(NetP2PConnect) << "Handshake Failed (Connection reset by peer)";

	m_socket->close();
	if (m_io != nullptr)
		delete m_io;
}

void RLPXHandshake::transition(boost::system::error_code _ech)
{
	if (_ech || m_nextState == Error || m_cancel)
	{
		clog(NetP2PConnect) << "Handshake Failed (I/O Error:" << _ech.message() << ")";
		return error();
	}

	auto self(shared_from_this());
	if (m_nextState == New)
	{
		m_nextState = AckAuth;
		if (m_originated)
			writeAuth();
		else
			readAuth();
	}
	else if (m_nextState == AckAuth)
	{
		m_nextState = WriteHello;
		if (m_originated)
			readAck();
		else
			writeAck();
	}
	else if (m_nextState == WriteHello)
	{
		m_nextState = ReadHello;
		clog(NetP2PConnect) << (m_originated ? "p2p.connect.egress" : "p2p.connect.ingress") << "sending capabilities handshake";

		/// This pointer will be freed if there is an error otherwise
		/// it will be passed to Host which will take ownership.
		m_io = new RLPXFrameIO(*this);

		// old packet format
		// 5 arguments, HelloPacket
		RLPStream s;
		s.append((unsigned)0).appendList(5)
		<< dev::p2p::c_protocolVersion
		<< m_host->m_clientVersion
		<< m_host->caps()
		<< m_host->listenPort()
		<< m_host->id();
		bytes packet;
		s.swapOut(packet);
		m_io->writeSingleFramePacket(&packet, m_handshakeOutBuffer);
		ba::async_write(m_socket->ref(), ba::buffer(m_handshakeOutBuffer), [this, self](boost::system::error_code ec, std::size_t)
		{
			transition(ec);
		});
	}
	else if (m_nextState == ReadHello)
	{
		// Authenticate and decrypt initial hello frame with initial RLPXFrameIO
		// and request m_host to start session.
		m_nextState = StartSession;

		// read frame header
		m_handshakeInBuffer.resize(h256::size);
		ba::async_read(m_socket->ref(), boost::asio::buffer(m_handshakeInBuffer, h256::size), [this, self](boost::system::error_code ec, std::size_t)
		{
			if (ec)
				transition(ec);
			else
			{
				/// authenticate and decrypt header
				if (!m_io->authAndDecryptHeader(bytesRef(m_handshakeInBuffer.data(), h256::size)))
				{
					m_nextState = Error;
					transition();
					return;
				}

				clog(NetP2PNote) << (m_originated ? "p2p.connect.egress" : "p2p.connect.ingress") << "recvd hello header";

				/// check frame size
				bytes& header = m_handshakeInBuffer;
				uint32_t frameSize = (uint32_t)(header[2]) | (uint32_t)(header[1])<<8 | (uint32_t)(header[0])<<16;
				if (frameSize > 1024)
				{
					// all future frames: 16777216
					clog(NetP2PWarn) << (m_originated ? "p2p.connect.egress" : "p2p.connect.ingress") << "hello frame is too large" << frameSize;
					m_nextState = Error;
					transition();
					return;
				}

				/// rlp of header has protocol-type, sequence-id[, total-packet-size]
				bytes headerRLP(header.size() - 3 - h128::size);
				bytesConstRef(&header).cropped(3).copyTo(&headerRLP);

				/// read padded frame and mac
				m_handshakeInBuffer.resize(frameSize + ((16 - (frameSize % 16)) % 16) + h128::size);
				ba::async_read(m_socket->ref(), boost::asio::buffer(m_handshakeInBuffer, m_handshakeInBuffer.size()), [this, self, headerRLP](boost::system::error_code ec, std::size_t)
				{
					if (ec)
						transition(ec);
					else
					{
						bytesRef frame(&m_handshakeInBuffer);
						if (!m_io->authAndDecryptFrame(frame))
						{
							clog(NetTriviaSummary) << (m_originated ? "p2p.connect.egress" : "p2p.connect.ingress") << "hello frame: decrypt failed";
							m_nextState = Error;
							transition();
							return;
						}

						PacketType packetType = (PacketType)(frame[0] == 0x80 ? 0x0 : frame[0]);
						if (packetType != 0)
						{
							clog(NetTriviaSummary) << (m_originated ? "p2p.connect.egress" : "p2p.connect.ingress") << "hello frame: invalid packet type";
							m_nextState = Error;
							transition();
							return;
						}

						clog(NetTriviaSummary) << (m_originated ? "p2p.connect.egress" : "p2p.connect.ingress") << "hello frame: success. starting session.";
						RLP rlp(frame.cropped(1), RLP::ThrowOnFail | RLP::FailIfTooSmall);
						m_host->startPeerSession(m_remote, rlp, m_io, m_socket->remoteEndpoint());
					}
				});
			}
		});
	}

	m_idleTimer.expires_from_now(c_timeout);
	m_idleTimer.async_wait([this, self](boost::system::error_code const& _ec)
	{
		if (!_ec)
		{
			if (!m_socket->remoteEndpoint().address().is_unspecified())
				clog(NetP2PConnect) << "Disconnecting " << m_socket->remoteEndpoint() << " (Handshake Timeout)";
			cancel();
		}
	});
}
<commit_msg>Log warning and disconnect when remote passes bad rlp during handshake.<commit_after>/*
 This file is part of cpp-ethereum.

 cpp-ethereum is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 cpp-ethereum 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 General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
 */
/** @file RLPXHandshake.cpp
 * @author Alex Leverington <nessence@gmail.com>
 * @date 2015
 */

#include "Host.h"
#include "Session.h"
#include "Peer.h"
#include "RLPxHandshake.h"
using namespace std;
using namespace dev;
using namespace dev::p2p;
using namespace CryptoPP;

void RLPXHandshake::writeAuth()
{
	clog(NetP2PConnect) << "p2p.connect.egress sending auth to " << m_socket->remoteEndpoint();
	m_auth.resize(Signature::size + h256::size + Public::size + h256::size + 1);
	bytesRef sig(&m_auth[0], Signature::size);
	bytesRef hepubk(&m_auth[Signature::size], h256::size);
	bytesRef pubk(&m_auth[Signature::size + h256::size], Public::size);
	bytesRef nonce(&m_auth[Signature::size + h256::size + Public::size], h256::size);

	// E(remote-pubk, S(ecdhe-random, ecdh-shared-secret^nonce) || H(ecdhe-random-pubk) || pubk || nonce || 0x0)
	Secret staticShared;
	crypto::ecdh::agree(m_host->m_alias.sec(), m_remote, staticShared);
	sign(m_ecdhe.seckey(), staticShared ^ m_nonce).ref().copyTo(sig);
	sha3(m_ecdhe.pubkey().ref(), hepubk);
	m_host->m_alias.pub().ref().copyTo(pubk);
	m_nonce.ref().copyTo(nonce);
	m_auth[m_auth.size() - 1] = 0x0;
	encryptECIES(m_remote, &m_auth, m_authCipher);

	auto self(shared_from_this());
	ba::async_write(m_socket->ref(), ba::buffer(m_authCipher), [this, self](boost::system::error_code ec, std::size_t)
	{
		transition(ec);
	});
}

void RLPXHandshake::writeAck()
{
	clog(NetP2PConnect) << "p2p.connect.ingress sending ack to " << m_socket->remoteEndpoint();
	m_ack.resize(Public::size + h256::size + 1);
	bytesRef epubk(&m_ack[0], Public::size);
	bytesRef nonce(&m_ack[Public::size], h256::size);
	m_ecdhe.pubkey().ref().copyTo(epubk);
	m_nonce.ref().copyTo(nonce);
	m_ack[m_ack.size() - 1] = 0x0;
	encryptECIES(m_remote, &m_ack, m_ackCipher);

	auto self(shared_from_this());
	ba::async_write(m_socket->ref(), ba::buffer(m_ackCipher), [this, self](boost::system::error_code ec, std::size_t)
	{
		transition(ec);
	});
}

void RLPXHandshake::readAuth()
{
	clog(NetP2PConnect) << "p2p.connect.ingress recving auth from " << m_socket->remoteEndpoint();
	m_authCipher.resize(307);
	auto self(shared_from_this());
	ba::async_read(m_socket->ref(), ba::buffer(m_authCipher, 307), [this, self](boost::system::error_code ec, std::size_t)
	{
		if (ec)
			transition(ec);
		else if (decryptECIES(m_host->m_alias.sec(), bytesConstRef(&m_authCipher), m_auth))
		{
			bytesConstRef sig(&m_auth[0], Signature::size);
			bytesConstRef hepubk(&m_auth[Signature::size], h256::size);
			bytesConstRef pubk(&m_auth[Signature::size + h256::size], Public::size);
			bytesConstRef nonce(&m_auth[Signature::size + h256::size + Public::size], h256::size);
			pubk.copyTo(m_remote.ref());
			nonce.copyTo(m_remoteNonce.ref());

			Secret sharedSecret;
			crypto::ecdh::agree(m_host->m_alias.sec(), m_remote, sharedSecret);
			m_remoteEphemeral = recover(*(Signature*)sig.data(), sharedSecret ^ m_remoteNonce);

			if (sha3(m_remoteEphemeral) != *(h256*)hepubk.data())
				clog(NetP2PConnect) << "p2p.connect.ingress auth failed (invalid: hash mismatch) for" << m_socket->remoteEndpoint();

			transition();
		}
		else
		{
			clog(NetP2PConnect) << "p2p.connect.ingress recving auth decrypt failed for" << m_socket->remoteEndpoint();
			m_nextState = Error;
			transition();
		}
	});
}

void RLPXHandshake::readAck()
{
	clog(NetP2PConnect) << "p2p.connect.egress recving ack from " << m_socket->remoteEndpoint();
	m_ackCipher.resize(210);
	auto self(shared_from_this());
	ba::async_read(m_socket->ref(), ba::buffer(m_ackCipher, 210), [this, self](boost::system::error_code ec, std::size_t)
	{
		if (ec)
			transition(ec);
		else if (decryptECIES(m_host->m_alias.sec(), bytesConstRef(&m_ackCipher), m_ack))
		{
			bytesConstRef(&m_ack).cropped(0, Public::size).copyTo(m_remoteEphemeral.ref());
			bytesConstRef(&m_ack).cropped(Public::size, h256::size).copyTo(m_remoteNonce.ref());
			transition();
		}
		else
		{
			clog(NetP2PConnect) << "p2p.connect.egress recving ack decrypt failed for " << m_socket->remoteEndpoint();
			m_nextState = Error;
			transition();
		}
	});
}

void RLPXHandshake::error()
{
	m_idleTimer.cancel();

	auto connected = m_socket->isConnected();
	if (connected && !m_socket->remoteEndpoint().address().is_unspecified())
		clog(NetP2PConnect) << "Disconnecting " << m_socket->remoteEndpoint() << " (Handshake Failed)";
	else
		clog(NetP2PConnect) << "Handshake Failed (Connection reset by peer)";

	m_socket->close();
	if (m_io != nullptr)
		delete m_io;
}

void RLPXHandshake::transition(boost::system::error_code _ech)
{
	if (_ech || m_nextState == Error || m_cancel)
	{
		clog(NetP2PConnect) << "Handshake Failed (I/O Error:" << _ech.message() << ")";
		return error();
	}

	auto self(shared_from_this());
	if (m_nextState == New)
	{
		m_nextState = AckAuth;
		if (m_originated)
			writeAuth();
		else
			readAuth();
	}
	else if (m_nextState == AckAuth)
	{
		m_nextState = WriteHello;
		if (m_originated)
			readAck();
		else
			writeAck();
	}
	else if (m_nextState == WriteHello)
	{
		m_nextState = ReadHello;
		clog(NetP2PConnect) << (m_originated ? "p2p.connect.egress" : "p2p.connect.ingress") << "sending capabilities handshake";

		/// This pointer will be freed if there is an error otherwise
		/// it will be passed to Host which will take ownership.
		m_io = new RLPXFrameIO(*this);

		// old packet format
		// 5 arguments, HelloPacket
		RLPStream s;
		s.append((unsigned)0).appendList(5)
		<< dev::p2p::c_protocolVersion
		<< m_host->m_clientVersion
		<< m_host->caps()
		<< m_host->listenPort()
		<< m_host->id();
		bytes packet;
		s.swapOut(packet);
		m_io->writeSingleFramePacket(&packet, m_handshakeOutBuffer);
		ba::async_write(m_socket->ref(), ba::buffer(m_handshakeOutBuffer), [this, self](boost::system::error_code ec, std::size_t)
		{
			transition(ec);
		});
	}
	else if (m_nextState == ReadHello)
	{
		// Authenticate and decrypt initial hello frame with initial RLPXFrameIO
		// and request m_host to start session.
		m_nextState = StartSession;

		// read frame header
		m_handshakeInBuffer.resize(h256::size);
		ba::async_read(m_socket->ref(), boost::asio::buffer(m_handshakeInBuffer, h256::size), [this, self](boost::system::error_code ec, std::size_t)
		{
			if (ec)
				transition(ec);
			else
			{
				/// authenticate and decrypt header
				if (!m_io->authAndDecryptHeader(bytesRef(m_handshakeInBuffer.data(), h256::size)))
				{
					m_nextState = Error;
					transition();
					return;
				}

				clog(NetP2PNote) << (m_originated ? "p2p.connect.egress" : "p2p.connect.ingress") << "recvd hello header";

				/// check frame size
				bytes& header = m_handshakeInBuffer;
				uint32_t frameSize = (uint32_t)(header[2]) | (uint32_t)(header[1])<<8 | (uint32_t)(header[0])<<16;
				if (frameSize > 1024)
				{
					// all future frames: 16777216
					clog(NetP2PWarn) << (m_originated ? "p2p.connect.egress" : "p2p.connect.ingress") << "hello frame is too large" << frameSize;
					m_nextState = Error;
					transition();
					return;
				}

				/// rlp of header has protocol-type, sequence-id[, total-packet-size]
				bytes headerRLP(header.size() - 3 - h128::size);
				bytesConstRef(&header).cropped(3).copyTo(&headerRLP);

				/// read padded frame and mac
				m_handshakeInBuffer.resize(frameSize + ((16 - (frameSize % 16)) % 16) + h128::size);
				ba::async_read(m_socket->ref(), boost::asio::buffer(m_handshakeInBuffer, m_handshakeInBuffer.size()), [this, self, headerRLP](boost::system::error_code ec, std::size_t)
				{
					if (ec)
						transition(ec);
					else
					{
						bytesRef frame(&m_handshakeInBuffer);
						if (!m_io->authAndDecryptFrame(frame))
						{
							clog(NetTriviaSummary) << (m_originated ? "p2p.connect.egress" : "p2p.connect.ingress") << "hello frame: decrypt failed";
							m_nextState = Error;
							transition();
							return;
						}

						PacketType packetType = (PacketType)(frame[0] == 0x80 ? 0x0 : frame[0]);
						if (packetType != 0)
						{
							clog(NetTriviaSummary) << (m_originated ? "p2p.connect.egress" : "p2p.connect.ingress") << "hello frame: invalid packet type";
							m_nextState = Error;
							transition();
							return;
						}

						clog(NetTriviaSummary) << (m_originated ? "p2p.connect.egress" : "p2p.connect.ingress") << "hello frame: success. starting session.";
						try
						{
							RLP rlp(frame.cropped(1), RLP::ThrowOnFail | RLP::FailIfTooSmall);
							m_host->startPeerSession(m_remote, rlp, m_io, m_socket->remoteEndpoint());
						}
						catch (std::exception const& _e)
						{
							clog(NetWarn) << "Handshake causing an exception:" << _e.what();
							m_nextState = Error;
							transition();
						}
					}
				});
			}
		});
	}

	m_idleTimer.expires_from_now(c_timeout);
	m_idleTimer.async_wait([this, self](boost::system::error_code const& _ec)
	{
		if (!_ec)
		{
			if (!m_socket->remoteEndpoint().address().is_unspecified())
				clog(NetP2PConnect) << "Disconnecting " << m_socket->remoteEndpoint() << " (Handshake Timeout)";
			cancel();
		}
	});
}
<|endoftext|>


<commit_before>#ifndef PUBNUB__PubNub_hpp
#define PUBNUB__PubNub_hpp

#include <string>
#include <vector>

#include <json.h>

#include <pubnub.h>

/** PubNub structures and constants */

struct pubnub;
class PubNub;

/* Callback functions to user code upon completion of various methods. */
/* Note that if the function wants to preserve the response, it should
 * bump its reference count, otherwise it will be auto-released after
 * callback is done. channels[], on the other hand, are dynamically
 * allocated and both the array and its individual items must be free()d
 * by the callee; to ease iteration by user code, there is guaranteed to
 * be as many elements as there are messages in the channels list, and
 * an extra NULL pointer at the end of the array. */
typedef void (*PubNub_publish_cb)(PubNub &p, enum pubnub_res result, json_object *response, void *ctx_data, void *call_data);
typedef void (*PubNub_subscribe_cb)(PubNub &p, enum pubnub_res result, std::vector<std::string> &channels, json_object *response, void *ctx_data, void *call_data);
typedef void (*PubNub_history_cb)(PubNub &p, enum pubnub_res result, json_object *response, void *ctx_data, void *call_data);
typedef void (*PubNub_here_now_cb)(PubNub &p, enum pubnub_res result, json_object *response, void *ctx_data, void *call_data);
typedef void (*PubNub_time_cb)(PubNub &p, enum pubnub_res result, json_object *response, void *ctx_data, void *call_data);

/* Only one method may operate on a single context at once - this means
 * that if a subscribe is in progress, you cannot publish in the same
 * context; either wait or use multiple contexts. If the same context
 * is used in multiple threads, the application must ensure locking to
 * prevent improper concurrent access. */

class PubNub {
public:

	/** PubNub context methods */

	/* Initialize the PubNub context and set the compulsory parameters
	 * @publish_key and @subscribe_key.
	 *
	 * @cb is a set of callbacks implementing libpubnub's needs for
	 * socket and timer handling, plus default completion callbacks
	 * for the API requests.  Typically, @cb value will be a structure
	 * exported by one of the frontends and @cb_data will be the
	 * appropriate frontend context.  However, you can also customize
	 * these or pass your own structure.
	 *
	 * This function will also initialize the libcurl library. This has
	 * an important connotation for multi-threaded programs, as the first
	 * call to this function will imply curl_global_init() call and that
	 * function is completely thread unsafe. If you need to call
	 * pubnub_init() with other threads already running (and not even
	 * necessarily doing anything PubNub-related), call curl_global_init()
	 * early before spawning other threads.
	 *
	 * One PubNub context can service only a single request at a time
	 * (and you must not access it from multiple threads at once), however
	 * you can maintain as many contexts as you wish. */
	PubNub(const std::string &publish_key, const std::string &subscribe_key,
		const struct pubnub_callbacks *cb, void *cb_data);

	/* You can also create a PubNub wrapper class from an existing pubnub
	 * context. @p_autodestroy determines whether PubNub destructor will
	 * call pubnub_done(p). */
	PubNub(struct pubnub *p, bool p_autodestroy = false);

	/* Deinitialize our PubNub context, freeing all memory that is
	 * associated with it. */
	~PubNub();

	/* Set the secret key that is used for signing published messages
	 * to confirm they are genuine. Using the secret key is optional. */
	void set_secret_key(const std::string &secret_key);

	/* Set the cipher key that is used for symmetric encryption of messages
	 * passed over the network (publish, subscribe, history). Using the
	 * cipher key is optional. */
	void set_cipher_key(const std::string &cipher_key);

	/* Set the origin server name. By default, http://pubsub.pubnub.com/
	 * is used. */
	void set_origin(const std::string &origin);

	/* Retrieve the currently used UUID of this PubNub context. This UUID
	 * is visible to other clients via the here_now call and is normally
	 * autogenerated randomly during pubnub_init(). */
	std::string current_uuid();

	/* Set the UUID of this PubNub context that is asserted during the
	 * subscribe call to identify us. This replaces the autogenerated
	 * UUID. */
	void set_uuid(const std::string &uuid);

	/* This function selects the value of CURLOPT_NOSIGNAL which involves
	 * a tradeoff:
	 *
	 * (i) nosignal is true (DEFAULT) - the library is thread safe and does
	 * not modify signal handlers, however timeout handling will be broken
	 * with regards to DNS requests
	 *
	 * (ii) nosignal is false - DNS requests will be timing out properly,
	 * but the library will install custom SIGPIPE (and possibly SIGCHLD)
	 * handlers and won't be thread safe */
	void set_nosignal(bool nosignal);

	/* Set PubNub error retry policy regarding error handling.
	 *
	 * The call may be retried if the error is possibly recoverable
	 * and retry is enabled for that error. This is controlled by
	 * @retry_mask; if PNR_xxx-th bit is set, the call is retried in case
	 * of the PNR_xxx result; this is the case for recoverable errors,
	 * specifically PNR_OK and PNR_OCCUPIED bits are always ignored (this
	 * may be further extended in the future). For example,
	 *
	 * 	pubnub_error_policy(p, 0, ...);
	 * will turn off automatic error retry for all errors,
	 *
	 * 	pubnub_error_policy(p, ~0, ...);
	 * will turn it on for all recoverable errors (this is the DEFAULT),
	 *
	 * 	pubnub_error_policy(p, ~(1<<PNR_TIMEOUT), ...);
	 * will turn it on for all errors *except* PNR_TIMEOUT, and so on.
	 *
	 * If the call is not automatically retried after an error, the error
	 * is reported to the application via its specified callback instead
	 * (if you use the pubnub_sync frontend, it can be obtained from
	 * pubnub_last_result(); for future compatibility, you should ideally
	 * check it even when relying on automatic error retry).
	 *
	 * A message about the error is printed on stderr if @print is true
	 * (the DEFAULT); this applies even to errors after which we do not
	 * retry for whatever reason. */
	void error_policy(unsigned int retry_mask, bool print);

	/** PubNub API requests */

	/* All the API request functions accept the @timeout [s] parameter
	 * and callback parameters @cb and @cb_data.
	 *
	 * The @timeout [s] parameter describes how long to wait for request
	 * fulfillment before the PNR_TIMEOUT error is generated. Supply -1
	 * if in doubt to obtain the optimal default value. (Note that normally,
	 * PNR_TIMEOUT will just print a message and retry the request; see
	 * pubnub_error_policy() above.)
	 *
	 * If you are using the pubnub_sync frontend, the function calls
	 * will block until the request is fulfilled and you should pass
	 * NULL for @cb and @cb_data. If you are using the pubnub_libevent
	 * or a custom frontend, the function calls will return immediately
	 * and @cb shall point to a function that will be called upon
	 * completion (with @cb_data as its last parameter). */

	/* Publish the @message JSON object on @channel. The response
	 * will usually be just a success confirmation. */
	void publish(const std::string &channel, json_object &message,
			long timeout = -1, PubNub_publish_cb cb = NULL, void *cb_data = NULL);

	/* Subscribe to @channel. The response will be a JSON array with
	 * one received message per item.
	 *
	 * Messages published on @channel since the last subscribe call
	 * are returned.  The first call will typically just establish
	 * the context and return immediately with an empty response array.
	 * Usually, you would issue the subscribe request in a loop. */
	void subscribe(const std::string &channel,
			long timeout = -1, PubNub_subscribe_cb cb = NULL, void *cb_data = NULL);

	/* Subscribe to a set of @channels. The response will contain
	 * received messages from any of these channels; use the channels
	 * callback parameter (or pubnub_sync_last_channels()) to determine
	 * the originating channel of each message. */
	void subscribe_multi(const std::vector<std::string> &channels,
			long timeout = -1, PubNub_subscribe_cb cb = NULL, void *cb_data = NULL);

	/* List the last @limit messages that appeared on a @channel.
	 * You do not need to be subscribed to the channel. The response
	 * will be a JSON array with one message per item. */
	void history(const std::string &channel, int limit,
			long timeout = -1, PubNub_history_cb cb = NULL, void *cb_data = NULL);

	/* List the clients subscribed to @channel. The response will be
	 * a JSON object with attributes "occupancy" (number of clients)
	 * and "uuids" (array of client UUIDs). */
	void here_now(const std::string &channel,
			long timeout = -1, PubNub_here_now_cb cb = NULL, void *cb_data = NULL);

	/* Retrieve the server timestamp (number of microseconds since
	 * 1970-01-01), stored as JSON value in the response. You can use
	 * this as a sort of "ping" message e.g. to estimate network lag,
	 * or if you do not trust the system time. */
	void time(long timeout = -1, PubNub_time_cb cb = NULL, void *cb_data = NULL);

protected:
	struct pubnub *p;
	bool p_autodestroy;
};

#endif
<commit_msg>libpubnub-cpp/pubnub.hpp: Mention enum pubnub_res, referring pubnub.h<commit_after>#ifndef PUBNUB__PubNub_hpp
#define PUBNUB__PubNub_hpp

#include <string>
#include <vector>

#include <json.h>

#include <pubnub.h>

/** PubNub structures and constants */

struct pubnub;
class PubNub;

/* The PubNub methods return result codes as listed in enum pubnub_res.
 * Please refer to pubnub.h for their listing and brief description. */

/* Callback functions to user code upon completion of various methods. */
/* Note that if the function wants to preserve the response, it should
 * bump its reference count, otherwise it will be auto-released after
 * callback is done. channels[], on the other hand, are dynamically
 * allocated and both the array and its individual items must be free()d
 * by the callee; to ease iteration by user code, there is guaranteed to
 * be as many elements as there are messages in the channels list, and
 * an extra NULL pointer at the end of the array. */
typedef void (*PubNub_publish_cb)(PubNub &p, enum pubnub_res result, json_object *response, void *ctx_data, void *call_data);
typedef void (*PubNub_subscribe_cb)(PubNub &p, enum pubnub_res result, std::vector<std::string> &channels, json_object *response, void *ctx_data, void *call_data);
typedef void (*PubNub_history_cb)(PubNub &p, enum pubnub_res result, json_object *response, void *ctx_data, void *call_data);
typedef void (*PubNub_here_now_cb)(PubNub &p, enum pubnub_res result, json_object *response, void *ctx_data, void *call_data);
typedef void (*PubNub_time_cb)(PubNub &p, enum pubnub_res result, json_object *response, void *ctx_data, void *call_data);

/* Only one method may operate on a single context at once - this means
 * that if a subscribe is in progress, you cannot publish in the same
 * context; either wait or use multiple contexts. If the same context
 * is used in multiple threads, the application must ensure locking to
 * prevent improper concurrent access. */

class PubNub {
public:

	/** PubNub context methods */

	/* Initialize the PubNub context and set the compulsory parameters
	 * @publish_key and @subscribe_key.
	 *
	 * @cb is a set of callbacks implementing libpubnub's needs for
	 * socket and timer handling, plus default completion callbacks
	 * for the API requests.  Typically, @cb value will be a structure
	 * exported by one of the frontends and @cb_data will be the
	 * appropriate frontend context.  However, you can also customize
	 * these or pass your own structure.
	 *
	 * This function will also initialize the libcurl library. This has
	 * an important connotation for multi-threaded programs, as the first
	 * call to this function will imply curl_global_init() call and that
	 * function is completely thread unsafe. If you need to call
	 * pubnub_init() with other threads already running (and not even
	 * necessarily doing anything PubNub-related), call curl_global_init()
	 * early before spawning other threads.
	 *
	 * One PubNub context can service only a single request at a time
	 * (and you must not access it from multiple threads at once), however
	 * you can maintain as many contexts as you wish. */
	PubNub(const std::string &publish_key, const std::string &subscribe_key,
		const struct pubnub_callbacks *cb, void *cb_data);

	/* You can also create a PubNub wrapper class from an existing pubnub
	 * context. @p_autodestroy determines whether PubNub destructor will
	 * call pubnub_done(p). */
	PubNub(struct pubnub *p, bool p_autodestroy = false);

	/* Deinitialize our PubNub context, freeing all memory that is
	 * associated with it. */
	~PubNub();

	/* Set the secret key that is used for signing published messages
	 * to confirm they are genuine. Using the secret key is optional. */
	void set_secret_key(const std::string &secret_key);

	/* Set the cipher key that is used for symmetric encryption of messages
	 * passed over the network (publish, subscribe, history). Using the
	 * cipher key is optional. */
	void set_cipher_key(const std::string &cipher_key);

	/* Set the origin server name. By default, http://pubsub.pubnub.com/
	 * is used. */
	void set_origin(const std::string &origin);

	/* Retrieve the currently used UUID of this PubNub context. This UUID
	 * is visible to other clients via the here_now call and is normally
	 * autogenerated randomly during pubnub_init(). */
	std::string current_uuid();

	/* Set the UUID of this PubNub context that is asserted during the
	 * subscribe call to identify us. This replaces the autogenerated
	 * UUID. */
	void set_uuid(const std::string &uuid);

	/* This function selects the value of CURLOPT_NOSIGNAL which involves
	 * a tradeoff:
	 *
	 * (i) nosignal is true (DEFAULT) - the library is thread safe and does
	 * not modify signal handlers, however timeout handling will be broken
	 * with regards to DNS requests
	 *
	 * (ii) nosignal is false - DNS requests will be timing out properly,
	 * but the library will install custom SIGPIPE (and possibly SIGCHLD)
	 * handlers and won't be thread safe */
	void set_nosignal(bool nosignal);

	/* Set PubNub error retry policy regarding error handling.
	 *
	 * The call may be retried if the error is possibly recoverable
	 * and retry is enabled for that error. This is controlled by
	 * @retry_mask; if PNR_xxx-th bit is set, the call is retried in case
	 * of the PNR_xxx result; this is the case for recoverable errors,
	 * specifically PNR_OK and PNR_OCCUPIED bits are always ignored (this
	 * may be further extended in the future). For example,
	 *
	 * 	pubnub_error_policy(p, 0, ...);
	 * will turn off automatic error retry for all errors,
	 *
	 * 	pubnub_error_policy(p, ~0, ...);
	 * will turn it on for all recoverable errors (this is the DEFAULT),
	 *
	 * 	pubnub_error_policy(p, ~(1<<PNR_TIMEOUT), ...);
	 * will turn it on for all errors *except* PNR_TIMEOUT, and so on.
	 *
	 * If the call is not automatically retried after an error, the error
	 * is reported to the application via its specified callback instead
	 * (if you use the pubnub_sync frontend, it can be obtained from
	 * pubnub_last_result(); for future compatibility, you should ideally
	 * check it even when relying on automatic error retry).
	 *
	 * A message about the error is printed on stderr if @print is true
	 * (the DEFAULT); this applies even to errors after which we do not
	 * retry for whatever reason. */
	void error_policy(unsigned int retry_mask, bool print);

	/** PubNub API requests */

	/* All the API request functions accept the @timeout [s] parameter
	 * and callback parameters @cb and @cb_data.
	 *
	 * The @timeout [s] parameter describes how long to wait for request
	 * fulfillment before the PNR_TIMEOUT error is generated. Supply -1
	 * if in doubt to obtain the optimal default value. (Note that normally,
	 * PNR_TIMEOUT will just print a message and retry the request; see
	 * pubnub_error_policy() above.)
	 *
	 * If you are using the pubnub_sync frontend, the function calls
	 * will block until the request is fulfilled and you should pass
	 * NULL for @cb and @cb_data. If you are using the pubnub_libevent
	 * or a custom frontend, the function calls will return immediately
	 * and @cb shall point to a function that will be called upon
	 * completion (with @cb_data as its last parameter). */

	/* Publish the @message JSON object on @channel. The response
	 * will usually be just a success confirmation. */
	void publish(const std::string &channel, json_object &message,
			long timeout = -1, PubNub_publish_cb cb = NULL, void *cb_data = NULL);

	/* Subscribe to @channel. The response will be a JSON array with
	 * one received message per item.
	 *
	 * Messages published on @channel since the last subscribe call
	 * are returned.  The first call will typically just establish
	 * the context and return immediately with an empty response array.
	 * Usually, you would issue the subscribe request in a loop. */
	void subscribe(const std::string &channel,
			long timeout = -1, PubNub_subscribe_cb cb = NULL, void *cb_data = NULL);

	/* Subscribe to a set of @channels. The response will contain
	 * received messages from any of these channels; use the channels
	 * callback parameter (or pubnub_sync_last_channels()) to determine
	 * the originating channel of each message. */
	void subscribe_multi(const std::vector<std::string> &channels,
			long timeout = -1, PubNub_subscribe_cb cb = NULL, void *cb_data = NULL);

	/* List the last @limit messages that appeared on a @channel.
	 * You do not need to be subscribed to the channel. The response
	 * will be a JSON array with one message per item. */
	void history(const std::string &channel, int limit,
			long timeout = -1, PubNub_history_cb cb = NULL, void *cb_data = NULL);

	/* List the clients subscribed to @channel. The response will be
	 * a JSON object with attributes "occupancy" (number of clients)
	 * and "uuids" (array of client UUIDs). */
	void here_now(const std::string &channel,
			long timeout = -1, PubNub_here_now_cb cb = NULL, void *cb_data = NULL);

	/* Retrieve the server timestamp (number of microseconds since
	 * 1970-01-01), stored as JSON value in the response. You can use
	 * this as a sort of "ping" message e.g. to estimate network lag,
	 * or if you do not trust the system time. */
	void time(long timeout = -1, PubNub_time_cb cb = NULL, void *cb_data = NULL);

protected:
	struct pubnub *p;
	bool p_autodestroy;
};

#endif
<|endoftext|>


<commit_before>#include <boost/foreach.hpp>
#include "bayesian/graph.hpp"
#include "bayesian/bp.hpp"

namespace bn {

matrix_type bp::operator()(
    graph_t const& graph,
    vertex_type const& node,
    std::vector<std::pair<vertex_type, int>> const& condition
    )
{
    // 前後の要素に伝播させる
    auto const e_minus = propagate_forward(graph, node, condition);
    auto const e_plus = propagate_backward(graph, node, condition);

    // 掛け算
    auto const elem_num = node->selectable_num;
    double sum = 0.0;
    matrix_type mat(elem_num, 1);
    for(std::size_t i = 0; i < e_minus.height(); ++i)
    {
        double const product = e_minus[i][0] * e_plus[0][i];
        sum += product;
        mat[i][0] = product;
    }

    // 正規化
    for(std::size_t i = 0; i < e_minus.height(); ++i)
    {
        mat[i][0] /= sum;
    }

    return mat;
}

std::pair<bool, int> find_condition(
    vertex_type const& node,
    std::vector<std::pair<vertex_type, int>> const& condition
    )
{
    for(auto const& c : condition)
    {
        if(c.first == node)
        {
            return std::make_pair(true, c.second);
        }
    }

    return std::make_pair(false, 0);
}

// 下流要素の確率推論
matrix_type bp::propagate_forward(
    graph_t const& graph,
    vertex_type const& node,
    std::vector<std::pair<vertex_type, int>> const& condition
    )
{
    // node ∈ condition
    auto is_condition = find_condition(node, condition);
    if(is_condition.first)
    {
        auto const elem_num = node->selectable_num;
        matrix_type mat(elem_num, 1);
        for(int i = 0; i < elem_num; ++i)
        {
            mat[i][0] = (i == is_condition.second) ? 1 : 0;
        }
        return mat;
    }

    // conditionに含まれないから伝播 (e-要素)
    auto const out_edges = graph.out_edges(node);
    if(!out_edges.empty())
    {
        auto const elem_num = node->selectable_num;
        matrix_type mat(elem_num, 1, 1);

        BOOST_FOREACH(auto const& edge, out_edges)
        {
            if(!edge->likelihood.first) throw std::runtime_error("no set edge of likelihood");
            mat = mat % (edge->likelihood.second * propagate_forward(graph, graph.target(edge), condition));
        }

        return mat;
    }

    // 末端は全ての確率が等しいとする
    auto const elem_num = node->selectable_num;
    matrix_type mat(elem_num, 1);
    for(int i = 0; i < elem_num; ++i)
    {
        mat[i][0] = 1.0;
    }
    return mat;
}

// 上流要素の確率推論
matrix_type bp::propagate_backward(
    graph_t const& graph,
    vertex_type const& node,
    std::vector<std::pair<vertex_type, int>> const& condition
    )
{
    // node ∈ condition
    auto is_condition = find_condition(node, condition);
    if(is_condition.first)
    {
        auto const elem_num = node->selectable_num;
        matrix_type mat(1, elem_num);
        for(int i = 0; i < elem_num; ++i)
        {
            mat[0][i] = (i == is_condition.second) ? 1 : 0;
        }
        return mat;
    }

    // conditionに含まれないから伝播 (e+要素)
    auto const in_edges = graph.in_edges(node);
    if(!in_edges.empty())
    {
        auto const elem_num = node->selectable_num;
        matrix_type mat(1, elem_num, 1);

        BOOST_FOREACH(auto const& edge, in_edges)
        {
            if(!edge->likelihood.first) throw std::runtime_error("no set edge of likelihood");
            mat = mat % (propagate_backward(graph, graph.source(edge), condition) * edge->likelihood.second);
        }

        return mat;
    }

    // 最上位ノードは事前確率を割り当てる
    auto& e = node->evidence;
    if(e.first)
    {
        return e.second;
    }
    else
    {
        throw std::runtime_error("highest node doesn't have prior probability.");
    }
}

} // namespace bn

<commit_msg>refactoring: bp process's duplicated code.<commit_after>#include <boost/foreach.hpp>
#include "bayesian/graph.hpp"
#include "bayesian/bp.hpp"

namespace bn {

matrix_type bp::operator()(
    graph_t const& graph,
    vertex_type const& node,
    std::vector<std::pair<vertex_type, int>> const& condition
    )
{
    // 前後の要素に伝播させる
    auto const e_minus = propagate_forward(graph, node, condition);
    auto const e_plus = propagate_backward(graph, node, condition);

    // 掛け算
    auto const elem_num = node->selectable_num;
    double sum = 0.0;
    matrix_type mat(elem_num, 1);
    for(std::size_t i = 0; i < e_minus.height(); ++i)
    {
        double const product = e_minus[i][0] * e_plus[0][i];
        sum += product;
        mat[i][0] = product;
    }

    // 正規化
    for(std::size_t i = 0; i < e_minus.height(); ++i)
    {
        mat[i][0] /= sum;
    }

    return mat;
}

std::pair<bool, int> find_condition(
    vertex_type const& node,
    std::vector<std::pair<vertex_type, int>> const& condition
    )
{
    for(auto const& c : condition)
    {
        if(c.first == node)
        {
            return std::make_pair(true, c.second);
        }
    }

    return std::make_pair(false, 0);
}

// 下流要素の確率推論
matrix_type bp::propagate_forward(
    graph_t const& graph,
    vertex_type const& node,
    std::vector<std::pair<vertex_type, int>> const& condition
    )
{
    auto const elem_num = node->selectable_num;
    matrix_type mat(elem_num, 1, 1);

    // node ∈ condition
    auto is_condition = find_condition(node, condition);
    if(is_condition.first)
    {
        for(int i = 0; i < elem_num; ++i)
        {
            mat[i][0] = (i == is_condition.second) ? 1 : 0;
        }
        return mat;
    }

    // conditionに含まれないから伝播 (e-要素)
    auto const out_edges = graph.out_edges(node);
    if(!out_edges.empty())
    {
        BOOST_FOREACH(auto const& edge, out_edges)
        {
            if(!edge->likelihood.first) throw std::runtime_error("no set edge of likelihood");
            mat = mat % (edge->likelihood.second * propagate_forward(graph, graph.target(edge), condition));
        }

        return mat;
    }

    // 末端は全ての確率が等しいとする
    for(int i = 0; i < elem_num; ++i)
    {
        mat[i][0] = 1.0;
    }
    return mat;
}

// 上流要素の確率推論
matrix_type bp::propagate_backward(
    graph_t const& graph,
    vertex_type const& node,
    std::vector<std::pair<vertex_type, int>> const& condition
    )
{
    auto const elem_num = node->selectable_num;
    matrix_type mat(1, elem_num, 1);

    // node ∈ condition
    auto is_condition = find_condition(node, condition);
    if(is_condition.first)
    {
        for(int i = 0; i < elem_num; ++i)
        {
            mat[0][i] = (i == is_condition.second) ? 1 : 0;
        }
        return mat;
    }

    // conditionに含まれないから伝播 (e+要素)
    auto const in_edges = graph.in_edges(node);
    if(!in_edges.empty())
    {
        BOOST_FOREACH(auto const& edge, in_edges)
        {
            if(!edge->likelihood.first) throw std::runtime_error("no set edge of likelihood");
            mat = mat % (propagate_backward(graph, graph.source(edge), condition) * edge->likelihood.second);
        }

        return mat;
    }

    // 最上位ノードは事前確率を割り当てる
    auto& e = node->evidence;
    if(e.first)
    {
        return e.second;
    }
    else
    {
        throw std::runtime_error("highest node doesn't have prior probability.");
    }
}

} // namespace bn

<|endoftext|>


<commit_before>/*
    Crystal Space input library
    Copyright (C) 1998 by Jorrit Tyberghein
    Written by Andrew Zabolotny <bit@eltech.ru>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 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
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "sysdef.h"
#include "cssys/system.h"
#include "csinput/csinput.h"
#include "csutil/inifile.h"
#include "isystem.h"

// This array defines first 32..128 character codes with SHIFT key applied
char ShiftedKey [128-32] =
{
  ' ', '!', '"', '#', '$', '%', '&', '"', '(', ')', '*', '+', '<', '_', '>', '?',
  ')', '!', '@', '#', '$', '%', '^', '&', '*', '(', ':', ':', '<', '+', '>', '?',
  '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
  'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '{', '|', '}', '^', '_',
  '~', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
  'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '{', '|', '}', '~', 127
};

// And this one performs backward conversion
char UnshiftedKey [128-32] =
{
  ' ', '1', '\'','3', '4', '5', '7', '\'','9', '0', '8', '=', ',', '-', '.', '/',
  '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ';', ';', ',', '=', '.', '/',
  '2', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
  'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '[', '\\',']', '6', '-',
  '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
  'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '[', '\\',']', '`', 127
};

//--//--//--//--//--//--//--//--//--//--//--//--//--/> Keyboard driver <--//--//

csKeyboardDriver::csKeyboardDriver ()
{
  EventQueue = NULL;
  Reset ();
}

csKeyboardDriver::~csKeyboardDriver ()
{
  Close ();
}

bool csKeyboardDriver::Open (csEventQueue *EvQueue)
{
  EventQueue = EvQueue;
  Reset ();
  return (EvQueue != NULL);
}

void csKeyboardDriver::Close ()
{
  // no-op
}

void csKeyboardDriver::Reset ()
{
  memset (KeyState, 0, sizeof (KeyState));
}

void csKeyboardDriver::do_keypress (time_t evtime, int key)
{
  int smask = (GetKeyState (CSKEY_SHIFT) ? CSMASK_SHIFT : 0)
            | (GetKeyState (CSKEY_CTRL) ? CSMASK_CTRL : 0)
            | (GetKeyState (CSKEY_ALT) ? CSMASK_ALT : 0);
  if (!GetKeyState (key))
    smask |= CSMASK_FIRST;
  if ((key >= 32) && (key < 128))
    if (GetKeyState (CSKEY_SHIFT))
      key = ShiftedKey [key - 32];
  if (EventQueue)
    CHKB (EventQueue->Put (new csEvent (evtime, csevKeyDown, key, smask)));
  SetKeyState (key, true);
}

void csKeyboardDriver::do_keyrelease (time_t evtime, int key)
{
  if ((key >= 32) && (key < 128))
    if (GetKeyState (CSKEY_SHIFT))
      key = ShiftedKey [key - 32];
  if (EventQueue)
    CHKB (EventQueue->Put (new csEvent (evtime, csevKeyUp, key, 0)));
  SetKeyState (key, false);
}

void csKeyboardDriver::SetKeyState (int key, bool state)
{
  int idx = (key < 256) ? key : (256 + key - CSKEY_FIRST);
  KeyState [idx] = state;
}

bool csKeyboardDriver::GetKeyState (int key)
{
  int idx = (key < 256) ? key : (256 + key - CSKEY_FIRST);
  return KeyState [idx];
}

//--//--//--//--//--//--//--//--//--//--//--//--//--//--> Mouse driver <--//--//

time_t csMouseDriver::DoubleClickTime;
size_t csMouseDriver::DoubleClickDist;

csMouseDriver::csMouseDriver ()
{
  EventQueue = NULL;
  Reset ();
}

csMouseDriver::~csMouseDriver ()
{
  Close ();
}

bool csMouseDriver::Open (iSystem* System, csEventQueue *EvQueue)
{
  EventQueue = EvQueue;
  Reset ();
  DoubleClickTime = System->ConfigGetInt ("MouseDriver", "DoubleClockTime", 300);
  DoubleClickDist = System->ConfigGetInt ("MouseDriver", "DoubleClickDist", 2);
  LastMouseX = LastMouseY = -99999;
  return (EvQueue != NULL);
}

void csMouseDriver::Close ()
{
  // no-op
}

void csMouseDriver::Reset ()
{
  if (EventQueue)
  {
    for (int i = 1; i < 10; i++)
      if (Button[i])
        do_buttonrelease (SysGetTime (), i, 0, 0);
  }
  else
    memset (Button, 0, sizeof (Button));
  LastClickButton = -1;
}

void csMouseDriver::do_buttonpress (time_t evtime, int button, int x, int y, bool shift,
  bool alt, bool ctrl)
{
  int smask = (shift ? CSMASK_SHIFT : 0)
            | (alt ? CSMASK_ALT : 0)
            | (ctrl ? CSMASK_CTRL : 0);
  Button [button] = true;

  int ev = csevMouseDown;

  if ((button == LastClickButton)
   && (evtime - LastClickTime <= DoubleClickTime)
   && (unsigned (ABS (x - LastClickX)) <= DoubleClickDist)
   && (unsigned (ABS (y - LastClickY)) <= DoubleClickDist))
    ev = csevMouseDoubleClick;
  LastClickButton = button;
  LastClickTime = evtime;
  LastMouseX = LastClickX = x;
  LastMouseY = LastClickY = y;

  if (EventQueue)
  {
    CHK (EventQueue->Put (new csEvent (evtime, ev, x, y, button, smask)));
  }
}

void csMouseDriver::do_buttonrelease (time_t evtime, int button, int x, int y)
{
  Button [button] = false;
  if (EventQueue)
  {
    CHK (EventQueue->Put (new csEvent (evtime, csevMouseUp, x, y, button, 0)));
  }
}

void csMouseDriver::do_mousemotion (time_t evtime, int x, int y)
{
  if ((x != LastMouseX)
   || (y != LastMouseY))
  {
    LastMouseX = x;
    LastMouseY = y;

    if (EventQueue)
    {
      CHK (EventQueue->Put (new csEvent (evtime, csevMouseMove, x, y, 0, 0)));
    }
  }
}
<commit_msg>Added Event.Key.ShiftKeys filling for csKeyUp messages as suggested by W.C.A. Wijngaards <wouterw@karveel.cs.vu.nl><commit_after>/*
    Crystal Space input library
    Copyright (C) 1998 by Jorrit Tyberghein
    Written by Andrew Zabolotny <bit@eltech.ru>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 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
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "sysdef.h"
#include "cssys/system.h"
#include "csinput/csinput.h"
#include "csutil/inifile.h"
#include "isystem.h"

// This array defines first 32..128 character codes with SHIFT key applied
char ShiftedKey [128-32] =
{
  ' ', '!', '"', '#', '$', '%', '&', '"', '(', ')', '*', '+', '<', '_', '>', '?',
  ')', '!', '@', '#', '$', '%', '^', '&', '*', '(', ':', ':', '<', '+', '>', '?',
  '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
  'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '{', '|', '}', '^', '_',
  '~', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
  'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '{', '|', '}', '~', 127
};

// And this one performs backward conversion
char UnshiftedKey [128-32] =
{
  ' ', '1', '\'','3', '4', '5', '7', '\'','9', '0', '8', '=', ',', '-', '.', '/',
  '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ';', ';', ',', '=', '.', '/',
  '2', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
  'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '[', '\\',']', '6', '-',
  '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
  'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '[', '\\',']', '`', 127
};

//--//--//--//--//--//--//--//--//--//--//--//--//--/> Keyboard driver <--//--//

csKeyboardDriver::csKeyboardDriver ()
{
  EventQueue = NULL;
  Reset ();
}

csKeyboardDriver::~csKeyboardDriver ()
{
  Close ();
}

bool csKeyboardDriver::Open (csEventQueue *EvQueue)
{
  EventQueue = EvQueue;
  Reset ();
  return (EvQueue != NULL);
}

void csKeyboardDriver::Close ()
{
  // no-op
}

void csKeyboardDriver::Reset ()
{
  memset (KeyState, 0, sizeof (KeyState));
}

void csKeyboardDriver::do_keypress (time_t evtime, int key)
{
  int smask = (GetKeyState (CSKEY_SHIFT) ? CSMASK_SHIFT : 0)
            | (GetKeyState (CSKEY_CTRL) ? CSMASK_CTRL : 0)
            | (GetKeyState (CSKEY_ALT) ? CSMASK_ALT : 0);
  if (!GetKeyState (key))
    smask |= CSMASK_FIRST;
  if ((key >= 32) && (key < 128))
    if (GetKeyState (CSKEY_SHIFT))
      key = ShiftedKey [key - 32];
  if (EventQueue)
    CHKB (EventQueue->Put (new csEvent (evtime, csevKeyDown, key, smask)));
  SetKeyState (key, true);
}

void csKeyboardDriver::do_keyrelease (time_t evtime, int key)
{
  int smask = (GetKeyState (CSKEY_SHIFT) ? CSMASK_SHIFT : 0)
            | (GetKeyState (CSKEY_CTRL) ? CSMASK_CTRL : 0)
            | (GetKeyState (CSKEY_ALT) ? CSMASK_ALT : 0);
  if ((key >= 32) && (key < 128))
    if (GetKeyState (CSKEY_SHIFT))
      key = ShiftedKey [key - 32];
  if (EventQueue)
    CHKB (EventQueue->Put (new csEvent (evtime, csevKeyUp, key, smask)));
  SetKeyState (key, false);
}

void csKeyboardDriver::SetKeyState (int key, bool state)
{
  int idx = (key < 256) ? key : (256 + key - CSKEY_FIRST);
  KeyState [idx] = state;
}

bool csKeyboardDriver::GetKeyState (int key)
{
  int idx = (key < 256) ? key : (256 + key - CSKEY_FIRST);
  return KeyState [idx];
}

//--//--//--//--//--//--//--//--//--//--//--//--//--//--> Mouse driver <--//--//

time_t csMouseDriver::DoubleClickTime;
size_t csMouseDriver::DoubleClickDist;

csMouseDriver::csMouseDriver ()
{
  EventQueue = NULL;
  Reset ();
}

csMouseDriver::~csMouseDriver ()
{
  Close ();
}

bool csMouseDriver::Open (iSystem* System, csEventQueue *EvQueue)
{
  EventQueue = EvQueue;
  Reset ();
  DoubleClickTime = System->ConfigGetInt ("MouseDriver", "DoubleClockTime", 300);
  DoubleClickDist = System->ConfigGetInt ("MouseDriver", "DoubleClickDist", 2);
  LastMouseX = LastMouseY = -99999;
  return (EvQueue != NULL);
}

void csMouseDriver::Close ()
{
  // no-op
}

void csMouseDriver::Reset ()
{
  if (EventQueue)
  {
    for (int i = 1; i < 10; i++)
      if (Button[i])
        do_buttonrelease (SysGetTime (), i, 0, 0);
  }
  else
    memset (Button, 0, sizeof (Button));
  LastClickButton = -1;
}

void csMouseDriver::do_buttonpress (time_t evtime, int button, int x, int y, bool shift,
  bool alt, bool ctrl)
{
  int smask = (shift ? CSMASK_SHIFT : 0)
            | (alt ? CSMASK_ALT : 0)
            | (ctrl ? CSMASK_CTRL : 0);
  Button [button] = true;

  int ev = csevMouseDown;

  if ((button == LastClickButton)
   && (evtime - LastClickTime <= DoubleClickTime)
   && (unsigned (ABS (x - LastClickX)) <= DoubleClickDist)
   && (unsigned (ABS (y - LastClickY)) <= DoubleClickDist))
    ev = csevMouseDoubleClick;
  LastClickButton = button;
  LastClickTime = evtime;
  LastMouseX = LastClickX = x;
  LastMouseY = LastClickY = y;

  if (EventQueue)
  {
    CHK (EventQueue->Put (new csEvent (evtime, ev, x, y, button, smask)));
  }
}

void csMouseDriver::do_buttonrelease (time_t evtime, int button, int x, int y)
{
  Button [button] = false;
  if (EventQueue)
  {
    CHK (EventQueue->Put (new csEvent (evtime, csevMouseUp, x, y, button, 0)));
  }
}

void csMouseDriver::do_mousemotion (time_t evtime, int x, int y)
{
  if ((x != LastMouseX)
   || (y != LastMouseY))
  {
    LastMouseX = x;
    LastMouseY = y;

    if (EventQueue)
    {
      CHK (EventQueue->Put (new csEvent (evtime, csevMouseMove, x, y, 0, 0)));
    }
  }
}
<|endoftext|>


<commit_before>// RUN: %clang_cc1 -fexceptions -fcxx-exceptions -fms-extensions -fms-compatibility -fms-compatibility-version=19 -std=c++11 -emit-llvm %s -o - -triple=i386-pc-win32 | FileCheck %s
struct S {
  S();
  ~S();
};

// CHECK-DAG: @"\01?s@?1??f@@YAAAUS@@XZ@4U2@A" = linkonce_odr thread_local global %struct.S zeroinitializer
// CHECK-DAG: @"\01??__J?1??f@@YAAAUS@@XZ@51" = linkonce_odr thread_local global i32 0
// CHECK-DAG: @"\01?s@?1??g@@YAAAUS@@XZ@4U2@A" = linkonce_odr global %struct.S zeroinitializer
// CHECK-DAG: @"\01?$TSS0@?1??g@@YAAAUS@@XZ" = linkonce_odr global i32 0
// CHECK-DAG: @_Init_thread_epoch = external thread_local global i32, align 4

// CHECK-LABEL: define {{.*}} @"\01?f@@YAAAUS@@XZ"()
extern inline S &f() {
  static thread_local S s;
// CHECK:       %[[guard:.*]] = load i32, i32* @"\01??__J?1??f@@YAAAUS@@XZ@51"
// CHECK-NEXT:  %[[mask:.*]] = and i32 %[[guard]], 1
// CHECK-NEXT:  %[[cmp:.*]] = icmp ne i32 %[[mask]], 0
// CHECK-NEXT:  br i1 %[[cmp]], label %[[init_end:.*]], label %[[init:.*]]
//
// CHECK:     [[init]]:
// CHECK-NEXT:  %[[or:.*]] = or i32 %[[guard]], 1
// CHECK-NEXT:  store i32 %[[or]], i32* @"\01??__J?1??f@@YAAAUS@@XZ@51"
// CHECK-NEXT:  invoke {{.*}} @"\01??0S@@QAE@XZ"(%struct.S* @"\01?s@?1??f@@YAAAUS@@XZ@4U2@A")
// CHECK-NEXT:    to label %[[invoke_cont:.*]] unwind label %[[lpad:.*]]
//
// CHECK:     [[invoke_cont]]:
// CHECK-NEXT:  call i32 @__tlregdtor(void ()* @"\01??__Fs@?1??f@@YAAAUS@@XZ@YAXXZ")
// CHECK-NEXT:  br label %[[init_end:.*]]

// CHECK:     [[init_end]]:
// CHECK-NEXT:  ret %struct.S* @"\01?s@?1??f@@YAAAUS@@XZ@4U2@A"

// CHECK:     [[lpad:.*]]:
// CHECK-NEXT:  landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
// CHECK-NEXT:    cleanup
// CHECK:       %[[guard:.*]] = load i32, i32* @"\01??__J?1??f@@YAAAUS@@XZ@51"
// CHECK-NEXT:  %[[mask:.*]] = and i32 %[[guard]], -2
// CHECK-NEXT:  store i32 %[[mask]], i32* @"\01??__J?1??f@@YAAAUS@@XZ@51"
// CHECK-NEXT:  br label %[[eh_resume:.*]]
//
// CHECK:     [[eh_resume]]:
// CHECK:       resume { i8*, i32 }
  return s;
}

// CHECK-LABEL: define {{.*}} @"\01?g@@YAAAUS@@XZ"()
extern inline S &g() {
  static S s;
// CHECK:  %[[guard:.*]] = load atomic i32, i32* @"\01?$TSS0@?1??g@@YAAAUS@@XZ" unordered, align 4
// CHECK-NEXT:  %[[epoch:.*]] = load i32, i32* @_Init_thread_epoch
// CHECK-NEXT:  %[[cmp:.*]] = icmp sgt i32 %[[guard]], %[[epoch]]
// CHECK-NEXT:  br i1 %[[cmp]], label %[[init_attempt:.*]], label %[[init_end:.*]]
//
// CHECK:     [[init_attempt]]:
// CHECK-NEXT:  call void @_Init_thread_header(i32* @"\01?$TSS0@?1??g@@YAAAUS@@XZ")
// CHECK-NEXT:  %[[guard2:.*]] = load atomic i32, i32* @"\01?$TSS0@?1??g@@YAAAUS@@XZ" unordered, align 4
// CHECK-NEXT:  %[[cmp2:.*]] = icmp eq i32 %[[guard2]], -1
// CHECK-NEXT:  br i1 %[[cmp2]], label %[[init:.*]], label %[[init_end:.*]]
//
// CHECK:     [[init]]:
// CHECK-NEXT:  invoke {{.*}} @"\01??0S@@QAE@XZ"(%struct.S* @"\01?s@?1??g@@YAAAUS@@XZ@4U2@A")
// CHECK-NEXT:    to label %[[invoke_cont:.*]] unwind label %[[lpad:.*]]
//
// CHECK:     [[invoke_cont]]:
// CHECK-NEXT:  call i32 @atexit(void ()* @"\01??__Fs@?1??g@@YAAAUS@@XZ@YAXXZ")
// CHECK-NEXT:  call void @_Init_thread_footer(i32* @"\01?$TSS0@?1??g@@YAAAUS@@XZ")
// CHECK-NEXT:  br label %init.end
//
// CHECK:     [[init_end]]:
// CHECK-NEXT:  ret %struct.S* @"\01?s@?1??g@@YAAAUS@@XZ@4U2@A"
//
// CHECK:     [[lpad]]:
// CHECK:       call void @_Init_thread_abort(i32* @"\01?$TSS0@?1??g@@YAAAUS@@XZ")
// CHECK-NEXT:  br label %[[eh_resume:.*]]
//
// CHECK:     [[eh_resume]]:
// CHECK:       resume { i8*, i32 }
  return s;
}
<commit_msg>Mark clang/test/CodeGenCXX/microsoft-abi-thread-safe-statics.cpp as REQUIRES:asserts. It relies on label names.<commit_after>// RUN: %clang_cc1 -fexceptions -fcxx-exceptions -fms-extensions -fms-compatibility -fms-compatibility-version=19 -std=c++11 -emit-llvm %s -o - -triple=i386-pc-win32 | FileCheck %s
struct S {
  S();
  ~S();
};

// CHECK-DAG: @"\01?s@?1??f@@YAAAUS@@XZ@4U2@A" = linkonce_odr thread_local global %struct.S zeroinitializer
// CHECK-DAG: @"\01??__J?1??f@@YAAAUS@@XZ@51" = linkonce_odr thread_local global i32 0
// CHECK-DAG: @"\01?s@?1??g@@YAAAUS@@XZ@4U2@A" = linkonce_odr global %struct.S zeroinitializer
// CHECK-DAG: @"\01?$TSS0@?1??g@@YAAAUS@@XZ" = linkonce_odr global i32 0
// CHECK-DAG: @_Init_thread_epoch = external thread_local global i32, align 4

// CHECK-LABEL: define {{.*}} @"\01?f@@YAAAUS@@XZ"()
extern inline S &f() {
  static thread_local S s;
// CHECK:       %[[guard:.*]] = load i32, i32* @"\01??__J?1??f@@YAAAUS@@XZ@51"
// CHECK-NEXT:  %[[mask:.*]] = and i32 %[[guard]], 1
// CHECK-NEXT:  %[[cmp:.*]] = icmp ne i32 %[[mask]], 0
// CHECK-NEXT:  br i1 %[[cmp]], label %[[init_end:.*]], label %[[init:.*]]
//
// CHECK:     [[init]]:
// CHECK-NEXT:  %[[or:.*]] = or i32 %[[guard]], 1
// CHECK-NEXT:  store i32 %[[or]], i32* @"\01??__J?1??f@@YAAAUS@@XZ@51"
// CHECK-NEXT:  invoke {{.*}} @"\01??0S@@QAE@XZ"(%struct.S* @"\01?s@?1??f@@YAAAUS@@XZ@4U2@A")
// CHECK-NEXT:    to label %[[invoke_cont:.*]] unwind label %[[lpad:.*]]
//
// CHECK:     [[invoke_cont]]:
// CHECK-NEXT:  call i32 @__tlregdtor(void ()* @"\01??__Fs@?1??f@@YAAAUS@@XZ@YAXXZ")
// CHECK-NEXT:  br label %[[init_end:.*]]

// CHECK:     [[init_end]]:
// CHECK-NEXT:  ret %struct.S* @"\01?s@?1??f@@YAAAUS@@XZ@4U2@A"

// CHECK:     [[lpad:.*]]:
// CHECK-NEXT:  landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
// CHECK-NEXT:    cleanup
// CHECK:       %[[guard:.*]] = load i32, i32* @"\01??__J?1??f@@YAAAUS@@XZ@51"
// CHECK-NEXT:  %[[mask:.*]] = and i32 %[[guard]], -2
// CHECK-NEXT:  store i32 %[[mask]], i32* @"\01??__J?1??f@@YAAAUS@@XZ@51"
// CHECK-NEXT:  br label %[[eh_resume:.*]]
//
// CHECK:     [[eh_resume]]:
// CHECK:       resume { i8*, i32 }
  return s;
}

// CHECK-LABEL: define {{.*}} @"\01?g@@YAAAUS@@XZ"()
extern inline S &g() {
  static S s;
// CHECK:  %[[guard:.*]] = load atomic i32, i32* @"\01?$TSS0@?1??g@@YAAAUS@@XZ" unordered, align 4
// CHECK-NEXT:  %[[epoch:.*]] = load i32, i32* @_Init_thread_epoch
// CHECK-NEXT:  %[[cmp:.*]] = icmp sgt i32 %[[guard]], %[[epoch]]
// CHECK-NEXT:  br i1 %[[cmp]], label %[[init_attempt:.*]], label %[[init_end:.*]]
//
// CHECK:     [[init_attempt]]:
// CHECK-NEXT:  call void @_Init_thread_header(i32* @"\01?$TSS0@?1??g@@YAAAUS@@XZ")
// CHECK-NEXT:  %[[guard2:.*]] = load atomic i32, i32* @"\01?$TSS0@?1??g@@YAAAUS@@XZ" unordered, align 4
// CHECK-NEXT:  %[[cmp2:.*]] = icmp eq i32 %[[guard2]], -1
// CHECK-NEXT:  br i1 %[[cmp2]], label %[[init:.*]], label %[[init_end:.*]]
//
// CHECK:     [[init]]:
// CHECK-NEXT:  invoke {{.*}} @"\01??0S@@QAE@XZ"(%struct.S* @"\01?s@?1??g@@YAAAUS@@XZ@4U2@A")
// CHECK-NEXT:    to label %[[invoke_cont:.*]] unwind label %[[lpad:.*]]
//
// CHECK:     [[invoke_cont]]:
// CHECK-NEXT:  call i32 @atexit(void ()* @"\01??__Fs@?1??g@@YAAAUS@@XZ@YAXXZ")
// CHECK-NEXT:  call void @_Init_thread_footer(i32* @"\01?$TSS0@?1??g@@YAAAUS@@XZ")
// CHECK-NEXT:  br label %init.end
//
// CHECK:     [[init_end]]:
// CHECK-NEXT:  ret %struct.S* @"\01?s@?1??g@@YAAAUS@@XZ@4U2@A"
//
// CHECK:     [[lpad]]:
// CHECK:       call void @_Init_thread_abort(i32* @"\01?$TSS0@?1??g@@YAAAUS@@XZ")
// CHECK-NEXT:  br label %[[eh_resume:.*]]
//
// CHECK:     [[eh_resume]]:
// CHECK:       resume { i8*, i32 }
  return s;
}

// REQUIRES: asserts
<|endoftext|>


<commit_before>// RUN: %check_clang_tidy %s misc-suspicious-enum-usage %t -- -config="{CheckOptions: [{key: misc-suspicious-enum-usage.StrictMode, value: 1}]}" --

enum A {
  A = 1,
  B = 2,
  C = 4,
  D = 8,
  E = 16,
  F = 32,
  G = 63
};

// CHECK-MESSAGES: :[[@LINE+2]]:1: warning: enum type seems like a bitmask (contains mostly power-of-2 literals) but a literal is not power-of-2
// CHECK-MESSAGES: :76:7: note: used here as a bitmask
enum X {
  X = 8,
  Y = 16,
  Z = 4,
  ZZ = 3
  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: enum type seems like a bitmask (contains mostly power-of-2 literals), but this literal is not a power-of-2 [misc-suspicious-enum-usage]
// CHECK-MESSAGES: :70:13: note: used here as a bitmask
};
// CHECK-MESSAGES: :[[@LINE+2]]:1: warning: enum type seems like a bitmask (contains mostly power-of-2 literals) but some literals are not power-of-2
// CHECK-MESSAGES: :73:8: note: used here as a bitmask
enum PP {
  P = 2,
  Q = 3,
  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: enum type seems like a bitmask (contains mostly power-of-2 literals), but this literal is not a power-of-2
  // CHECK-MESSAGES: :65:11: note: used here as a bitmask
  R = 4,
  S = 8,
  T = 16,
  U = 31
};

enum {
  H,
  I,
  J,
  K,
  L
};

enum Days {
  Monday,
  Tuesday,
  Wednesday,
  Thursday,
  Friday,
  Saturday,
  Sunday
};

Days bestDay() {
  return Friday;
}

int trigger() {
  if (bestDay() | A)
    return 1;
  // CHECK-MESSAGES: :[[@LINE-2]]:17: warning: enum values are from different enum types
  if (I | Y)
    return 1;
  // CHECK-MESSAGES: :[[@LINE-2]]:9: warning: enum values are from different enum types
  if (P + Q == R)
    return 1;
  else if ((Q | R) == T)
    return 1;
  else
    int k = ZZ | Z;
  unsigned p = R;
  PP pp = Q;
  p |= pp;

  enum X x = Z;
  p = x | Z;
  return 0;
}

int dont_trigger() {
  int a = 1, b = 5;
  int c = a + b;
  int d = c | H, e = b * a;
  a = B | C;
  b = X | Z;

  unsigned bitflag;
  enum A aa = B;
  bitflag = aa | C;

  if (Tuesday != Monday + 1 ||
      Friday - Thursday != 1 ||
      Sunday + Wednesday == (Sunday | Wednesday))
    return 1;
  if (H + I + L == 42)
    return 1;
  return 42;
}
<commit_msg>Fix another nondeterminism in a tidy test.<commit_after>// RUN: %check_clang_tidy %s misc-suspicious-enum-usage %t -- -config="{CheckOptions: [{key: misc-suspicious-enum-usage.StrictMode, value: 1}]}" --

enum A {
  A = 1,
  B = 2,
  C = 4,
  D = 8,
  E = 16,
  F = 32,
  G = 63
};

// CHECK-MESSAGES: :[[@LINE+2]]:1: warning: enum type seems like a bitmask (contains mostly power-of-2 literals) but a literal is not power-of-2
// CHECK-MESSAGES: :76:7: note: used here as a bitmask
enum X {
  X = 8,
  Y = 16,
  Z = 4,
  ZZ = 3
  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: enum type seems like a bitmask (contains mostly power-of-2 literals), but this literal is not a power-of-2 [misc-suspicious-enum-usage]
// CHECK-MESSAGES: :70:13: note: used here as a bitmask
};
// CHECK-MESSAGES: :[[@LINE+2]]:1: warning: enum type seems like a bitmask (contains mostly power-of-2 literals) but some literals are not power-of-2
// CHECK-MESSAGES: :73:8: note: used here as a bitmask
enum PP {
  P = 2,
  Q = 3,
  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: enum type seems like a bitmask (contains mostly power-of-2 literals), but this literal is not a power-of-2
  // CHECK-MESSAGES: :65:11: note: used here as a bitmask
  R = 4,
  S = 8,
  T = 16,
  U = 31
};

enum {
  H,
  I,
  J,
  K,
  L
};

enum Days {
  Monday,
  Tuesday,
  Wednesday,
  Thursday,
  Friday,
  Saturday,
  Sunday
};

Days bestDay() {
  return Friday;
}

int trigger() {
  if (bestDay() | A)
    return 1;
  // CHECK-MESSAGES: :[[@LINE-2]]:17: warning: enum values are from different enum types
  if (I | Y)
    return 1;
  // CHECK-MESSAGES: :[[@LINE-2]]:9: warning: enum values are from different enum types
  if (P + Q == R)
    return 1;
  else if ((S | R) == T)
    return 1;
  else
    int k = ZZ | Z;
  unsigned p = R;
  PP pp = Q;
  p |= pp;

  enum X x = Z;
  p = x | Z;
  return 0;
}

int dont_trigger() {
  int a = 1, b = 5;
  int c = a + b;
  int d = c | H, e = b * a;
  a = B | C;
  b = X | Z;

  unsigned bitflag;
  enum A aa = B;
  bitflag = aa | C;

  if (Tuesday != Monday + 1 ||
      Friday - Thursday != 1 ||
      Sunday + Wednesday == (Sunday | Wednesday))
    return 1;
  if (H + I + L == 42)
    return 1;
  return 42;
}
<|endoftext|>