|
Packit |
4e8bc4 |
//=== itoa_ljust.cpp - Fast integer to ascii conversion --*- C++ -*-//
|
|
Packit |
4e8bc4 |
//
|
|
Packit |
4e8bc4 |
// Substantially simplified (and slightly faster) version
|
|
Packit |
4e8bc4 |
// based on the following functions in Google's protocol buffers:
|
|
Packit |
4e8bc4 |
//
|
|
Packit |
4e8bc4 |
// FastInt32ToBufferLeft()
|
|
Packit |
4e8bc4 |
// FastUInt32ToBufferLeft()
|
|
Packit |
4e8bc4 |
// FastInt64ToBufferLeft()
|
|
Packit |
4e8bc4 |
// FastUInt64ToBufferLeft()
|
|
Packit |
4e8bc4 |
//
|
|
Packit |
4e8bc4 |
// Differences:
|
|
Packit |
4e8bc4 |
// 1) Greatly simplified
|
|
Packit |
4e8bc4 |
// 2) Avoids GOTO statements - uses "switch" instead and relies on
|
|
Packit |
4e8bc4 |
// compiler constant folding and propagation for high performance
|
|
Packit |
4e8bc4 |
// 3) Avoids unary minus of signed types - undefined behavior if value
|
|
Packit |
4e8bc4 |
// is INT_MIN in platforms using two's complement representation
|
|
Packit |
4e8bc4 |
// 4) Uses memcpy to store 2 digits at a time - lets the compiler
|
|
Packit |
4e8bc4 |
// generate a 2-byte load/store in platforms that support
|
|
Packit |
4e8bc4 |
// unaligned access, this is faster (and less code) than explicitly
|
|
Packit |
4e8bc4 |
// loading and storing each byte
|
|
Packit |
4e8bc4 |
//
|
|
Packit |
4e8bc4 |
// Copyright (c) 2016 Arturo Martin-de-Nicolas
|
|
Packit |
4e8bc4 |
// arturomdn@gmail.com
|
|
Packit |
4e8bc4 |
// https://github.com/amdn/itoa_ljust/
|
|
Packit |
4e8bc4 |
//
|
|
Packit |
4e8bc4 |
// Released under the BSD 3-Clause License, see Google's original copyright
|
|
Packit |
4e8bc4 |
// and license below.
|
|
Packit |
4e8bc4 |
//===----------------------------------------------------------------------===//
|
|
Packit |
4e8bc4 |
|
|
Packit |
4e8bc4 |
// Protocol Buffers - Google's data interchange format
|
|
Packit |
4e8bc4 |
// Copyright 2008 Google Inc. All rights reserved.
|
|
Packit |
4e8bc4 |
// https://developers.google.com/protocol-buffers/
|
|
Packit |
4e8bc4 |
//
|
|
Packit |
4e8bc4 |
// Redistribution and use in source and binary forms, with or without
|
|
Packit |
4e8bc4 |
// modification, are permitted provided that the following conditions are
|
|
Packit |
4e8bc4 |
// met:
|
|
Packit |
4e8bc4 |
//
|
|
Packit |
4e8bc4 |
// * Redistributions of source code must retain the above copyright
|
|
Packit |
4e8bc4 |
// notice, this list of conditions and the following disclaimer.
|
|
Packit |
4e8bc4 |
// * Redistributions in binary form must reproduce the above
|
|
Packit |
4e8bc4 |
// copyright notice, this list of conditions and the following disclaimer
|
|
Packit |
4e8bc4 |
// in the documentation and/or other materials provided with the
|
|
Packit |
4e8bc4 |
// distribution.
|
|
Packit |
4e8bc4 |
// * Neither the name of Google Inc. nor the names of its
|
|
Packit |
4e8bc4 |
// contributors may be used to endorse or promote products derived from
|
|
Packit |
4e8bc4 |
// this software without specific prior written permission.
|
|
Packit |
4e8bc4 |
//
|
|
Packit |
4e8bc4 |
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
Packit |
4e8bc4 |
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
Packit |
4e8bc4 |
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
Packit |
4e8bc4 |
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
Packit |
4e8bc4 |
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
Packit |
4e8bc4 |
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
Packit |
4e8bc4 |
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
Packit |
4e8bc4 |
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
Packit |
4e8bc4 |
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
Packit |
4e8bc4 |
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
Packit |
4e8bc4 |
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
Packit |
4e8bc4 |
//===----------------------------------------------------------------------===//
|
|
Packit |
4e8bc4 |
|
|
Packit |
4e8bc4 |
#include "itoa_ljust.h"
|
|
Packit |
4e8bc4 |
#include <string.h>
|
|
Packit |
4e8bc4 |
|
|
Packit |
4e8bc4 |
static const char lut[201] =
|
|
Packit |
4e8bc4 |
"0001020304050607080910111213141516171819"
|
|
Packit |
4e8bc4 |
"2021222324252627282930313233343536373839"
|
|
Packit |
4e8bc4 |
"4041424344454647484950515253545556575859"
|
|
Packit |
4e8bc4 |
"6061626364656667686970717273747576777879"
|
|
Packit |
4e8bc4 |
"8081828384858687888990919293949596979899";
|
|
Packit |
4e8bc4 |
|
|
Packit |
4e8bc4 |
#define dd(u) ((const uint16_t)(lut[u]))
|
|
Packit |
4e8bc4 |
|
|
Packit |
4e8bc4 |
static inline char* out2(const int d, char* p) {
|
|
Packit |
4e8bc4 |
memcpy(p, &((uint16_t *)lut)[d], 2);
|
|
Packit |
4e8bc4 |
return p + 2;
|
|
Packit |
4e8bc4 |
}
|
|
Packit |
4e8bc4 |
|
|
Packit |
4e8bc4 |
static inline char* out1(const char in, char* p) {
|
|
Packit |
4e8bc4 |
memcpy(p, &in, 1);
|
|
Packit |
4e8bc4 |
return p + 1;
|
|
Packit |
4e8bc4 |
}
|
|
Packit |
4e8bc4 |
|
|
Packit |
4e8bc4 |
static inline int digits( uint32_t u, unsigned k, int* d, char** p, int n ) {
|
|
Packit |
4e8bc4 |
if (u < k*10) {
|
|
Packit |
4e8bc4 |
*d = u / k;
|
|
Packit |
4e8bc4 |
*p = out1('0'+*d, *p);
|
|
Packit |
4e8bc4 |
--n;
|
|
Packit |
4e8bc4 |
}
|
|
Packit |
4e8bc4 |
return n;
|
|
Packit |
4e8bc4 |
}
|
|
Packit |
4e8bc4 |
|
|
Packit |
4e8bc4 |
static inline char* itoa(uint32_t u, char* p, int d, int n) {
|
|
Packit |
4e8bc4 |
switch(n) {
|
|
Packit |
4e8bc4 |
case 10: d = u / 100000000; p = out2( d, p );
|
|
Packit |
4e8bc4 |
case 9: u -= d * 100000000;
|
|
Packit |
4e8bc4 |
case 8: d = u / 1000000; p = out2( d, p );
|
|
Packit |
4e8bc4 |
case 7: u -= d * 1000000;
|
|
Packit |
4e8bc4 |
case 6: d = u / 10000; p = out2( d, p );
|
|
Packit |
4e8bc4 |
case 5: u -= d * 10000;
|
|
Packit |
4e8bc4 |
case 4: d = u / 100; p = out2( d, p );
|
|
Packit |
4e8bc4 |
case 3: u -= d * 100;
|
|
Packit |
4e8bc4 |
case 2: d = u / 1; p = out2( d, p );
|
|
Packit |
4e8bc4 |
case 1: ;
|
|
Packit |
4e8bc4 |
}
|
|
Packit |
4e8bc4 |
*p = '\0';
|
|
Packit |
4e8bc4 |
return p;
|
|
Packit |
4e8bc4 |
}
|
|
Packit |
4e8bc4 |
|
|
Packit |
4e8bc4 |
char* itoa_u32(uint32_t u, char* p) {
|
|
Packit |
4e8bc4 |
int d = 0,n;
|
|
Packit |
4e8bc4 |
if (u >=100000000) n = digits(u, 100000000, &d, &p, 10);
|
|
Packit |
4e8bc4 |
else if (u < 100) n = digits(u, 1, &d, &p, 2);
|
|
Packit |
4e8bc4 |
else if (u < 10000) n = digits(u, 100, &d, &p, 4);
|
|
Packit |
4e8bc4 |
else if (u < 1000000) n = digits(u, 10000, &d, &p, 6);
|
|
Packit |
4e8bc4 |
else n = digits(u, 1000000, &d, &p, 8);
|
|
Packit |
4e8bc4 |
return itoa( u, p, d, n );
|
|
Packit |
4e8bc4 |
}
|
|
Packit |
4e8bc4 |
|
|
Packit |
4e8bc4 |
char* itoa_32(int32_t i, char* p) {
|
|
Packit |
4e8bc4 |
uint32_t u = i;
|
|
Packit |
4e8bc4 |
if (i < 0) {
|
|
Packit |
4e8bc4 |
*p++ = '-';
|
|
Packit |
4e8bc4 |
u = -u;
|
|
Packit |
4e8bc4 |
}
|
|
Packit |
4e8bc4 |
return itoa_u32(u, p);
|
|
Packit |
4e8bc4 |
}
|
|
Packit |
4e8bc4 |
|
|
Packit |
4e8bc4 |
char* itoa_u64(uint64_t u, char* p) {
|
|
Packit |
4e8bc4 |
int d;
|
|
Packit |
4e8bc4 |
|
|
Packit |
4e8bc4 |
uint32_t lower = (uint32_t)u;
|
|
Packit |
4e8bc4 |
if (lower == u) return itoa_u32(lower, p);
|
|
Packit |
4e8bc4 |
|
|
Packit |
4e8bc4 |
uint64_t upper = u / 1000000000;
|
|
Packit |
4e8bc4 |
p = itoa_u64(upper, p);
|
|
Packit |
4e8bc4 |
lower = u - (upper * 1000000000);
|
|
Packit |
4e8bc4 |
d = lower / 100000000;
|
|
Packit |
4e8bc4 |
p = out1('0'+d,p);
|
|
Packit |
4e8bc4 |
return itoa( lower, p, d, 9 );
|
|
Packit |
4e8bc4 |
}
|
|
Packit |
4e8bc4 |
|
|
Packit |
4e8bc4 |
char* itoa_64(int64_t i, char* p) {
|
|
Packit |
4e8bc4 |
uint64_t u = i;
|
|
Packit |
4e8bc4 |
if (i < 0) {
|
|
Packit |
4e8bc4 |
*p++ = '-';
|
|
Packit |
4e8bc4 |
u = -u;
|
|
Packit |
4e8bc4 |
}
|
|
Packit |
4e8bc4 |
return itoa_u64(u, p);
|
|
Packit |
4e8bc4 |
}
|