Conv是一个类型转换的库,主要实现了字符串到整数和浮点数的转换,性能要比snprintf和strtol要好上一些。
double和string的来回转换主要是用google的开源项目double conversion来实现的,这里按下不表
我们主要考察int和string的来回转换的实现
其中int->string的关键代码是,可以看到是非常简单的查表操作:
extern const chardigit1[101] =
"00000000001111111111222222222233333333334444444444"
"55555555556666666666777777777788888888889999999999";
extern const chardigit2[101] =
"01234567890123456789012345678901234567890123456789"
"01234567890123456789012345678901234567890123456789";
// Returns the offset ofthe formatted string from the start of
// the supplied buffer.The new string will be at range
//[buf+begin,buf+bufLen). Uint will be either uint32_t or uint64_t.
template
size_tuintToBuffer(char*const buffer, size_t bufLen, Uint v) {
extern const char digit1[101], digit2[101];
for (;;) {
if (v < 100) {
if (v < 10) {
buffer[--bufLen] =static_cast(v + '0');
} else {
size_t r =static_cast(v);
bufLen -= 2;
buffer[bufLen] = digit1[r];
buffer[bufLen + 1] = digit2[r];
}
break;
}
Uint t = v;
v /= 100;
size_t r = static_cast (t - v* 100);
bufLen -= 2;
buffer[bufLen] = digit1[r];
buffer[bufLen + 1] = digit2[r];
}
return bufLen;
}
性能:1y随机数转化成string,耗时3.8s,snprintf耗时27.3s
而从string->int的操作的核心代码如下,也是简单的差别操作:
/*
* Lookup tables that converts from a decimalcharacter value to an integral
* binary value, shifted by a decimal"shift" multiplier.
* For all character values in the range'0'..'9', the table at those
* index locations returns the actual decimalvalue shifted by the multiplier.
* For all other values, the lookup tablereturns an invalid OOR value.
*/
// Out-of-range flagvalue, larger than the largest value that can fit in
// four decimal bytes(9999), but four of these added up together should
// still not overflowuint16_t.
constexpr int32_t OOR =10000;
__attribute__((aligned(16)))constexpr uint16_t shift1[] = {
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 0-9
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 10
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 20
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 30
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,0, // 40
1, 2, 3, 4, 5, 6, 7, 8, 9, OOR, OOR,
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 60
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 70
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 80
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 90
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 100
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 110
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 120
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 130
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 140
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 150
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 160
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 170
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 180
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 190
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 200
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 210
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 220
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 230
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 240
OOR, OOR, OOR, OOR, OOR, OOR // 250
};
__attribute__((aligned(16)))constexpr uint16_t shift10[] = {
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 0-9
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 10
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 20
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 30
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,0, // 40
10, 20, 30, 40, 50, 60, 70, 80, 90, OOR, OOR,
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 60
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 70
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 80
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 90
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 100
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 110
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 120
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 130
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 140
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 150
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 160
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 170
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 180
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 190
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 200
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 210
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 220
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 230
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 240
OOR, OOR, OOR, OOR, OOR, OOR // 250
};
__attribute__((aligned(16)))constexpr uint16_t shift100[] = {
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 0-9
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 10
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 20
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 30
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,0, // 40
100, 200, 300, 400, 500, 600, 700, 800, 900,OOR, OOR,
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 60
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 70
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 80
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 90
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 100
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 110
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 120
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 130
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 140
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 150
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 160
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 170
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 180
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 190
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 200
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 210
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 220
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 230
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 240
OOR, OOR, OOR, OOR, OOR, OOR // 250
};
__attribute__((aligned(16)))constexpr uint16_t shift1000[] = {
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 0-9
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 10
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 20
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 30
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,0, // 40
1000, 2000, 3000, 4000, 5000, 6000, 7000,8000, 9000, OOR, OOR,
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 60
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 70
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 80
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 90
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 100
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 110
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 120
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 130
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 140
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 150
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 160
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 170
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 180
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 190
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 200
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 210
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 220
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 230
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,OOR, // 240
OOR, OOR, OOR, OOR, OOR, OOR // 250
};
/**
* String represented as a pair of pointers tochar to unsigned
* integrals. Assumes NO whitespace before orafter, and also that the
* string is composed entirely of digits. Tgtmust be unsigned, and no
* sign is allowed in the string (even it's'+'). String may be empty,
* in which case digits_to throws.
*/
template
Tgt digits_to(const char * b, const char * e){
static_assert(!std::is_signed::value, "Unsigned typeexpected");
assert(b <= e);
const size_t size = e - b;
/* Although the string is entirely made ofdigits, we still need to
* check for overflow.
*/
if (size >=std::numeric_limits::digits10 + 1) {
// Leading zeros? If so, recurse to keepthings simple
if (b < e && *b == '0') {
for (++b;; ++b) {
if (b == e) return 0; // just zeros,e.g. "0000"
if (*b != '0') returndigits_to(b, e);
}
}
FOLLY_RANGE_CHECK(size ==std::numeric_limits::digits10 + 1 &&
strncmp(b,detail::MaxString::value, size) <= 0,
"Numeric overflowupon conversion");
}
// Here we know that the number won'toverflow when
// converted. Proceed without checks.
Tgt result = 0;
for (; e - b >= 4; b += 4) {
result *= 10000;
const int32_t r0 =shift1000[static_cast(b[0])];
const int32_t r1 =shift100[static_cast(b[1])];
const int32_t r2 =shift10[static_cast(b[2])];
const int32_t r3 =shift1[static_cast(b[3])];
const auto sum = r0 + r1 + r2 + r3;
assert(sum < OOR &&"Assumption: string only has digits");
result += sum;
}
switch (e - b) {
case 3: {
const int32_t r0 =shift100[static_cast(b[0])];
const int32_t r1 =shift10[static_cast(b[1])];
const int32_t r2 =shift1[static_cast(b[2])];
const auto sum = r0 + r1 + r2;
assert(sum < OOR &&"Assumption: string only has digits");
return result * 1000 + sum;
}
case 2: {
const int32_t r0 =shift10[static_cast(b[0])];
const int32_t r1 =shift1[static_cast(b[1])];
const auto sum = r0 + r1;
assert(sum < OOR &&"Assumption: string only has digits");
return result * 100 + sum;
}
case 1: {
const int32_t sum =shift1[static_cast(b[0])];
assert(sum < OOR &&"Assumption: string only has digits");
return result * 10 + sum;
}
}
assert(b == e);
FOLLY_RANGE_CHECK(size > 0, "Foundno digits to convert in input");
return result;
}
性能:1y数据digits_to耗时5s,strtol耗时10s