Line data Source code
1 : /* 2 : * lwan - web server 3 : * Copyright (c) 2012 L. A. F. Pereira <l@tia.mat.br> 4 : * 5 : * This program is free software; you can redistribute it and/or 6 : * modify it under the terms of the GNU General Public License 7 : * as published by the Free Software Foundation; either version 2 8 : * of the License, or any later version. 9 : * 10 : * This program is distributed in the hope that it will be useful, 11 : * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 : * GNU General Public License for more details. 14 : * 15 : * You should have received a copy of the GNU General Public License 16 : * along with this program; if not, write to the Free Software 17 : * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 18 : * USA. 19 : */ 20 : 21 : #include <assert.h> 22 : 23 : #include "lwan-private.h" 24 : 25 : #include "int-to-str.h" 26 : 27 : static const char digits[201] = "0001020304050607080910111213141516171819" 28 : "2021222324252627282930313233343536373839" 29 : "4041424344454647484950515253545556575859" 30 : "6061626364656667686970717273747576777879" 31 : "8081828384858687888990919293949596979899"; 32 : 33 : ALWAYS_INLINE __attribute__((pure)) const char * 34 2460 : uint_to_string_2_digits(size_t value) 35 : { 36 2460 : assert(value <= 99); 37 2460 : return &digits[2 * value]; 38 : } 39 : 40 506 : ALWAYS_INLINE char *uint_to_string(size_t value, 41 : char dst[static INT_TO_STR_BUFFER_SIZE], 42 : size_t *length_out) 43 : { 44 : /* 45 : * Based on routine by A. Alexandrescu, licensed under CC0 46 : * https://creativecommons.org/publicdomain/zero/1.0/legalcode 47 : */ 48 : static const size_t length = INT_TO_STR_BUFFER_SIZE; 49 2757 : size_t next = length - 1; 50 2757 : dst[next--] = '\0'; 51 5069 : while (value >= 100) { 52 2312 : const uint32_t i = (uint32_t)((value % 100) * 2); 53 2312 : value /= 100; 54 2312 : dst[next] = digits[i + 1]; 55 2312 : dst[next - 1] = digits[i]; 56 2312 : next -= 2; 57 : } 58 : // Handle last 1-2 digits 59 2757 : if (value < 10) { 60 297 : dst[next] = (char)('0' + (uint32_t)value); 61 297 : *length_out = length - next - 1; 62 297 : return dst + next; 63 : } 64 2460 : uint32_t i = (uint32_t)value * 2; 65 2460 : dst[next] = digits[i + 1]; 66 2460 : dst[next - 1] = digits[i]; 67 2460 : *length_out = length - next; 68 2460 : return dst + next - 1; 69 : } 70 : 71 2251 : ALWAYS_INLINE char *int_to_string(ssize_t value, 72 : char dst[static INT_TO_STR_BUFFER_SIZE], 73 : size_t *length_out) 74 : { 75 2251 : if (value < 0) { 76 0 : char *p = uint_to_string((size_t)-value, dst, length_out); 77 0 : *--p = '-'; 78 0 : ++*length_out; 79 : 80 0 : return p; 81 : } 82 : 83 4502 : return uint_to_string((size_t)value, dst, length_out); 84 : }