contains cybozulib

dev
MITSUNARI Shigeo 6 years ago
parent f8661811a8
commit 9b43a872c6
  1. 2
      .travis.yml
  2. 21
      CMakeLists.txt
  3. 9
      Makefile
  4. 2
      common.mk
  5. 197
      include/cybozu/array.hpp
  6. 239
      include/cybozu/atoi.hpp
  7. 212
      include/cybozu/benchmark.hpp
  8. 139
      include/cybozu/bit_operation.hpp
  9. 60
      include/cybozu/critical_section.hpp
  10. 321
      include/cybozu/crypto.hpp
  11. 224
      include/cybozu/endian.hpp
  12. 252
      include/cybozu/exception.hpp
  13. 67
      include/cybozu/hash.hpp
  14. 163
      include/cybozu/inttype.hpp
  15. 337
      include/cybozu/itoa.hpp
  16. 21
      include/cybozu/link_libeay32.hpp
  17. 18
      include/cybozu/link_mpir.hpp
  18. 19
      include/cybozu/link_ssleay32.hpp
  19. 141
      include/cybozu/mutex.hpp
  20. 723
      include/cybozu/option.hpp
  21. 139
      include/cybozu/random_generator.hpp
  22. 363
      include/cybozu/serializer.hpp
  23. 438
      include/cybozu/sha2.hpp
  24. 267
      include/cybozu/stream.hpp
  25. 373
      include/cybozu/test.hpp
  26. 13
      include/cybozu/unordered_map.hpp
  27. 172
      include/cybozu/xorshift.hpp
  28. 11
      readme.md
  29. 2
      setvar.bat

@ -7,8 +7,6 @@ compiler:
before_install:
- sudo apt install -y libgmp-dev
script:
- git clone https://github.com/herumi/cybozulib.git
- git clone https://github.com/herumi/xbyak.git
- git clone https://github.com/herumi/mcl.git
- cd mcl
- make test DEBUG=1

@ -9,10 +9,9 @@ option(
)
option(
DOWNLOAD_SOURCE
"download xbyak, cybozulib"
"download cybozulib_ext"
OFF
)
set(DOWNLOAD_SOURCE ON)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
@ -50,19 +49,6 @@ else()
endif()
if(DOWNLOAD_SOURCE)
set(XBYAK_TAG v5.64)
foreach(file IN ITEMS xbyak.h xbyak_util.h xbyak_mnemonic.h)
file(DOWNLOAD https://raw.githubusercontent.com/herumi/xbyak/${XBYAK_TAG}/xbyak/${file} ${mcl_SOURCE_DIR}/include/xbyak/${file})
message("download xbyak/" ${file})
endforeach()
set(CYBOZULIB_TAG release20180528)
set(CYBOZULIB_FILES atoi.hpp bit_operation.hpp endian.hpp hash.hpp itoa.hpp random_generator.hpp unordered_map.hpp benchmark.hpp crypto.hpp exception.hpp inttype.hpp option.hpp test.hpp xorshift.hpp link_mpir.hpp link_libeay32.hpp link_ssleay32.hpp critical_section.hpp mutex.hpp serializer.hpp stream.hpp)
foreach(file IN ITEMS ${CYBOZULIB_FILES})
file(DOWNLOAD https://raw.githubusercontent.com/herumi/cybozulib/${CYBOZULIB_TAG}/include/cybozu/${file} ${mcl_SOURCE_DIR}/include/cybozu/${file})
message("download cybozu/" ${file})
endforeach()
if(MSVC)
set(CYBOZULIB_EXT_TAG release20170521)
set(FILES config.h gmp-impl.h gmp-mparam.h gmp.h gmpxx.h longlong.h mpir.h mpirxx.h)
@ -87,11 +73,6 @@ if(DOWNLOAD_SOURCE)
endif()
endif()
else()
include_directories(
${mcl_SOURCE_DIR}/../cybozulib/include
${mcl_SOURCE_DIR}/../xbyak
${mcl_SOURCE_DIR}/../cybozulib_ext/include
)
if(MSVC)
include_directories(
${mcl_SOURCE_DIR}/../cybozulib_ext/include

@ -260,7 +260,7 @@ test: $(TEST_EXE)
@sh -ec 'for i in $(TEST_EXE); do $$i|grep "ctest:name"; done' > result.txt
@grep -v "ng=0, exception=0" result.txt; if [ $$? -eq 1 ]; then echo "all unit tests succeed"; else exit 1; fi
EMCC_OPT=-I./include -I./src -I../cybozulib/include -Wall -Wextra
EMCC_OPT=-I./include -I./src -Wall -Wextra
EMCC_OPT+=-O3 -DNDEBUG -DMCLSHE_WIN_SIZE=8
EMCC_OPT+=-s WASM=1 -s NO_EXIT_RUNTIME=1 -s MODULARIZE=1 #-s ASSERTIONS=1
EMCC_OPT+=-DCYBOZU_MINIMUM_EXCEPTION
@ -299,9 +299,10 @@ ecdsa-wasm:
# test
bin/emu:
$(CXX) -g -o $@ src/fp.cpp src/bn_c256.cpp test/bn_c256_test.cpp -DMCL_DONT_USE_XBYAK -DMCL_DONT_USE_OPENSSL -DMCL_USE_VINT -DMCL_SIZEOF_UNIT=8 -DMCL_VINT_64BIT_PORTABLE -DMCL_VINT_FIXED_BUFFER -DMCL_MAX_BIT_SIZE=256 -I./include -I../cybozulib/include
$(CXX) -g -o $@ src/fp.cpp src/bn_c256.cpp test/bn_c256_test.cpp -DMCL_DONT_USE_XBYAK -DMCL_DONT_USE_OPENSSL -DMCL_USE_VINT -DMCL_SIZEOF_UNIT=8 -DMCL_VINT_64BIT_PORTABLE -DMCL_VINT_FIXED_BUFFER -DMCL_MAX_BIT_SIZE=256 -I./include
bin/pairing_c_min.exe: sample/pairing_c.c include/mcl/vint.hpp src/fp.cpp include/mcl/bn.hpp
$(CXX) -o $@ sample/pairing_c.c src/fp.cpp src/bn_c256.cpp -Ofast -g -I./include -I../cybozulib/include -fno-exceptions -fno-rtti -fno-threadsafe-statics -DMCL_DONT_USE_XBYAK -DMCL_DONT_USE_OPENSSL -DMCL_USE_VINT -DMCL_SIZEOF_UNIT=8 -DMCL_VINT_FIXED_BUFFER -DCYBOZU_DONT_USE_EXCEPTION -DCYBOZU_DONT_USE_STRING -DMCL_DONT_USE_CSPRNG -DMCL_MAX_BIT_SIZE=256 -DMCL_VINT_64BIT_PORTABLE -DNDEBUG
# $(CXX) -o $@ sample/pairing_c.c src/fp.cpp src/bn_c256.cpp -O2 -g -I./include -fno-exceptions -fno-rtti -fno-threadsafe-statics -DMCL_DONT_USE_XBYAK -DMCL_DONT_USE_OPENSSL -DMCL_USE_VINT -DMCL_SIZEOF_UNIT=8 -DMCL_VINT_FIXED_BUFFER -DCYBOZU_DONT_USE_EXCEPTION -DCYBOZU_DONT_USE_STRING -DMCL_DONT_USE_CSPRNG -DMCL_MAX_BIT_SIZE=256 -DMCL_VINT_64BIT_PORTABLE -DNDEBUG -pg
$(CXX) -o $@ sample/pairing_c.c src/fp.cpp src/bn_c256.cpp -O2 -g -I./include -fno-threadsafe-statics -DMCL_DONT_USE_XBYAK -DMCL_DONT_USE_OPENSSL -DMCL_USE_VINT -DMCL_SIZEOF_UNIT=8 -DMCL_VINT_FIXED_BUFFER -DMCL_DONT_USE_CSPRNG -DMCL_MAX_BIT_SIZE=256 -DMCL_VINT_64BIT_PORTABLE -DNDEBUG
clean:
$(RM) $(MCL_LIB) $(MCL_SLIB) $(BN256_LIB) $(BN256_SLIB) $(BN384_LIB) $(BN384_SLIB) $(BN512_LIB) $(BN512_SLIB) $(SHE256_LIB) $(OBJ_DIR)/*.o $(OBJ_DIR)/*.d $(EXE_DIR)/*.exe $(GEN_EXE) $(ASM_OBJ) $(LIB_OBJ) $(BN256_OBJ) $(BN384_OBJ) $(BN512_OBJ) $(LLVM_SRC) $(FUNC_LIST) src/*.ll lib/*.a
@ -312,9 +313,9 @@ DEPEND_FILE=$(addprefix $(OBJ_DIR)/, $(addsuffix .d,$(basename $(ALL_SRC))))
PREFIX?=/usr/local
install: lib/libmcl.a lib/libmcl$(SHARE_BASENAME_SUF).$(LIB_SUF)
$(MAKE) -C ../cybozulib install PREFIX=$(PREFIX)
$(MKDIR) $(PREFIX)/include/mcl
cp -a include/mcl/ $(PREFIX)/include/
cp -a include/cybozu/ $(PREFIX)/include/
$(MKDIR) $(PREFIX)/lib
cp -a lib/libmcl.a lib/libmcl$(SHARE_BASENAME_SUF).$(LIB_SUF) $(PREFIX)/lib/

@ -82,7 +82,7 @@ else
endif
CFLAGS_WARN=-Wall -Wextra -Wformat=2 -Wcast-qual -Wcast-align -Wwrite-strings -Wfloat-equal -Wpointer-arith
CFLAGS+=-g3
INC_OPT=-I include -I test -I ../cybozulib/include
INC_OPT=-I include -I test
CFLAGS+=$(CFLAGS_WARN) $(BIT_OPT) $(INC_OPT)
DEBUG=0
CFLAGS_OPT_USER?=$(CFLAGS_OPT)

@ -0,0 +1,197 @@
#pragma once
/**
@file
@brief scoped array and aligned array
@author MITSUNARI Shigeo(@herumi)
*/
#include <new>
#include <utility>
#ifdef _WIN32
#include <malloc.h>
#else
#include <stdlib.h>
#endif
#include <cybozu/inttype.hpp>
namespace cybozu {
inline void *AlignedMalloc(size_t size, size_t alignment)
{
#ifdef _WIN32
return _aligned_malloc(size, alignment);
#else
void *p;
int ret = posix_memalign(&p, alignment, size);
return (ret == 0) ? p : 0;
#endif
}
inline void AlignedFree(void *p)
{
#ifdef _WIN32
if (p == 0) return;
_aligned_free(p);
#else
free(p);
#endif
}
template<class T>
class ScopedArray {
T *p_;
size_t size_;
ScopedArray(const ScopedArray&);
void operator=(const ScopedArray&);
public:
explicit ScopedArray(size_t size)
: p_(new T[size])
, size_(size)
{
}
~ScopedArray()
{
delete[] p_;
}
T& operator[](size_t idx) CYBOZU_NOEXCEPT { return p_[idx]; }
const T& operator[](size_t idx) const CYBOZU_NOEXCEPT { return p_[idx]; }
size_t size() const CYBOZU_NOEXCEPT { return size_; }
bool empty() const CYBOZU_NOEXCEPT { return size_ == 0; }
T* begin() CYBOZU_NOEXCEPT { return p_; }
T* end() CYBOZU_NOEXCEPT { return p_ + size_; }
const T* begin() const CYBOZU_NOEXCEPT { return p_; }
const T* end() const CYBOZU_NOEXCEPT { return p_ + size_; }
T* data() CYBOZU_NOEXCEPT { return p_; }
const T* data() const CYBOZU_NOEXCEPT { return p_; }
};
/**
T must be POD type
16byte aligment array
*/
template<class T, size_t N = 16, bool defaultDoClear = true>
class AlignedArray {
T *p_;
size_t size_;
size_t allocSize_;
T *alloc(size_t size) const
{
T *p = static_cast<T*>(AlignedMalloc(size * sizeof(T), N));
if (p == 0) throw std::bad_alloc();
return p;
}
void copy(T *dst, const T *src, size_t n) const
{
for (size_t i = 0; i < n; i++) dst[i] = src[i];
}
void setZero(T *p, size_t n) const
{
for (size_t i = 0; i < n; i++) p[i] = 0;
}
/*
alloc allocN and copy [p, p + copyN) to new p_
don't modify size_
*/
void allocCopy(size_t allocN, const T *p, size_t copyN)
{
T *q = alloc(allocN);
copy(q, p, copyN);
AlignedFree(p_);
p_ = q;
allocSize_ = allocN;
}
public:
/*
don't clear buffer with zero if doClear is false
*/
explicit AlignedArray(size_t size = 0, bool doClear = defaultDoClear)
: p_(0)
, size_(0)
, allocSize_(0)
{
resize(size, doClear);
}
AlignedArray(const AlignedArray& rhs)
: p_(0)
, size_(0)
, allocSize_(0)
{
*this = rhs;
}
AlignedArray& operator=(const AlignedArray& rhs)
{
if (allocSize_ < rhs.size_) {
allocCopy(rhs.size_, rhs.p_, rhs.size_);
} else {
copy(p_, rhs.p_, rhs.size_);
}
size_ = rhs.size_;
return *this;
}
#if (CYBOZU_CPP_VERSION >= CYBOZU_CPP_VERSION_CPP11)
AlignedArray(AlignedArray&& rhs) CYBOZU_NOEXCEPT
: p_(rhs.p_)
, size_(rhs.size_)
, allocSize_(rhs.allocSize_)
{
rhs.p_ = 0;
rhs.size_ = 0;
rhs.allocSize_ = 0;
}
AlignedArray& operator=(AlignedArray&& rhs) CYBOZU_NOEXCEPT
{
swap(rhs);
rhs.clear();
return *this;
}
#endif
/*
don't clear buffer with zero if doClear is false
@note don't free if shrinked
*/
void resize(size_t size, bool doClear = defaultDoClear)
{
// shrink
if (size <= size_) {
size_ = size;
return;
}
// realloc if necessary
if (size > allocSize_) {
allocCopy(size, p_, size_);
}
if (doClear) setZero(p_ + size_, size - size_);
size_ = size;
}
void clear() // not free
{
size_ = 0;
}
~AlignedArray()
{
AlignedFree(p_);
}
void swap(AlignedArray& rhs) CYBOZU_NOEXCEPT
{
std::swap(p_, rhs.p_);
std::swap(size_, rhs.size_);
std::swap(allocSize_, rhs.allocSize_);
}
T& operator[](size_t idx) CYBOZU_NOEXCEPT { return p_[idx]; }
const T& operator[](size_t idx) const CYBOZU_NOEXCEPT { return p_[idx]; }
size_t size() const CYBOZU_NOEXCEPT { return size_; }
bool empty() const CYBOZU_NOEXCEPT { return size_ == 0; }
T* begin() CYBOZU_NOEXCEPT { return p_; }
T* end() CYBOZU_NOEXCEPT { return p_ + size_; }
const T* begin() const CYBOZU_NOEXCEPT { return p_; }
const T* end() const CYBOZU_NOEXCEPT { return p_ + size_; }
T* data() CYBOZU_NOEXCEPT { return p_; }
const T* data() const CYBOZU_NOEXCEPT { return p_; }
#if (CYBOZU_CPP_VERSION >= CYBOZU_CPP_VERSION_CPP11)
const T* cbegin() const CYBOZU_NOEXCEPT { return p_; }
const T* cend() const CYBOZU_NOEXCEPT { return p_ + size_; }
#endif
};
} // cybozu

@ -0,0 +1,239 @@
#pragma once
/**
@file
@brief converter between integer and string
@author MITSUNARI Shigeo(@herumi)
*/
#include <memory.h>
#include <limits.h>
#include <limits>
#include <cybozu/exception.hpp>
namespace cybozu {
namespace atoi_local {
template<typename T, size_t n>
T convertToInt(bool *b, const char *p, size_t size, const char (&max)[n], T min, T overflow1, char overflow2)
{
if (size > 0 && *p) {
bool isMinus = false;
size_t i = 0;
if (*p == '-') {
isMinus = true;
i++;
}
if (i < size && p[i]) {
// skip leading zero
while (i < size && p[i] == '0') i++;
// check minimum
if (isMinus && size - i >= n - 1 && memcmp(max, &p[i], n - 1) == 0) {
if (b) *b = true;
return min;
}
T x = 0;
for (;;) {
unsigned char c;
if (i == size || (c = static_cast<unsigned char>(p[i])) == '\0') {
if (b) *b = true;
return isMinus ? -x : x;
}
unsigned int y = c - '0';
if (y > 9 || x > overflow1 || (x == overflow1 && c >= overflow2)) {
break;
}
x = x * 10 + T(y);
i++;
}
}
}
if (b) {
*b = false;
return 0;
} else {
throw cybozu::Exception("atoi::convertToInt") << cybozu::exception::makeString(p, size);
}
}
template<typename T>
T convertToUint(bool *b, const char *p, size_t size, T overflow1, char overflow2)
{
if (size > 0 && *p) {
size_t i = 0;
// skip leading zero
while (i < size && p[i] == '0') i++;
T x = 0;
for (;;) {
unsigned char c;
if (i == size || (c = static_cast<unsigned char>(p[i])) == '\0') {
if (b) *b = true;
return x;
}
unsigned int y = c - '0';
if (y > 9 || x > overflow1 || (x == overflow1 && c >= overflow2)) {
break;
}
x = x * 10 + T(y);
i++;
}
}
if (b) {
*b = false;
return 0;
} else {
throw cybozu::Exception("atoi::convertToUint") << cybozu::exception::makeString(p, size);
}
}
template<typename T>
T convertHexToInt(bool *b, const char *p, size_t size)
{
if (size > 0 && *p) {
size_t i = 0;
T x = 0;
for (;;) {
unsigned int c;
if (i == size || (c = static_cast<unsigned char>(p[i])) == '\0') {
if (b) *b = true;
return x;
}
if (c - 'A' <= 'F' - 'A') {
c = (c - 'A') + 10;
} else if (c - 'a' <= 'f' - 'a') {
c = (c - 'a') + 10;
} else if (c - '0' <= '9' - '0') {
c = c - '0';
} else {
break;
}
// avoid overflow
if (x > (std::numeric_limits<T>::max)() / 16) break;
x = x * 16 + T(c);
i++;
}
}
if (b) {
*b = false;
return 0;
} else {
throw cybozu::Exception("atoi::convertHexToInt") << cybozu::exception::makeString(p, size);
}
}
} // atoi_local
/**
auto detect return value class
@note if you set bool pointer p then throw nothing and set *p = false if bad string
*/
class atoi {
const char *p_;
size_t size_;
bool *b_;
void set(bool *b, const char *p, size_t size)
{
b_ = b;
p_ = p;
size_ = size;
}
public:
atoi(const char *p, size_t size = -1)
{
set(0, p, size);
}
atoi(bool *b, const char *p, size_t size = -1)
{
set(b, p, size);
}
atoi(const std::string& str)
{
set(0, str.c_str(), str.size());
}
atoi(bool *b, const std::string& str)
{
set(b, str.c_str(), str.size());
}
inline operator signed char() const
{
return atoi_local::convertToInt<signed char>(b_, p_, size_, "128", -128, 12, '8');
}
inline operator unsigned char() const
{
return atoi_local::convertToUint<unsigned char>(b_, p_, size_, 25, '6');
}
inline operator short() const
{
return atoi_local::convertToInt<short>(b_, p_, size_, "32768", -32768, 3276, '8');
}
inline operator unsigned short() const
{
return atoi_local::convertToUint<unsigned short>(b_, p_, size_, 6553, '6');
}
inline operator int() const
{
return atoi_local::convertToInt<int>(b_, p_, size_, "2147483648", INT_MIN, 214748364, '8');
}
inline operator unsigned int() const
{
return atoi_local::convertToUint<unsigned int>(b_, p_, size_, 429496729, '6');
}
inline operator long long() const
{
return atoi_local::convertToInt<long long>(b_, p_, size_, "9223372036854775808", LLONG_MIN, 922337203685477580LL, '8');
}
inline operator unsigned long long() const
{
return atoi_local::convertToUint<unsigned long long>(b_, p_, size_, 1844674407370955161ULL, '6');
}
#if defined(__SIZEOF_LONG__) && (__SIZEOF_LONG__ == 8)
inline operator long() const { return static_cast<long>(static_cast<long long>(*this)); }
inline operator unsigned long() const { return static_cast<unsigned long>(static_cast<unsigned long long>(*this)); }
#else
inline operator long() const { return static_cast<long>(static_cast<int>(*this)); }
inline operator unsigned long() const { return static_cast<unsigned long>(static_cast<unsigned int>(*this)); }
#endif
};
class hextoi {
const char *p_;
size_t size_;
bool *b_;
void set(bool *b, const char *p, size_t size)
{
b_ = b;
p_ = p;
size_ = size;
}
public:
hextoi(const char *p, size_t size = -1)
{
set(0, p, size);
}
hextoi(bool *b, const char *p, size_t size = -1)
{
set(b, p, size);
}
hextoi(const std::string& str)
{
set(0, str.c_str(), str.size());
}
hextoi(bool *b, const std::string& str)
{
set(b, str.c_str(), str.size());
}
operator unsigned char() const { return atoi_local::convertHexToInt<unsigned char>(b_, p_, size_); }
operator unsigned short() const { return atoi_local::convertHexToInt<unsigned short>(b_, p_, size_); }
operator unsigned int() const { return atoi_local::convertHexToInt<unsigned int>(b_, p_, size_); }
operator unsigned long() const { return atoi_local::convertHexToInt<unsigned long>(b_, p_, size_); }
operator unsigned long long() const { return atoi_local::convertHexToInt<unsigned long long>(b_, p_, size_); }
operator char() const { return atoi_local::convertHexToInt<char>(b_, p_, size_); }
operator signed char() const { return atoi_local::convertHexToInt<signed char>(b_, p_, size_); }
operator short() const { return atoi_local::convertHexToInt<short>(b_, p_, size_); }
operator int() const { return atoi_local::convertHexToInt<int>(b_, p_, size_); }
operator long() const { return atoi_local::convertHexToInt<long>(b_, p_, size_); }
operator long long() const { return atoi_local::convertHexToInt<long long>(b_, p_, size_); }
};
} // cybozu

@ -0,0 +1,212 @@
#pragma once
/**
@file
@brief measure exec time of function
@author MITSUNARI Shigeo
*/
#if defined(_MSC_VER) && (MSC_VER <= 1500)
#include <cybozu/inttype.hpp>
#else
#include <stdint.h>
#endif
#include <stdio.h>
#ifdef __EMSCRIPTEN__
#define CYBOZU_BENCH_USE_GETTIMEOFDAY
#endif
#ifdef CYBOZU_BENCH_USE_GETTIMEOFDAY
#include <sys/time.h>
#elif !defined(CYBOZU_BENCH_DONT_USE_RDTSC)
#if defined(_M_IX86) || defined(_M_X64) || defined(__i386__) || defined(__x86_64__)
#define CYBOZU_BENCH_USE_RDTSC
#define CYBOZU_BENCH_USE_CPU_TIMER
#endif
#if defined(__GNUC__) && defined(__ARM_ARCH_7A__)
// #define CYBOZU_BENCH_USE_MRC
// #define CYBOZU_BENCH_USE_CPU_TIMER
#endif
#endif
#include <assert.h>
#include <time.h>
#ifdef _MSC_VER
#include <intrin.h>
#include <sys/timeb.h>
#else
#endif
#ifndef CYBOZU_UNUSED
#ifdef __GNUC__
#define CYBOZU_UNUSED __attribute__((unused))
#else
#define CYBOZU_UNUSED
#endif
#endif
namespace cybozu {
namespace bench {
static void (*g_putCallback)(double);
static inline void setPutCallback(void (*f)(double))
{
g_putCallback = f;
}
} // cybozu::bench
class CpuClock {
public:
static inline uint64_t getCpuClk()
{
#ifdef CYBOZU_BENCH_USE_RDTSC
#ifdef _MSC_VER
return __rdtsc();
#else
unsigned int eax, edx;
__asm__ volatile("rdtsc" : "=a"(eax), "=d"(edx));
return ((uint64_t)edx << 32) | eax;
#endif
#elif defined(CYBOZU_BENCH_USE_MRC)
uint32_t clk;
__asm__ volatile("mrc p15, 0, %0, c9, c13, 0" : "=r"(clk));
return clk;
#else
#ifdef _MSC_VER
struct _timeb timeb;
_ftime_s(&timeb);
return uint64_t(timeb.time) * 1000000000 + timeb.millitm * 1000000;
#elif defined(CYBOZU_BENCH_USE_GETTIMEOFDAY)
struct timeval tv;
int ret CYBOZU_UNUSED = gettimeofday(&tv, 0);
assert(ret == 0);
return uint64_t(tv.tv_sec) * 1000000000 + tv.tv_usec * 1000;
#else
struct timespec tp;
int ret CYBOZU_UNUSED = clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tp);
assert(ret == 0);
return uint64_t(tp.tv_sec) * 1000000000 + tp.tv_nsec;
#endif
#endif
}
CpuClock()
: clock_(0)
, count_(0)
{
}
void begin()
{
clock_ -= getCpuClk();
}
void end()
{
clock_ += getCpuClk();
count_++;
}
int getCount() const { return count_; }
uint64_t getClock() const { return clock_; }
void clear() { count_ = 0; clock_ = 0; }
void put(const char *msg = 0, int N = 1) const
{
double t = getClock() / double(getCount()) / N;
if (msg && *msg) printf("%s ", msg);
if (bench::g_putCallback) {
bench::g_putCallback(t);
return;
}
#ifdef CYBOZU_BENCH_USE_CPU_TIMER
if (t > 1e6) {
printf("%7.3fMclk", t * 1e-6);
} else if (t > 1e3) {
printf("%7.3fKclk", t * 1e-3);
} else {
printf("%6.2f clk", t);
}
#else
if (t > 1e6) {
printf("%7.3fmsec", t * 1e-6);
} else if (t > 1e3) {
printf("%7.3fusec", t * 1e-3);
} else {
printf("%6.2fnsec", t);
}
#endif
if (msg && *msg) printf("\n");
}
// adhoc constatns for CYBOZU_BENCH
#ifdef CYBOZU_BENCH_USE_CPU_TIMER
static const int loopN1 = 1000;
static const int loopN2 = 100;
static const uint64_t maxClk = (uint64_t)1e8;
#else
static const int loopN1 = 100;
static const int loopN2 = 100;
static const uint64_t maxClk = (uint64_t)1e8;
#endif
private:
uint64_t clock_;
int count_;
};
namespace bench {
static CpuClock g_clk;
static int CYBOZU_UNUSED g_loopNum;
} // cybozu::bench
/*
loop counter is automatically determined
CYBOZU_BENCH(<msg>, <func>, <param1>, <param2>, ...);
if msg == "" then only set g_clk, g_loopNum
*/
#define CYBOZU_BENCH(msg, func, ...) \
{ \
const uint64_t _cybozu_maxClk = cybozu::CpuClock::maxClk; \
cybozu::CpuClock _cybozu_clk; \
for (int _cybozu_i = 0; _cybozu_i < cybozu::CpuClock::loopN2; _cybozu_i++) { \
_cybozu_clk.begin(); \
for (int _cybozu_j = 0; _cybozu_j < cybozu::CpuClock::loopN1; _cybozu_j++) { func(__VA_ARGS__); } \
_cybozu_clk.end(); \
if (_cybozu_clk.getClock() > _cybozu_maxClk) break; \
} \
if (msg && *msg) _cybozu_clk.put(msg, cybozu::CpuClock::loopN1); \
cybozu::bench::g_clk = _cybozu_clk; cybozu::bench::g_loopNum = cybozu::CpuClock::loopN1; \
}
/*
double clk;
CYBOZU_BENCH_T(clk, <func>, <param1>, <param2>, ...);
clk is set by CYBOZU_BENCH_T
*/
#define CYBOZU_BENCH_T(clk, func, ...) \
{ \
const uint64_t _cybozu_maxClk = cybozu::CpuClock::maxClk; \
cybozu::CpuClock _cybozu_clk; \
for (int _cybozu_i = 0; _cybozu_i < cybozu::CpuClock::loopN2; _cybozu_i++) { \
_cybozu_clk.begin(); \
for (int _cybozu_j = 0; _cybozu_j < cybozu::CpuClock::loopN1; _cybozu_j++) { func(__VA_ARGS__); } \
_cybozu_clk.end(); \
if (_cybozu_clk.getClock() > _cybozu_maxClk) break; \
} \
clk = _cybozu_clk.getClock() / (double)_cybozu_clk.getCount() / cybozu::CpuClock::loopN1; \
}
/*
loop counter N is given
CYBOZU_BENCH_C(<msg>, <counter>, <func>, <param1>, <param2>, ...);
if msg == "" then only set g_clk, g_loopNum
*/
#define CYBOZU_BENCH_C(msg, _N, func, ...) \
{ \
cybozu::CpuClock _cybozu_clk; \
_cybozu_clk.begin(); \
for (int _cybozu_j = 0; _cybozu_j < _N; _cybozu_j++) { func(__VA_ARGS__); } \
_cybozu_clk.end(); \
if (msg && *msg) _cybozu_clk.put(msg, _N); \
cybozu::bench::g_clk = _cybozu_clk; cybozu::bench::g_loopNum = _N; \
}
} // cybozu

@ -0,0 +1,139 @@
#pragma once
/**
@file
@brief bit operation
*/
#include <assert.h>
#include <cybozu/inttype.hpp>
#if (CYBOZU_HOST == CYBOZU_HOST_INTEL)
#if defined(_WIN32)
#include <intrin.h>
#elif defined(__linux__) || defined(__CYGWIN__) || defined(__clang__)
#include <x86intrin.h>
#elif defined(__GNUC__)
#include <emmintrin.h>
#endif
#endif
namespace cybozu {
namespace bit_op_local {
template<bool equalTo8>
struct Tag {};
// sizeof(T) < 8
template<>
struct Tag<false> {
template<class T>
static inline int bsf(T x)
{
#if defined(_MSC_VER)
unsigned long out;
_BitScanForward(&out, x);
#pragma warning(suppress: 6102)
return out;
#else
return __builtin_ctz(x);
#endif
}
template<class T>
static inline int bsr(T x)
{
#if defined(_MSC_VER)
unsigned long out;
_BitScanReverse(&out, x);
#pragma warning(suppress: 6102)
return out;
#else
return __builtin_clz(x) ^ 0x1f;
#endif
}
};
// sizeof(T) == 8
template<>
struct Tag<true> {
template<class T>
static inline int bsf(T x)
{
#if defined(_MSC_VER) && defined(_WIN64)
unsigned long out;
_BitScanForward64(&out, x);
#pragma warning(suppress: 6102)
return out;
#elif defined(__x86_64__)
return __builtin_ctzll(x);
#else
const uint32_t L = uint32_t(x);
if (L) return Tag<false>::bsf(L);
const uint32_t H = uint32_t(x >> 32);
return Tag<false>::bsf(H) + 32;
#endif
}
template<class T>
static inline int bsr(T x)
{
#if defined(_MSC_VER) && defined(_WIN64)
unsigned long out;
_BitScanReverse64(&out, x);
#pragma warning(suppress: 6102)
return out;
#elif defined(__x86_64__)
return __builtin_clzll(x) ^ 0x3f;
#else
const uint32_t H = uint32_t(x >> 32);
if (H) return Tag<false>::bsr(H) + 32;
const uint32_t L = uint32_t(x);
return Tag<false>::bsr(L);
#endif
}
};
} // bit_op_local
template<class T>
int bsf(T x)
{
return bit_op_local::Tag<sizeof(T) == 8>::bsf(x);
}
template<class T>
int bsr(T x)
{
return bit_op_local::Tag<sizeof(T) == 8>::bsr(x);
}
template<class T>
uint64_t makeBitMask64(T x)
{
assert(x < 64);
return (uint64_t(1) << x) - 1;
}
template<class T>
uint32_t popcnt(T x);
template<>
inline uint32_t popcnt<uint32_t>(uint32_t x)
{
#if defined(_MSC_VER)
return static_cast<uint32_t>(_mm_popcnt_u32(x));
#else
return static_cast<uint32_t>(__builtin_popcount(x));
#endif
}
template<>
inline uint32_t popcnt<uint64_t>(uint64_t x)
{
#if defined(__x86_64__)
return static_cast<uint32_t>(__builtin_popcountll(x));
#elif defined(_WIN64)
return static_cast<uint32_t>(_mm_popcnt_u64(x));
#else
return popcnt<uint32_t>(static_cast<uint32_t>(x)) + popcnt<uint32_t>(static_cast<uint32_t>(x >> 32));
#endif
}
} // cybozu

@ -0,0 +1,60 @@
#pragma once
/**
@file
@brief critical section
@author MITSUNARI Shigeo(@herumi)
@author MITSUNARI Shigeo
*/
#include <cybozu/mutex.hpp>
namespace cybozu {
class ConditionVariableCs;
namespace thread {
#ifdef _WIN32
typedef CRITICAL_SECTION CsHandle;
inline void CsInit(CsHandle& cs) { InitializeCriticalSection(&cs); }
inline void CsLock(CsHandle& cs) { EnterCriticalSection(&cs); }
inline void CsUnlock(CsHandle& cs) { LeaveCriticalSection(&cs); }
inline void CsTerm(CsHandle& cs) { DeleteCriticalSection(&cs); }
#else
typedef pthread_mutex_t CsHandle;
inline void CsInit(CsHandle& cs) { pthread_mutex_init(&cs, NULL); }
inline void CsLock(CsHandle& cs) { pthread_mutex_lock(&cs); }
inline void CsUnlock(CsHandle& cs) { pthread_mutex_unlock(&cs); }
inline void CsTerm(CsHandle& cs) { pthread_mutex_destroy(&cs); }
#endif
} // cybozu::thread
class CriticalSection {
friend class cybozu::ConditionVariableCs;
public:
CriticalSection()
{
thread::CsInit(hdl_);
}
~CriticalSection()
{
thread::CsTerm(hdl_);
}
inline void lock()
{
thread::CsLock(hdl_);
}
inline void unlock()
{
thread::CsUnlock(hdl_);
}
private:
CriticalSection(const CriticalSection&);
CriticalSection& operator=(const CriticalSection&);
thread::CsHandle hdl_;
};
typedef cybozu::thread::AutoLockT<cybozu::CriticalSection> AutoLockCs; //!< auto lock critical section
} // cybozu

@ -0,0 +1,321 @@
#pragma once
/**
@file
@brief wrap openssl
@author MITSUNARI Shigeo(@herumi)
*/
#include <cybozu/exception.hpp>
#ifdef __APPLE__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif
#if 0 //#ifdef __APPLE__
#define COMMON_DIGEST_FOR_OPENSSL
#include <CommonCrypto/CommonDigest.h>
#include <CommonCrypto/CommonHMAC.h>
#define SHA1 CC_SHA1
#define SHA224 CC_SHA224
#define SHA256 CC_SHA256
#define SHA384 CC_SHA384
#define SHA512 CC_SHA512
#else
#include <openssl/hmac.h>
#include <openssl/evp.h>
#include <openssl/sha.h>
#endif
#ifdef _MSC_VER
#include <cybozu/link_libeay32.hpp>
#endif
namespace cybozu {
namespace crypto {
class Hash {
public:
enum Name {
N_SHA1,
N_SHA224,
N_SHA256,
N_SHA384,
N_SHA512
};
private:
Name name_;
size_t hashSize_;
union {
SHA_CTX sha1;
SHA256_CTX sha256;
SHA512_CTX sha512;
} ctx_;
public:
static inline size_t getSize(Name name)
{
switch (name) {
case N_SHA1: return SHA_DIGEST_LENGTH;
case N_SHA224: return SHA224_DIGEST_LENGTH;
case N_SHA256: return SHA256_DIGEST_LENGTH;
case N_SHA384: return SHA384_DIGEST_LENGTH;
case N_SHA512: return SHA512_DIGEST_LENGTH;
default:
throw cybozu::Exception("crypto:Hash:getSize") << name;
}
}
static inline const char *getName(Name name)
{
switch (name) {
case N_SHA1: return "sha1";
case N_SHA224: return "sha224";
case N_SHA256: return "sha256";
case N_SHA384: return "sha384";
case N_SHA512: return "sha512";
default:
throw cybozu::Exception("crypto:Hash:getName") << name;
}
}
static inline Name getName(const std::string& nameStr)
{
static const struct {
const char *nameStr;
Name name;
} tbl[] = {
{ "sha1", N_SHA1 },
{ "sha224", N_SHA224 },
{ "sha256", N_SHA256 },
{ "sha384", N_SHA384 },
{ "sha512", N_SHA512 },
};
for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
if (nameStr == tbl[i].nameStr) return tbl[i].name;
}
throw cybozu::Exception("crypto:Hash:getName") << nameStr;
}
explicit Hash(Name name = N_SHA1)
: name_(name)
, hashSize_(getSize(name))
{
reset();
}
void update(const void *buf, size_t bufSize)
{
switch (name_) {
case N_SHA1: SHA1_Update(&ctx_.sha1, buf, bufSize); break;
case N_SHA224: SHA224_Update(&ctx_.sha256, buf, bufSize); break;
case N_SHA256: SHA256_Update(&ctx_.sha256, buf, bufSize); break;
case N_SHA384: SHA384_Update(&ctx_.sha512, buf, bufSize); break;
case N_SHA512: SHA512_Update(&ctx_.sha512, buf, bufSize); break;
}
}
void update(const std::string& buf)
{
update(buf.c_str(), buf.size());
}
void reset()
{
switch (name_) {
case N_SHA1: SHA1_Init(&ctx_.sha1); break;
case N_SHA224: SHA224_Init(&ctx_.sha256); break;
case N_SHA256: SHA256_Init(&ctx_.sha256); break;
case N_SHA384: SHA384_Init(&ctx_.sha512); break;
case N_SHA512: SHA512_Init(&ctx_.sha512); break;
default:
throw cybozu::Exception("crypto:Hash:rset") << name_;
}
}
/*
md must have hashSize byte
@note clear inner buffer after calling digest
*/
void digest(void *out, const void *buf, size_t bufSize)
{
update(buf, bufSize);
unsigned char *md = reinterpret_cast<unsigned char*>(out);
switch (name_) {
case N_SHA1: SHA1_Final(md, &ctx_.sha1); break;
case N_SHA224: SHA224_Final(md, &ctx_.sha256); break;
case N_SHA256: SHA256_Final(md, &ctx_.sha256); break;
case N_SHA384: SHA384_Final(md, &ctx_.sha512); break;
case N_SHA512: SHA512_Final(md, &ctx_.sha512); break;
default:
throw cybozu::Exception("crypto:Hash:digest") << name_;
}
reset();
}
std::string digest(const void *buf, size_t bufSize)
{
std::string ret;
ret.resize(hashSize_);
digest(&ret[0], buf, bufSize);
return ret;
}
std::string digest(const std::string& buf = "")
{
return digest(buf.c_str(), buf.size());
}
/*
out must have necessary size
@note return written size
*/
static inline size_t digest(void *out, Name name, const void *buf, size_t bufSize)
{
unsigned char *md = (unsigned char*)out;
const unsigned char *src = cybozu::cast<const unsigned char *>(buf);
switch (name) {
case N_SHA1: SHA1(src, bufSize, md); return 160 / 8;
case N_SHA224: SHA224(src, bufSize, md); return 224 / 8;
case N_SHA256: SHA256(src, bufSize, md); return 256 / 8;
case N_SHA384: SHA384(src, bufSize, md); return 384 / 8;
case N_SHA512: SHA512(src, bufSize, md); return 512 / 8;
default:
return 0;
}
}
static inline std::string digest(Name name, const void *buf, size_t bufSize)
{
char md[128];
size_t size = digest(md, name, buf, bufSize);
if (size == 0) throw cybozu::Exception("crypt:Hash:digest") << name;
return std::string(md, size);
}
static inline std::string digest(Name name, const std::string& buf)
{
return digest(name, buf.c_str(), buf.size());
}
};
class Hmac {
const EVP_MD *evp_;
public:
explicit Hmac(Hash::Name name = Hash::N_SHA1)
{
switch (name) {
case Hash::N_SHA1: evp_ = EVP_sha1(); break;
case Hash::N_SHA224: evp_ = EVP_sha224(); break;
case Hash::N_SHA256: evp_ = EVP_sha256(); break;
case Hash::N_SHA384: evp_ = EVP_sha384(); break;
case Hash::N_SHA512: evp_ = EVP_sha512(); break;
default:
throw cybozu::Exception("crypto:Hmac:") << name;
}
}
std::string eval(const std::string& key, const std::string& data)
{
std::string out(EVP_MD_size(evp_) + 1, 0);
unsigned int outLen = 0;
if (HMAC(evp_, key.c_str(), static_cast<int>(key.size()),
cybozu::cast<const uint8_t *>(data.c_str()), data.size(), cybozu::cast<uint8_t *>(&out[0]), &outLen)) {
out.resize(outLen);
return out;
}
throw cybozu::Exception("crypto::Hamc::eval");
}
};
class Cipher {
const EVP_CIPHER *cipher_;
EVP_CIPHER_CTX *ctx_;
public:
enum Name {
N_AES128_CBC,
N_AES192_CBC,
N_AES256_CBC,
N_AES128_ECB, // be carefull to use
N_AES192_ECB, // be carefull to use
N_AES256_ECB, // be carefull to use
};
static inline size_t getSize(Name name)
{
switch (name) {
case N_AES128_CBC: return 128;
case N_AES192_CBC: return 192;
case N_AES256_CBC: return 256;
case N_AES128_ECB: return 128;
case N_AES192_ECB: return 192;
case N_AES256_ECB: return 256;
default:
throw cybozu::Exception("crypto:Cipher:getSize") << name;
}
}
enum Mode {
Decoding,
Encoding
};
explicit Cipher(Name name = N_AES128_CBC)
: cipher_(0)
, ctx_(0)
{
ctx_ = EVP_CIPHER_CTX_new();
if (ctx_ == 0) throw cybozu::Exception("crypto:Cipher:EVP_CIPHER_CTX_new");
switch (name) {
case N_AES128_CBC: cipher_ = EVP_aes_128_cbc(); break;
case N_AES192_CBC: cipher_ = EVP_aes_192_cbc(); break;
case N_AES256_CBC: cipher_ = EVP_aes_256_cbc(); break;
case N_AES128_ECB: cipher_ = EVP_aes_128_ecb(); break;
case N_AES192_ECB: cipher_ = EVP_aes_192_ecb(); break;
case N_AES256_ECB: cipher_ = EVP_aes_256_ecb(); break;
default:
throw cybozu::Exception("crypto:Cipher:Cipher:name") << (int)name;
}
}
~Cipher()
{
if (ctx_) EVP_CIPHER_CTX_free(ctx_);
}
/*
@note don't use padding = true
*/
void setup(Mode mode, const std::string& key, const std::string& iv, bool padding = false)
{
const int keyLen = static_cast<int>(key.size());
const int expectedKeyLen = EVP_CIPHER_key_length(cipher_);
if (keyLen != expectedKeyLen) {
throw cybozu::Exception("crypto:Cipher:setup:keyLen") << keyLen << expectedKeyLen;
}
int ret = EVP_CipherInit_ex(ctx_, cipher_, NULL, cybozu::cast<const uint8_t*>(key.c_str()), cybozu::cast<const uint8_t*>(iv.c_str()), mode == Encoding ? 1 : 0);
if (ret != 1) {
throw cybozu::Exception("crypto:Cipher:setup:EVP_CipherInit_ex") << ret;
}
ret = EVP_CIPHER_CTX_set_padding(ctx_, padding ? 1 : 0);
if (ret != 1) {
throw cybozu::Exception("crypto:Cipher:setup:EVP_CIPHER_CTX_set_padding") << ret;
}
/*
const int ivLen = static_cast<int>(iv.size());
const int expectedIvLen = EVP_CIPHER_CTX_iv_length(&ctx_);
if (ivLen != expectedIvLen) {
throw cybozu::Exception("crypto:Cipher:setup:ivLen") << ivLen << expectedIvLen;
}
*/
}
/*
the size of outBuf must be larger than inBufSize + blockSize
@retval positive or 0 : writeSize(+blockSize)
@retval -1 : error
*/
int update(char *outBuf, const char *inBuf, int inBufSize)
{
int outLen = 0;
int ret = EVP_CipherUpdate(ctx_, cybozu::cast<uint8_t*>(outBuf), &outLen, cybozu::cast<const uint8_t*>(inBuf), inBufSize);
if (ret != 1) return -1;
return outLen;
}
/*
return -1 if padding
@note don't use
*/
int finalize(char *outBuf)
{
int outLen = 0;
int ret = EVP_CipherFinal_ex(ctx_, cybozu::cast<uint8_t*>(outBuf), &outLen);
if (ret != 1) return -1;
return outLen;
}
};
} } // cybozu::crypto
#ifdef __APPLE__
#pragma GCC diagnostic pop
#endif

@ -0,0 +1,224 @@
#pragma once
/**
@file
@brief deal with big and little endian
@author MITSUNARI Shigeo(@herumi)
*/
#include <cybozu/inttype.hpp>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
namespace cybozu {
#ifdef _MSC_VER
inline uint16_t byteSwap(uint16_t x) { return _byteswap_ushort(x); }
inline uint32_t byteSwap(uint32_t x) { return _byteswap_ulong(x); }
inline uint64_t byteSwap(uint64_t x) { return _byteswap_uint64(x); }
#else
#if (((__GNUC__) << 16) + (__GNUC_MINOR__)) >= ((4 << 16) + 8)
inline uint16_t byteSwap(uint16_t x) { return __builtin_bswap16(x); }
#else
inline uint16_t byteSwap(uint16_t x) { return (x >> 8) | (x << 8); }
#endif
inline uint32_t byteSwap(uint32_t x) { return __builtin_bswap32(x); }
inline uint64_t byteSwap(uint64_t x) { return __builtin_bswap64(x); }
#endif
/**
get 16bit integer as little endian
@param src [in] pointer
*/
inline uint16_t Get16bitAsLE(const void *src)
{
#if CYBOZU_ENDIAN == CYBOZU_ENDIAN_LITTLE
uint16_t x;
memcpy(&x, src, sizeof(x));
return x;
#else
const uint8_t *p = static_cast<const uint8_t *>(src);
return p[0] | (p[1] << 8);
#endif
}
/**
get 32bit integer as little endian
@param src [in] pointer
*/
inline uint32_t Get32bitAsLE(const void *src)
{
#if CYBOZU_ENDIAN == CYBOZU_ENDIAN_LITTLE
uint32_t x;
memcpy(&x, src, sizeof(x));
return x;
#else
const uint8_t *p = static_cast<const uint8_t *>(src);
return Get16bitAsLE(p) | (static_cast<uint32_t>(Get16bitAsLE(p + 2)) << 16);
#endif
}
/**
get 64bit integer as little endian
@param src [in] pointer
*/
inline uint64_t Get64bitAsLE(const void *src)
{
#if CYBOZU_ENDIAN == CYBOZU_ENDIAN_LITTLE
uint64_t x;
memcpy(&x, src, sizeof(x));
return x;
#else
const uint8_t *p = static_cast<const uint8_t *>(src);
return Get32bitAsLE(p) | (static_cast<uint64_t>(Get32bitAsLE(p + 4)) << 32);
#endif
}
/**
get 16bit integer as bit endian
@param src [in] pointer
*/
inline uint16_t Get16bitAsBE(const void *src)
{
#if CYBOZU_ENDIAN == CYBOZU_ENDIAN_LITTLE
uint16_t x;
memcpy(&x, src, sizeof(x));
return byteSwap(x);
#else
const uint8_t *p = static_cast<const uint8_t *>(src);
return p[1] | (p[0] << 8);
#endif
}
/**
get 32bit integer as bit endian
@param src [in] pointer
*/
inline uint32_t Get32bitAsBE(const void *src)
{
#if CYBOZU_ENDIAN == CYBOZU_ENDIAN_LITTLE
uint32_t x;
memcpy(&x, src, sizeof(x));
return byteSwap(x);
#else
const uint8_t *p = static_cast<const uint8_t *>(src);
return Get16bitAsBE(p + 2) | (static_cast<uint32_t>(Get16bitAsBE(p)) << 16);
#endif
}
/**
get 64bit integer as big endian
@param src [in] pointer
*/
inline uint64_t Get64bitAsBE(const void *src)
{
#if CYBOZU_ENDIAN == CYBOZU_ENDIAN_LITTLE
uint64_t x;
memcpy(&x, src, sizeof(x));
return byteSwap(x);
#else
const uint8_t *p = static_cast<const uint8_t *>(src);
return Get32bitAsBE(p + 4) | (static_cast<uint64_t>(Get32bitAsBE(p)) << 32);
#endif
}
/**
set 16bit integer as little endian
@param src [out] pointer
@param x [in] integer
*/
inline void Set16bitAsLE(void *src, uint16_t x)
{
#if CYBOZU_ENDIAN == CYBOZU_ENDIAN_LITTLE
memcpy(src, &x, sizeof(x));
#else
uint8_t *p = static_cast<uint8_t *>(src);
p[0] = static_cast<uint8_t>(x);
p[1] = static_cast<uint8_t>(x >> 8);
#endif
}
/**
set 32bit integer as little endian
@param src [out] pointer
@param x [in] integer
*/
inline void Set32bitAsLE(void *src, uint32_t x)
{
#if CYBOZU_ENDIAN == CYBOZU_ENDIAN_LITTLE
memcpy(src, &x, sizeof(x));
#else
uint8_t *p = static_cast<uint8_t *>(src);
p[0] = static_cast<uint8_t>(x);
p[1] = static_cast<uint8_t>(x >> 8);
p[2] = static_cast<uint8_t>(x >> 16);
p[3] = static_cast<uint8_t>(x >> 24);
#endif
}
/**
set 64bit integer as little endian
@param src [out] pointer
@param x [in] integer
*/
inline void Set64bitAsLE(void *src, uint64_t x)
{
#if CYBOZU_ENDIAN == CYBOZU_ENDIAN_LITTLE
memcpy(src, &x, sizeof(x));
#else
uint8_t *p = static_cast<uint8_t *>(src);
Set32bitAsLE(p, static_cast<uint32_t>(x));
Set32bitAsLE(p + 4, static_cast<uint32_t>(x >> 32));
#endif
}
/**
set 16bit integer as big endian
@param src [out] pointer
@param x [in] integer
*/
inline void Set16bitAsBE(void *src, uint16_t x)
{
#if CYBOZU_ENDIAN == CYBOZU_ENDIAN_LITTLE
x = byteSwap(x);
memcpy(src, &x, sizeof(x));
#else
uint8_t *p = static_cast<uint8_t *>(src);
p[0] = static_cast<uint8_t>(x >> 8);
p[1] = static_cast<uint8_t>(x);
#endif
}
/**
set 32bit integer as big endian
@param src [out] pointer
@param x [in] integer
*/
inline void Set32bitAsBE(void *src, uint32_t x)
{
#if CYBOZU_ENDIAN == CYBOZU_ENDIAN_LITTLE
x = byteSwap(x);
memcpy(src, &x, sizeof(x));
#else
uint8_t *p = static_cast<uint8_t *>(src);
p[0] = static_cast<uint8_t>(x >> 24);
p[1] = static_cast<uint8_t>(x >> 16);
p[2] = static_cast<uint8_t>(x >> 8);
p[3] = static_cast<uint8_t>(x);
#endif
}
/**
set 64bit integer as big endian
@param src [out] pointer
@param x [in] integer
*/
inline void Set64bitAsBE(void *src, uint64_t x)
{
#if CYBOZU_ENDIAN == CYBOZU_ENDIAN_LITTLE
x = byteSwap(x);
memcpy(src, &x, sizeof(x));
#else
uint8_t *p = static_cast<uint8_t *>(src);
Set32bitAsBE(p, static_cast<uint32_t>(x >> 32));
Set32bitAsBE(p + 4, static_cast<uint32_t>(x));
#endif
}
} // cybozu

@ -0,0 +1,252 @@
#pragma once
/**
@file
@brief definition of abstruct exception class
@author MITSUNARI Shigeo(@herumi)
*/
#ifdef CYBOZU_MINIMUM_EXCEPTION
#include <cybozu/inttype.hpp>
namespace cybozu {
namespace exception {
inline const char *makeString(const char *, size_t)
{
return "";
}
} // cybozu::exception
class Exception {
public:
explicit Exception(const char* = 0, bool = true)
{
}
~Exception() CYBOZU_NOEXCEPT {}
const char *what() const CYBOZU_NOEXCEPT { return "cybozu:Exception"; }
template<class T>
Exception& operator<<(const T&)
{
return *this;
}
};
} // cybozu
#else
#include <string>
#include <algorithm>
#include <sstream>
#include <errno.h>
#include <stdio.h>
#ifdef _WIN32
#include <winsock2.h>
#include <windows.h>
#else
#include <string.h> // for strerror_r
#endif
#include <cybozu/inttype.hpp>
#ifdef CYBOZU_EXCEPTION_WITH_STACKTRACE
#include <cybozu/stacktrace.hpp>
#endif
namespace cybozu {
const bool DontThrow = true;
namespace exception {
/* get max 16 characters to avoid buffer overrun */
inline std::string makeString(const char *str, size_t size)
{
return std::string(str, std::min<size_t>(size, 16));
}
#ifdef _WIN32
inline std::string wstr2str(const std::wstring& wstr)
{
std::string str;
for (size_t i = 0; i < wstr.size(); i++) {
uint16_t c = wstr[i];
if (c < 0x80) {
str += char(c);
} else {
char buf[16];
CYBOZU_SNPRINTF(buf, sizeof(buf), "\\u%04x", c);
str += buf;
}
}
return str;
}
#endif
} // cybozu::exception
/**
convert errno to string
@param err [in] errno
@note for both windows and linux
*/
inline std::string ConvertErrorNoToString(int err)
{
char errBuf[256];
std::string ret;
#ifdef _WIN32
if (strerror_s(errBuf, sizeof(errBuf), err) == 0) {
ret = errBuf;
} else {
ret = "err";
}
#elif defined(_GNU_SOURCE)
ret = ::strerror_r(err, errBuf, sizeof(errBuf));
#else
if (strerror_r(err, errBuf, sizeof(errBuf)) == 0) {
ret = errBuf;
} else {
ret = "err";
}
#endif
char buf2[64];
CYBOZU_SNPRINTF(buf2, sizeof(buf2), "(%d)", err);
ret += buf2;
return ret;
}
class Exception : public std::exception {
mutable std::string str_;
#ifdef CYBOZU_EXCEPTION_WITH_STACKTRACE
mutable std::string stackTrace_;
#endif
public:
explicit Exception(const std::string& name = "", bool enableStackTrace = true)
: str_(name)
{
#ifdef CYBOZU_EXCEPTION_WITH_STACKTRACE
if (enableStackTrace) stackTrace_ = cybozu::StackTrace().toString();
#else
cybozu::disable_warning_unused_variable(enableStackTrace);
#endif
}
~Exception() CYBOZU_NOEXCEPT {}
const char *what() const CYBOZU_NOEXCEPT { return toString().c_str(); }
const std::string& toString() const CYBOZU_NOEXCEPT
{
#ifdef CYBOZU_EXCEPTION_WITH_STACKTRACE
try {
if (!stackTrace_.empty()) {
#ifdef CYBOZU_STACKTRACE_ONELINE
str_ += "\n<<<STACKTRACE>>> ";
str_ += stackTrace_;
#else
str_ += "\n<<<STACKTRACE\n";
str_ += stackTrace_;
str_ += "\n>>>STACKTRACE";
#endif
}
} catch (...) {
}
stackTrace_.clear();
#endif
return str_;
}
Exception& operator<<(const char *s)
{
str_ += ':';
str_ += s;
return *this;
}
Exception& operator<<(const std::string& s)
{
return operator<<(s.c_str());
}
#ifdef _WIN32
Exception& operator<<(const std::wstring& s)
{
return operator<<(cybozu::exception::wstr2str(s));
}
#endif
template<class T>
Exception& operator<<(const T& x)
{
std::ostringstream os;
os << x;
return operator<<(os.str());
}
};
class ErrorNo {
public:
#ifdef _WIN32
typedef unsigned int NativeErrorNo;
#else
typedef int NativeErrorNo;
#endif
explicit ErrorNo(NativeErrorNo err)
: err_(err)
{
}
ErrorNo()
: err_(getLatestNativeErrorNo())
{
}
NativeErrorNo getLatestNativeErrorNo() const
{
#ifdef _WIN32
return ::GetLastError();
#else
return errno;
#endif
}
/**
convert NativeErrNo to string(maybe UTF8)
@param err [in] errno
@note Linux : same as ConvertErrorNoToString
Windows : for Win32 API(use en-us)
*/
std::string toString() const
{
#ifdef _WIN32
const int msgSize = 256;
wchar_t msg[msgSize];
int size = FormatMessageW(
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
0,
err_,
MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
msg,
msgSize,
NULL
);
if (size <= 0) return "";
// remove last "\r\n"
if (size > 2 && msg[size - 2] == '\r') {
msg[size - 2] = 0;
size -= 2;
}
std::string ret;
ret.resize(size);
// assume ascii only
for (int i = 0; i < size; i++) {
ret[i] = (char)msg[i];
}
char buf2[64];
CYBOZU_SNPRINTF(buf2, sizeof(buf2), "(%u)", err_);
ret += buf2;
return ret;
#else
return ConvertErrorNoToString(err_);
#endif
}
private:
NativeErrorNo err_;
};
inline std::ostream& operator<<(std::ostream& os, const cybozu::ErrorNo& self)
{
return os << self.toString();
}
} // cybozu
#endif

@ -0,0 +1,67 @@
#pragma once
#include <cybozu/inttype.hpp>
namespace cybozu {
template<class Iter>
uint32_t hash32(Iter begin, Iter end, uint32_t v = 0)
{
if (v == 0) v = 2166136261U;
while (begin != end) {
v ^= *begin++;
v *= 16777619;
}
return v;
}
template<class Iter>
uint64_t hash64(Iter begin, Iter end, uint64_t v = 0)
{
if (v == 0) v = 14695981039346656037ULL;
while (begin != end) {
v ^= *begin++;
v *= 1099511628211ULL;
}
v ^= v >> 32;
return v;
}
template<class T>
uint32_t hash32(const T *x, size_t n, uint32_t v = 0)
{
return hash32(x, x + n, v);
}
template<class T>
uint64_t hash64(const T *x, size_t n, uint64_t v = 0)
{
return hash64(x, x + n, v);
}
} // cybozu
namespace boost {
template<class T>
struct hash;
} // boost
#if CYBOZU_CPP_VERSION >= CYBOZU_CPP_VERSION_CPP11
#include <functional>
#else
namespace std { CYBOZU_NAMESPACE_TR1_BEGIN
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 4099) // missmatch class and struct
#endif
#ifndef __APPLE__
template<class T>
struct hash;
#endif
#ifdef _MSC_VER
#pragma warning(pop)
#endif
CYBOZU_NAMESPACE_TR1_END } // std
#endif

@ -0,0 +1,163 @@
#pragma once
/**
@file
@brief int type definition and macros
@author MITSUNARI Shigeo(@herumi)
*/
#if defined(_MSC_VER) && (MSC_VER <= 1500) && !defined(CYBOZU_DEFINED_INTXX)
#define CYBOZU_DEFINED_INTXX
typedef __int64 int64_t;
typedef unsigned __int64 uint64_t;
typedef unsigned int uint32_t;
typedef int int32_t;
typedef unsigned short uint16_t;
typedef short int16_t;
typedef unsigned char uint8_t;
typedef signed char int8_t;
#else
#include <stdint.h>
#endif
#ifdef _MSC_VER
#ifndef CYBOZU_DEFINED_SSIZE_T
#define CYBOZU_DEFINED_SSIZE_T
#ifdef _WIN64
typedef int64_t ssize_t;
#else
typedef int32_t ssize_t;
#endif
#endif
#else
#include <unistd.h> // for ssize_t
#endif
#ifndef CYBOZU_ALIGN
#ifdef _MSC_VER
#define CYBOZU_ALIGN(x) __declspec(align(x))
#else
#define CYBOZU_ALIGN(x) __attribute__((aligned(x)))
#endif
#endif
#ifndef CYBOZU_FORCE_INLINE
#ifdef _MSC_VER
#define CYBOZU_FORCE_INLINE __forceinline
#else
#define CYBOZU_FORCE_INLINE __attribute__((always_inline))
#endif
#endif
#ifndef CYBOZU_UNUSED
#ifdef __GNUC__
#define CYBOZU_UNUSED __attribute__((unused))
#else
#define CYBOZU_UNUSED
#endif
#endif
#ifndef CYBOZU_ALLOCA
#ifdef _MSC_VER
#include <malloc.h>
#define CYBOZU_ALLOCA(x) _malloca(x)
#else
#define CYBOZU_ALLOCA(x) __builtin_alloca(x)
#endif
#endif
#ifndef CYBOZU_NUM_OF_ARRAY
#define CYBOZU_NUM_OF_ARRAY(x) (sizeof(x) / sizeof(*x))
#endif
#ifndef CYBOZU_SNPRINTF
#if defined(_MSC_VER) && (_MSC_VER < 1900)
#define CYBOZU_SNPRINTF(x, len, ...) (void)_snprintf_s(x, len, len - 1, __VA_ARGS__)
#else
#define CYBOZU_SNPRINTF(x, len, ...) (void)snprintf(x, len, __VA_ARGS__)
#endif
#endif
#define CYBOZU_CPP_VERSION_CPP03 0
#define CYBOZU_CPP_VERSION_TR1 1
#define CYBOZU_CPP_VERSION_CPP11 2
#define CYBOZU_CPP_VERSION_CPP14 3
#define CYBOZU_CPP_VERSION_CPP17 4
#ifdef __GNUC__
#define CYBOZU_GNUC_PREREQ(major, minor) ((__GNUC__) * 100 + (__GNUC_MINOR__) >= (major) * 100 + (minor))
#else
#define CYBOZU_GNUC_PREREQ(major, minor) 0
#endif
#if (__cplusplus >= 201703)
#define CYBOZU_CPP_VERSION CYBOZU_CPP_VERSION_CPP17
#elif (__cplusplus >= 201402)
#define CYBOZU_CPP_VERSION CYBOZU_CPP_VERSION_CPP14
#elif (__cplusplus >= 201103) || (_MSC_VER >= 1500) || defined(__GXX_EXPERIMENTAL_CXX0X__)
#if defined(_MSC_VER) && (_MSC_VER <= 1600)
#define CYBOZU_CPP_VERSION CYBOZU_CPP_VERSION_TR1
#else
#define CYBOZU_CPP_VERSION CYBOZU_CPP_VERSION_CPP11
#endif
#elif CYBOZU_GNUC_PREREQ(4, 5) || (CYBOZU_GNUC_PREREQ(4, 2) && __GLIBCXX__ >= 20070719) || defined(__INTEL_COMPILER) || (__clang_major__ >= 3)
#define CYBOZU_CPP_VERSION CYBOZU_CPP_VERSION_TR1
#else
#define CYBOZU_CPP_VERSION CYBOZU_CPP_VERSION_CPP03
#endif
#ifdef CYBOZU_USE_BOOST
#define CYBOZU_NAMESPACE_STD boost
#define CYBOZU_NAMESPACE_TR1_BEGIN
#define CYBOZU_NAMESPACE_TR1_END
#elif (CYBOZU_CPP_VERSION == CYBOZU_CPP_VERSION_TR1) && !defined(__APPLE__)
#define CYBOZU_NAMESPACE_STD std::tr1
#define CYBOZU_NAMESPACE_TR1_BEGIN namespace tr1 {
#define CYBOZU_NAMESPACE_TR1_END }
#else
#define CYBOZU_NAMESPACE_STD std
#define CYBOZU_NAMESPACE_TR1_BEGIN
#define CYBOZU_NAMESPACE_TR1_END
#endif
#ifndef CYBOZU_OS_BIT
#if defined(_WIN64) || defined(__x86_64__) || defined(__AARCH64EL__) || defined(__EMSCRIPTEN__)
#define CYBOZU_OS_BIT 64
#else
#define CYBOZU_OS_BIT 32
#endif
#endif
#ifndef CYBOZU_HOST
#define CYBOZU_HOST_UNKNOWN 0
#define CYBOZU_HOST_INTEL 1
#define CYBOZU_HOST_ARM 2
#if defined(_M_IX86) || defined(_M_AMD64) || defined(__x86_64__) || defined(__i386__)
#define CYBOZU_HOST CYBOZU_HOST_INTEL
#elif defined(__arm__) || defined(__AARCH64EL__)
#define CYBOZU_HOST CYBOZU_HOST_ARM
#else
#define CYBOZU_HOST CYBOZU_HOST_UNKNOWN
#endif
#endif
#ifndef CYBOZU_ENDIAN
#define CYBOZU_ENDIAN_UNKNOWN 0
#define CYBOZU_ENDIAN_LITTLE 1
#define CYBOZU_ENDIAN_BIG 2
#if (CYBOZU_HOST == CYBOZU_HOST_INTEL)
#define CYBOZU_ENDIAN CYBOZU_ENDIAN_LITTLE
#elif (CYBOZU_HOST == CYBOZU_HOST_ARM) && (defined(__ARM_EABI__) || defined(__AARCH64EL__))
#define CYBOZU_ENDIAN CYBOZU_ENDIAN_LITTLE
#else
#define CYBOZU_ENDIAN CYBOZU_ENDIAN_UNKNOWN
#endif
#endif
#if CYBOZU_CPP_VERSION >= CYBOZU_CPP_VERSION_CPP11
#define CYBOZU_NOEXCEPT noexcept
#else
#define CYBOZU_NOEXCEPT throw()
#endif
namespace cybozu {
template<class T>
void disable_warning_unused_variable(const T&) { }
template<class T, class S>
T cast(const S* ptr) { return static_cast<T>(static_cast<const void*>(ptr)); }
template<class T, class S>
T cast(S* ptr) { return static_cast<T>(static_cast<void*>(ptr)); }
} // cybozu

@ -0,0 +1,337 @@
#pragma once
/**
@file
@brief convert integer to string(ascii)
@author MITSUNARI Shigeo(@herumi)
*/
#include <limits.h>
#ifndef CYBOZU_DONT_USE_STRING
#include <string>
#endif
#include <memory.h>
#include <cybozu/inttype.hpp>
#include <cybozu/bit_operation.hpp>
namespace cybozu {
template<class T>
size_t getHexLength(T x)
{
return x == 0 ? 1 : cybozu::bsr(x) / 4 + 1;
}
template<class T>
size_t getBinLength(T x)
{
return x == 0 ? 1 : cybozu::bsr(x) + 1;
}
/*
convert x to hex string with len
@note out should have getHexLength(x) size
out is not NUL terminated
*/
template<class T>
void itohex(char *out, size_t len, T x, bool upCase = true)
{
static const char *hexTbl[] = {
"0123456789abcdef",
"0123456789ABCDEF"
};
const char *tbl = hexTbl[upCase];
for (size_t i = 0; i < len; i++) {
out[len - i - 1] = tbl[x % 16];
x /= 16;
}
}
/*
convert x to bin string with len
@note out should have getBinLength(x) size
out is not NUL terminated
*/
template<class T>
void itobin(char *out, size_t len, T x)
{
for (size_t i = 0; i < len; i++) {
out[len - i - 1] = '0' + (x & 1);
x >>= 1;
}
}
namespace itoa_local {
/*
convert x to dec
use buf[0, bufSize)
return 0 if false
return writtenSize which is not terminated
@REMARK the top of string is buf + bufSize - writtenSize
*/
template<class UT>
size_t uintToDec(char *buf, size_t bufSize, UT x)
{
for (size_t i = 0; i < bufSize; i++) {
buf[bufSize - 1 - i] = '0' + static_cast<int>(x % 10);
x /= 10;
if (x == 0) return i + 1;
}
return 0;
}
/*
convert x to hex
use buf[0, bufSize)
return 0 if false
return writtenSize which is not terminated
@REMARK the top of string is buf + bufSize - writtenSize
*/
template<class UT>
size_t uintToHex(char *buf, size_t bufSize, UT x, bool upCase = true)
{
static const char *hexTbl[] = {
"0123456789abcdef",
"0123456789ABCDEF"
};
const char *tbl = hexTbl[upCase];
for (size_t i = 0; i < bufSize; i++) {
buf[bufSize - 1 - i] = tbl[x % 16];
x /= 16;
if (x == 0) return i + 1;
}
return 0;
}
/*
convert x to bin
use buf[0, bufSize)
return 0 if false
return writtenSize which is not terminated
@REMARK the top of string is buf + bufSize - writtenSize
*/
template<class UT>
size_t uintToBin(char *buf, size_t bufSize, UT x)
{
for (size_t i = 0; i < bufSize; i++) {
buf[bufSize - 1 - i] = '0' + (x & 1);
x >>= 1;
if (x == 0) return i + 1;
}
return 0;
}
template<class T>
size_t intToDec(char *buf, size_t bufSize, T x)
{
if (x == LLONG_MIN) {
const char minStr[] = "-9223372036854775808";
const size_t minStrLen = sizeof(minStr) - 1;
if (bufSize < minStrLen) {
return 0;
} else {
memcpy(buf + bufSize - minStrLen, minStr, minStrLen);
return minStrLen;
}
}
bool negative = x < 0;
uint64_t absX = negative ? -x : x;
size_t n = uintToDec(buf, bufSize, absX);
if (n == 0) return 0;
if (negative) {
if (bufSize == n) return 0;
n++;
buf[bufSize - n] = '-';
}
return n;
}
#ifndef CYBOZU_DONT_USE_STRING
template<typename T>
void convertFromUint(std::string& out, T x)
{
char buf[40];
size_t n = uintToDec(buf, sizeof(buf), x);
assert(n > 0);
out.assign(buf + sizeof(buf) - n, n);
}
inline void convertFromInt(std::string& out, long long x)
{
char buf[40];
size_t n = intToDec(buf, sizeof(buf), x);
assert(n > 0);
out.assign(buf + sizeof(buf) - n, n);
}
template<typename T>
void itohexLocal(std::string& out, T x, bool upCase, bool withZero)
{
const size_t size = withZero ? sizeof(T) * 2 : getHexLength(x);
out.resize(size);
itohex(&out[0], size, x, upCase);
}
template<class T>
void itobinLocal(std::string& out, T x, bool withZero)
{
const size_t size = withZero ? sizeof(T) * 8 : getBinLength(x);
out.resize(size);
itobin(&out[0], size, x);
}
#endif
} // itoa_local
#ifndef CYBOZU_DONT_USE_STRING
/**
convert int to string
@param out [out] string
@param x [in] int
*/
inline void itoa(std::string& out, int x)
{
itoa_local::convertFromInt(out, x);
}
/**
convert long long to string
@param out [out] string
@param x [in] long long
*/
inline void itoa(std::string& out, long long x)
{
itoa_local::convertFromInt(out, x);
}
/**
convert unsigned int to string
@param out [out] string
@param x [in] unsigned int
*/
inline void itoa(std::string& out, unsigned int x)
{
itoa_local::convertFromUint(out, x);
}
/**
convert unsigned long long to string
@param out [out] string
@param x [in] unsigned long long
*/
inline void itoa(std::string& out, unsigned long long x)
{
itoa_local::convertFromUint(out, x);
}
#if defined(__SIZEOF_LONG__) && (__SIZEOF_LONG__ == 8)
inline void itoa(std::string& out, long x) { itoa(out, static_cast<long long>(x)); }
inline void itoa(std::string& out, unsigned long x) { itoa(out, static_cast<unsigned long long>(x)); }
#else
inline void itoa(std::string& out, long x) { itoa(out, static_cast<int>(x)); }
inline void itoa(std::string& out, unsigned long x) { itoa(out, static_cast<int>(x)); }
#endif
/**
convert integer to string
@param x [in] int
*/
template<typename T>
inline std::string itoa(T x)
{
std::string ret;
itoa(ret, x);
return ret;
}
inline void itohex(std::string& out, unsigned char x, bool upCase = true, bool withZero = true)
{
itoa_local::itohexLocal(out, x, upCase, withZero);
}
inline void itohex(std::string& out, unsigned short x, bool upCase = true, bool withZero = true)
{
itoa_local::itohexLocal(out, x, upCase, withZero);
}
inline void itohex(std::string& out, unsigned int x, bool upCase = true, bool withZero = true)
{
itoa_local::itohexLocal(out, x, upCase, withZero);
}
inline void itohex(std::string& out, unsigned long x, bool upCase = true, bool withZero = true)
{
itoa_local::itohexLocal(out, x, upCase, withZero);
}
inline void itohex(std::string& out, unsigned long long x, bool upCase = true, bool withZero = true)
{
itoa_local::itohexLocal(out, x, upCase, withZero);
}
template<typename T>
inline std::string itobin(T x, bool withZero = true)
{
std::string out;
itoa_local::itobinLocal(out, x, withZero);
return out;
}
inline void itobin(std::string& out, unsigned char x, bool withZero = true)
{
itoa_local::itobinLocal(out, x, withZero);
}
inline void itobin(std::string& out, unsigned short x, bool withZero = true)
{
itoa_local::itobinLocal(out, x, withZero);
}
inline void itobin(std::string& out, unsigned int x, bool withZero = true)
{
itoa_local::itobinLocal(out, x, withZero);
}
inline void itobin(std::string& out, unsigned long x, bool withZero = true)
{
itoa_local::itobinLocal(out, x, withZero);
}
inline void itobin(std::string& out, unsigned long long x, bool withZero = true)
{
itoa_local::itobinLocal(out, x, withZero);
}
template<typename T>
inline std::string itohex(T x, bool upCase = true, bool withZero = true)
{
std::string out;
itohex(out, x, upCase, withZero);
return out;
}
/**
convert integer to string with zero padding
@param x [in] int
@param len [in] minimum lengh of string
@param c [in] padding character
@note
itoa(12, 4) == "0012"
itoa(1234, 4) == "1234"
itoa(12345, 4) == "12345"
itoa(-12, 4) == "-012"
*/
template<typename T>
inline std::string itoaWithZero(T x, size_t len, char c = '0')
{
std::string ret;
itoa(ret, x);
if (ret.size() < len) {
std::string zero(len - ret.size(), c);
if (x >= 0) {
ret = zero + ret;
} else {
ret = "-" + zero + ret.substr(1);
}
}
return ret;
}
#endif
} // cybozu

@ -0,0 +1,21 @@
#pragma once
/**
@file
@brief link libeay32.lib of openssl
@author MITSUNARI Shigeo(@herumi)
*/
#if defined(_WIN32) && defined(_MT)
#if _MSC_VER >= 1900 // VC2015
#ifdef _WIN64
#pragma comment(lib, "mt/14/libeay32.lib")
#else
#pragma comment(lib, "mt/14/32/libeay32.lib")
#endif
// #elif _MSC_VER == 1800 // VC2013
#else
#pragma comment(lib, "mt/12/libeay32.lib")
#endif
#pragma comment(lib, "advapi32.lib")
#pragma comment(lib, "gdi32.lib")
#pragma comment(lib, "user32.lib")
#endif

@ -0,0 +1,18 @@
#pragma once
/**
@file
@brief link mpir/mpirxx of mpir
@author MITSUNARI Shigeo(@herumi)
*/
#if defined(_WIN32) && defined(_MT)
#if _MSC_VER >= 1900 // VC2015, VC2017(1910)
#pragma comment(lib, "mt/14/mpir.lib")
#pragma comment(lib, "mt/14/mpirxx.lib")
#elif _MSC_VER == 1800 // VC2013
#pragma comment(lib, "mt/12/mpir.lib")
#pragma comment(lib, "mt/12/mpirxx.lib")
#elif _MSC_VER == 1700 // VC2012
#pragma comment(lib, "mt/11/mpir.lib")
#pragma comment(lib, "mt/11/mpirxx.lib")
#endif
#endif

@ -0,0 +1,19 @@
#pragma once
/**
@file
@brief link ssleay32.lib of openssl
@author MITSUNARI Shigeo(@herumi)
*/
#if defined(_WIN32) && defined(_MT)
#if _MSC_VER >= 1900 // VC2015
#ifdef _WIN64
#pragma comment(lib, "mt/14/ssleay32.lib")
#else
#pragma comment(lib, "mt/14/32/ssleay32.lib")
#endif
// #elif _MSC_VER == 1800 // VC2013
#else
#pragma comment(lib, "mt/12/ssleay32.lib")
#endif
#pragma comment(lib, "user32.lib")
#endif

@ -0,0 +1,141 @@
#pragma once
/**
@file
@brief mutex
@author MITSUNARI Shigeo(@herumi)
@author MITSUNARI Shigeo
*/
#ifdef _WIN32
#include <windows.h>
#else
#include <pthread.h>
#include <time.h>
#endif
#include <assert.h>
#include <stdlib.h>
namespace cybozu {
class ConditionVariable;
namespace thread {
#ifdef _WIN32
typedef HANDLE MutexHandle;
inline void MutexInit(MutexHandle& mutex)
{
// mutex = CreateSemaphore(NULL /* no security */, 1 /* init */, 0x7FFFFFFF /* max */, NULL /* no name */);
mutex = CreateMutex(NULL /* no security */, FALSE /* no owner */, NULL /* no name */);
}
inline void MutexLock(MutexHandle& mutex) { WaitForSingleObject(mutex, INFINITE); }
/*
return false if timeout
@param msec [in] msec
*/
inline bool MutexLockTimeout(MutexHandle& mutex, int msec)
{
DWORD ret = WaitForSingleObject(mutex, msec);
if (ret == WAIT_OBJECT_0) {
return true;
}
if (ret == WAIT_TIMEOUT) {
return false;
}
/* ret == WAIT_ABANDONED */
assert(0);
return false;
}
inline void MutexUnlock(MutexHandle& mutex)
{
// ReleaseSemaphore(mutex, 1, NULL);
ReleaseMutex(mutex);
}
inline void MutexTerm(MutexHandle& mutex) { CloseHandle(mutex); }
#else
typedef pthread_mutex_t MutexHandle;
inline void MutexInit(MutexHandle& mutex)
{
#if 1
pthread_mutex_init(&mutex, NULL);
#else
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_TIMED_NP)) {
perror("pthread_mutexattr_settype");
exit(1);
}
pthread_mutex_init(&mutex, &attr);
pthread_mutexattr_destroy(&attr);
#endif
}
inline void MutexLock(MutexHandle& mutex) { pthread_mutex_lock(&mutex); }
#if 0
inline bool MutexLockTimeout(MutexHandle& mutex, int msec)
{
timespec absTime;
clock_gettime(CLOCK_REALTIME, &absTime);
absTime.tv_sec += msec / 1000;
absTime.tv_nsec += msec % 1000;
bool ret = pthread_mutex_timedlock(&mutex, &absTime) == 0;
return ret;
}
#endif
inline void MutexUnlock(MutexHandle& mutex) { pthread_mutex_unlock(&mutex); }
inline void MutexTerm(MutexHandle& mutex) { pthread_mutex_destroy(&mutex); }
#endif
template<class T>
class AutoLockT {
public:
explicit AutoLockT(T &t)
: t_(t)
{
t_.lock();
}
~AutoLockT()
{
t_.unlock();
}
private:
T& t_;
AutoLockT& operator=(const AutoLockT&);
};
} // cybozu::thread
class Mutex {
friend class cybozu::ConditionVariable;
public:
Mutex()
{
thread::MutexInit(hdl_);
}
~Mutex()
{
thread::MutexTerm(hdl_);
}
void lock()
{
thread::MutexLock(hdl_);
}
#if 0
bool lockTimeout(int msec)
{
return thread::MutexLockTimeout(hdl_, msec);
}
#endif
void unlock()
{
thread::MutexUnlock(hdl_);
}
private:
Mutex(const Mutex&);
Mutex& operator=(const Mutex&);
thread::MutexHandle hdl_;
};
typedef cybozu::thread::AutoLockT<cybozu::Mutex> AutoLock;
} // cybozu

@ -0,0 +1,723 @@
#pragma once
/**
@file
@brief command line parser
@author MITSUNARI Shigeo(@herumi)
*/
#include <string>
#include <vector>
#include <map>
#include <sstream>
#include <iostream>
#include <limits>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <cybozu/exception.hpp>
#include <cybozu/atoi.hpp>
/*
Option parser
progName (opt1-name|opt2-name|...) param1 param2 ...
param1:param1-help
param2:param2-help
-op1-name:opt1-help
...
How to setup
int num;
-n num ; (optional) option => appendOpt(&x, <defaultValue>, "num", "num-help");
-n num ; must option => appendMust(&x, "num", "num-help");
std::vector<int> v;
-v s1 s2 s3 ... => appendVec(&v, "v");
Remark1: terminate parsing of v if argv begins with '-[^0-9]'
Remark2: the begining character of opt-name is not a number ('0'...'9')
because avoid conflict with minus number
std::string file1;
file1 is param => appendParam(&file1, "input-file");
file2 is optional param => appendParamOpt(&file2, "output-file");
How to use
opt.parse(argc, argv);
see sample/option_smpl.cpp
*/
namespace cybozu {
struct OptionError : public cybozu::Exception {
enum Type {
NoError = 0,
BAD_OPT = 1,
BAD_VALUE,
NO_VALUE,
OPT_IS_NECESSARY,
PARAM_IS_NECESSARY,
REDUNDANT_VAL,
BAD_ARGC
};
Type type;
int argPos;
OptionError()
: cybozu::Exception("OptionError", false)
, type(NoError)
, argPos(0)
{
}
cybozu::Exception& set(Type _type, int _argPos = 0)
{
this->type = _type;
this->argPos = _argPos;
switch (_type) {
case BAD_OPT:
(*this) << "bad opt";
break;
case BAD_VALUE:
(*this) << "bad value";
break;
case NO_VALUE:
(*this) << "no value";
break;
case OPT_IS_NECESSARY:
(*this) << "opt is necessary";
break;
case PARAM_IS_NECESSARY:
(*this) << "param is necessary";
break;
case REDUNDANT_VAL:
(*this) << "redundant argVal";
break;
case BAD_ARGC:
(*this) << "bad argc";
default:
break;
}
return *this;
}
};
namespace option_local {
template<class T>
bool convert(T* x, const char *str)
{
std::istringstream is(str);
is >> *x;
return !!is;
}
template<>
inline bool convert(std::string* x, const char *str)
{
*x = str;
return true;
}
template<class T>
bool convertInt(T* x, const char *str)
{
if (str[0] == '0' && str[1] == 'x') {
bool b;
*x = cybozu::hextoi(&b, str + 2);
return b;
}
size_t len = strlen(str);
int factor = 1;
if (len > 1) {
switch (str[len - 1]) {
case 'k': factor = 1000; len--; break;
case 'm': factor = 1000 * 1000; len--; break;
case 'g': factor = 1000 * 1000 * 1000; len--; break;
case 'K': factor = 1024; len--; break;
case 'M': factor = 1024 * 1024; len--; break;
case 'G': factor = 1024 * 1024 * 1024; len--; break;
default: break;
}
}
bool b;
T y = cybozu::atoi(&b, str, len);
if (!b) return false;
if (factor > 1) {
if ((std::numeric_limits<T>::min)() / factor <= y
&& y <= (std::numeric_limits<T>::max)() / factor) {
*x = y * factor;
} else {
return false;
}
} else {
*x = y;
}
return true;
}
#define CYBOZU_OPTION_DEFINE_CONVERT_INT(type) \
template<>inline bool convert(type* x, const char *str) { return convertInt(x, str); }
CYBOZU_OPTION_DEFINE_CONVERT_INT(int)
CYBOZU_OPTION_DEFINE_CONVERT_INT(long)
CYBOZU_OPTION_DEFINE_CONVERT_INT(long long)
CYBOZU_OPTION_DEFINE_CONVERT_INT(unsigned int)
CYBOZU_OPTION_DEFINE_CONVERT_INT(unsigned long)
CYBOZU_OPTION_DEFINE_CONVERT_INT(unsigned long long)
#undef CYBOZU_OPTION_DEFINE_CONVERT_INT
struct HolderBase {
virtual ~HolderBase(){}
virtual bool set(const char*) = 0;
virtual HolderBase *clone() const = 0;
virtual std::string toStr() const = 0;
virtual const void *get() const = 0;
};
template<class T>
struct Holder : public HolderBase {
T *p_;
Holder(T *p) : p_(p) {}
HolderBase *clone() const { return new Holder(p_); }
bool set(const char *str) { return option_local::convert(p_, str); }
std::string toStr() const
{
std::ostringstream os;
os << *p_;
return os.str();
}
const void *get() const { return (void*)p_; }
};
/*
for gcc 7 with -fnew-ttp-matching
this specialization is not necessary under -fno-new-ttp-matching
*/
template struct Holder<std::string>;
template<class T, class Alloc, template<class T_, class Alloc_>class Container>
struct Holder<Container<T, Alloc> > : public HolderBase {
typedef Container<T, Alloc> Vec;
Vec *p_;
Holder(Vec *p) : p_(p) {}
HolderBase *clone() const { return new Holder<Vec>(p_); }
bool set(const char *str)
{
T t;
bool b = option_local::convert(&t, str);
if (b) p_->push_back(t);
return b;
}
std::string toStr() const
{
std::ostringstream os;
bool isFirst = true;
for (typename Vec::const_iterator i = p_->begin(), ie = p_->end(); i != ie; ++i) {
if (isFirst) {
isFirst = false;
} else {
os << ' ';
}
os << *i;
}
return os.str();
}
const void *get() const { return (void*)p_; }
};
class Var {
HolderBase *p_;
bool isSet_;
public:
Var() : p_(0), isSet_(false) { }
Var(const Var& rhs) : p_(rhs.p_->clone()), isSet_(false) { }
template<class T>
explicit Var(T *x) : p_(new Holder<T>(x)), isSet_(false) { }
~Var() { delete p_; }
void swap(Var& rhs) CYBOZU_NOEXCEPT
{
std::swap(p_, rhs.p_);
std::swap(isSet_, rhs.isSet_);
}
void operator=(const Var& rhs)
{
Var v(rhs);
swap(v);
}
bool set(const char *str)
{
isSet_ = true;
return p_->set(str);
}
std::string toStr() const { return p_ ? p_->toStr() : ""; }
bool isSet() const { return isSet_; }
const void *get() const { return p_ ? p_->get() : 0; }
};
} // option_local
class Option {
enum Mode { // for opt
N_is0 = 0, // for bool by appendBoolOpt()
N_is1 = 1,
N_any = 2
};
enum ParamMode {
P_exact = 0, // one
P_optional = 1, // zero or one
P_variable = 2 // zero or greater
};
struct Info {
option_local::Var var;
Mode mode; // 0 or 1 or any ; for opt, not used for Param
bool isMust; // this option is must
std::string opt; // option param name without '-'
std::string help; // description of option
Info() : mode(N_is0), isMust(false) {}
template<class T>
Info(T* pvar, Mode mode, bool isMust, const char *opt, const std::string& help)
: var(pvar)
, mode(mode)
, isMust(isMust)
, opt(opt)
, help(help)
{
}
friend inline std::ostream& operator<<(std::ostream& os, const Info& self)
{
os << self.opt << '=' << self.var.toStr();
if (self.var.isSet()) {
os << " (set)";
} else {
os << " (default)";
}
return os;
}
void put() const
{
std::cout << *this;
}
void usage() const
{
printf(" -%s %s%s\n", opt.c_str(), help.c_str(), isMust ? " (must)" : "");
}
void shortUsage() const
{
printf(" -%s %s", opt.c_str(), mode == N_is0 ? "" : mode == N_is1 ? "para" : "para...");
}
bool isSet() const { return var.isSet(); }
const void *get() const { return var.get(); }
};
typedef std::vector<Info> InfoVec;
typedef std::vector<std::string> StrVec;
typedef std::map<std::string, size_t> OptMap;
InfoVec infoVec_;
InfoVec paramVec_;
Info remains_;
OptMap optMap_;
bool showOptUsage_;
ParamMode paramMode_;
std::string progName_;
std::string desc_;
std::string helpOpt_;
std::string help_;
std::string usage_;
StrVec delimiters_;
StrVec *remainsAfterDelimiter_;
int nextDelimiter_;
template<class T>
void appendSub(T *pvar, Mode mode, bool isMust, const char *opt, const std::string& help)
{
const char c = opt[0];
if ('0' <= c && c <= '9') throw cybozu::Exception("Option::appendSub:opt must begin with not number") << opt;
if (optMap_.find(opt) != optMap_.end()) {
throw cybozu::Exception("Option::append:duplicate option") << opt;
}
optMap_[opt] = infoVec_.size();
infoVec_.push_back(Info(pvar, mode, isMust, opt, help));
}
template<class T, class U>
void append(T *pvar, const U& defaultVal, bool isMust, const char *opt, const std::string& help = "")
{
*pvar = defaultVal;
appendSub(pvar, N_is1, isMust, opt, help);
}
/*
don't deal with negative number as option
*/
bool isOpt(const char *str) const
{
if (str[0] != '-') return false;
const char c = str[1];
if ('0' <= c && c <= '9') return false;
return true;
}
void verifyParamMode()
{
if (paramMode_ != P_exact) throw cybozu::Exception("Option:appendParamVec:appendParam is forbidden after appendParamOpt/appendParamVec");
}
std::string getBaseName(const std::string& name) const
{
size_t pos = name.find_last_of("/\\");
if (pos == std::string::npos) return name;
return name.substr(pos + 1);
}
bool inDelimiters(const std::string& str) const
{
return std::find(delimiters_.begin(), delimiters_.end(), str) != delimiters_.end();
}
public:
Option()
: showOptUsage_(true)
, paramMode_(P_exact)
, remainsAfterDelimiter_(0)
, nextDelimiter_(-1)
{
}
virtual ~Option() {}
/*
append optional option with default value
@param pvar [in] pointer to option variable
@param defaultVal [in] default value
@param opt [in] option name
@param help [in] option help
@note you can use 123k, 56M if T is int/long/long long
k : *1000
m : *1000000
g : *1000000000
K : *1024
M : *1024*1024
G : *1024*1024*1024
*/
template<class T, class U>
void appendOpt(T *pvar, const U& defaultVal, const char *opt, const std::string& help = "")
{
append(pvar, defaultVal, false, opt, help);
}
/*
default value of *pvar is false
*/
void appendBoolOpt(bool *pvar, const char *opt, const std::string& help = "")
{
*pvar = false;
appendSub(pvar, N_is0, false, opt, help);
}
/*
append necessary option
@param pvar [in] pointer to option variable
@param opt [in] option name
@param help [in] option help
*/
template<class T>
void appendMust(T *pvar, const char *opt, const std::string& help = "")
{
append(pvar, T(), true, opt, help);
}
/*
append vector option
@param pvar [in] pointer to option variable
@param opt [in] option name
@param help [in] option help
*/
template<class T, class Alloc, template<class T_, class Alloc_>class Container>
void appendVec(Container<T, Alloc> *pvar, const char *opt, const std::string& help = "")
{
appendSub(pvar, N_any, false, opt, help);
}
/*
append parameter
@param pvar [in] pointer to parameter
@param opt [in] option name
@param help [in] option help
*/
template<class T>
void appendParam(T *pvar, const char *opt, const std::string& help = "")
{
verifyParamMode();
paramVec_.push_back(Info(pvar, N_is1, true, opt, help));
}
/*
append optional parameter
@param pvar [in] pointer to parameter
@param defaultVal [in] default value
@param opt [in] option name
@param help [in] option help
@note you can call appendParamOpt once after appendParam
*/
template<class T, class U>
void appendParamOpt(T *pvar, const U& defaultVal, const char *opt, const std::string& help = "")
{
verifyParamMode();
*pvar = defaultVal;
paramMode_ = P_optional;
paramVec_.push_back(Info(pvar, N_is1, false, opt, help));
}
/*
append remain parameter
@param pvar [in] pointer to vector of parameter
@param opt [in] option name
@param help [in] option help
@note you can call appendParamVec once after appendParam
*/
template<class T, class Alloc, template<class T_, class Alloc_>class Container>
void appendParamVec(Container<T, Alloc> *pvar, const char *name, const std::string& help = "")
{
verifyParamMode();
paramMode_ = P_variable;
remains_.var = option_local::Var(pvar);
remains_.mode = N_any;
remains_.isMust = false;
remains_.opt = name;
remains_.help = help;
}
void appendHelp(const char *opt, const std::string& help = ": show this message")
{
helpOpt_ = opt;
help_ = help;
}
/*
stop parsing after delimiter is found
@param delimiter [in] string to stop
@param remain [out] set remaining strings if remain
*/
void setDelimiter(const std::string& delimiter, std::vector<std::string> *remain = 0)
{
delimiters_.push_back(delimiter);
remainsAfterDelimiter_ = remain;
}
/*
stop parsing after delimiter is found
@param delimiter [in] string to stop to append list of delimiters
*/
void appendDelimiter(const std::string& delimiter)
{
delimiters_.push_back(delimiter);
}
/*
clear list of delimiters
*/
void clearDelimiterList() { delimiters_.clear(); }
/*
return the next position of delimiter between [0, argc]
@note return argc if delimiter is not set nor found
*/
int getNextPositionOfDelimiter() const { return nextDelimiter_; }
/*
parse (argc, argv)
@param argc [in] argc of main
@param argv [in] argv of main
@param startPos [in] start position of argc
@param progName [in] used instead of argv[0]
*/
bool parse(int argc, const char *const argv[], int startPos = 1, const char *progName = 0)
{
if (argc < 1 || startPos > argc) return false;
progName_ = getBaseName(progName ? progName : argv[startPos - 1]);
nextDelimiter_ = argc;
OptionError err;
for (int pos = startPos; pos < argc; pos++) {
if (inDelimiters(argv[pos])) {
nextDelimiter_ = pos + 1;
if (remainsAfterDelimiter_) {
for (int i = nextDelimiter_; i < argc; i++) {
remainsAfterDelimiter_->push_back(argv[i]);
}
}
break;
}
if (isOpt(argv[pos])) {
const std::string str = argv[pos] + 1;
if (helpOpt_ == str) {
usage();
exit(0);
}
OptMap::const_iterator i = optMap_.find(str);
if (i == optMap_.end()) {
err.set(OptionError::BAD_OPT, pos);
goto ERR;
}
Info& info = infoVec_[i->second];
switch (info.mode) {
case N_is0:
if (!info.var.set("1")) {
err.set(OptionError::BAD_VALUE, pos);
goto ERR;
}
break;
case N_is1:
pos++;
if (pos == argc) {
err.set(OptionError::BAD_VALUE, pos) << (std::string("no value for -") + info.opt);
goto ERR;
}
if (!info.var.set(argv[pos])) {
err.set(OptionError::BAD_VALUE, pos) << (std::string(argv[pos]) + " for -" + info.opt);
goto ERR;
}
break;
case N_any:
default:
{
pos++;
int j = 0;
while (pos < argc && !isOpt(argv[pos])) {
if (!info.var.set(argv[pos])) {
err.set(OptionError::BAD_VALUE, pos) << (std::string(argv[pos]) + " for -" + info.opt) << j;
goto ERR;
}
pos++;
j++;
}
if (j > 0) {
pos--;
} else {
err.set(OptionError::NO_VALUE, pos) << (std::string("for -") + info.opt);
goto ERR;
}
}
break;
}
} else {
bool used = false;
for (size_t i = 0; i < paramVec_.size(); i++) {
Info& param = paramVec_[i];
if (!param.var.isSet()) {
if (!param.var.set(argv[pos])) {
err.set(OptionError::BAD_VALUE, pos) << (std::string(argv[pos]) + " for " + param.opt);
goto ERR;
}
used = true;
break;
}
}
if (!used) {
if (paramMode_ == P_variable) {
remains_.var.set(argv[pos]);
} else {
err.set(OptionError::REDUNDANT_VAL, pos) << argv[pos];
goto ERR;
}
}
}
}
// check whether must-opt is set
for (size_t i = 0; i < infoVec_.size(); i++) {
const Info& info = infoVec_[i];
if (info.isMust && !info.var.isSet()) {
err.set(OptionError::OPT_IS_NECESSARY) << info.opt;
goto ERR;
}
}
// check whether param is set
for (size_t i = 0; i < paramVec_.size(); i++) {
const Info& param = paramVec_[i];
if (param.isMust && !param.var.isSet()) {
err.set(OptionError::PARAM_IS_NECESSARY) << param.opt;
goto ERR;
}
}
// check whether remains is set
if (paramMode_ == P_variable && remains_.isMust && !remains_.var.isSet()) {
err.set(OptionError::PARAM_IS_NECESSARY) << remains_.opt;
goto ERR;
}
return true;
ERR:
assert(err.type);
printf("%s\n", err.what());
return false;
}
/*
show desc at first in usage()
*/
void setDescription(const std::string& desc)
{
desc_ = desc;
}
/*
show command line after desc
don't put option message if not showOptUsage
*/
void setUsage(const std::string& usage, bool showOptUsage = false)
{
usage_ = usage;
showOptUsage_ = showOptUsage;
}
void usage() const
{
if (!desc_.empty()) printf("%s\n", desc_.c_str());
if (usage_.empty()) {
printf("usage:%s", progName_.c_str());
if (!infoVec_.empty()) printf(" [opt]");
for (size_t i = 0; i < infoVec_.size(); i++) {
if (infoVec_[i].isMust) infoVec_[i].shortUsage();
}
for (size_t i = 0; i < paramVec_.size(); i++) {
printf(" %s", paramVec_[i].opt.c_str());
}
if (paramMode_ == P_variable) {
printf(" %s", remains_.opt.c_str());
}
printf("\n");
} else {
printf("%s\n", usage_.c_str());
if (!showOptUsage_) return;
}
for (size_t i = 0; i < paramVec_.size(); i++) {
const Info& param = paramVec_[i];
if (!param.help.empty()) printf(" %s %s\n", paramVec_[i].opt.c_str(), paramVec_[i].help.c_str());
}
if (!remains_.help.empty()) printf(" %s %s\n", remains_.opt.c_str(), remains_.help.c_str());
if (!helpOpt_.empty()) {
printf(" -%s %s\n", helpOpt_.c_str(), help_.c_str());
}
for (size_t i = 0; i < infoVec_.size(); i++) {
infoVec_[i].usage();
}
}
friend inline std::ostream& operator<<(std::ostream& os, const Option& self)
{
for (size_t i = 0; i < self.paramVec_.size(); i++) {
const Info& param = self.paramVec_[i];
os << param.opt << '=' << param.var.toStr() << std::endl;
}
if (self.paramMode_ == P_variable) {
os << "remains=" << self.remains_.var.toStr() << std::endl;
}
for (size_t i = 0; i < self.infoVec_.size(); i++) {
os << self.infoVec_[i] << std::endl;
}
return os;
}
void put() const
{
std::cout << *this;
}
/*
whether pvar is set or not
*/
template<class T>
bool isSet(const T* pvar) const
{
const void *p = static_cast<const void*>(pvar);
for (size_t i = 0; i < paramVec_.size(); i++) {
const Info& v = paramVec_[i];
if (v.get() == p) return v.isSet();
}
if (remains_.get() == p) return remains_.isSet();
for (size_t i = 0; i < infoVec_.size(); i++) {
const Info& v = infoVec_[i];
if (v.get() == p) return v.isSet();
}
throw cybozu::Exception("Option:isSet:no assigned var") << pvar;
}
};
} // cybozu

@ -0,0 +1,139 @@
#pragma once
/**
@file
@brief pseudrandom generator
@author MITSUNARI Shigeo(@herumi)
@license modified new BSD license
http://opensource.org/licenses/BSD-3-Clause
*/
#include <cybozu/exception.hpp>
#ifdef _WIN32
#include <winsock2.h>
#include <windows.h>
#include <wincrypt.h>
#ifdef _MSC_VER
#pragma comment (lib, "advapi32.lib")
#endif
#include <cybozu/critical_section.hpp>
#else
#include <sys/types.h>
#include <fcntl.h>
#endif
namespace cybozu {
class RandomGenerator {
RandomGenerator(const RandomGenerator&);
void operator=(const RandomGenerator&);
public:
uint32_t operator()()
{
return get32();
}
uint32_t get32()
{
uint32_t ret;
read(&ret, 1);
return ret;
}
uint64_t get64()
{
uint64_t ret;
read(&ret, 1);
return ret;
}
#ifdef _WIN32
RandomGenerator()
: prov_(0)
, pos_(bufSize)
{
DWORD flagTbl[] = { 0, CRYPT_NEWKEYSET };
for (int i = 0; i < 2; i++) {
if (CryptAcquireContext(&prov_, NULL, NULL, PROV_RSA_FULL, flagTbl[i]) != 0) return;
}
throw cybozu::Exception("randomgenerator");
}
void read_inner(void *buf, size_t byteSize)
{
if (CryptGenRandom(prov_, static_cast<DWORD>(byteSize), static_cast<BYTE*>(buf)) == 0) {
throw cybozu::Exception("randomgenerator:read") << byteSize;
}
}
~RandomGenerator()
{
if (prov_) {
CryptReleaseContext(prov_, 0);
}
}
/*
fill buf[0..bufNum-1] with random data
@note bufNum is not byte size
*/
template<class T>
void read(T *buf, size_t bufNum)
{
cybozu::AutoLockCs al(cs_);
const size_t byteSize = sizeof(T) * bufNum;
if (byteSize > bufSize) {
read_inner(buf, byteSize);
} else {
if (pos_ + byteSize > bufSize) {
read_inner(buf_, bufSize);
pos_ = 0;
}
memcpy(buf, buf_ + pos_, byteSize);
pos_ += byteSize;
}
}
private:
HCRYPTPROV prov_;
static const size_t bufSize = 1024;
char buf_[bufSize];
size_t pos_;
cybozu::CriticalSection cs_;
#else
RandomGenerator()
: fp_(::fopen("/dev/urandom", "rb"))
{
if (!fp_) throw cybozu::Exception("randomgenerator");
}
~RandomGenerator()
{
if (fp_) ::fclose(fp_);
}
/*
fill buf[0..bufNum-1] with random data
@note bufNum is not byte size
*/
template<class T>
void read(T *buf, size_t bufNum)
{
const size_t byteSize = sizeof(T) * bufNum;
if (::fread(buf, 1, (int)byteSize, fp_) != byteSize) {
throw cybozu::Exception("randomgenerator:read") << byteSize;
}
}
#endif
private:
FILE *fp_;
};
template<class T, class RG>
void shuffle(T* v, size_t n, RG& rg)
{
if (n <= 1) return;
for (size_t i = 0; i < n - 1; i++) {
size_t r = i + size_t(rg.get64() % (n - i));
using namespace std;
swap(v[i], v[r]);
}
}
template<class V, class RG>
void shuffle(V& v, RG& rg)
{
shuffle(v.data(), v.size(), rg);
}
} // cybozu

@ -0,0 +1,363 @@
#pragma once
/**
@file
@brief serializer for vector, list, map and so on
@author MITSUNARI Shigeo(@herumi)
*/
#include <assert.h>
#include <cybozu/stream.hpp>
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 4127)
#endif
//#define CYBOZU_SERIALIZER_FIXED_SIZE_INTEGER
namespace cybozu {
namespace serializer_local {
template<class T>
union ci {
T i;
uint8_t c[sizeof(T)];
};
template<class S, void (S::*)(size_t)>
struct HasMemFunc { };
template<class T>
void dispatch_reserve(T& t, size_t size, int, HasMemFunc<T, &T::reserve>* = 0)
{
t.reserve(size);
}
template<class T>
void dispatch_reserve(T&, size_t, int*)
{
}
template<class T>
void reserve_if_exists(T& t, size_t size)
{
dispatch_reserve(t, size, 0);
}
} // serializer_local
template<class InputStream, class T>
void loadRange(T *p, size_t num, InputStream& is)
{
cybozu::read(p, num * sizeof(T), is);
}
template<class OutputStream, class T>
void saveRange(OutputStream& os, const T *p, size_t num)
{
cybozu::write(os, p, num * sizeof(T));
}
template<class InputStream, class T>
void loadPod(T& x, InputStream& is)
{
serializer_local::ci<T> ci;
loadRange(ci.c, sizeof(ci.c), is);
x = ci.i;
}
template<class OutputStream, class T>
void savePod(OutputStream& os, const T& x)
{
serializer_local::ci<T> ci;
ci.i = x;
saveRange(os, ci.c, sizeof(ci.c));
}
template<class InputStream, class T>
void load(T& x, InputStream& is)
{
x.load(is);
}
template<class OutputStream, class T>
void save(OutputStream& os, const T& x)
{
x.save(os);
}
#define CYBOZU_SERIALIZER_MAKE_SERIALIZER_F(type) \
template<class InputStream>void load(type& x, InputStream& is) { loadPod(x, is); } \
template<class OutputStream>void save(OutputStream& os, type x) { savePod(os, x); }
CYBOZU_SERIALIZER_MAKE_SERIALIZER_F(bool)
CYBOZU_SERIALIZER_MAKE_SERIALIZER_F(char)
CYBOZU_SERIALIZER_MAKE_SERIALIZER_F(short)
CYBOZU_SERIALIZER_MAKE_SERIALIZER_F(unsigned char)
CYBOZU_SERIALIZER_MAKE_SERIALIZER_F(unsigned short)
CYBOZU_SERIALIZER_MAKE_SERIALIZER_F(wchar_t)
CYBOZU_SERIALIZER_MAKE_SERIALIZER_F(float)
CYBOZU_SERIALIZER_MAKE_SERIALIZER_F(double)
#ifdef CYBOZU_SERIALIZER_FIXED_SIZE_INTEGER
#define CYBOZU_SERIALIZER_MAKE_INT_SERIALIZER(type) CYBOZU_SERIALIZER_MAKE_SERIALIZER_F(type)
#else
namespace serializer_local {
template<class S, class T>
bool isRecoverable(T x)
{
return T(S(x)) == x;
}
/*
data structure H:D of integer x
H:header(1byte)
0x80 ; D = 1 byte zero ext
0x81 ; D = 2 byte zero ext
0x82 ; D = 4 byte zero ext
0x83 ; D = 8 byte zero ext
0x84 ; D = 1 byte signed ext
0x85 ; D = 2 byte signed ext
0x86 ; D = 4 byte signed ext
0x87 ; D = 8 byte signed ext
other; x = signed H, D = none
*/
template<class OutputStream, class T>
void saveVariableInt(OutputStream& os, const T& x)
{
if (isRecoverable<int8_t>(x)) {
uint8_t u8 = uint8_t(x);
if (unsigned(u8 - 0x80) <= 7) {
savePod(os, uint8_t(0x84));
}
savePod(os, u8);
} else if (isRecoverable<uint8_t>(x)) {
savePod(os, uint8_t(0x80));
savePod(os, uint8_t(x));
} else if (isRecoverable<uint16_t>(x) || isRecoverable<int16_t>(x)) {
savePod(os, uint8_t(isRecoverable<uint16_t>(x) ? 0x81 : 0x85));
savePod(os, uint16_t(x));
} else if (isRecoverable<uint32_t>(x) || isRecoverable<int32_t>(x)) {
savePod(os, uint8_t(isRecoverable<uint32_t>(x) ? 0x82 : 0x86));
savePod(os, uint32_t(x));
} else {
assert(sizeof(T) == 8);
savePod(os, uint8_t(0x83));
savePod(os, uint64_t(x));
}
}
template<class InputStream, class T>
void loadVariableInt(T& x, InputStream& is)
{
uint8_t h;
loadPod(h, is);
if (h == 0x80) {
uint8_t v;
loadPod(v, is);
x = v;
} else if (h == 0x81) {
uint16_t v;
loadPod(v, is);
x = v;
} else if (h == 0x82) {
uint32_t v;
loadPod(v, is);
x = v;
} else if (h == 0x83) {
if (sizeof(T) == 4) throw cybozu::Exception("loadVariableInt:bad header") << h;
uint64_t v;
loadPod(v, is);
x = static_cast<T>(v);
} else if (h == 0x84) {
int8_t v;
loadPod(v, is);
x = v;
} else if (h == 0x85) {
int16_t v;
loadPod(v, is);
x = v;
} else if (h == 0x86) {
int32_t v;
loadPod(v, is);
x = v;
} else if (h == 0x87) {
if (sizeof(T) == 4) throw cybozu::Exception("loadVariableInt:bad header") << h;
int64_t v;
loadPod(v, is);
x = static_cast<T>(v);
} else {
x = static_cast<int8_t>(h);
}
}
} // serializer_local
#define CYBOZU_SERIALIZER_MAKE_INT_SERIALIZER(type) \
template<class InputStream>void load(type& x, InputStream& is) { serializer_local::loadVariableInt(x, is); } \
template<class OutputStream>void save(OutputStream& os, type x) { serializer_local::saveVariableInt(os, x); }
#endif
CYBOZU_SERIALIZER_MAKE_INT_SERIALIZER(int)
CYBOZU_SERIALIZER_MAKE_INT_SERIALIZER(long)
CYBOZU_SERIALIZER_MAKE_INT_SERIALIZER(long long)
CYBOZU_SERIALIZER_MAKE_INT_SERIALIZER(unsigned int)
CYBOZU_SERIALIZER_MAKE_INT_SERIALIZER(unsigned long)
CYBOZU_SERIALIZER_MAKE_INT_SERIALIZER(unsigned long long)
#undef CYBOZU_SERIALIZER_MAKE_INT_SERIALIZER
#undef CYBOZU_SERIALIZER_MAKE_UNT_SERIALIZER
#undef CYBOZU_SERIALIZER_MAKE_SERIALIZER_F
#undef CYBOZU_SERIALIZER_MAKE_SERIALIZER_V
// only for std::vector<POD>
template<class V, class InputStream>
void loadPodVec(V& v, InputStream& is)
{
size_t size;
load(size, is);
v.resize(size);
if (size > 0) loadRange(&v[0], size, is);
}
// only for std::vector<POD>
template<class V, class OutputStream>
void savePodVec(OutputStream& os, const V& v)
{
save(os, v.size());
if (!v.empty()) saveRange(os, &v[0], v.size());
}
template<class InputStream>
void load(std::string& str, InputStream& is)
{
loadPodVec(str, is);
}
template<class OutputStream>
void save(OutputStream& os, const std::string& str)
{
savePodVec(os, str);
}
template<class OutputStream>
void save(OutputStream& os, const char *x)
{
const size_t len = strlen(x);
save(os, len);
if (len > 0) saveRange(os, x, len);
}
// for vector, list
template<class InputStream, class T, class Alloc, template<class T_, class Alloc_>class Container>
void load(Container<T, Alloc>& x, InputStream& is)
{
size_t size;
load(size, is);
serializer_local::reserve_if_exists(x, size);
for (size_t i = 0; i < size; i++) {
x.push_back(T());
T& t = x.back();
load(t, is);
}
}
template<class OutputStream, class T, class Alloc, template<class T_, class Alloc_>class Container>
void save(OutputStream& os, const Container<T, Alloc>& x)
{
typedef Container<T, Alloc> V;
save(os, x.size());
for (typename V::const_iterator i = x.begin(), end = x.end(); i != end; ++i) {
save(os, *i);
}
}
// for set
template<class InputStream, class K, class Pred, class Alloc, template<class K_, class Pred_, class Alloc_>class Container>
void load(Container<K, Pred, Alloc>& x, InputStream& is)
{
size_t size;
load(size, is);
for (size_t i = 0; i < size; i++) {
K t;
load(t, is);
x.insert(t);
}
}
template<class OutputStream, class K, class Pred, class Alloc, template<class K_, class Pred_, class Alloc_>class Container>
void save(OutputStream& os, const Container<K, Pred, Alloc>& x)
{
typedef Container<K, Pred, Alloc> Set;
save(os, x.size());
for (typename Set::const_iterator i = x.begin(), end = x.end(); i != end; ++i) {
save(os, *i);
}
}
// for map
template<class InputStream, class K, class V, class Pred, class Alloc, template<class K_, class V_, class Pred_, class Alloc_>class Container>
void load(Container<K, V, Pred, Alloc>& x, InputStream& is)
{
typedef Container<K, V, Pred, Alloc> Map;
size_t size;
load(size, is);
for (size_t i = 0; i < size; i++) {
std::pair<typename Map::key_type, typename Map::mapped_type> vt;
load(vt.first, is);
load(vt.second, is);
x.insert(vt);
}
}
template<class OutputStream, class K, class V, class Pred, class Alloc, template<class K_, class V_, class Pred_, class Alloc_>class Container>
void save(OutputStream& os, const Container<K, V, Pred, Alloc>& x)
{
typedef Container<K, V, Pred, Alloc> Map;
save(os, x.size());
for (typename Map::const_iterator i = x.begin(), end = x.end(); i != end; ++i) {
save(os, i->first);
save(os, i->second);
}
}
// unordered_map
template<class InputStream, class K, class V, class Hash, class Pred, class Alloc, template<class K_, class V_, class Hash_, class Pred_, class Alloc_>class Container>
void load(Container<K, V, Hash, Pred, Alloc>& x, InputStream& is)
{
typedef Container<K, V, Hash, Pred, Alloc> Map;
size_t size;
load(size, is);
// x.reserve(size); // tr1::unordered_map may not have reserve
cybozu::serializer_local::reserve_if_exists(x, size);
for (size_t i = 0; i < size; i++) {
std::pair<typename Map::key_type, typename Map::mapped_type> vt;
load(vt.first, is);
load(vt.second, is);
x.insert(vt);
}
}
template<class OutputStream, class K, class V, class Hash, class Pred, class Alloc, template<class K_, class V_, class Hash_, class Pred_, class Alloc_>class Container>
void save(OutputStream& os, const Container<K, V, Hash, Pred, Alloc>& x)
{
typedef Container<K, V, Hash, Pred, Alloc> Map;
save(os, x.size());
for (typename Map::const_iterator i = x.begin(), end = x.end(); i != end; ++i) {
save(os, i->first);
save(os, i->second);
}
}
} // cybozu
#ifdef _MSC_VER
#pragma warning(pop)
#endif

@ -0,0 +1,438 @@
#pragma once
/**
@file
@brief SHA-256, SHA-512 class
@author MITSUNARI Shigeo(@herumi)
@license modified new BSD license
http://opensource.org/licenses/BSD-3-Clause
*/
#include <cybozu/endian.hpp>
#ifndef CYBOZU_DONT_USE_STRING
#include <cybozu/itoa.hpp>
#include <string>
#endif
#include <memory.h>
#include <assert.h>
namespace cybozu {
namespace sha2_local {
template<class T>
T min_(T x, T y) { return x < y ? x : y;; }
#ifndef CYBOZU_DONT_USE_STRING
inline void uint32toHexStr(char *buf, const uint32_t *x, size_t n)
{
for (size_t i = 0; i < n; i++) {
cybozu::itohex(buf + i * 8, 8, x[i], false);
}
}
inline void uint64toHexStr(char *buf, const uint64_t *x, size_t n)
{
for (size_t i = 0; i < n; i++) {
cybozu::itohex(buf + i * 16, 16, x[i], false);
}
}
#endif
inline uint32_t rot32(uint32_t x, int s)
{
#ifdef _MSC_VER
return _rotr(x, s);
#else
return (x >> s) | (x << (32 - s));
#endif
}
inline uint64_t rot64(uint64_t x, int s)
{
#ifdef _MSC_VER
return _rotr64(x, s);
#else
return (x >> s) | (x << (64 - s));
#endif
}
} // cybozu::sha2_local
class Sha256 {
private:
static const size_t blockSize_ = 64;
static const size_t hSize_ = 8;
uint64_t totalSize_;
size_t roundBufSize_;
char roundBuf_[blockSize_];
uint32_t h_[hSize_];
static const size_t outByteSize_ = hSize_ * sizeof(uint32_t);
const uint32_t *k_;
/**
@param buf [in] buffer(64byte)
*/
void round(const char *buf)
{
using namespace sha2_local;
uint32_t w[64];
for (int i = 0; i < 16; i++) {
w[i] = cybozu::Get32bitAsBE(&buf[i * 4]);
}
for (int i = 16 ; i < 64; i++) {
uint32_t t = w[i - 15];
uint32_t s0 = rot32(t, 7) ^ rot32(t, 18) ^ (t >> 3);
t = w[i - 2];
uint32_t s1 = rot32(t, 17) ^ rot32(t, 19) ^ (t >> 10);
w[i] = w[i - 16] + s0 + w[i - 7] + s1;
}
uint32_t a = h_[0];
uint32_t b = h_[1];
uint32_t c = h_[2];
uint32_t d = h_[3];
uint32_t e = h_[4];
uint32_t f = h_[5];
uint32_t g = h_[6];
uint32_t h = h_[7];
for (int i = 0; i < 64; i++) {
uint32_t s1 = rot32(e, 6) ^ rot32(e, 11) ^ rot32(e, 25);
uint32_t ch = g ^ (e & (f ^ g));
uint32_t t1 = h + s1 + ch + k_[i] + w[i];
uint32_t s0 = rot32(a, 2) ^ rot32(a, 13) ^ rot32(a, 22);
uint32_t maj = ((a | b) & c) | (a & b);
uint32_t t2 = s0 + maj;
h = g;
g = f;
f = e;
e = d + t1;
d = c;
c = b;
b = a;
a = t1 + t2;
}
h_[0] += a;
h_[1] += b;
h_[2] += c;
h_[3] += d;
h_[4] += e;
h_[5] += f;
h_[6] += g;
h_[7] += h;
totalSize_ += 64;
}
/*
final phase
*/
void term(const char *buf, size_t bufSize)
{
assert(bufSize < blockSize_);
const uint64_t totalSize = totalSize_ + bufSize;
uint8_t last[blockSize_];
memcpy(last, buf, bufSize);
memset(&last[bufSize], 0, blockSize_ - bufSize);
last[bufSize] = uint8_t(0x80); /* top bit = 1 */
if (bufSize >= blockSize_ - 8) {
round(reinterpret_cast<const char*>(last));
memset(last, 0, sizeof(last)); // clear stack
}
cybozu::Set32bitAsBE(&last[56], uint32_t(totalSize >> 29));
cybozu::Set32bitAsBE(&last[60], uint32_t(totalSize * 8));
round(reinterpret_cast<const char*>(last));
}
public:
Sha256()
{
clear();
}
Sha256(const void *buf, size_t bufSize)
{
clear();
digest(buf, bufSize);
}
void clear()
{
static const uint32_t kTbl[] = {
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
};
k_ = kTbl;
totalSize_ = 0;
roundBufSize_ = 0;
h_[0] = 0x6a09e667;
h_[1] = 0xbb67ae85;
h_[2] = 0x3c6ef372;
h_[3] = 0xa54ff53a;
h_[4] = 0x510e527f;
h_[5] = 0x9b05688c;
h_[6] = 0x1f83d9ab;
h_[7] = 0x5be0cd19;
}
void update(const void *buf_, size_t bufSize)
{
const char *buf = reinterpret_cast<const char*>(buf_);
if (bufSize == 0) return;
if (roundBufSize_ > 0) {
size_t size = sha2_local::min_(blockSize_ - roundBufSize_, bufSize);
memcpy(roundBuf_ + roundBufSize_, buf, size);
roundBufSize_ += size;
buf += size;
bufSize -= size;
}
if (roundBufSize_ == blockSize_) {
round(roundBuf_);
roundBufSize_ = 0;
}
while (bufSize >= blockSize_) {
assert(roundBufSize_ == 0);
round(buf);
buf += blockSize_;
bufSize -= blockSize_;
}
if (bufSize > 0) {
assert(bufSize < blockSize_);
assert(roundBufSize_ == 0);
memcpy(roundBuf_, buf, bufSize);
roundBufSize_ = bufSize;
}
assert(roundBufSize_ < blockSize_);
}
void digest(const void *buf, size_t bufSize)
{
update(buf, bufSize);
term(roundBuf_, roundBufSize_);
}
size_t get(void *out) const
{
char *p = reinterpret_cast<char*>(out);
for (size_t i = 0; i < hSize_; i++) {
cybozu::Set32bitAsBE(&p[i * sizeof(h_[0])], h_[i]);
}
return outByteSize_;
}
#ifndef CYBOZU_DONT_USE_STRING
void update(const std::string& buf)
{
update(buf.c_str(), buf.size());
}
void digest(const std::string& str = "")
{
digest(str.c_str(), str.size());
}
std::string get() const
{
char out[outByteSize_];
get(out);
return std::string(out, sizeof(out));
}
std::string toHexStr() const
{
char buf[outByteSize_ * 2];
sha2_local::uint32toHexStr(buf, h_, hSize_);
return std::string(buf, sizeof(buf));
}
#endif
};
class Sha512 {
private:
static const size_t blockSize_ = 128;
static const size_t hSize_ = 8;
uint64_t totalSize_;
size_t roundBufSize_;
char roundBuf_[blockSize_];
uint64_t h_[hSize_];
static const size_t outByteSize_ = hSize_ * sizeof(uint64_t);
const uint64_t *k_;
template<size_t i0, size_t i1, size_t i2, size_t i3, size_t i4, size_t i5, size_t i6, size_t i7>
void round1(uint64_t *S, const uint64_t *w, size_t i)
{
using namespace sha2_local;
uint64_t& a = S[i0];
uint64_t& b = S[i1];
uint64_t& c = S[i2];
uint64_t& d = S[i3];
uint64_t& e = S[i4];
uint64_t& f = S[i5];
uint64_t& g = S[i6];
uint64_t& h = S[i7];
uint64_t s1 = rot64(e, 14) ^ rot64(e, 18) ^ rot64(e, 41);
uint64_t ch = g ^ (e & (f ^ g));
uint64_t t0 = h + s1 + ch + k_[i] + w[i];
uint64_t s0 = rot64(a, 28) ^ rot64(a, 34) ^ rot64(a, 39);
uint64_t maj = ((a | b) & c) | (a & b);
uint64_t t1 = s0 + maj;
d += t0;
h = t0 + t1;
}
/**
@param buf [in] buffer(64byte)
*/
void round(const char *buf)
{
using namespace sha2_local;
uint64_t w[80];
for (int i = 0; i < 16; i++) {
w[i] = cybozu::Get64bitAsBE(&buf[i * 8]);
}
for (int i = 16 ; i < 80; i++) {
uint64_t t = w[i - 15];
uint64_t s0 = rot64(t, 1) ^ rot64(t, 8) ^ (t >> 7);
t = w[i - 2];
uint64_t s1 = rot64(t, 19) ^ rot64(t, 61) ^ (t >> 6);
w[i] = w[i - 16] + s0 + w[i - 7] + s1;
}
uint64_t s[8];
for (int i = 0; i < 8; i++) {
s[i] = h_[i];
}
for (int i = 0; i < 80; i += 8) {
round1<0, 1, 2, 3, 4, 5, 6, 7>(s, w, i + 0);
round1<7, 0, 1, 2, 3, 4, 5, 6>(s, w, i + 1);
round1<6, 7, 0, 1, 2, 3, 4, 5>(s, w, i + 2);
round1<5, 6, 7, 0, 1, 2, 3, 4>(s, w, i + 3);
round1<4, 5, 6, 7, 0, 1, 2, 3>(s, w, i + 4);
round1<3, 4, 5, 6, 7, 0, 1, 2>(s, w, i + 5);
round1<2, 3, 4, 5, 6, 7, 0, 1>(s, w, i + 6);
round1<1, 2, 3, 4, 5, 6, 7, 0>(s, w, i + 7);
}
for (int i = 0; i < 8; i++) {
h_[i] += s[i];
}
totalSize_ += blockSize_;
}
/*
final phase
*/
void term(const char *buf, size_t bufSize)
{
assert(bufSize < blockSize_);
const uint64_t totalSize = totalSize_ + bufSize;
uint8_t last[blockSize_];
memcpy(last, buf, bufSize);
memset(&last[bufSize], 0, blockSize_ - bufSize);
last[bufSize] = uint8_t(0x80); /* top bit = 1 */
if (bufSize >= blockSize_ - 16) {
round(reinterpret_cast<const char*>(last));
memset(last, 0, sizeof(last)); // clear stack
}
cybozu::Set64bitAsBE(&last[blockSize_ - 8], totalSize * 8);
round(reinterpret_cast<const char*>(last));
}
public:
Sha512()
{
clear();
}
Sha512(const void *buf, size_t bufSize)
{
clear();
digest(buf, bufSize);
}
void clear()
{
static const uint64_t kTbl[] = {
0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL, 0x3956c25bf348b538ULL,
0x59f111f1b605d019ULL, 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL,
0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL,
0xc19bf174cf692694ULL, 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, 0x983e5152ee66dfabULL,
0xa831c66d2db43210ULL, 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL, 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL,
0x53380d139d95b3dfULL, 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, 0xd192e819d6ef5218ULL,
0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL,
0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL, 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, 0x5b9cca4f7763e373ULL,
0x682e6ff3d6b2b8a3ULL, 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL, 0xca273eceea26619cULL,
0xd186b8c721c0c207ULL, 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL,
0x113f9804bef90daeULL, 0x1b710b35131c471bULL, 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL,
0x431d67c49c100d4cULL, 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL
};
k_ = kTbl;
totalSize_ = 0;
roundBufSize_ = 0;
h_[0] = 0x6a09e667f3bcc908ull;
h_[1] = 0xbb67ae8584caa73bull;
h_[2] = 0x3c6ef372fe94f82bull;
h_[3] = 0xa54ff53a5f1d36f1ull;
h_[4] = 0x510e527fade682d1ull;
h_[5] = 0x9b05688c2b3e6c1full;
h_[6] = 0x1f83d9abfb41bd6bull;
h_[7] = 0x5be0cd19137e2179ull;
}
void update(const void *buf_, size_t bufSize)
{
const char *buf = reinterpret_cast<const char*>(buf_);
if (bufSize == 0) return;
if (roundBufSize_ > 0) {
size_t size = sha2_local::min_(blockSize_ - roundBufSize_, bufSize);
memcpy(roundBuf_ + roundBufSize_, buf, size);
roundBufSize_ += size;
buf += size;
bufSize -= size;
}
if (roundBufSize_ == blockSize_) {
round(roundBuf_);
roundBufSize_ = 0;
}
while (bufSize >= blockSize_) {
assert(roundBufSize_ == 0);
round(buf);
buf += blockSize_;
bufSize -= blockSize_;
}
if (bufSize > 0) {
assert(bufSize < blockSize_);
assert(roundBufSize_ == 0);
memcpy(roundBuf_, buf, bufSize);
roundBufSize_ = bufSize;
}
assert(roundBufSize_ < blockSize_);
}
void digest(const void *buf, size_t bufSize)
{
update(buf, bufSize);
term(roundBuf_, roundBufSize_);
}
size_t get(void *out) const
{
char *p = reinterpret_cast<char*>(out);
for (size_t i = 0; i < hSize_; i++) {
cybozu::Set64bitAsBE(&p[i * sizeof(h_[0])], h_[i]);
}
return outByteSize_;
}
#ifndef CYBOZU_DONT_USE_STRING
void digest(const std::string& str = "")
{
digest(str.c_str(), str.size());
}
void update(const std::string& buf)
{
update(buf.c_str(), buf.size());
}
std::string get() const
{
char out[outByteSize_];
get(out);
return std::string(out, sizeof(out));
}
std::string toHexStr() const
{
char buf[outByteSize_ * 2];
sha2_local::uint64toHexStr(buf, h_, hSize_);
return std::string(buf, sizeof(buf));
}
#endif
};
} // cybozu

@ -0,0 +1,267 @@
#pragma once
/**
@file
@brief stream and line stream class
@author MITSUNARI Shigeo(@herumi)
*/
#ifndef CYBOZU_DONT_USE_STRING
#include <string>
#include <iosfwd>
#endif
#include <cybozu/exception.hpp>
#include <memory.h>
namespace cybozu {
namespace stream_local {
template <typename From, typename To>
struct is_convertible {
typedef char yes;
typedef int no;
static no test(...);
static yes test(const To*);
static const bool value = sizeof(test(static_cast<const From*>(0))) == sizeof(yes);
};
template <bool b, class T = void>
struct enable_if { typedef T type; };
template <class T>
struct enable_if<false, T> {};
#ifndef CYBOZU_DONT_USE_STRING
/* specialization for istream */
template<class InputStream>
size_t readSome_inner(void *buf, size_t size, InputStream& is, typename enable_if<is_convertible<InputStream, std::istream>::value>::type* = 0)
{
if (size > 0x7fffffff) size = 0x7fffffff;
is.read(static_cast<char *>(buf), size);
const int64_t readSize = is.gcount();
if (readSize < 0) return 0;
if (size == 1 && readSize == 0) is.clear();
return static_cast<size_t>(readSize);
}
/* generic version for size_t readSome(void *, size_t) */
template<class InputStream>
size_t readSome_inner(void *buf, size_t size, InputStream& is, typename enable_if<!is_convertible<InputStream, std::istream>::value>::type* = 0)
{
return is.readSome(buf, size);
}
#else
template<class InputStream>
size_t readSome_inner(void *buf, size_t size, InputStream& is)
{
return is.readSome(buf, size);
}
#endif
#ifndef CYBOZU_DONT_USE_EXCEPTION
/* specialization for ostream */
template<class OutputStream>
void writeSub(OutputStream& os, const void *buf, size_t size, typename enable_if<is_convertible<OutputStream, std::ostream>::value>::type* = 0)
{
if (!os.write(static_cast<const char *>(buf), size)) throw cybozu::Exception("stream:writeSub") << size;
}
#endif
#ifndef CYBOZU_DONT_USE_STRING
/* generic version for void write(const void*, size_t), which writes all data */
template<class OutputStream>
void writeSub(OutputStream& os, const void *buf, size_t size, typename enable_if<!is_convertible<OutputStream, std::ostream>::value>::type* = 0)
{
os.write(buf, size);
}
template<class OutputStream>
void writeSub(bool *pb, OutputStream& os, const void *buf, size_t size, typename enable_if<is_convertible<OutputStream, std::ostream>::value>::type* = 0)
{
*pb = !!os.write(static_cast<const char *>(buf), size);
}
/* generic version for void write(const void*, size_t), which writes all data */
template<class OutputStream>
void writeSub(bool *pb, OutputStream& os, const void *buf, size_t size, typename enable_if<!is_convertible<OutputStream, std::ostream>::value>::type* = 0)
{
os.write(pb, buf, size);
}
#else
template<class OutputStream>
void writeSub(bool *pb, OutputStream& os, const void *buf, size_t size)
{
os.write(pb, buf, size);
}
#endif
} // stream_local
/*
make a specializaiton of class to use new InputStream, OutputStream
*/
template<class InputStream>
struct InputStreamTag {
static size_t readSome(void *buf, size_t size, InputStream& is)
{
return stream_local::readSome_inner<InputStream>(buf, size, is);
}
static bool readChar(char *c, InputStream& is)
{
return readSome(c, 1, is) == 1;
}
};
template<class OutputStream>
struct OutputStreamTag {
static void write(OutputStream& os, const void *buf, size_t size)
{
stream_local::writeSub<OutputStream>(os, buf, size);
}
};
class MemoryInputStream {
const char *p_;
size_t size_;
size_t pos;
public:
MemoryInputStream(const void *p, size_t size) : p_(static_cast<const char *>(p)), size_(size), pos(0) {}
size_t readSome(void *buf, size_t size)
{
if (size > size_ - pos) size = size_ - pos;
memcpy(buf, p_ + pos, size);
pos += size;
return size;
}
size_t getPos() const { return pos; }
};
class MemoryOutputStream {
char *p_;
size_t size_;
size_t pos;
public:
MemoryOutputStream(void *p, size_t size) : p_(static_cast<char *>(p)), size_(size), pos(0) {}
void write(bool *pb, const void *buf, size_t size)
{
if (size > size_ - pos) {
*pb = false;
return;
}
memcpy(p_ + pos, buf, size);
pos += size;
*pb = true;
}
#ifndef CYBOZU_DONT_USE_EXCEPTION
void write(const void *buf, size_t size)
{
bool b;
write(&b, buf, size);
if (!b) throw cybozu::Exception("MemoryOutputStream:write") << size << size_ << pos;
}
#endif
size_t getPos() const { return pos; }
};
#ifndef CYBOZU_DONT_USE_STRING
class StringInputStream {
const std::string& str_;
size_t pos;
StringInputStream(const StringInputStream&);
void operator=(const StringInputStream&);
public:
explicit StringInputStream(const std::string& str) : str_(str), pos(0) {}
size_t readSome(void *buf, size_t size)
{
const size_t remainSize = str_.size() - pos;
if (size > remainSize) size = remainSize;
memcpy(buf, &str_[pos], size);
pos += size;
return size;
}
size_t getPos() const { return pos; }
};
class StringOutputStream {
std::string& str_;
StringOutputStream(const StringOutputStream&);
void operator=(const StringOutputStream&);
public:
explicit StringOutputStream(std::string& str) : str_(str) {}
void write(bool *pb, const void *buf, size_t size)
{
str_.append(static_cast<const char *>(buf), size);
*pb = true;
}
void write(const void *buf, size_t size)
{
str_.append(static_cast<const char *>(buf), size);
}
size_t getPos() const { return str_.size(); }
};
#endif
template<class InputStream>
size_t readSome(void *buf, size_t size, InputStream& is)
{
return stream_local::readSome_inner(buf, size, is);
}
template<class OutputStream>
void write(OutputStream& os, const void *buf, size_t size)
{
stream_local::writeSub(os, buf, size);
}
template<class OutputStream>
void write(bool *pb, OutputStream& os, const void *buf, size_t size)
{
stream_local::writeSub(pb, os, buf, size);
}
template<typename InputStream>
void read(bool *pb, void *buf, size_t size, InputStream& is)
{
char *p = static_cast<char*>(buf);
while (size > 0) {
size_t readSize = cybozu::readSome(p, size, is);
if (readSize == 0) {
*pb = false;
return;
}
p += readSize;
size -= readSize;
}
*pb = true;
}
#ifndef CYBOZU_DONT_USE_EXCEPTION
template<typename InputStream>
void read(void *buf, size_t size, InputStream& is)
{
bool b;
read(&b, buf, size, is);
if (!b) throw cybozu::Exception("stream:read");
}
#endif
template<class InputStream>
bool readChar(char *c, InputStream& is)
{
return readSome(c, 1, is) == 1;
}
template<class OutputStream>
void writeChar(OutputStream& os, char c)
{
cybozu::write(os, &c, 1);
}
template<class OutputStream>
void writeChar(bool *pb, OutputStream& os, char c)
{
cybozu::write(pb, os, &c, 1);
}
} // cybozu

@ -0,0 +1,373 @@
#pragma once
/**
@file
@brief unit test class
@author MITSUNARI Shigeo(@herumi)
*/
#include <stdio.h>
#include <string.h>
#include <string>
#include <list>
#include <iostream>
#include <utility>
#if defined(_MSC_VER) && (MSC_VER <= 1500)
#include <cybozu/inttype.hpp>
#else
#include <stdint.h>
#endif
namespace cybozu { namespace test {
class AutoRun {
typedef void (*Func)();
typedef std::list<std::pair<const char*, Func> > UnitTestList;
public:
AutoRun()
: init_(0)
, term_(0)
, okCount_(0)
, ngCount_(0)
, exceptionCount_(0)
{
}
void setup(Func init, Func term)
{
init_ = init;
term_ = term;
}
void append(const char *name, Func func)
{
list_.push_back(std::make_pair(name, func));
}
void set(bool isOK)
{
if (isOK) {
okCount_++;
} else {
ngCount_++;
}
}
std::string getBaseName(const std::string& name) const
{
#ifdef _WIN32
const char sep = '\\';
#else
const char sep = '/';
#endif
size_t pos = name.find_last_of(sep);
std::string ret = name.substr(pos + 1);
pos = ret.find('.');
return ret.substr(0, pos);
}
int run(int, char *argv[])
{
std::string msg;
try {
if (init_) init_();
for (UnitTestList::const_iterator i = list_.begin(), ie = list_.end(); i != ie; ++i) {
std::cout << "ctest:module=" << i->first << std::endl;
try {
(i->second)();
} catch (std::exception& e) {
exceptionCount_++;
std::cout << "ctest: " << i->first << " is stopped by exception " << e.what() << std::endl;
} catch (...) {
exceptionCount_++;
std::cout << "ctest: " << i->first << " is stopped by unknown exception" << std::endl;
}
}
if (term_) term_();
} catch (std::exception& e) {
msg = std::string("ctest:err:") + e.what();
} catch (...) {
msg = "ctest:err: catch unknown exception";
}
fflush(stdout);
if (msg.empty()) {
int err = ngCount_ + exceptionCount_;
int total = okCount_ + err;
std::cout << "ctest:name=" << getBaseName(*argv)
<< ", module=" << list_.size()
<< ", total=" << total
<< ", ok=" << okCount_
<< ", ng=" << ngCount_
<< ", exception=" << exceptionCount_ << std::endl;
return err > 0 ? 1 : 0;
} else {
std::cout << msg << std::endl;
return 1;
}
}
static inline AutoRun& getInstance()
{
static AutoRun instance;
return instance;
}
private:
Func init_;
Func term_;
int okCount_;
int ngCount_;
int exceptionCount_;
UnitTestList list_;
};
static AutoRun& autoRun = AutoRun::getInstance();
inline void test(bool ret, const std::string& msg, const std::string& param, const char *file, int line)
{
autoRun.set(ret);
if (!ret) {
printf("%s(%d):ctest:%s(%s);\n", file, line, msg.c_str(), param.c_str());
}
}
template<typename T, typename U>
bool isEqual(const T& lhs, const U& rhs)
{
return lhs == rhs;
}
// avoid warning of comparision of integers of different signs
inline bool isEqual(size_t lhs, int rhs)
{
return lhs == size_t(rhs);
}
inline bool isEqual(int lhs, size_t rhs)
{
return size_t(lhs) == rhs;
}
inline bool isEqual(const char *lhs, const char *rhs)
{
return strcmp(lhs, rhs) == 0;
}
inline bool isEqual(char *lhs, const char *rhs)
{
return strcmp(lhs, rhs) == 0;
}
inline bool isEqual(const char *lhs, char *rhs)
{
return strcmp(lhs, rhs) == 0;
}
inline bool isEqual(char *lhs, char *rhs)
{
return strcmp(lhs, rhs) == 0;
}
// avoid to compare float directly
inline bool isEqual(float lhs, float rhs)
{
union fi {
float f;
uint32_t i;
} lfi, rfi;
lfi.f = lhs;
rfi.f = rhs;
return lfi.i == rfi.i;
}
// avoid to compare double directly
inline bool isEqual(double lhs, double rhs)
{
union di {
double d;
uint64_t i;
} ldi, rdi;
ldi.d = lhs;
rdi.d = rhs;
return ldi.i == rdi.i;
}
} } // cybozu::test
#ifndef CYBOZU_TEST_DISABLE_AUTO_RUN
int main(int argc, char *argv[])
{
return cybozu::test::autoRun.run(argc, argv);
}
#endif
/**
alert if !x
@param x [in]
*/
#define CYBOZU_TEST_ASSERT(x) cybozu::test::test(!!(x), "CYBOZU_TEST_ASSERT", #x, __FILE__, __LINE__)
/**
alert if x != y
@param x [in]
@param y [in]
*/
#define CYBOZU_TEST_EQUAL(x, y) { \
bool _cybozu_eq = cybozu::test::isEqual(x, y); \
cybozu::test::test(_cybozu_eq, "CYBOZU_TEST_EQUAL", #x ", " #y, __FILE__, __LINE__); \
if (!_cybozu_eq) { \
std::cout << "ctest: lhs=" << (x) << std::endl; \
std::cout << "ctest: rhs=" << (y) << std::endl; \
} \
}
/**
alert if fabs(x, y) >= eps
@param x [in]
@param y [in]
*/
#define CYBOZU_TEST_NEAR(x, y, eps) { \
bool _cybozu_isNear = fabs((x) - (y)) < eps; \
cybozu::test::test(_cybozu_isNear, "CYBOZU_TEST_NEAR", #x ", " #y, __FILE__, __LINE__); \
if (!_cybozu_isNear) { \
std::cout << "ctest: lhs=" << (x) << std::endl; \
std::cout << "ctest: rhs=" << (y) << std::endl; \
} \
}
#define CYBOZU_TEST_EQUAL_POINTER(x, y) { \
bool _cybozu_eq = x == y; \
cybozu::test::test(_cybozu_eq, "CYBOZU_TEST_EQUAL_POINTER", #x ", " #y, __FILE__, __LINE__); \
if (!_cybozu_eq) { \
std::cout << "ctest: lhs=" << static_cast<const void*>(x) << std::endl; \
std::cout << "ctest: rhs=" << static_cast<const void*>(y) << std::endl; \
} \
}
/**
alert if x[] != y[]
@param x [in]
@param y [in]
@param n [in]
*/
#define CYBOZU_TEST_EQUAL_ARRAY(x, y, n) { \
for (size_t _cybozu_test_i = 0, _cybozu_ie = (size_t)(n); _cybozu_test_i < _cybozu_ie; _cybozu_test_i++) { \
bool _cybozu_eq = cybozu::test::isEqual((x)[_cybozu_test_i], (y)[_cybozu_test_i]); \
cybozu::test::test(_cybozu_eq, "CYBOZU_TEST_EQUAL_ARRAY", #x ", " #y ", " #n, __FILE__, __LINE__); \
if (!_cybozu_eq) { \
std::cout << "ctest: i=" << _cybozu_test_i << std::endl; \
std::cout << "ctest: lhs=" << (x)[_cybozu_test_i] << std::endl; \
std::cout << "ctest: rhs=" << (y)[_cybozu_test_i] << std::endl; \
} \
} \
}
/**
always alert
@param msg [in]
*/
#define CYBOZU_TEST_FAIL(msg) cybozu::test::test(false, "CYBOZU_TEST_FAIL", msg, __FILE__, __LINE__)
/**
verify message in exception
*/
#define CYBOZU_TEST_EXCEPTION_MESSAGE(statement, Exception, msg) \
{ \
int _cybozu_ret = 0; \
std::string _cybozu_errMsg; \
try { \
statement; \
_cybozu_ret = 1; \
} catch (const Exception& _cybozu_e) { \
_cybozu_errMsg = _cybozu_e.what(); \
if (_cybozu_errMsg.find(msg) == std::string::npos) { \
_cybozu_ret = 2; \
} \
} catch (...) { \
_cybozu_ret = 3; \
} \
if (_cybozu_ret) { \
cybozu::test::test(false, "CYBOZU_TEST_EXCEPTION_MESSAGE", #statement ", " #Exception ", " #msg, __FILE__, __LINE__); \
if (_cybozu_ret == 1) { \
std::cout << "ctest: no exception" << std::endl; \
} else if (_cybozu_ret == 2) { \
std::cout << "ctest: bad exception msg:" << _cybozu_errMsg << std::endl; \
} else { \
std::cout << "ctest: unexpected exception" << std::endl; \
} \
} else { \
cybozu::test::autoRun.set(true); \
} \
}
#define CYBOZU_TEST_EXCEPTION(statement, Exception) \
{ \
int _cybozu_ret = 0; \
try { \
statement; \
_cybozu_ret = 1; \
} catch (const Exception&) { \
} catch (...) { \
_cybozu_ret = 2; \
} \
if (_cybozu_ret) { \
cybozu::test::test(false, "CYBOZU_TEST_EXCEPTION", #statement ", " #Exception, __FILE__, __LINE__); \
if (_cybozu_ret == 1) { \
std::cout << "ctest: no exception" << std::endl; \
} else { \
std::cout << "ctest: unexpected exception" << std::endl; \
} \
} else { \
cybozu::test::autoRun.set(true); \
} \
}
/**
verify statement does not throw
*/
#define CYBOZU_TEST_NO_EXCEPTION(statement) \
try { \
statement; \
cybozu::test::autoRun.set(true); \
} catch (...) { \
cybozu::test::test(false, "CYBOZU_TEST_NO_EXCEPTION", #statement, __FILE__, __LINE__); \
}
/**
append auto unit test
@param name [in] module name
*/
#define CYBOZU_TEST_AUTO(name) \
void cybozu_test_ ## name(); \
struct cybozu_test_local_ ## name { \
cybozu_test_local_ ## name() \
{ \
cybozu::test::autoRun.append(#name, cybozu_test_ ## name); \
} \
} cybozu_test_local_instance_ ## name; \
void cybozu_test_ ## name()
/**
append auto unit test with fixture
@param name [in] module name
*/
#define CYBOZU_TEST_AUTO_WITH_FIXTURE(name, Fixture) \
void cybozu_test_ ## name(); \
void cybozu_test_real_ ## name() \
{ \
Fixture f; \
cybozu_test_ ## name(); \
} \
struct cybozu_test_local_ ## name { \
cybozu_test_local_ ## name() \
{ \
cybozu::test::autoRun.append(#name, cybozu_test_real_ ## name); \
} \
} cybozu_test_local_instance_ ## name; \
void cybozu_test_ ## name()
/**
setup fixture
@param Fixture [in] class name of fixture
@note cstr of Fixture is called before test and dstr of Fixture is called after test
*/
#define CYBOZU_TEST_SETUP_FIXTURE(Fixture) \
Fixture *cybozu_test_local_fixture; \
void cybozu_test_local_init() \
{ \
cybozu_test_local_fixture = new Fixture(); \
} \
void cybozu_test_local_term() \
{ \
delete cybozu_test_local_fixture; \
} \
struct cybozu_test_local_fixture_setup_ { \
cybozu_test_local_fixture_setup_() \
{ \
cybozu::test::autoRun.setup(cybozu_test_local_init, cybozu_test_local_term); \
} \
} cybozu_test_local_fixture_setup_instance_;

@ -0,0 +1,13 @@
#pragma once
#include <cybozu/inttype.hpp>
#ifdef CYBOZU_USE_BOOST
#include <boost/unordered_map.hpp>
#elif (CYBOZU_CPP_VERSION >= CYBOZU_CPP_VERSION_CPP11) || (defined __APPLE__)
#include <unordered_map>
#elif (CYBOZU_CPP_VERSION == CYBOZU_CPP_VERSION_TR1)
#include <list>
#include <tr1/unordered_map>
#endif

@ -0,0 +1,172 @@
#pragma once
/**
@file
@brief XorShift
@author MITSUNARI Shigeo(@herumi)
@author MITSUNARI Shigeo
*/
#include <cybozu/inttype.hpp>
namespace cybozu {
class XorShift {
uint32_t x_, y_, z_, w_;
public:
explicit XorShift(uint32_t x = 0, uint32_t y = 0, uint32_t z = 0, uint32_t w = 0)
{
init(x, y, z, w);
}
void init(uint32_t x = 0, uint32_t y = 0, uint32_t z = 0, uint32_t w = 0)
{
x_ = x ? x : 123456789;
y_ = y ? y : 362436069;
z_ = z ? z : 521288629;
w_ = w ? w : 88675123;
}
uint32_t get32()
{
unsigned int t = x_ ^ (x_ << 11);
x_ = y_; y_ = z_; z_ = w_;
return w_ = (w_ ^ (w_ >> 19)) ^ (t ^ (t >> 8));
}
uint32_t operator()() { return get32(); }
uint64_t get64()
{
uint32_t a = get32();
uint32_t b = get32();
return (uint64_t(a) << 32) | b;
}
template<class T>
void read(T *x, size_t n)
{
const size_t size = sizeof(T) * n;
uint8_t *p8 = static_cast<uint8_t*>(x);
for (size_t i = 0; i < size; i++) {
p8[i] = static_cast<uint8_t>(get32());
}
}
void read(uint32_t *x, size_t n)
{
for (size_t i = 0; i < n; i++) {
x[i] = get32();
}
}
void read(uint64_t *x, size_t n)
{
for (size_t i = 0; i < n; i++) {
x[i] = get64();
}
}
};
// see http://xorshift.di.unimi.it/xorshift128plus.c
class XorShift128Plus {
uint64_t s_[2];
static const uint64_t seed0 = 123456789;
static const uint64_t seed1 = 987654321;
public:
explicit XorShift128Plus(uint64_t s0 = seed0, uint64_t s1 = seed1)
{
init(s0, s1);
}
void init(uint64_t s0 = seed0, uint64_t s1 = seed1)
{
s_[0] = s0;
s_[1] = s1;
}
uint32_t get32()
{
return static_cast<uint32_t>(get64());
}
uint64_t operator()() { return get64(); }
uint64_t get64()
{
uint64_t s1 = s_[0];
const uint64_t s0 = s_[1];
s_[0] = s0;
s1 ^= s1 << 23;
s_[1] = s1 ^ s0 ^ (s1 >> 18) ^ (s0 >> 5);
return s_[1] + s0;
}
template<class T>
void read(T *x, size_t n)
{
const size_t size = sizeof(T) * n;
uint8_t *p8 = static_cast<uint8_t*>(x);
for (size_t i = 0; i < size; i++) {
p8[i] = static_cast<uint8_t>(get32());
}
}
void read(uint32_t *x, size_t n)
{
for (size_t i = 0; i < n; i++) {
x[i] = get32();
}
}
void read(uint64_t *x, size_t n)
{
for (size_t i = 0; i < n; i++) {
x[i] = get64();
}
}
};
// see http://xoroshiro.di.unimi.it/xoroshiro128plus.c
class Xoroshiro128Plus {
uint64_t s_[2];
static const uint64_t seed0 = 123456789;
static const uint64_t seed1 = 987654321;
uint64_t rotl(uint64_t x, unsigned int k) const
{
return (x << k) | (x >> (64 - k));
}
public:
explicit Xoroshiro128Plus(uint64_t s0 = seed0, uint64_t s1 = seed1)
{
init(s0, s1);
}
void init(uint64_t s0 = seed0, uint64_t s1 = seed1)
{
s_[0] = s0;
s_[1] = s1;
}
uint32_t get32()
{
return static_cast<uint32_t>(get64());
}
uint64_t operator()() { return get64(); }
uint64_t get64()
{
uint64_t s0 = s_[0];
uint64_t s1 = s_[1];
uint64_t result = s0 + s1;
s1 ^= s0;
s_[0] = rotl(s0, 55) ^ s1 ^ (s1 << 14);
s_[1] = rotl(s1, 36);
return result;
}
template<class T>
void read(T *x, size_t n)
{
const size_t size = sizeof(T) * n;
uint8_t *p8 = static_cast<uint8_t*>(x);
for (size_t i = 0; i < size; i++) {
p8[i] = static_cast<uint8_t>(get32());
}
}
void read(uint32_t *x, size_t n)
{
for (size_t i = 0; i < n; i++) {
x[i] = get32();
}
}
void read(uint64_t *x, size_t n)
{
for (size_t i = 0; i < n; i++) {
x[i] = get64();
}
}
};
} // cybozu

@ -81,7 +81,6 @@ Create a working directory (e.g., work) and clone the following repositories.
mkdir work
cd work
git clone git://github.com/herumi/mcl
git clone git://github.com/herumi/cybozulib
git clone git://github.com/herumi/cybozulib_ext ; for only Windows
```
* Cybozulib\_ext is a prerequisite for running OpenSSL and GMP on VC (Visual C++).
@ -149,18 +148,12 @@ cmake .. -A x64
msbuild mcl.sln /p:Configuration=Release /m
```
## Build for wasm(WebAssembly)
mcl supports emcc (Emscripten) and `test/bn_test.cpp` runs on browers such as Firefox, Chrome and Edge(enable extended JavaScript at about:config).
mcl supports emcc (Emscripten) and `test/bn_test.cpp` runs on browers such as Firefox, Chrome and Edge.
* [IBE on browser](https://herumi.github.io/mcl-wasm/ibe-demo.html)
* [SHE on browser](https://herumi.github.io/she-wasm/she-demo.html)
* [BLS signature on brower](https://herumi.github.io/bls-wasm/bls-demo.html)
Type
```
emcc -O3 -I ./include/ -I ../cybozulib/include/ src/fp.cpp test/bn_test.cpp -DNDEBUG -s WASM=1 -o t.html
emrun --no_browser --port 8080 --no_emrun_detect .
```
and open `http://<address>:8080/t.html`.
The timing of a pairing on `BN254` is 2.8msec on 64-bit Firefox with Skylake 3.4GHz.
### Node.js
@ -321,7 +314,7 @@ http://opensource.org/licenses/BSD-3-Clause
This library contains some part of the followings software licensed by BSD-3-Clause.
* [xbyak](https://github.com/heurmi/xbyak)
* [mie](https://github.com/herumi/mie)
* [cybozulib](https://github.com/heurmi/cybozulib)
* [Lifted-ElGamal](https://github.com/aistcrypt/Lifted-ElGamal)
# References

@ -1,2 +1,2 @@
set CFLAGS=/MT /DNOMINMAX /Ox /DNDEBUG /W4 /Zi /EHsc /nologo -I ./include -I../xbyak -I../cybozulib/include -I../cybozulib_ext/include
set CFLAGS=/MT /DNOMINMAX /Ox /DNDEBUG /W4 /Zi /EHsc /nologo -I./include -I../cybozulib_ext/include
set LDFLAGS=/LIBPATH:..\cybozulib_ext\lib /LIBPATH:.\lib

Loading…
Cancel
Save