digits10的实现简直亮晕了双眼,居然这么巧妙,主要是基于效率的考虑:
- /* Modify the buffer replacing all occurrences of chars from the 'from'
- * set with the corresponding char in the 'to' set. Always returns s.
- */
- char *memmapchars(char *s, size_t len, const char *from, const char *to, size_t setlen) {
- for (size_t j = 0; j < len; j++) {
- for (size_t i = 0; i < setlen; i++) {
- if (s[j] == from[i]) {
- s[j] = to[i];
- break;
- }
- }
- }
- return s;
- }
-
- /* Return the number of digits of 'v' when converted to string in radix 10.
- * See ll2string() for more information. */
- uint32_t digits10(uint64_t v) {
- if (v < 10) return 1;
- if (v < 100) return 2;
- if (v < 1000) return 3;
- if (v < 1000000000000UL) {
- if (v < 100000000UL) {
- if (v < 1000000) {
- if (v < 10000) return 4;
- return 5 + (v >= 100000);
- }
- return 7 + (v >= 10000000UL);
- }
- if (v < 10000000000UL) {
- return 9 + (v >= 1000000000UL);
- }
- return 11 + (v >= 100000000000UL);
- }
- return 12 + digits10(v / 1000000000000UL);
- }
-
- /* Like digits10() but for signed values. */
- uint32_t sdigits10(int64_t v) {
- if (v < 0) {
- /* Abs value of LLONG_MIN requires special handling. */
- uint64_t uv = (v != LLONG_MIN) ?
- (uint64_t)-v : ((uint64_t) LLONG_MAX)+1;
- return digits10(uv)+1; /* +1 for the minus. */
- } else {
- return digits10(v);
- }
- }