/
githubmirror
/
nvme-cli
Обзор
Документация
Войти
/
githubmirror
/
nvme-cli
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
shared/suffix-util.c
247 строк
5 KB
Daniel Wagner
shared: move util/suffix.{c,h} to shared/suffix-util
07 авг 2026, 16:15
07 авг 2026, 16:15
80eb924
Код
Авторство
О чём код?
// SPDX-License-Identifier: LGPL-2.1-or-later /* * This file is part of nvme-cli. * Copyright (c) 2026 Tokunori Ikegami * Copyright (c) 2026 SUSE Software Solutions * * Authors: Daniel Wagner <dwagner@suse.de> * Tokunori Ikegami <ikegami.t@gmail.com> */ #include <ctype.h> #include <errno.h> #include <float.h> #include <limits.h> #include <locale.h> #include <math.h> #include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ccan/array_size/array_size.h> #include "suffix-util.h" static struct si_suffix { long double magnitude; unsigned int exponent; const char *suffix; } si_suffixes[] = { {1e30, 30, "Q"}, {1e27, 27, "R"}, {1e24, 24, "Y"}, {1e21, 21, "Z"}, {1e18, 18, "E"}, {1e15, 15, "P"}, {1e12, 12, "T"}, {1e9, 9, "G"}, {1e6, 6, "M"}, {1e3, 3, "k"}, }; const char *shr_suffix_si_get(double *value) { long double value_ld = *value; const char *suffix = shr_suffix_si_get_ld(&value_ld); *value = value_ld; return suffix; } static bool suffix_si_check(const char val) { int i; struct si_suffix *s; for (i = 0; i < ARRAY_SIZE(si_suffixes); i++) { s = &si_suffixes[i]; if (val == *s->suffix) return true; } return false; } int shr_suffix_si_parse(const char *str, char **endptr, uint64_t *val) { unsigned long long num, frac = 0; char *sep, *tmp; int frac_len = 0, len, i; num = strtoull(str, endptr, 0); if (str == *endptr || ((num == ULLONG_MAX) && errno == ERANGE)) return -EINVAL; /* simple number, no decimal point not suffix */ if ((*endptr)[0] == '\0') { *val = num; return 0; } /* get rid of the decimal point */ sep = localeconv()->decimal_point; if (sep) len = strlen(sep); else len = 0; for (i = 0; i < len; i++) { if (suffix_si_check((*endptr)[i])) break; if (((*endptr)[i] == '\0') || (*endptr)[i] != sep[i]) return -EINVAL; } if (suffix_si_check((*endptr)[i])) { if ((*endptr)[i + 1] != '\0') return -EINVAL; } else { *endptr += len; tmp = *endptr; /* extract the digits after decimal point */ frac = strtoull(tmp, endptr, 0); if (tmp == *endptr || ((frac == ULLONG_MAX) && errno == ERANGE)) return -EINVAL; /* test that we have max one character as suffix */ if ((*endptr)[0] != '\0' && (*endptr)[1] != '\0') return -EINVAL; frac_len = *endptr - tmp; } for (i = 0; i < ARRAY_SIZE(si_suffixes); i++) { struct si_suffix *s = &si_suffixes[i]; if ((*endptr)[0] != s->suffix[0]) continue; /* we should check for overflow */ for (int j = 0; j < s->exponent; j++) num *= 10; if (s->exponent > frac_len) { for (int j = 0; j < s->exponent - frac_len; j++) frac *= 10; } else if (s->exponent < frac_len) { for (int j = 0; j < frac_len - s->exponent; j++) frac /= 10; } else { frac = 0; } *val = num + frac; return 0; } if ((*endptr)[0] != '\0') return -EINVAL; *val = num; return 0; } const char *shr_suffix_si_get_ld(long double *value) { int i; for (i = 0; i < ARRAY_SIZE(si_suffixes); i++) { struct si_suffix *s = &si_suffixes[i]; if (*value >= s->magnitude) { *value /= s->magnitude; return s->suffix; } } return ""; } static struct binary_suffix { int shift; const char *suffix; } binary_suffixes[] = { {50, "Pi"}, {40, "Ti"}, {30, "Gi"}, {20, "Mi"}, {10, "Ki"}, }; const char *shr_suffix_binary_get(long long *value) { int i; for (i = 0; i < ARRAY_SIZE(binary_suffixes); i++) { struct binary_suffix *s = &binary_suffixes[i]; if (llabs(*value) >= (1LL << s->shift)) { *value = (*value + (1LL << (s->shift - 1))) / (1LL << s->shift); return s->suffix; } } return ""; } const char *shr_suffix_dbinary_get(double *value) { int i; for (i = 0; i < ARRAY_SIZE(binary_suffixes); i++) { struct binary_suffix *s = &binary_suffixes[i]; if (fabs(*value) >= (1LL << s->shift)) { *value = *value / (1LL << s->shift); return s->suffix; } } return ""; } int shr_suffix_binary_parse(const char *str, char **endptr, uint64_t *val) { uint64_t ret; int i; ret = strtoull(str, endptr, 0); if (str == *endptr || ((ret == ULLONG_MAX) && errno == ERANGE)) return -EINVAL; if (str == *endptr) { *val = ret; return 0; } /* simple number, no decimal point, no suffix */ if ((*endptr)[0] == '\0') { *val = ret; return 0; } for (i = 0; i < ARRAY_SIZE(binary_suffixes); i++) { struct binary_suffix *s = &binary_suffixes[i]; if (tolower((*endptr)[0]) == tolower(s->suffix[0]) && (s->suffix[0] != '\0' && (((*endptr)[0] != '\0' && (*endptr)[1] != '\0' && (*endptr)[2] == '\0') && (tolower((*endptr)[1]) == tolower(s->suffix[1]))))) { ret <<= s->shift; *val = ret; return 0; } } return -EINVAL; }