You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
338 lines
7.2 KiB
338 lines
7.2 KiB
6 years ago
|
#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
|