<commit_before>#ifndef BITOPS_HH
#define BITOPS_HH

#include <limits>
#include <type_traits>
#include <cstdint>
#include <climits>

namespace std {

///////////////////////////
//Basic bitwise operations
///////////////////////////

//Returns the number of trailing 0-bits in x, starting at the least significant bit position. If x is 0, the result is undefined.
template <typename T> constexpr int ctz(T t) noexcept = delete;
template <> constexpr int ctz(unsigned int t) noexcept {
  return __builtin_ctz(t);
}
template <> constexpr int ctz(unsigned long t) noexcept {
  return __builtin_ctzl(t);
}
template <> constexpr int ctz(unsigned long long t) noexcept {
  return __builtin_ctzll(t);
}
template <> constexpr int ctz(unsigned char t) noexcept {
  return ctz<unsigned int>(t);
}
template <> constexpr int ctz(unsigned short t) noexcept {
  return ctz<unsigned int>(t);
}

//Returns the number of leading 0-bits in x, starting at the most significant bit position. If x is 0, the result is undefined.
template <typename T> constexpr int clz(T t) noexcept = delete;
template <> constexpr int clz(unsigned int t) noexcept {
  return __builtin_clz(t);
}
template <> constexpr int clz(unsigned long t) noexcept {
  return __builtin_clzl(t);
}
template <> constexpr int clz(unsigned long long t) noexcept {
  return __builtin_clzll(t);
}
template <> constexpr int clz(unsigned char t) noexcept {
  return clz<unsigned int>(t) - ((sizeof(unsigned int) - sizeof(t)) * CHAR_BIT);
}
template <> constexpr int clz(unsigned short t) noexcept {
  return clz<unsigned int>(t) - ((sizeof(unsigned int) - sizeof(t)) * CHAR_BIT);
}

//Return position of the first bit set in t.
template <typename T> constexpr int ffs(T t) noexcept = delete;
template <> constexpr int ffs(unsigned int t) noexcept {
  return __builtin_ffs(t);
}
template <> constexpr int ffs(unsigned long t) noexcept {
  return __builtin_ffsl(t);
}
template <> constexpr int ffs(unsigned long long t) noexcept {
  return __builtin_ffsll(t);
}
template <> constexpr int ffs(unsigned char t) noexcept {
  return ffs<unsigned int>(t);
}
template <> constexpr int ffs(unsigned short t) noexcept {
  return ffs<unsigned int>(t);
}

//Returns position of the last bit set in t
template <typename T> constexpr int fls(T t) noexcept {
  static_assert(std::is_unsigned<T>::value, "T must be unsigned!");
  return (sizeof(t) * CHAR_BIT) - clz(t);
}

//Returns the number of leading redundant sign bits in x, i.e. the number of bits following the most significant bit that are identical to it. There are no special cases for 0 or other values
template <typename T> constexpr int clrsb(T t) noexcept = delete;
template <> constexpr int clrsb(unsigned int t) noexcept {
  return __builtin_clrsb(t);
}
template <> constexpr int clrsb(unsigned long t) noexcept {
  return __builtin_clrsbl(t);
}
template <> constexpr int clrsb(unsigned long long t) noexcept {
  return __builtin_clrsbll(t);
}
template <> constexpr int clrsb(unsigned char t) noexcept {
  return clrsb<unsigned int>(t) - ((sizeof(unsigned int) - sizeof(t)) * CHAR_BIT);
}
template <> constexpr int clrsb(unsigned short t) noexcept {
  return clrsb<unsigned int>(t) - ((sizeof(unsigned int) - sizeof(t)) * CHAR_BIT);
}

//Returns the number of 1-bits in x.
template <typename T> constexpr int popcount(T t) noexcept = delete;
template <> constexpr int popcount(unsigned int t) noexcept {
  return __builtin_popcount(t);
}
template <> constexpr int popcount(unsigned long t) noexcept {
  return __builtin_popcount(t);
}
template <> constexpr int popcount(unsigned long long t) noexcept {
  return __builtin_popcount(t);
}
template <> constexpr int popcount(unsigned char t) noexcept {
  return popcount<unsigned int>(t);
}
template <> constexpr int popcount(unsigned short t) noexcept {
  return popcount<unsigned int>(t);
}

//Returns the parity of x, i.e. the number of 1-bits in x modulo 2.
template <typename T> constexpr int parity(T t) noexcept = delete;
template <> constexpr int parity(unsigned int t) noexcept {
  return __builtin_parity(t);
}
template <> constexpr int parity(unsigned long t) noexcept {
  return __builtin_parityl(t);
}
template <> constexpr int parity(unsigned long long t) noexcept {
  return __builtin_parityll(t);
}
template <> constexpr int parity(unsigned char t) noexcept {
  return parity<unsigned int>(t);
}
template <> constexpr int parity(unsigned short t) noexcept {
  return parity<unsigned int>(t);
}

///////////////////////////
//Explicit bit shifts
///////////////////////////

//logical shift left
template <typename T>
constexpr auto shl(T t, unsigned int s)
  noexcept -> typename std::enable_if<std::is_unsigned<T>::value,T>::type {
    return t << s;
  }

//logical shift right
template <typename T>
constexpr auto shr(T t, unsigned int s)
  noexcept -> typename std::enable_if<std::is_unsigned<T>::value,T>::type {
    //For unsigned types, built in right shift is guaranteed to be logical
    return t >> s;
  }
//logical shift, left if s < 0, otherwise right
template <typename T>
constexpr auto sh(T t, int s)
  noexcept -> typename std::enable_if<std::is_unsigned<T>::value,T>::type {
    return s < 0 ? shl(t, -s) : shr(t, s);
  }

//left shift arithmetic
template <typename T>
constexpr auto sal(T t, unsigned int s)
  noexcept -> typename std::enable_if<std::is_unsigned<T>::value,T>::type {
    //Same as logical shift
    return shl(t, s);
  }

//right shift arithmetic. This implementation assumes right shift on signed types is arithmetic but this cannot be assumed in general
template <typename T>
constexpr auto sar(T t, unsigned int s)
  noexcept -> typename std::enable_if<std::is_unsigned<T>::value,T>::type {
    return static_cast<typename make_signed<T>::type>(t) >> s;
  }
//arithmetic shift, left if s < 0, otherwise right
template <typename T>
constexpr auto sa(T t, int s)
  noexcept -> typename std::enable_if<std::is_unsigned<T>::value,T>::type {
    return s < 0 ? sal(t, -s) : sar(t, s);
  }

//Left rotate shift
template <typename T>
constexpr auto rotl(T t, unsigned int s)
  noexcept -> typename std::enable_if<std::is_unsigned<T>::value,T>::type {
    return shl(t, s) | shr(t, (sizeof(t) * CHAR_BIT) - s);
  }

//Right rotate shift
template <typename T>
constexpr auto rotr(T t, unsigned int s)
  noexcept -> typename std::enable_if<std::is_unsigned<T>::value,T>::type {
    return shr(t, s) | shl(t, (sizeof(t) * CHAR_BIT) - s);
  }

//rotate shift, left if s < 0, otherwise right
template <typename T>
constexpr auto rot(T t, int s)
  noexcept -> typename std::enable_if<std::is_unsigned<T>::value,T>::type {
    return s < 0 ? rotl(t, -s) : rotr(t, s);
  }

///////////////////////////
//Alignment manipulation
///////////////////////////

//Returns the smallest number n when n >= val && is_aligned(n, align). align must be a power of 2!
//Question: Provide a version of this for char* pointers? Or require user to cast to uint_ptr_t?
template <typename T>
constexpr T align_up(T val, size_t a) noexcept {
  return ((val + (a -1)) & -a);
}

//Returns the largest number n when n <= val && is_aligned(n, align). align must be a power of 2!
//Question: Provide a version of this for char* pointers? Or require user to cast to uint_ptr_t?
template <typename T>
constexpr T align_down(T val, size_t a) noexcept {
  return val & -a;
}

//Returns true if t is aligned to a
//Question: Provide a version of this for char* pointers? Or require user to cast to uint_ptr_t?
template <typename T>
constexpr bool is_aligned(T t, size_t a) noexcept {
  return ((t & (a-1)) == 0);
}

///////////////////////////
//Power of 2 manipulation
///////////////////////////

//Returns true if t == 0 or t is a power of 2
template <typename T> constexpr bool is_pow2_or_zero(T t) noexcept {
  static_assert(is_unsigned<T>::value, "T must be an unsigned type!");
  return (t & (t-1)) == 0;
}

//Returns true if t is a power of 2
template <typename T> constexpr bool is_pow2(T t) noexcept {
  static_assert(is_unsigned<T>::value, "T must be an unsigned type!");
  return (t != 0) && is_pow2_or_zero(t);
}

//Return smallest power of 2 >= t
template <typename T>
constexpr T pow2_ge(T t) noexcept {
  static_assert(is_unsigned<T>::value, "T must be an unsigned type!");
  return is_pow2(t) ? t : pow2_gt(t);
}

//Return smallest power of 2 > t
template <typename T> constexpr T pow2_gt(T t) noexcept;

//Return smallest power of 2 <= t
template <typename T>
constexpr T pow2_le(T t) noexcept {
  return is_pow2(t) ? t : pow2_lt(t);
}

//Return smallest power of 2 < t
template <typename T>
constexpr T pow2_lt(T t) noexcept;

///////////////////////////
//Setting/Resetting bits
///////////////////////////

//Sets bit b of t, no effect if b >= number of bits in t
template <typename T>
constexpr T set_bit(T t, unsigned int b) noexcept {
  return t | (1 << b);
}

//Set all bits in t >= b
template <typename T>
constexpr T set_bits_gt(T t, unsigned int b) noexcept {
  return t | ~((1 << (b+1)) -1);
}

//Set all bits in t > b
template <typename T>
constexpr T set_bits_ge(T t, unsigned int b) noexcept {
  return t | ~((1 << b) -1);
}

//Set all bits in t <= b
template <typename T>
constexpr T set_bits_le(T t, unsigned int b) noexcept {
  return t | ((1 << (b+1)) -1);
}

//Set all bits in t < b
template <typename T>
constexpr T set_bits_lt(T t, unsigned int b) noexcept {
  return t | ((1 << b) -1);
}

//Resets bit b of t, no effect if b >= number of bits in t
template <typename T>
constexpr T reset_bit(T t, unsigned int b) noexcept {
  return t & ~(1 << b);
}

//Reset all bits in t >= b
template <typename T>
constexpr T reset_bits_gt(T t, unsigned int b) noexcept ;

//Reset all bits in t > b
template <typename T>
constexpr T reset_bits_ge(T t, unsigned int b) noexcept ;

//Reset all bits in t <= b
template <typename T>
constexpr T reset_bits_le(T t, unsigned int b) noexcept ;

//Reset all bits in t < b
template <typename T>
constexpr T reset_bits_lt(T t, unsigned int b) noexcept ;

//Resets the least significant bit set
template <typename T>
constexpr T reset_lsb(T t) noexcept {
  return t & (t -1);
}

//Resets the most significant bit set
template <typename T>
constexpr T reset_msb(T t);

////////////////////////
//Saturated Arithmetic
////////////////////////

//Saturated addition, like normal addition except on overflow the result will be the maximum value for decltype(L + R).
template <typename L, typename R>
constexpr auto sat_add(L l, R r) -> decltype(l+r) {
  typedef decltype(l+r) LR;
  return static_cast<LR>(l) > numeric_limits<LR>::max() - static_cast<LR>(r) ?
    numeric_limits<LR>::max() : l + r;
}

//Saturated subtraction, like normal subtraction except on overflow the result will be the minimum value for decltype(L - R).
template <typename L, typename R>
constexpr auto sat_sub(L l, R r) -> decltype(l-r) {
  typedef decltype(l-r) LR;
  return static_cast<LR>(l) < numeric_limits<LR>::min() + static_cast<LR>(r) ?
    numeric_limits<LR>::min() : l - r;
}

////////////////////////
//Misc
////////////////////////

//Reverses all of the bits in t
template <typename T>
constexpr T reverse_bits(T t) noexcept ;

//Returns a value whos even bits are set to the even bits of even, and odd bits set to the odd bits of odd.
template <typename T>
constexpr T interleave_bits(T even, T odd);

//Swaps the nibbles (4 bits) of the given byte
constexpr uint8_t swap_nibbles(uint8_t byte) {
  return (byte >> 4) | (byte << 4);
}

} //namespace std

#endif
<commit_msg>use int for shift amounts. Implement more functions.<commit_after>#ifndef BITOPS_HH
#define BITOPS_HH

#include <limits>
#include <type_traits>
#include <cstdint>
#include <climits>

namespace std {

///////////////////////////
//Basic bitwise operations
///////////////////////////

//Returns the number of trailing 0-bits in x, starting at the least significant bit position. If x is 0, the result is undefined.
template <typename T> constexpr int ctz(T t) noexcept = delete;
template <> constexpr int ctz(unsigned int t) noexcept {
  return __builtin_ctz(t);
}
template <> constexpr int ctz(unsigned long t) noexcept {
  return __builtin_ctzl(t);
}
template <> constexpr int ctz(unsigned long long t) noexcept {
  return __builtin_ctzll(t);
}
template <> constexpr int ctz(unsigned char t) noexcept {
  return ctz<unsigned int>(t);
}
template <> constexpr int ctz(unsigned short t) noexcept {
  return ctz<unsigned int>(t);
}

//Returns the number of leading 0-bits in x, starting at the most significant bit position. If x is 0, the result is undefined.
template <typename T> constexpr int clz(T t) noexcept = delete;
template <> constexpr int clz(unsigned int t) noexcept {
  return __builtin_clz(t);
}
template <> constexpr int clz(unsigned long t) noexcept {
  return __builtin_clzl(t);
}
template <> constexpr int clz(unsigned long long t) noexcept {
  return __builtin_clzll(t);
}
template <> constexpr int clz(unsigned char t) noexcept {
  return clz<unsigned int>(t) - ((sizeof(unsigned int) - sizeof(t)) * CHAR_BIT);
}
template <> constexpr int clz(unsigned short t) noexcept {
  return clz<unsigned int>(t) - ((sizeof(unsigned int) - sizeof(t)) * CHAR_BIT);
}

//Return position of the first bit set in t.
template <typename T> constexpr int ffs(T t) noexcept = delete;
template <> constexpr int ffs(unsigned int t) noexcept {
  return __builtin_ffs(t);
}
template <> constexpr int ffs(unsigned long t) noexcept {
  return __builtin_ffsl(t);
}
template <> constexpr int ffs(unsigned long long t) noexcept {
  return __builtin_ffsll(t);
}
template <> constexpr int ffs(unsigned char t) noexcept {
  return ffs<unsigned int>(t);
}
template <> constexpr int ffs(unsigned short t) noexcept {
  return ffs<unsigned int>(t);
}

//Returns position of the last bit set in t
template <typename T> constexpr int fls(T t) noexcept {
  static_assert(std::is_unsigned<T>::value, "T must be unsigned!");
  return (sizeof(t) * CHAR_BIT) - clz(t);
}

//Returns the number of leading redundant sign bits in x, i.e. the number of bits following the most significant bit that are identical to it. There are no special cases for 0 or other values
template <typename T> constexpr int clrsb(T t) noexcept = delete;
template <> constexpr int clrsb(unsigned int t) noexcept {
  return __builtin_clrsb(t);
}
template <> constexpr int clrsb(unsigned long t) noexcept {
  return __builtin_clrsbl(t);
}
template <> constexpr int clrsb(unsigned long long t) noexcept {
  return __builtin_clrsbll(t);
}
template <> constexpr int clrsb(unsigned char t) noexcept {
  return clrsb<unsigned int>(t) - ((sizeof(unsigned int) - sizeof(t)) * CHAR_BIT);
}
template <> constexpr int clrsb(unsigned short t) noexcept {
  return clrsb<unsigned int>(t) - ((sizeof(unsigned int) - sizeof(t)) * CHAR_BIT);
}

//Returns the number of 1-bits in x.
template <typename T> constexpr int popcount(T t) noexcept = delete;
template <> constexpr int popcount(unsigned int t) noexcept {
  return __builtin_popcount(t);
}
template <> constexpr int popcount(unsigned long t) noexcept {
  return __builtin_popcount(t);
}
template <> constexpr int popcount(unsigned long long t) noexcept {
  return __builtin_popcount(t);
}
template <> constexpr int popcount(unsigned char t) noexcept {
  return popcount<unsigned int>(t);
}
template <> constexpr int popcount(unsigned short t) noexcept {
  return popcount<unsigned int>(t);
}

//Returns the parity of x, i.e. the number of 1-bits in x modulo 2.
template <typename T> constexpr int parity(T t) noexcept = delete;
template <> constexpr int parity(unsigned int t) noexcept {
  return __builtin_parity(t);
}
template <> constexpr int parity(unsigned long t) noexcept {
  return __builtin_parityl(t);
}
template <> constexpr int parity(unsigned long long t) noexcept {
  return __builtin_parityll(t);
}
template <> constexpr int parity(unsigned char t) noexcept {
  return parity<unsigned int>(t);
}
template <> constexpr int parity(unsigned short t) noexcept {
  return parity<unsigned int>(t);
}

///////////////////////////
//Explicit bit shifts
///////////////////////////

//logical shift left
template <typename T>
constexpr auto shl(T t, int s)
  noexcept -> typename std::enable_if<std::is_unsigned<T>::value,T>::type {
    return t << s;
  }

//logical shift right
template <typename T>
constexpr auto shr(T t, int s)
  noexcept -> typename std::enable_if<std::is_unsigned<T>::value,T>::type {
    //For unsigned types, built in right shift is guaranteed to be logical
    return t >> s;
  }
//logical shift, left if s < 0, otherwise right
template <typename T>
constexpr auto sh(T t, int s)
  noexcept -> typename std::enable_if<std::is_unsigned<T>::value,T>::type {
    return s < 0 ? shl(t, -s) : shr(t, s);
  }

//left shift arithmetic
template <typename T>
constexpr auto sal(T t, int s)
  noexcept -> typename std::enable_if<std::is_unsigned<T>::value,T>::type {
    //Same as logical shift
    return shl(t, s);
  }

//right shift arithmetic.
template <typename T>
constexpr auto sar(T t, int s)
  noexcept -> typename std::enable_if<std::is_unsigned<T>::value,T>::type {
    //This implementation assumes right shift on signed types is arithmetic but this cannot be assumed in general
    return static_cast<typename make_signed<T>::type>(t) >> s;
  }
//arithmetic shift, left if s < 0, otherwise right
template <typename T>
constexpr auto sa(T t, int s)
  noexcept -> typename std::enable_if<std::is_unsigned<T>::value,T>::type {
    return s < 0 ? sal(t, -s) : sar(t, s);
  }

//Left rotate shift
template <typename T>
constexpr auto rotl(T t, int s)
  noexcept -> typename std::enable_if<std::is_unsigned<T>::value,T>::type {
    return shl(t, s) | shr(t, (sizeof(t) * CHAR_BIT) - s);
  }

//Right rotate shift
template <typename T>
constexpr auto rotr(T t, int s)
  noexcept -> typename std::enable_if<std::is_unsigned<T>::value,T>::type {
    return shr(t, s) | shl(t, (sizeof(t) * CHAR_BIT) - s);
  }

//rotate shift, left if s < 0, otherwise right
template <typename T>
constexpr auto rot(T t, int s)
  noexcept -> typename std::enable_if<std::is_unsigned<T>::value,T>::type {
    return s < 0 ? rotl(t, -s) : rotr(t, s);
  }

///////////////////////////
//Alignment manipulation
///////////////////////////

//Returns the smallest number n when n >= val && is_aligned(n, align). align must be a power of 2!
template <typename T>
constexpr auto align_up(T val, size_t a)
  noexcept -> typename std::enable_if<std::is_integral<T>::value,T>::type {
  return ((val + (a -1)) & -a);
}
constexpr void* align_up(void* val, size_t a) noexcept {
  return (void*)align_up(uintptr_t(val), a);
}

//Returns the largest number n when n <= val && is_aligned(n, align). align must be a power of 2!
template <typename T>
constexpr auto align_down(T val, size_t a)
  noexcept -> typename std::enable_if<std::is_integral<T>::value,T>::type {
  return val & -a;
}
constexpr void* align_down(void* val, size_t a) noexcept {
  return (void*)align_down(uintptr_t(val), a);
}

//Returns true if t is aligned to a
template <typename T>
constexpr auto is_aligned(T t, size_t a)
  noexcept -> typename std::enable_if<std::is_integral<T>::value,bool>::type {
  return ((t & (a-1)) == 0);
}
constexpr bool is_aligned(void* t, size_t a) noexcept {
  return is_aligned(uintptr_t(t), a);
}

///////////////////////////
//Power of 2 manipulation
///////////////////////////

//Returns true if t == 0 or t is a power of 2
template <typename T>
constexpr auto is_pow2_or_zero(T t)
  noexcept -> typename std::enable_if<std::is_integral<T>::value,bool>::type {
  return (t & (t-1)) == 0;
}

//Returns true if t is a power of 2
template <typename T>
constexpr auto is_pow2(T t)
  noexcept -> typename std::enable_if<std::is_integral<T>::value,bool>::type {
  return (t != 0) && is_pow2_or_zero(t);
}

//Return smallest power of 2 >= t
template <typename T>
constexpr auto pow2_ge(T t)
  noexcept -> typename std::enable_if<std::is_integral<T>::value,T>::type {
  return is_pow2(t) ? t : pow2_gt(t);
}

//Return smallest power of 2 > t
template <typename T>
constexpr auto pow2_gt(T t)
  noexcept -> typename std::enable_if<std::is_integral<T>::value,T>::type {
    return (T(1) << (fls(make_unsigned<T>::type(t)) +1));
  }

//Return smallest power of 2 <= t
template <typename T>
constexpr auto pow2_le(T t)
  noexcept -> typename std::enable_if<std::is_integral<T>::value,T>::type {
  return is_pow2(t) ? t : pow2_lt(t);
}

//Return smallest power of 2 < t
template <typename T>
constexpr auto pow2_lt(T t)
  noexcept -> typename std::enable_if<std::is_integral<T>::value,T>::type {
    return T(1) << fls(make_unsigned<T>::type(t-1));
}

///////////////////////////
//Setting/Resetting bits
///////////////////////////

//Sets bit b of t, no effect if b >= number of bits in t
template <typename T>
constexpr auto set_bit(T t, int b)
  noexcept -> typename std::enable_if<std::is_unsigned<T>::value,T>::type {
  return t | (1 << b);
}

//Set all bits in t >= b
template <typename T>
constexpr auto set_bits_gt(T t, int b)
  noexcept -> typename std::enable_if<std::is_unsigned<T>::value,T>::type {
  return t | ~((1 << (b+1)) -1);
}

//Set all bits in t > b
template <typename T>
constexpr auto set_bits_ge(T t, int b)
  noexcept -> typename std::enable_if<std::is_unsigned<T>::value,T>::type {
  return t | ~((1 << b) -1);
}

//Set all bits in t <= b
template <typename T>
constexpr auto set_bits_le(T t, int b)
  noexcept -> typename std::enable_if<std::is_unsigned<T>::value,T>::type {
  return t | ((1 << (b+1)) -1);
}

//Set all bits in t < b
template <typename T>
constexpr auto set_bits_lt(T t, int b)
  noexcept -> typename std::enable_if<std::is_unsigned<T>::value,T>::type {
  return t | ((1 << b) -1);
}

//Resets bit b of t, no effect if b >= number of bits in t
template <typename T>
constexpr auto reset_bit(T t, int b)
  noexcept -> typename std::enable_if<std::is_unsigned<T>::value,T>::type {
  return t & ~(1 << b);
}

//Reset all bits in t >= b
template <typename T>
constexpr auto reset_bits_gt(T t, int b)
  noexcept -> typename std::enable_if<std::is_unsigned<T>::value,T>::type {
    return t & ~((T(1) << (b+1))-1);
  }

//Reset all bits in t > b
template <typename T>
constexpr auto reset_bits_ge(T t, int b)
  noexcept -> typename std::enable_if<std::is_unsigned<T>::value,T>::type {
    return t & ~((T(1) << b)-1);
  }

//Reset all bits in t <= b
template <typename T>
constexpr auto reset_bits_le(T t, int b)
  noexcept -> typename std::enable_if<std::is_unsigned<T>::value,T>::type {
    return t & ((T(1) << (b+1))-1);
  }

//Reset all bits in t < b
template <typename T>
constexpr auto reset_bits_lt(T t, int b)
  noexcept -> typename std::enable_if<std::is_unsigned<T>::value,T>::type {
    return t & ((T(1) << b)-1);
  }

//Resets the least significant bit set
template <typename T>
constexpr auto reset_lsb(T t)
  noexcept -> typename std::enable_if<std::is_unsigned<T>::value,T>::type {
  return t & (t -1);
}

//Resets the most significant bit set
template <typename T>
constexpr auto reset_msb(T t)
  noexcept -> typename std::enable_if<std::is_unsigned<T>::value,T>::type {
  return t & ~(T(1) << ((sizeof(t)*8) - clz(t)-1));
}

////////////////////////
//Saturated Arithmetic
////////////////////////

//Saturated addition, like normal addition except on overflow the result will be the maximum value for decltype(L + R).
template <typename L, typename R>
constexpr auto sat_add(L l, R r)
  noexcept -> typename std::enable_if<std::is_integral<L>::value && std::is_integral<R>::value,decltype(l+r)>::type {
  typedef decltype(l+r) LR;
  return static_cast<LR>(l) > numeric_limits<LR>::max() - static_cast<LR>(r) ?
    numeric_limits<LR>::max() : l + r;
}

//Saturated subtraction, like normal subtraction except on overflow the result will be the minimum value for decltype(L - R).
template <typename L, typename R>
constexpr auto sat_sub(L l, R r)
  noexcept -> typename std::enable_if<std::is_integral<L>::value && std::is_integral<R>::value,decltype(l-r)>::type {
  typedef decltype(l-r) LR;
  return static_cast<LR>(l) < numeric_limits<LR>::min() + static_cast<LR>(r) ?
    numeric_limits<LR>::min() : l - r;
}

////////////////////////
//Misc
////////////////////////

//Reverses all of the bits in t
template <typename T>
constexpr auto reverse_bits(T t)
  noexcept -> typename std::enable_if<std::is_unsigned<T>::value,T>::type;

//Returns a value whos even bits are set to the even bits of even, and odd bits set to the odd bits of odd.
template <typename T>
constexpr auto interleave_bits(T even, T odd)
  noexcept -> typename std::enable_if<std::is_unsigned<T>::value,T>::type;

//Swaps the nibbles (4 bits) of the given byte
constexpr uint8_t swap_nibbles(uint8_t byte) {
  return (byte >> 4) | (byte << 4);
}

} //namespace std

#endif
<|endoftext|>


<commit_before>#include "hornet/java.hh"

#include "hornet/system_error.hh"
#include "hornet/java.hh"
#include "hornet/zip.hh"
#include "hornet/vm.hh"

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <unistd.h>

#include <algorithm>
#include <cassert>
#include <climits>
#include <cstring>
#include <fcntl.h>
#include <cstdio>

namespace hornet {

bool verbose_class;

void loader::register_entry(std::string path)
{
    struct stat st;

    if (stat(path.c_str(), &st) < 0) {
        fprintf(stderr, "warning: %s: %s\n", path.c_str(), strerror(errno));
        return;
    }
    if (S_ISDIR(st.st_mode)) {
        _entries.push_back(std::make_shared<classpath_dir>(path));
    } else {
        _entries.push_back(std::make_shared<jar>(path));
    }
}

std::shared_ptr<klass> loader::load_class(std::string class_name)
{
    std::replace(class_name.begin(), class_name.end(), '.', '/');

    if (is_array_type_name(class_name)) {
        auto elem_type_name = class_name.substr(1, std::string::npos);
        auto elem_type = load_class(elem_type_name);
        if (!elem_type) {
            hornet::throw_exception(java_lang_NoClassDefFoundError);
            return nullptr;
        }
        auto klass = std::make_shared<array_klass>(class_name, elem_type.get());
        hornet::_jvm->register_class(klass);
        return klass;
    }

    auto klass = hornet::_jvm->lookup_class(class_name);

    if (klass) {
        return klass;
    }

    klass = try_to_load_class(class_name);

    if (!klass) {
        hornet::throw_exception(java_lang_NoClassDefFoundError);
        return nullptr;
    }

    if (!klass->verify()) {
        throw_exception(java_lang_VerifyError);
        return nullptr;
    }

    return klass;
}

std::shared_ptr<klass> loader::try_to_load_class(std::string class_name)
{
    for (auto entry : _entries) {
        auto klass = entry->load_class(class_name);
        if (klass) {
            return klass;
        }
    }
    return nullptr;
}

classpath_dir::classpath_dir(std::string path)
    : _path(path)
{
}

classpath_dir::~classpath_dir()
{
}

std::shared_ptr<klass> classpath_dir::load_class(std::string class_name)
{
    char pathname[PATH_MAX];

    snprintf(pathname, sizeof(pathname), "%s/%s.class", _path.c_str(), class_name.c_str());

    auto klass = load_file(pathname);

    if (verbose_class && klass) {
        printf("[Loaded %s from file:%s]\n", class_name.c_str(), _path.c_str());
    }
    return klass;
}

std::shared_ptr<klass> classpath_dir::load_file(const char *pathname)
{
    auto fd = open(pathname, O_RDONLY);
    if (fd < 0) {
        return nullptr;
    }

    struct stat st;
    if (fstat(fd, &st) < 0) {
        throw_system_error("fstat");
    }

    auto data = mmap(0, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
    if (data == MAP_FAILED) {
        throw_system_error("mmap");
    }

    auto file = class_file{data, static_cast<size_t>(st.st_size)};

    auto klass = file.parse();

    if (munmap(data, st.st_size) < 0) {
        throw_system_error("munmap");
    }

    if (close(fd) < 0) {
        throw_system_error("close");
    }

    return klass;
}

jar::jar(std::string filename)
    : _filename{filename}
    , _zip{zip_open(filename.c_str())}
{
    if (verbose_class) {
        printf("[Opened %s]\n", _filename.c_str());
    }
}

jar::~jar()
{
    if (verbose_class) {
        printf("[Closed %s]\n", _filename.c_str());
    }
    zip_close(_zip);
}

std::shared_ptr<klass> jar::load_class(std::string class_name)
{
    if (!_zip) {
        return nullptr;
    }
    zip_entry *entry = zip_entry_find_class(_zip, class_name.c_str());
    if (!entry) {
        return nullptr;
    }
    char *data = (char*)zip_entry_data(_zip, entry);

    auto file = class_file{data, static_cast<size_t>(entry->uncomp_size)};

    auto klass = file.parse();

    free(data);

    if (verbose_class && klass) {
        printf("[Loaded %s from %s]\n", class_name.c_str(), _filename.c_str());
    }

    return klass;
}

}
<commit_msg>java/loader: Fix class cache lookup for array types<commit_after>#include "hornet/java.hh"

#include "hornet/system_error.hh"
#include "hornet/java.hh"
#include "hornet/zip.hh"
#include "hornet/vm.hh"

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <unistd.h>

#include <algorithm>
#include <cassert>
#include <climits>
#include <cstring>
#include <fcntl.h>
#include <cstdio>

namespace hornet {

bool verbose_class;

void loader::register_entry(std::string path)
{
    struct stat st;

    if (stat(path.c_str(), &st) < 0) {
        fprintf(stderr, "warning: %s: %s\n", path.c_str(), strerror(errno));
        return;
    }
    if (S_ISDIR(st.st_mode)) {
        _entries.push_back(std::make_shared<classpath_dir>(path));
    } else {
        _entries.push_back(std::make_shared<jar>(path));
    }
}

std::shared_ptr<klass> loader::load_class(std::string class_name)
{
    std::replace(class_name.begin(), class_name.end(), '.', '/');

    auto klass = hornet::_jvm->lookup_class(class_name);
    if (klass) {
        return klass;
    }

    if (is_array_type_name(class_name)) {
        auto elem_type_name = class_name.substr(1, std::string::npos);
        auto elem_type = load_class(elem_type_name);
        if (!elem_type) {
            hornet::throw_exception(java_lang_NoClassDefFoundError);
            return nullptr;
        }
        auto klass = std::make_shared<array_klass>(class_name, elem_type.get());
        hornet::_jvm->register_class(klass);
        return klass;
    }

    klass = try_to_load_class(class_name);

    if (!klass) {
        hornet::throw_exception(java_lang_NoClassDefFoundError);
        return nullptr;
    }

    if (!klass->verify()) {
        throw_exception(java_lang_VerifyError);
        return nullptr;
    }

    return klass;
}

std::shared_ptr<klass> loader::try_to_load_class(std::string class_name)
{
    for (auto entry : _entries) {
        auto klass = entry->load_class(class_name);
        if (klass) {
            return klass;
        }
    }
    return nullptr;
}

classpath_dir::classpath_dir(std::string path)
    : _path(path)
{
}

classpath_dir::~classpath_dir()
{
}

std::shared_ptr<klass> classpath_dir::load_class(std::string class_name)
{
    char pathname[PATH_MAX];

    snprintf(pathname, sizeof(pathname), "%s/%s.class", _path.c_str(), class_name.c_str());

    auto klass = load_file(pathname);

    if (verbose_class && klass) {
        printf("[Loaded %s from file:%s]\n", class_name.c_str(), _path.c_str());
    }
    return klass;
}

std::shared_ptr<klass> classpath_dir::load_file(const char *pathname)
{
    auto fd = open(pathname, O_RDONLY);
    if (fd < 0) {
        return nullptr;
    }

    struct stat st;
    if (fstat(fd, &st) < 0) {
        throw_system_error("fstat");
    }

    auto data = mmap(0, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
    if (data == MAP_FAILED) {
        throw_system_error("mmap");
    }

    auto file = class_file{data, static_cast<size_t>(st.st_size)};

    auto klass = file.parse();

    if (munmap(data, st.st_size) < 0) {
        throw_system_error("munmap");
    }

    if (close(fd) < 0) {
        throw_system_error("close");
    }

    return klass;
}

jar::jar(std::string filename)
    : _filename{filename}
    , _zip{zip_open(filename.c_str())}
{
    if (verbose_class) {
        printf("[Opened %s]\n", _filename.c_str());
    }
}

jar::~jar()
{
    if (verbose_class) {
        printf("[Closed %s]\n", _filename.c_str());
    }
    zip_close(_zip);
}

std::shared_ptr<klass> jar::load_class(std::string class_name)
{
    if (!_zip) {
        return nullptr;
    }
    zip_entry *entry = zip_entry_find_class(_zip, class_name.c_str());
    if (!entry) {
        return nullptr;
    }
    char *data = (char*)zip_entry_data(_zip, entry);

    auto file = class_file{data, static_cast<size_t>(entry->uncomp_size)};

    auto klass = file.parse();

    free(data);

    if (verbose_class && klass) {
        printf("[Loaded %s from %s]\n", class_name.c_str(), _filename.c_str());
    }

    return klass;
}

}
<|endoftext|>


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

#include "chrome/test/testing_profile.h"

#include "build/build_config.h"
#include "base/string_util.h"
#include "chrome/browser/bookmarks/bookmark_model.h"
#include "chrome/browser/history/history_backend.h"
#include "chrome/common/chrome_constants.h"

#if defined(OS_LINUX) && !defined(TOOLKIT_VIEWS)
#include "chrome/browser/gtk/gtk_theme_provider.h"
#endif

using base::Time;

namespace {

// Task used to make sure history has finished processing a request. Intended
// for use with BlockUntilHistoryProcessesPendingRequests.

class QuittingHistoryDBTask : public HistoryDBTask {
 public:
  QuittingHistoryDBTask() {}

  virtual bool RunOnDBThread(history::HistoryBackend* backend,
                             history::HistoryDatabase* db) {
    return true;
  }

  virtual void DoneRunOnMainThread() {
    MessageLoop::current()->Quit();
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(QuittingHistoryDBTask);
};

// BookmarkLoadObserver is used when blocking until the BookmarkModel
// finishes loading. As soon as the BookmarkModel finishes loading the message
// loop is quit.
class BookmarkLoadObserver : public BookmarkModelObserver {
 public:
  BookmarkLoadObserver() {}
  virtual void Loaded(BookmarkModel* model) {
    MessageLoop::current()->Quit();
  }

  virtual void BookmarkNodeMoved(BookmarkModel* model,
                                 const BookmarkNode* old_parent,
                                 int old_index,
                                 const BookmarkNode* new_parent,
                                 int new_index) {}
  virtual void BookmarkNodeAdded(BookmarkModel* model,
                                 const BookmarkNode* parent,
                                 int index) {}
  virtual void BookmarkNodeRemoved(BookmarkModel* model,
                                   const BookmarkNode* parent,
                                   int old_index,
                                   const BookmarkNode* node) {}
  virtual void BookmarkNodeChanged(BookmarkModel* model,
                                   const BookmarkNode* node) {}
  virtual void BookmarkNodeChildrenReordered(BookmarkModel* model,
                                             const BookmarkNode* node) {}
  virtual void BookmarkNodeFavIconLoaded(BookmarkModel* model,
                                         const BookmarkNode* node) {}

 private:
  DISALLOW_COPY_AND_ASSIGN(BookmarkLoadObserver);
};

}  // namespace

TestingProfile::TestingProfile()
    : start_time_(Time::Now()),
      created_theme_provider_(false),
      has_history_service_(false),
      off_the_record_(false),
      last_session_exited_cleanly_(true) {
  PathService::Get(base::DIR_TEMP, &path_);
  path_ = path_.Append(FILE_PATH_LITERAL("TestingProfilePath"));
  file_util::Delete(path_, true);
  file_util::CreateDirectory(path_);
}

TestingProfile::TestingProfile(int count)
    : start_time_(Time::Now()),
      has_history_service_(false),
      off_the_record_(false),
      last_session_exited_cleanly_(true) {
  PathService::Get(base::DIR_TEMP, &path_);
  path_ = path_.Append(FILE_PATH_LITERAL("TestingProfilePath"));
  path_ = path_.AppendASCII(IntToString(count));
  file_util::Delete(path_, true);
  file_util::CreateDirectory(path_);
}

TestingProfile::~TestingProfile() {
  DestroyHistoryService();
  file_util::Delete(path_, true);
}

void TestingProfile::CreateHistoryService(bool delete_file) {
  if (history_service_.get())
    history_service_->Cleanup();

  history_service_ = NULL;

  if (delete_file) {
    FilePath path = GetPath();
    path = path.Append(chrome::kHistoryFilename);
    file_util::Delete(path, false);
  }
  history_service_ = new HistoryService(this);
  history_service_->Init(GetPath(), bookmark_bar_model_.get());
}

void TestingProfile::DestroyHistoryService() {
  if (!history_service_.get())
    return;

  history_service_->NotifyRenderProcessHostDestruction(0);
  history_service_->SetOnBackendDestroyTask(new MessageLoop::QuitTask);
  history_service_->Cleanup();
  history_service_ = NULL;

  // Wait for the backend class to terminate before deleting the files and
  // moving to the next test. Note: if this never terminates, somebody is
  // probably leaking a reference to the history backend, so it never calls
  // our destroy task.
  MessageLoop::current()->Run();

  // Make sure we don't have any event pending that could disrupt the next
  // test.
  MessageLoop::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask);
  MessageLoop::current()->Run();
}

void TestingProfile::CreateBookmarkModel(bool delete_file) {
  // Nuke the model first, that way we're sure it's done writing to disk.
  bookmark_bar_model_.reset(NULL);

  if (delete_file) {
    FilePath path = GetPath();
    path = path.Append(chrome::kBookmarksFileName);
    file_util::Delete(path, false);
  }
  bookmark_bar_model_.reset(new BookmarkModel(this));
  if (history_service_.get()) {
    history_service_->history_backend_->bookmark_service_ =
        bookmark_bar_model_.get();
    history_service_->history_backend_->expirer_.bookmark_service_ =
        bookmark_bar_model_.get();
  }
  bookmark_bar_model_->Load();
}

void TestingProfile::BlockUntilBookmarkModelLoaded() {
  DCHECK(bookmark_bar_model_.get());
  if (bookmark_bar_model_->IsLoaded())
    return;
  BookmarkLoadObserver observer;
  bookmark_bar_model_->AddObserver(&observer);
  MessageLoop::current()->Run();
  bookmark_bar_model_->RemoveObserver(&observer);
  DCHECK(bookmark_bar_model_->IsLoaded());
}

void TestingProfile::CreateTemplateURLModel() {
  template_url_model_.reset(new TemplateURLModel(this));
}

void TestingProfile::UseThemeProvider(BrowserThemeProvider* theme_provider) {
  theme_provider->Init(this);
  created_theme_provider_ = true;
  theme_provider_.reset(theme_provider);
}

void TestingProfile::InitThemes() {
  if (!created_theme_provider_) {
#if defined(OS_LINUX) && !defined(TOOLKIT_VIEWS)
    theme_provider_.reset(new GtkThemeProvider);
#else
    theme_provider_.reset(new BrowserThemeProvider);
#endif
    theme_provider_->Init(this);
    created_theme_provider_ = true;
  }
}

void TestingProfile::BlockUntilHistoryProcessesPendingRequests() {
  DCHECK(history_service_.get());
  DCHECK(MessageLoop::current());

  CancelableRequestConsumer consumer;
  history_service_->ScheduleDBTask(new QuittingHistoryDBTask(), &consumer);
  MessageLoop::current()->Run();
}
<commit_msg>Coverity: initialize created_theme_provider_ in the other constructor.<commit_after>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/test/testing_profile.h"

#include "build/build_config.h"
#include "base/string_util.h"
#include "chrome/browser/bookmarks/bookmark_model.h"
#include "chrome/browser/history/history_backend.h"
#include "chrome/common/chrome_constants.h"

#if defined(OS_LINUX) && !defined(TOOLKIT_VIEWS)
#include "chrome/browser/gtk/gtk_theme_provider.h"
#endif

using base::Time;

namespace {

// Task used to make sure history has finished processing a request. Intended
// for use with BlockUntilHistoryProcessesPendingRequests.

class QuittingHistoryDBTask : public HistoryDBTask {
 public:
  QuittingHistoryDBTask() {}

  virtual bool RunOnDBThread(history::HistoryBackend* backend,
                             history::HistoryDatabase* db) {
    return true;
  }

  virtual void DoneRunOnMainThread() {
    MessageLoop::current()->Quit();
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(QuittingHistoryDBTask);
};

// BookmarkLoadObserver is used when blocking until the BookmarkModel
// finishes loading. As soon as the BookmarkModel finishes loading the message
// loop is quit.
class BookmarkLoadObserver : public BookmarkModelObserver {
 public:
  BookmarkLoadObserver() {}
  virtual void Loaded(BookmarkModel* model) {
    MessageLoop::current()->Quit();
  }

  virtual void BookmarkNodeMoved(BookmarkModel* model,
                                 const BookmarkNode* old_parent,
                                 int old_index,
                                 const BookmarkNode* new_parent,
                                 int new_index) {}
  virtual void BookmarkNodeAdded(BookmarkModel* model,
                                 const BookmarkNode* parent,
                                 int index) {}
  virtual void BookmarkNodeRemoved(BookmarkModel* model,
                                   const BookmarkNode* parent,
                                   int old_index,
                                   const BookmarkNode* node) {}
  virtual void BookmarkNodeChanged(BookmarkModel* model,
                                   const BookmarkNode* node) {}
  virtual void BookmarkNodeChildrenReordered(BookmarkModel* model,
                                             const BookmarkNode* node) {}
  virtual void BookmarkNodeFavIconLoaded(BookmarkModel* model,
                                         const BookmarkNode* node) {}

 private:
  DISALLOW_COPY_AND_ASSIGN(BookmarkLoadObserver);
};

}  // namespace

TestingProfile::TestingProfile()
    : start_time_(Time::Now()),
      created_theme_provider_(false),
      has_history_service_(false),
      off_the_record_(false),
      last_session_exited_cleanly_(true) {
  PathService::Get(base::DIR_TEMP, &path_);
  path_ = path_.Append(FILE_PATH_LITERAL("TestingProfilePath"));
  file_util::Delete(path_, true);
  file_util::CreateDirectory(path_);
}

TestingProfile::TestingProfile(int count)
    : start_time_(Time::Now()),
      created_theme_provider_(false),
      has_history_service_(false),
      off_the_record_(false),
      last_session_exited_cleanly_(true) {
  PathService::Get(base::DIR_TEMP, &path_);
  path_ = path_.Append(FILE_PATH_LITERAL("TestingProfilePath"));
  path_ = path_.AppendASCII(IntToString(count));
  file_util::Delete(path_, true);
  file_util::CreateDirectory(path_);
}

TestingProfile::~TestingProfile() {
  DestroyHistoryService();
  file_util::Delete(path_, true);
}

void TestingProfile::CreateHistoryService(bool delete_file) {
  if (history_service_.get())
    history_service_->Cleanup();

  history_service_ = NULL;

  if (delete_file) {
    FilePath path = GetPath();
    path = path.Append(chrome::kHistoryFilename);
    file_util::Delete(path, false);
  }
  history_service_ = new HistoryService(this);
  history_service_->Init(GetPath(), bookmark_bar_model_.get());
}

void TestingProfile::DestroyHistoryService() {
  if (!history_service_.get())
    return;

  history_service_->NotifyRenderProcessHostDestruction(0);
  history_service_->SetOnBackendDestroyTask(new MessageLoop::QuitTask);
  history_service_->Cleanup();
  history_service_ = NULL;

  // Wait for the backend class to terminate before deleting the files and
  // moving to the next test. Note: if this never terminates, somebody is
  // probably leaking a reference to the history backend, so it never calls
  // our destroy task.
  MessageLoop::current()->Run();

  // Make sure we don't have any event pending that could disrupt the next
  // test.
  MessageLoop::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask);
  MessageLoop::current()->Run();
}

void TestingProfile::CreateBookmarkModel(bool delete_file) {
  // Nuke the model first, that way we're sure it's done writing to disk.
  bookmark_bar_model_.reset(NULL);

  if (delete_file) {
    FilePath path = GetPath();
    path = path.Append(chrome::kBookmarksFileName);
    file_util::Delete(path, false);
  }
  bookmark_bar_model_.reset(new BookmarkModel(this));
  if (history_service_.get()) {
    history_service_->history_backend_->bookmark_service_ =
        bookmark_bar_model_.get();
    history_service_->history_backend_->expirer_.bookmark_service_ =
        bookmark_bar_model_.get();
  }
  bookmark_bar_model_->Load();
}

void TestingProfile::BlockUntilBookmarkModelLoaded() {
  DCHECK(bookmark_bar_model_.get());
  if (bookmark_bar_model_->IsLoaded())
    return;
  BookmarkLoadObserver observer;
  bookmark_bar_model_->AddObserver(&observer);
  MessageLoop::current()->Run();
  bookmark_bar_model_->RemoveObserver(&observer);
  DCHECK(bookmark_bar_model_->IsLoaded());
}

void TestingProfile::CreateTemplateURLModel() {
  template_url_model_.reset(new TemplateURLModel(this));
}

void TestingProfile::UseThemeProvider(BrowserThemeProvider* theme_provider) {
  theme_provider->Init(this);
  created_theme_provider_ = true;
  theme_provider_.reset(theme_provider);
}

void TestingProfile::InitThemes() {
  if (!created_theme_provider_) {
#if defined(OS_LINUX) && !defined(TOOLKIT_VIEWS)
    theme_provider_.reset(new GtkThemeProvider);
#else
    theme_provider_.reset(new BrowserThemeProvider);
#endif
    theme_provider_->Init(this);
    created_theme_provider_ = true;
  }
}

void TestingProfile::BlockUntilHistoryProcessesPendingRequests() {
  DCHECK(history_service_.get());
  DCHECK(MessageLoop::current());

  CancelableRequestConsumer consumer;
  history_service_->ScheduleDBTask(new QuittingHistoryDBTask(), &consumer);
  MessageLoop::current()->Run();
}
<|endoftext|>


<commit_before>/* * This file is part of meego-im-framework *
 *
 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
 * All rights reserved.
 * Contact: Nokia Corporation (directui@nokia.com)
 *
 * If you have questions regarding the use of this file, please contact
 * Nokia at directui@nokia.com.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License version 2.1 as published by the Free Software Foundation
 * and appearing in the file LICENSE.LGPL included in the packaging
 * of this file.
 */

#include "glibdbusimserverproxy.h"
#include "minputcontext.h"

#include <QPoint>
#include <QRect>
#include <QString>
#include <QDataStream>
#include <QVariant>
#include <QTimer>
#include <QDateTime>
#include <QDebug>

#include <unistd.h>
#include <sys/types.h>

namespace
{
    const char * const DBusPath("/com/meego/inputmethod/uiserver1");
    const char * const DBusInterface("com.meego.inputmethod.uiserver1");
    const char * const SocketPath = "unix:path=/tmp/meego-im-uiserver/imserver_dbus";
    const int ConnectionRetryInterval(6*1000); // in ms

    Maliit::DBusGLib::ConnectionRef toRef(DBusGConnection *connection)
    {
        return Maliit::DBusGLib::ConnectionRef(connection,
                                               dbus_g_connection_unref);
    }
}

GlibDBusIMServerProxy::GlibDBusIMServerProxy(GObject *inputContextAdaptor, const QString &icAdaptorPath)
    : glibObjectProxy(NULL),
      connection(),
      inputContextAdaptor(inputContextAdaptor),
      icAdaptorPath(icAdaptorPath),
      active(true)
{
    dbus_g_thread_init();

    connectToDBus();
}

GlibDBusIMServerProxy::~GlibDBusIMServerProxy()
{
    active = false;

    foreach (DBusGProxyCall *callId, pendingResetCalls) {
        dbus_g_proxy_cancel_call(glibObjectProxy, callId);
    }
}

// Auxiliary connection handling.............................................

void GlibDBusIMServerProxy::onDisconnectionTrampoline(DBusGProxy */*proxy*/, gpointer userData)
{
    if (MInputContext::debug) qDebug() << "MInputContext" << __PRETTY_FUNCTION__;
    static_cast<GlibDBusIMServerProxy *>(userData)->onDisconnection();
}

void GlibDBusIMServerProxy::connectToDBus()
{
    if (MInputContext::debug) qDebug() << "MInputContext" << __PRETTY_FUNCTION__;

    GError *error = NULL;

    connection = toRef(dbus_g_connection_open(SocketPath, &error));
    if (!connection) {
        if (error) {
            qWarning("MInputContext: unable to create D-Bus connection: %s", error->message);
            g_error_free(error);
        }
        QTimer::singleShot(ConnectionRetryInterval, this, SLOT(connectToDBus()));
        return;
    }

    glibObjectProxy = dbus_g_proxy_new_for_peer(connection.get(), DBusPath, DBusInterface);
    if (!glibObjectProxy) {
        qWarning("MInputContext: unable to find the D-Bus service.");
        connection.reset();
        QTimer::singleShot(ConnectionRetryInterval, this, SLOT(connectToDBus()));
        return;
    }
    g_signal_connect(G_OBJECT(glibObjectProxy), "destroy", G_CALLBACK(onDisconnectionTrampoline),
                     this);

    dbus_g_connection_register_g_object(connection.get(), icAdaptorPath.toAscii().data(), inputContextAdaptor);

    emit dbusConnected();
}

void GlibDBusIMServerProxy::onDisconnection()
{
    if (MInputContext::debug) qDebug() << "MInputContext" << __PRETTY_FUNCTION__;

    glibObjectProxy = 0;
    connection.reset();
    emit dbusDisconnected();
    if (active) {
        QTimer::singleShot(ConnectionRetryInterval, this, SLOT(connectToDBus()));
    }
}

void GlibDBusIMServerProxy::resetNotifyTrampoline(DBusGProxy *proxy, DBusGProxyCall *callId,
                                                  gpointer userData)
{
    static_cast<GlibDBusIMServerProxy *>(userData)->resetNotify(proxy, callId);
}

void GlibDBusIMServerProxy::resetNotify(DBusGProxy *proxy, DBusGProxyCall *callId)
{
    if (MInputContext::debug) qDebug() << "MInputContext" << __PRETTY_FUNCTION__;

    dbus_g_proxy_end_call(proxy, callId, 0, G_TYPE_INVALID);
    pendingResetCalls.remove(callId);
}

// Remote methods............................................................

void GlibDBusIMServerProxy::activateContext()
{
    if (!glibObjectProxy) {
        return;
    }
    dbus_g_proxy_call_no_reply(glibObjectProxy, "activateContext",
                               G_TYPE_INVALID);
}

void GlibDBusIMServerProxy::showInputMethod()
{
    if (!glibObjectProxy) {
        return;
    }
    dbus_g_proxy_call_no_reply(glibObjectProxy, "showInputMethod",
                               G_TYPE_INVALID);
}

void GlibDBusIMServerProxy::hideInputMethod()
{
    if (!glibObjectProxy) {
        return;
    }
    dbus_g_proxy_call_no_reply(glibObjectProxy, "hideInputMethod",
                               G_TYPE_INVALID);
}

void GlibDBusIMServerProxy::mouseClickedOnPreedit(const QPoint &pos, const QRect &preeditRect)
{
    if (!glibObjectProxy) {
        return;
    }
    dbus_g_proxy_call_no_reply(glibObjectProxy, "mouseClickedOnPreedit",
                               G_TYPE_INT, pos.x(),
                               G_TYPE_INT, pos.y(),
                               G_TYPE_INT, preeditRect.x(),
                               G_TYPE_INT, preeditRect.y(),
                               G_TYPE_INT, preeditRect.width(),
                               G_TYPE_INT, preeditRect.height(),
                               G_TYPE_INVALID);
}

void GlibDBusIMServerProxy::setPreedit(const QString &text, int cursorPos)
{
    if (!glibObjectProxy) {
        return;
    }
    dbus_g_proxy_call_no_reply(glibObjectProxy, "setPreedit",
                               G_TYPE_STRING, text.toUtf8().data(),
                               G_TYPE_INT, cursorPos,
                               G_TYPE_INVALID);
}

namespace {

bool encodeVariant(GValue *dest, const QVariant &source)
{
    switch (source.type()) {
    case QVariant::Bool:
        g_value_init(dest, G_TYPE_BOOLEAN);
        g_value_set_boolean(dest, source.toBool());
        return true;
    case QVariant::Int:
        g_value_init(dest, G_TYPE_INT);
        g_value_set_int(dest, source.toInt());
        return true;
    case QVariant::UInt:
        g_value_init(dest, G_TYPE_UINT);
        g_value_set_uint(dest, source.toUInt());
        return true;
    case QVariant::LongLong:
        g_value_init(dest, G_TYPE_INT64);
        g_value_set_int64(dest, source.toLongLong());
        return true;
    case QVariant::ULongLong:
        g_value_init(dest, G_TYPE_UINT64);
        g_value_set_uint64(dest, source.toULongLong());
        return true;
    case QVariant::Double:
        g_value_init(dest, G_TYPE_DOUBLE);
        g_value_set_double(dest, source.toDouble());
        return true;
    case QVariant::String:
        g_value_init(dest, G_TYPE_STRING);
        // string is copied by g_value_set_string
        g_value_set_string(dest, source.toString().toUtf8().constData());
        return true;
    case QVariant::Rect:
        {
            // QRect is encoded as (iiii).
            // This is compatible with QDBusArgument encoding. see more in decoder
            GType structType = dbus_g_type_get_struct("GValueArray",
                                                      G_TYPE_INT, G_TYPE_INT,
                                                      G_TYPE_INT, G_TYPE_INT,
                                                      G_TYPE_INVALID);
            g_value_init(dest, structType);
            GValueArray *array = (GValueArray*)dbus_g_type_specialized_construct(structType);
            if (!array) {
                qWarning() << Q_FUNC_INFO << "failed to initialize Rect instance";
            }
            g_value_take_boxed(dest, array);
            QRect rect = source.toRect();
            if (!dbus_g_type_struct_set(dest,
                                    0, rect.left(),
                                    1, rect.top(),
                                    2, rect.width(),
                                    3, rect.height(),
                                    G_MAXUINT)) {
                g_value_unset(dest);
                qWarning() << Q_FUNC_INFO << "failed to fill Rect instance";
                return false;
            }
            return true;
        }
    case QMetaType::ULong:
        g_value_init(dest, G_TYPE_ULONG);
        g_value_set_ulong(dest, source.value<ulong>());
        return true;
    default:
        qWarning() << Q_FUNC_INFO << "unsupported data:" << source.type() << source;
        return false;
    }
}

void destroyGValue(GValue *value)
{
    g_value_unset(value);
    g_free(value);
}

GHashTable *encodeVariantMap(const QMap<QString, QVariant> &source)
{
    GHashTable* result = g_hash_table_new_full(&g_str_hash, &g_str_equal,
                                               &g_free, GDestroyNotify(&destroyGValue));
    foreach (QString key, source.keys()) {
        GValue *valueVariant = g_new0(GValue, 1);
        if (!encodeVariant(valueVariant, source[key])) {
            g_free(valueVariant);
            g_hash_table_unref(result);
            return 0;
        }
        g_hash_table_insert(result, g_strdup(key.toUtf8().constData()), valueVariant);
    }
    return result;
}

}

void GlibDBusIMServerProxy::updateWidgetInformation(const QMap<QString, QVariant> &stateInformation,
                                                    bool focusChanged)
{
    if (!glibObjectProxy) {
        return;
    }
    GHashTable *encodedState = encodeVariantMap(stateInformation);
    if (encodedState == 0)
        return;

    GType encodedStateType = dbus_g_type_get_map("GHashTable", G_TYPE_STRING, G_TYPE_VALUE);
    dbus_g_proxy_call_no_reply(glibObjectProxy, "updateWidgetInformation",
                               encodedStateType, encodedState,
                               G_TYPE_BOOLEAN, focusChanged,
                               G_TYPE_INVALID);
    g_hash_table_unref(encodedState);
}

void GlibDBusIMServerProxy::reset(bool requireSynchronization)
{
    if (!glibObjectProxy) {
        return;
    }

    if (requireSynchronization) {
        DBusGProxyCall *resetCall = dbus_g_proxy_begin_call(glibObjectProxy, "reset",
                                                            resetNotifyTrampoline, this,
                                                            0, G_TYPE_INVALID);
        pendingResetCalls.insert(resetCall);
    } else {
        dbus_g_proxy_call_no_reply(glibObjectProxy, "reset",
                                   G_TYPE_INVALID);
    }
}

bool GlibDBusIMServerProxy::pendingResets()
{
    return (pendingResetCalls.size() > 0);
}

void GlibDBusIMServerProxy::appOrientationAboutToChange(int angle)
{
    if (!glibObjectProxy) {
        return;
    }
    dbus_g_proxy_call_no_reply(glibObjectProxy, "appOrientationAboutToChange",
                               G_TYPE_INT, angle,
                               G_TYPE_INVALID);
}

void GlibDBusIMServerProxy::appOrientationChanged(int angle)
{
    if (!glibObjectProxy) {
        return;
    }
    dbus_g_proxy_call_no_reply(glibObjectProxy, "appOrientationChanged",
                               G_TYPE_INT, angle,
                               G_TYPE_INVALID);
}

void GlibDBusIMServerProxy::setCopyPasteState(bool copyAvailable, bool pasteAvailable)
{
    if (!glibObjectProxy) {
        return;
    }
    dbus_g_proxy_call_no_reply(glibObjectProxy, "setCopyPasteState",
                               G_TYPE_BOOLEAN, copyAvailable,
                               G_TYPE_BOOLEAN, pasteAvailable,
                               G_TYPE_INVALID);
}

void GlibDBusIMServerProxy::processKeyEvent(QEvent::Type keyType, Qt::Key keyCode,
                                            Qt::KeyboardModifiers modifiers,
                                            const QString &text, bool autoRepeat, int count,
                                            quint32 nativeScanCode, quint32 nativeModifiers,
                                            unsigned long time)
{
    if (!glibObjectProxy) {
        return;
    }
    dbus_g_proxy_call_no_reply(glibObjectProxy, "processKeyEvent",
                               G_TYPE_INT, static_cast<int>(keyType),
                               G_TYPE_INT, static_cast<int>(keyCode),
                               G_TYPE_INT, static_cast<int>(modifiers),
                               G_TYPE_STRING, text.toUtf8().data(),
                               G_TYPE_BOOLEAN, autoRepeat, G_TYPE_INT, count,
                               G_TYPE_UINT, nativeScanCode, G_TYPE_UINT, nativeModifiers,
                               G_TYPE_ULONG, time,
                               G_TYPE_INVALID);
}

void GlibDBusIMServerProxy::registerAttributeExtension(int id, const QString &fileName)
{
    if (!glibObjectProxy) {
        return;
    }
    dbus_g_proxy_call_no_reply(glibObjectProxy, "registerAttributeExtension",
                               G_TYPE_INT, id,
                               G_TYPE_STRING, fileName.toUtf8().data(),
                               G_TYPE_INVALID);
}

void GlibDBusIMServerProxy::unregisterAttributeExtension(int id)
{
    if (!glibObjectProxy) {
        return;
    }
    dbus_g_proxy_call_no_reply(glibObjectProxy, "unregisterAttributeExtension",
                               G_TYPE_INT, id,
                               G_TYPE_INVALID);
}

void GlibDBusIMServerProxy::setExtendedAttribute(int id, const QString &target, const QString &targetItem,
                                                 const QString &attribute, const QVariant &value)
{
    if (!glibObjectProxy) {
        return;
    }
    GValue valueData = {0, {{0}, {0}}};
    if (!encodeVariant(&valueData, value)) {
        return;
    }

    dbus_g_proxy_call_no_reply(glibObjectProxy, "setExtendedAttribute",
                               G_TYPE_INT, id,
                               G_TYPE_STRING, target.toUtf8().data(),
                               G_TYPE_STRING, targetItem.toUtf8().data(),
                               G_TYPE_STRING, attribute.toUtf8().data(),
                               G_TYPE_VALUE, &valueData,
                               G_TYPE_INVALID);
    g_value_unset(&valueData);
}
<commit_msg>Fixes: crash in ut_minputocntextplugin<commit_after>/* * This file is part of meego-im-framework *
 *
 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
 * All rights reserved.
 * Contact: Nokia Corporation (directui@nokia.com)
 *
 * If you have questions regarding the use of this file, please contact
 * Nokia at directui@nokia.com.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License version 2.1 as published by the Free Software Foundation
 * and appearing in the file LICENSE.LGPL included in the packaging
 * of this file.
 */

#include "glibdbusimserverproxy.h"
#include "minputcontext.h"

#include <QPoint>
#include <QRect>
#include <QString>
#include <QDataStream>
#include <QVariant>
#include <QTimer>
#include <QDateTime>
#include <QDebug>

#include <unistd.h>
#include <sys/types.h>

namespace
{
    const char * const DBusPath("/com/meego/inputmethod/uiserver1");
    const char * const DBusInterface("com.meego.inputmethod.uiserver1");
    const char * const SocketPath = "unix:path=/tmp/meego-im-uiserver/imserver_dbus";
    const int ConnectionRetryInterval(6*1000); // in ms

    Maliit::DBusGLib::ConnectionRef toRef(DBusGConnection *connection)
    {
        if (!connection)
            return Maliit::DBusGLib::ConnectionRef();

        return Maliit::DBusGLib::ConnectionRef(connection,
                                               dbus_g_connection_unref);
    }
}

GlibDBusIMServerProxy::GlibDBusIMServerProxy(GObject *inputContextAdaptor, const QString &icAdaptorPath)
    : glibObjectProxy(NULL),
      connection(),
      inputContextAdaptor(inputContextAdaptor),
      icAdaptorPath(icAdaptorPath),
      active(true)
{
    dbus_g_thread_init();

    connectToDBus();
}

GlibDBusIMServerProxy::~GlibDBusIMServerProxy()
{
    active = false;

    foreach (DBusGProxyCall *callId, pendingResetCalls) {
        dbus_g_proxy_cancel_call(glibObjectProxy, callId);
    }
}

// Auxiliary connection handling.............................................

void GlibDBusIMServerProxy::onDisconnectionTrampoline(DBusGProxy */*proxy*/, gpointer userData)
{
    if (MInputContext::debug) qDebug() << "MInputContext" << __PRETTY_FUNCTION__;
    static_cast<GlibDBusIMServerProxy *>(userData)->onDisconnection();
}

void GlibDBusIMServerProxy::connectToDBus()
{
    if (MInputContext::debug) qDebug() << "MInputContext" << __PRETTY_FUNCTION__;

    GError *error = NULL;

    connection = toRef(dbus_g_connection_open(SocketPath, &error));
    if (!connection) {
        if (error) {
            qWarning("MInputContext: unable to create D-Bus connection: %s", error->message);
            g_error_free(error);
        }
        QTimer::singleShot(ConnectionRetryInterval, this, SLOT(connectToDBus()));
        return;
    }

    glibObjectProxy = dbus_g_proxy_new_for_peer(connection.get(), DBusPath, DBusInterface);
    if (!glibObjectProxy) {
        qWarning("MInputContext: unable to find the D-Bus service.");
        connection.reset();
        QTimer::singleShot(ConnectionRetryInterval, this, SLOT(connectToDBus()));
        return;
    }
    g_signal_connect(G_OBJECT(glibObjectProxy), "destroy", G_CALLBACK(onDisconnectionTrampoline),
                     this);

    dbus_g_connection_register_g_object(connection.get(), icAdaptorPath.toAscii().data(), inputContextAdaptor);

    emit dbusConnected();
}

void GlibDBusIMServerProxy::onDisconnection()
{
    if (MInputContext::debug) qDebug() << "MInputContext" << __PRETTY_FUNCTION__;

    glibObjectProxy = 0;
    connection.reset();
    emit dbusDisconnected();
    if (active) {
        QTimer::singleShot(ConnectionRetryInterval, this, SLOT(connectToDBus()));
    }
}

void GlibDBusIMServerProxy::resetNotifyTrampoline(DBusGProxy *proxy, DBusGProxyCall *callId,
                                                  gpointer userData)
{
    static_cast<GlibDBusIMServerProxy *>(userData)->resetNotify(proxy, callId);
}

void GlibDBusIMServerProxy::resetNotify(DBusGProxy *proxy, DBusGProxyCall *callId)
{
    if (MInputContext::debug) qDebug() << "MInputContext" << __PRETTY_FUNCTION__;

    dbus_g_proxy_end_call(proxy, callId, 0, G_TYPE_INVALID);
    pendingResetCalls.remove(callId);
}

// Remote methods............................................................

void GlibDBusIMServerProxy::activateContext()
{
    if (!glibObjectProxy) {
        return;
    }
    dbus_g_proxy_call_no_reply(glibObjectProxy, "activateContext",
                               G_TYPE_INVALID);
}

void GlibDBusIMServerProxy::showInputMethod()
{
    if (!glibObjectProxy) {
        return;
    }
    dbus_g_proxy_call_no_reply(glibObjectProxy, "showInputMethod",
                               G_TYPE_INVALID);
}

void GlibDBusIMServerProxy::hideInputMethod()
{
    if (!glibObjectProxy) {
        return;
    }
    dbus_g_proxy_call_no_reply(glibObjectProxy, "hideInputMethod",
                               G_TYPE_INVALID);
}

void GlibDBusIMServerProxy::mouseClickedOnPreedit(const QPoint &pos, const QRect &preeditRect)
{
    if (!glibObjectProxy) {
        return;
    }
    dbus_g_proxy_call_no_reply(glibObjectProxy, "mouseClickedOnPreedit",
                               G_TYPE_INT, pos.x(),
                               G_TYPE_INT, pos.y(),
                               G_TYPE_INT, preeditRect.x(),
                               G_TYPE_INT, preeditRect.y(),
                               G_TYPE_INT, preeditRect.width(),
                               G_TYPE_INT, preeditRect.height(),
                               G_TYPE_INVALID);
}

void GlibDBusIMServerProxy::setPreedit(const QString &text, int cursorPos)
{
    if (!glibObjectProxy) {
        return;
    }
    dbus_g_proxy_call_no_reply(glibObjectProxy, "setPreedit",
                               G_TYPE_STRING, text.toUtf8().data(),
                               G_TYPE_INT, cursorPos,
                               G_TYPE_INVALID);
}

namespace {

bool encodeVariant(GValue *dest, const QVariant &source)
{
    switch (source.type()) {
    case QVariant::Bool:
        g_value_init(dest, G_TYPE_BOOLEAN);
        g_value_set_boolean(dest, source.toBool());
        return true;
    case QVariant::Int:
        g_value_init(dest, G_TYPE_INT);
        g_value_set_int(dest, source.toInt());
        return true;
    case QVariant::UInt:
        g_value_init(dest, G_TYPE_UINT);
        g_value_set_uint(dest, source.toUInt());
        return true;
    case QVariant::LongLong:
        g_value_init(dest, G_TYPE_INT64);
        g_value_set_int64(dest, source.toLongLong());
        return true;
    case QVariant::ULongLong:
        g_value_init(dest, G_TYPE_UINT64);
        g_value_set_uint64(dest, source.toULongLong());
        return true;
    case QVariant::Double:
        g_value_init(dest, G_TYPE_DOUBLE);
        g_value_set_double(dest, source.toDouble());
        return true;
    case QVariant::String:
        g_value_init(dest, G_TYPE_STRING);
        // string is copied by g_value_set_string
        g_value_set_string(dest, source.toString().toUtf8().constData());
        return true;
    case QVariant::Rect:
        {
            // QRect is encoded as (iiii).
            // This is compatible with QDBusArgument encoding. see more in decoder
            GType structType = dbus_g_type_get_struct("GValueArray",
                                                      G_TYPE_INT, G_TYPE_INT,
                                                      G_TYPE_INT, G_TYPE_INT,
                                                      G_TYPE_INVALID);
            g_value_init(dest, structType);
            GValueArray *array = (GValueArray*)dbus_g_type_specialized_construct(structType);
            if (!array) {
                qWarning() << Q_FUNC_INFO << "failed to initialize Rect instance";
            }
            g_value_take_boxed(dest, array);
            QRect rect = source.toRect();
            if (!dbus_g_type_struct_set(dest,
                                    0, rect.left(),
                                    1, rect.top(),
                                    2, rect.width(),
                                    3, rect.height(),
                                    G_MAXUINT)) {
                g_value_unset(dest);
                qWarning() << Q_FUNC_INFO << "failed to fill Rect instance";
                return false;
            }
            return true;
        }
    case QMetaType::ULong:
        g_value_init(dest, G_TYPE_ULONG);
        g_value_set_ulong(dest, source.value<ulong>());
        return true;
    default:
        qWarning() << Q_FUNC_INFO << "unsupported data:" << source.type() << source;
        return false;
    }
}

void destroyGValue(GValue *value)
{
    g_value_unset(value);
    g_free(value);
}

GHashTable *encodeVariantMap(const QMap<QString, QVariant> &source)
{
    GHashTable* result = g_hash_table_new_full(&g_str_hash, &g_str_equal,
                                               &g_free, GDestroyNotify(&destroyGValue));
    foreach (QString key, source.keys()) {
        GValue *valueVariant = g_new0(GValue, 1);
        if (!encodeVariant(valueVariant, source[key])) {
            g_free(valueVariant);
            g_hash_table_unref(result);
            return 0;
        }
        g_hash_table_insert(result, g_strdup(key.toUtf8().constData()), valueVariant);
    }
    return result;
}

}

void GlibDBusIMServerProxy::updateWidgetInformation(const QMap<QString, QVariant> &stateInformation,
                                                    bool focusChanged)
{
    if (!glibObjectProxy) {
        return;
    }
    GHashTable *encodedState = encodeVariantMap(stateInformation);
    if (encodedState == 0)
        return;

    GType encodedStateType = dbus_g_type_get_map("GHashTable", G_TYPE_STRING, G_TYPE_VALUE);
    dbus_g_proxy_call_no_reply(glibObjectProxy, "updateWidgetInformation",
                               encodedStateType, encodedState,
                               G_TYPE_BOOLEAN, focusChanged,
                               G_TYPE_INVALID);
    g_hash_table_unref(encodedState);
}

void GlibDBusIMServerProxy::reset(bool requireSynchronization)
{
    if (!glibObjectProxy) {
        return;
    }

    if (requireSynchronization) {
        DBusGProxyCall *resetCall = dbus_g_proxy_begin_call(glibObjectProxy, "reset",
                                                            resetNotifyTrampoline, this,
                                                            0, G_TYPE_INVALID);
        pendingResetCalls.insert(resetCall);
    } else {
        dbus_g_proxy_call_no_reply(glibObjectProxy, "reset",
                                   G_TYPE_INVALID);
    }
}

bool GlibDBusIMServerProxy::pendingResets()
{
    return (pendingResetCalls.size() > 0);
}

void GlibDBusIMServerProxy::appOrientationAboutToChange(int angle)
{
    if (!glibObjectProxy) {
        return;
    }
    dbus_g_proxy_call_no_reply(glibObjectProxy, "appOrientationAboutToChange",
                               G_TYPE_INT, angle,
                               G_TYPE_INVALID);
}

void GlibDBusIMServerProxy::appOrientationChanged(int angle)
{
    if (!glibObjectProxy) {
        return;
    }
    dbus_g_proxy_call_no_reply(glibObjectProxy, "appOrientationChanged",
                               G_TYPE_INT, angle,
                               G_TYPE_INVALID);
}

void GlibDBusIMServerProxy::setCopyPasteState(bool copyAvailable, bool pasteAvailable)
{
    if (!glibObjectProxy) {
        return;
    }
    dbus_g_proxy_call_no_reply(glibObjectProxy, "setCopyPasteState",
                               G_TYPE_BOOLEAN, copyAvailable,
                               G_TYPE_BOOLEAN, pasteAvailable,
                               G_TYPE_INVALID);
}

void GlibDBusIMServerProxy::processKeyEvent(QEvent::Type keyType, Qt::Key keyCode,
                                            Qt::KeyboardModifiers modifiers,
                                            const QString &text, bool autoRepeat, int count,
                                            quint32 nativeScanCode, quint32 nativeModifiers,
                                            unsigned long time)
{
    if (!glibObjectProxy) {
        return;
    }
    dbus_g_proxy_call_no_reply(glibObjectProxy, "processKeyEvent",
                               G_TYPE_INT, static_cast<int>(keyType),
                               G_TYPE_INT, static_cast<int>(keyCode),
                               G_TYPE_INT, static_cast<int>(modifiers),
                               G_TYPE_STRING, text.toUtf8().data(),
                               G_TYPE_BOOLEAN, autoRepeat, G_TYPE_INT, count,
                               G_TYPE_UINT, nativeScanCode, G_TYPE_UINT, nativeModifiers,
                               G_TYPE_ULONG, time,
                               G_TYPE_INVALID);
}

void GlibDBusIMServerProxy::registerAttributeExtension(int id, const QString &fileName)
{
    if (!glibObjectProxy) {
        return;
    }
    dbus_g_proxy_call_no_reply(glibObjectProxy, "registerAttributeExtension",
                               G_TYPE_INT, id,
                               G_TYPE_STRING, fileName.toUtf8().data(),
                               G_TYPE_INVALID);
}

void GlibDBusIMServerProxy::unregisterAttributeExtension(int id)
{
    if (!glibObjectProxy) {
        return;
    }
    dbus_g_proxy_call_no_reply(glibObjectProxy, "unregisterAttributeExtension",
                               G_TYPE_INT, id,
                               G_TYPE_INVALID);
}

void GlibDBusIMServerProxy::setExtendedAttribute(int id, const QString &target, const QString &targetItem,
                                                 const QString &attribute, const QVariant &value)
{
    if (!glibObjectProxy) {
        return;
    }
    GValue valueData = {0, {{0}, {0}}};
    if (!encodeVariant(&valueData, value)) {
        return;
    }

    dbus_g_proxy_call_no_reply(glibObjectProxy, "setExtendedAttribute",
                               G_TYPE_INT, id,
                               G_TYPE_STRING, target.toUtf8().data(),
                               G_TYPE_STRING, targetItem.toUtf8().data(),
                               G_TYPE_STRING, attribute.toUtf8().data(),
                               G_TYPE_VALUE, &valueData,
                               G_TYPE_INVALID);
    g_value_unset(&valueData);
}
<|endoftext|>


<commit_before>#include <sys/ucontext.h>

namespace factor {

// Fault handler information.  MacOSX version.
// Copyright (C) 1993-1999, 2002-2003  Bruno Haible <clisp.org at bruno>
// Copyright (C) 2003  Paolo Bonzini <gnu.org at bonzini>

// Used under BSD license with permission from Paolo Bonzini and Bruno Haible,
// 2005-03-10:

// http://sourceforge.net/mailarchive/message.php?msg_name=200503102200.32002.bruno%40clisp.org

// Modified for Factor by Slava Pestov and Daniel Ehrenberg
// Modified for arm64 by Doug Coleman

/*
#define MACH_EXC_STATE_TYPE x86_exception_state64_t
#define MACH_EXC_STATE_FLAVOR x86_EXCEPTION_STATE64
#define MACH_EXC_STATE_COUNT x86_EXCEPTION_STATE64_COUNT

#define MACH_EXC_INTEGER_DIV EXC_I386_DIV

#define MACH_THREAD_STATE_TYPE x86_thread_state64_t
#define MACH_THREAD_STATE_FLAVOR x86_THREAD_STATE64
#define MACH_THREAD_STATE_COUNT MACHINE_THREAD_STATE_COUNT

#define MACH_FLOAT_STATE_TYPE x86_float_state64_t
#define MACH_FLOAT_STATE_FLAVOR x86_FLOAT_STATE64
#define MACH_FLOAT_STATE_COUNT x86_FLOAT_STATE64_COUNT

#if __DARWIN_UNIX03
#define MACH_EXC_STATE_FAULT(exc_state) (exc_state)->__faultvaddr
#define MACH_STACK_POINTER(thr_state) (thr_state)->__rsp
#define MACH_PROGRAM_COUNTER(thr_state) (thr_state)->__rip
#define UAP_SS(ucontext) &(((ucontext_t*)(ucontext))->uc_mcontext->__ss)
#define UAP_FS(ucontext) &(((ucontext_t*)(ucontext))->uc_mcontext->__fs)

#define MXCSR(float_state) (float_state)->__fpu_mxcsr
#define X87SW(float_state) (float_state)->__fpu_fsw
#else
#define MACH_EXC_STATE_FAULT(exc_state) (exc_state)->faultvaddr
#define MACH_STACK_POINTER(thr_state) (thr_state)->rsp
#define MACH_PROGRAM_COUNTER(thr_state) (thr_state)->rip
#define UAP_SS(ucontext) &(((ucontext_t*)(ucontext))->uc_mcontext->ss)
#define UAP_FS(ucontext) &(((ucontext_t*)(ucontext))->uc_mcontext->fs)

#define MXCSR(float_state) (float_state)->fpu_mxcsr
#define X87SW(float_state) (float_state)->fpu_fsw
#endif

#define UAP_PROGRAM_COUNTER(ucontext) MACH_PROGRAM_COUNTER(UAP_SS(ucontext))

inline static unsigned int mach_fpu_status(x86_float_state64_t* float_state) {
  unsigned short x87sw;
  memcpy(&x87sw, &X87SW(float_state), sizeof(x87sw));
  return MXCSR(float_state) | x87sw;
}

inline static unsigned int uap_fpu_status(void* uap) {
  return mach_fpu_status(UAP_FS(uap));
}

inline static void mach_clear_fpu_status(x86_float_state64_t* float_state) {
  MXCSR(float_state) &= 0xffffffc0;
  memset(&X87SW(float_state), 0, sizeof(X87SW(float_state)));
}

inline static void uap_clear_fpu_status(void* uap) {
  mach_clear_fpu_status(UAP_FS(uap));
}

// Must match the stack-frame-size constant in
// basis/bootstrap/assembler/x86.64.unix.factor
static const unsigned JIT_FRAME_SIZE = 32;

*/

#define MACH_EXC_STATE_TYPE _STRUCT_ARM_EXCEPTION_STATE64 // arm_exception_state64_t
#define MACH_EXC_STATE_FAULT(exc_state) (exc_state)->__far
#define MACH_EXC_STATE_COUNT ARM_EXCEPTION_STATE64_COUNT
#define MACH_EXC_STATE_FLAVOR ARM_EXCEPTION_STATE64

//#define MACH_EXC_INTEGER_DIV undefined on arm? https://opensource.apple.com/source/lldb/lldb-112/source/Plugins/Process/Utility/StopInfoMachException.cpp.auto.html

#define MACH_THREAD_STATE_TYPE _STRUCT_ARM_THREAD_STATE64
#define MACH_THREAD_STATE_COUNT MACHINE_THREAD_STATE_COUNT
#define MACH_THREAD_STATE_FLAVOR ARM_THREAD_STATE64

#define MACH_FLOAT_STATE_TYPE _STRUCT_ARM_NEON_STATE64
#define MACH_FLOAT_STATE_COUNT ARM_NEON_STATE64_COUNT
#define MACH_FLOAT_STATE_FLAVOR ARM_NEON_STATE64

#define MACH_STACK_POINTER(thr_state) (thr_state)->__sp

#define MACH_PROGRAM_COUNTER(thr_state) (thr_state)->__pc
#define UAP_PROGRAM_COUNTER(ucontext) MACH_PROGRAM_COUNTER(UAP_SS(ucontext))

#define UAP_SS(ucontext) &(((ucontext_t*)(ucontext))->uc_mcontext->__ss)
#define UAP_FS(ucontext) &(((ucontext_t*)(ucontext))->uc_mcontext->__ns)

// omg
inline static unsigned int mach_fpu_status(_STRUCT_ARM_NEON_STATE64* float_state) {
  // unsigned short x87sw;
  // memcpy(&x87sw, &X87SW(float_state), sizeof(x87sw));
  // return MXCSR(float_state) | x87sw;
  return float_state->__fpsr;
}

// omg
inline static unsigned int uap_fpu_status(void* uap) {
  return mach_fpu_status(UAP_FS(uap));
}

// omg
inline static void uap_clear_fpu_status(void* uap) {
  // mach_clear_fpu_status(UAP_FS(uap));
}

inline static void mach_clear_fpu_status(arm_neon_state64_t* float_state) {
  // MXCSR(float_state) &= 0xffffffc0; // omg
  // memset(&X87SW(float_state), 0, sizeof(X87SW(float_state))); // omg
}

// omg
inline static unsigned int fpu_status(unsigned int status) {
  unsigned int r = 0;

/*
  if (status & 0x01)
    r |= FP_TRAP_INVALID_OPERATION;
  if (status & 0x04)
    r |= FP_TRAP_ZERO_DIVIDE;
  if (status & 0x08)
    r |= FP_TRAP_OVERFLOW;
  if (status & 0x10)
    r |= FP_TRAP_UNDERFLOW;
  if (status & 0x20)
    r |= FP_TRAP_INEXACT;
*/
  return r;
}

static const unsigned JIT_FRAME_SIZE = 32; // omg

}<commit_msg>vm: use EXC_ARM_FP_DZ on macosx-arm64.<commit_after>#include <sys/ucontext.h>

namespace factor {

// Fault handler information.  MacOSX version.
// Copyright (C) 1993-1999, 2002-2003  Bruno Haible <clisp.org at bruno>
// Copyright (C) 2003  Paolo Bonzini <gnu.org at bonzini>

// Used under BSD license with permission from Paolo Bonzini and Bruno Haible,
// 2005-03-10:

// http://sourceforge.net/mailarchive/message.php?msg_name=200503102200.32002.bruno%40clisp.org

// Modified for Factor by Slava Pestov and Daniel Ehrenberg
// Modified for arm64 by Doug Coleman

/*
#define MACH_EXC_STATE_TYPE x86_exception_state64_t
#define MACH_EXC_STATE_FLAVOR x86_EXCEPTION_STATE64
#define MACH_EXC_STATE_COUNT x86_EXCEPTION_STATE64_COUNT
*/
#define MACH_EXC_INTEGER_DIV EXC_ARM_FP_DZ
/*
#define MACH_THREAD_STATE_TYPE x86_thread_state64_t
#define MACH_THREAD_STATE_FLAVOR x86_THREAD_STATE64
#define MACH_THREAD_STATE_COUNT MACHINE_THREAD_STATE_COUNT

#define MACH_FLOAT_STATE_TYPE x86_float_state64_t
#define MACH_FLOAT_STATE_FLAVOR x86_FLOAT_STATE64
#define MACH_FLOAT_STATE_COUNT x86_FLOAT_STATE64_COUNT

#if __DARWIN_UNIX03
#define MACH_EXC_STATE_FAULT(exc_state) (exc_state)->__faultvaddr
#define MACH_STACK_POINTER(thr_state) (thr_state)->__rsp
#define MACH_PROGRAM_COUNTER(thr_state) (thr_state)->__rip
#define UAP_SS(ucontext) &(((ucontext_t*)(ucontext))->uc_mcontext->__ss)
#define UAP_FS(ucontext) &(((ucontext_t*)(ucontext))->uc_mcontext->__fs)

#define MXCSR(float_state) (float_state)->__fpu_mxcsr
#define X87SW(float_state) (float_state)->__fpu_fsw
#else
#define MACH_EXC_STATE_FAULT(exc_state) (exc_state)->faultvaddr
#define MACH_STACK_POINTER(thr_state) (thr_state)->rsp
#define MACH_PROGRAM_COUNTER(thr_state) (thr_state)->rip
#define UAP_SS(ucontext) &(((ucontext_t*)(ucontext))->uc_mcontext->ss)
#define UAP_FS(ucontext) &(((ucontext_t*)(ucontext))->uc_mcontext->fs)

#define MXCSR(float_state) (float_state)->fpu_mxcsr
#define X87SW(float_state) (float_state)->fpu_fsw
#endif

#define UAP_PROGRAM_COUNTER(ucontext) MACH_PROGRAM_COUNTER(UAP_SS(ucontext))

inline static unsigned int mach_fpu_status(x86_float_state64_t* float_state) {
  unsigned short x87sw;
  memcpy(&x87sw, &X87SW(float_state), sizeof(x87sw));
  return MXCSR(float_state) | x87sw;
}

inline static unsigned int uap_fpu_status(void* uap) {
  return mach_fpu_status(UAP_FS(uap));
}

inline static void mach_clear_fpu_status(x86_float_state64_t* float_state) {
  MXCSR(float_state) &= 0xffffffc0;
  memset(&X87SW(float_state), 0, sizeof(X87SW(float_state)));
}

inline static void uap_clear_fpu_status(void* uap) {
  mach_clear_fpu_status(UAP_FS(uap));
}

// Must match the stack-frame-size constant in
// basis/bootstrap/assembler/x86.64.unix.factor
static const unsigned JIT_FRAME_SIZE = 32;

*/

#define MACH_EXC_STATE_TYPE _STRUCT_ARM_EXCEPTION_STATE64 // arm_exception_state64_t
#define MACH_EXC_STATE_FAULT(exc_state) (exc_state)->__far
#define MACH_EXC_STATE_COUNT ARM_EXCEPTION_STATE64_COUNT
#define MACH_EXC_STATE_FLAVOR ARM_EXCEPTION_STATE64

//#define MACH_EXC_INTEGER_DIV undefined on arm? https://opensource.apple.com/source/lldb/lldb-112/source/Plugins/Process/Utility/StopInfoMachException.cpp.auto.html

#define MACH_THREAD_STATE_TYPE _STRUCT_ARM_THREAD_STATE64
#define MACH_THREAD_STATE_COUNT MACHINE_THREAD_STATE_COUNT
#define MACH_THREAD_STATE_FLAVOR ARM_THREAD_STATE64

#define MACH_FLOAT_STATE_TYPE _STRUCT_ARM_NEON_STATE64
#define MACH_FLOAT_STATE_COUNT ARM_NEON_STATE64_COUNT
#define MACH_FLOAT_STATE_FLAVOR ARM_NEON_STATE64

#define MACH_STACK_POINTER(thr_state) (thr_state)->__sp

#define MACH_PROGRAM_COUNTER(thr_state) (thr_state)->__pc
#define UAP_PROGRAM_COUNTER(ucontext) MACH_PROGRAM_COUNTER(UAP_SS(ucontext))

#define UAP_SS(ucontext) &(((ucontext_t*)(ucontext))->uc_mcontext->__ss)
#define UAP_FS(ucontext) &(((ucontext_t*)(ucontext))->uc_mcontext->__ns)

// omg
inline static unsigned int mach_fpu_status(_STRUCT_ARM_NEON_STATE64* float_state) {
  // unsigned short x87sw;
  // memcpy(&x87sw, &X87SW(float_state), sizeof(x87sw));
  // return MXCSR(float_state) | x87sw;
  return float_state->__fpsr;
}

// omg
inline static unsigned int uap_fpu_status(void* uap) {
  return mach_fpu_status(UAP_FS(uap));
}

// omg
inline static void uap_clear_fpu_status(void* uap) {
  // mach_clear_fpu_status(UAP_FS(uap));
}

inline static void mach_clear_fpu_status(arm_neon_state64_t* float_state) {
  // MXCSR(float_state) &= 0xffffffc0; // omg
  // memset(&X87SW(float_state), 0, sizeof(X87SW(float_state))); // omg
}

// omg
inline static unsigned int fpu_status(unsigned int status) {
  unsigned int r = 0;

/*
  if (status & 0x01)
    r |= FP_TRAP_INVALID_OPERATION;
  if (status & 0x04)
    r |= FP_TRAP_ZERO_DIVIDE;
  if (status & 0x08)
    r |= FP_TRAP_OVERFLOW;
  if (status & 0x10)
    r |= FP_TRAP_UNDERFLOW;
  if (status & 0x20)
    r |= FP_TRAP_INEXACT;
*/
  return r;
}

static const unsigned JIT_FRAME_SIZE = 32; // omg

}
<|endoftext|>


<commit_before>// Copyright 2015 FMAW

#include <iostream>
#include <fstream>
#include "./grid.h"
#include "./gridmap.h"
#include <fat.h>
#include <nds.h>

namespace GridMap{

void loadDefaultGridMap( Grid &g ) { loadGridMap("defaultMap", g); }

void loadGridMap( const char* mapName, Grid &g ){
	FILE* test = fopen ("./defaultMap", "r");

	int rows, cols, aux;

	fscanf( test, "%d %d\n", &rows, &cols );
	for( int row = 0; row < rows; row++ ){
		for( int col = 0; col < cols; col++ ){
			if(col < cols-1) fscanf( test, "%d ", &aux );
			else fscanf( test, "%d\n", &aux );

			IndexPath path {row, col};
			g.cellAtIndexPath(path)->setBackgroundType(
				static_cast<CellBackgroundType>(aux)
			);

			g.cellAtIndexPath(path)->renderBackground();
		}
	}

	fclose(test);
}

}
<commit_msg>Fix to prevent crashing if file couldn't be opened.<commit_after>// Copyright 2015 FMAW

#include <fat.h>
#include <nds.h>
#include <iostream>
#include <fstream>
#include "./grid.h"
#include "./gridmap.h"

namespace GridMap {

void loadDefaultGridMap(Grid &g) {
    loadGridMap("defaultMap", g);
}

void loadGridMap(const char *mapName, Grid &g) {
    FILE *test = fopen("./defaultMap", "r");

    if (test != NULL) {
        int rows, cols, aux;

        fscanf(test, "%d %d\n", &rows, &cols);
        for (int row = 0; row < rows; row++) {
            for (int col = 0; col < cols; col++) {
                if (col < cols - 1) {
                    fscanf(test, "%d ", &aux);
                } else {
                    fscanf(test, "%d\n", &aux);
                }

                IndexPath path {row, col};
                g.cellAtIndexPath(path)->setBackgroundType(
                    static_cast<CellBackgroundType>(aux));

                g.cellAtIndexPath(path)->renderBackground();
            }
        }

        fclose(test);
    }
}

}  // namespace GridMap
<|endoftext|>