Print Int64's as Floats (long doubles)
/*******************************************************************************
* This file is part of the ARK Ecosystem.
*
* Copyright (c) ARK Ecosystem <info@ark.io>
* Copyright (c) Simon Downey <simon@ark.io> (https://github.com/sleepdefic1t)
*
* The MIT License (MIT)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
******************************************************************************/
#ifndef PRINT_INT64_TO_FLOAT_HPP
#define PRINT_INT64_TO_FLOAT_HPP
#include <cstdbool>
#include <cstddef>
#include <cstdint>
////////////////////////////////////////////////////////////////////////////////
static bool adjustDecimals(char *src,
size_t srcSize,
char *target,
size_t targetSize,
uint8_t decimals) {
size_t startOffset;
size_t lastZeroOffset = 0;
size_t offset = 0;
if ((srcSize == 1) && (*src == '0')) {
if (targetSize < 2) {
return false;
}
target[offset++] = '0';
target[offset++] = '\0';
return true;
}
if (srcSize <= decimals) {
size_t delta = decimals - srcSize;
if (targetSize < srcSize + 1 + 2 + delta) {
return false;
}
target[offset++] = '0';
if (decimals > 0) {
target[offset++] = '.';
}
for (size_t i = 0; i < delta; i++) {
target[offset++] = '0';
}
startOffset = offset;
for (size_t i = 0; i < srcSize; i++) {
target[offset++] = src[i];
}
target[offset] = '\0';
}
else {
size_t sourceOffset = 0;
size_t delta = srcSize - decimals;
if (targetSize < srcSize + 1 + 1) {
return false;
}
while (offset < delta) {
target[offset++] = src[sourceOffset++];
}
if (decimals != 0) {
target[offset++] = '.';
}
startOffset = offset;
while (sourceOffset < srcSize) {
target[offset++] = src[sourceOffset++];
}
target[offset] = '\0';
}
for (size_t i = startOffset; i < offset; i++) {
if (target[i] == '0') {
if (lastZeroOffset == 0) {
lastZeroOffset = i;
}
}
else {
lastZeroOffset = 0;
}
}
if (lastZeroOffset != 0) {
target[lastZeroOffset] = '\0';
if (target[lastZeroOffset - 1] == '.') {
target[lastZeroOffset - 1] = '\0';
}
}
return true;
}
////////////////////////////////////////////////////////////////////////////////
std::string PrintInt64ToFloat(int64_t value,
size_t targetSize,
uint8_t decimals) {
size_t numDigits = 0UL;
size_t i = 0UL;
int64_t base = 1LL;
int64_t tempInt = value;
// '-' + int64-max-chars(20) + '.' + '\0'
const size_t maxTmpSize = 23;
char tmp[maxTmpSize] = { '\0' };
std::string out;
out.reserve(targetSize);
size_t negOffset = tempInt < 0LL ? 1UL : 0UL;
if (negOffset == 1UL) {
out[0] = '-';
tempInt = -tempInt;
}
while (base <= tempInt) {
base *= 0x0A;
numDigits++;
}
if (numDigits > sizeof(tmp) - 1) {
return 0;
}
base /= 0x0A;
for (; i < numDigits; i++) {
tmp[i] = '0' + ((tempInt / base) % 0x0A);
base /= 0x0A;
}
adjustDecimals(tmp, i, &out[negOffset], targetSize, decimals);
if (numDigits + 1 + negOffset > targetSize - 1) {
out[0] = '\0';
}
return out;
}
#endif // #define PRINT_INT64_TO_FLOAT_HPP