Skip to content

Instantly share code, notes, and snippets.

@sleepdefic1t
Last active March 4, 2020 22:52
Show Gist options
  • Save sleepdefic1t/ce02192a6b33487cb2b6b5b37df703b9 to your computer and use it in GitHub Desktop.
Save sleepdefic1t/ce02192a6b33487cb2b6b5b37df703b9 to your computer and use it in GitHub Desktop.
Print Numbers and Token Amounts as Strings in C
#ifndef TOKEN_PRINTING_H
#define TOKEN_PRINTING_H
#include <stddef.h>
#include <stdint.h>
#include <string.h>
////////////////////////////////////////////////////////////////////////////////
static size_t adjustDecimals(const 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 0;
}
target[offset++] = '0';
target[offset++] = '\0';
return offset;
}
if (srcSize <= decimals) {
size_t delta = decimals - srcSize;
if (targetSize < srcSize + 1 + 2 + delta) {
return offset;
}
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 offset;
}
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 offset + lastZeroOffset;
}
////////////////////////////////////////////////////////////////////////////////
size_t UintToString(uint64_t value, char *dst, size_t maxLen) {
if (dst == NULL || maxLen < 2) {
return 0;
}
if (value == 0) {
dst[0] = '0';
dst[1] = '\0';
return 2;
}
uint64_t base = 1;
size_t n = 0;
size_t i = 0;
const size_t maxN = 20;
// count how many characters are needed
while (base <= value && n <= maxN) {
base *= 0x0A;
n++;
}
if (n > maxLen - 1) {
dst[0] = '\0';
return 0;
}
base /= 0x0A;
while (i < n) {
dst[i++] = '0' + ((value / base) % 0x0A);
base /= 0x0A;
}
dst[i] = '\0';
return n + 1;
}
////////////////////////////////////////////////////////////////////////////////
size_t TokenAmountToString(uint64_t amount,
char *dst, size_t maxLen,
const char *tokenName, size_t tokenNameSize,
uint8_t decimals) {
if (dst == NULL) {
return 0;
}
if (tokenNameSize > 0) {
memcpy(dst, tokenName, tokenNameSize);
}
if (decimals == 0) {
return tokenNameSize + UintToString(amount, dst + tokenNameSize, maxLen);
}
else {
char buffer[25];
const size_t len = UintToString(amount, buffer, maxLen);
return tokenNameSize +
adjustDecimals(buffer, len, dst + tokenNameSize, maxLen, decimals + 1);;
}
}
#endif // TOKEN_PRINTING_H
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment