Blame itoa_ljust.c

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