]> git.proxmox.com Git - ceph.git/blame - ceph/src/common/strtol.h
update ceph source to reef 18.2.0
[ceph.git] / ceph / src / common / strtol.h
CommitLineData
7c673cae
FG
1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2// vim: ts=8 sw=2 smarttab
3/*
4 * Ceph - scalable distributed file system
5 *
6 * Copyright (C) 2011 New Dream Network
7 *
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
12 *
13 */
14
15#ifndef CEPH_COMMON_STRTOL_H
16#define CEPH_COMMON_STRTOL_H
17
f91f0fd5 18#include <charconv>
f91f0fd5
TL
19#include <cinttypes>
20#include <cstdlib>
21#include <optional>
7c673cae 22#include <string>
f91f0fd5
TL
23#include <string_view>
24#include <system_error>
25#include <type_traits>
26
27
28namespace ceph {
f91f0fd5
TL
29// Wrappers around std::from_chars.
30//
31// Why do we want this instead of strtol and friends? Because the
32// string doesn't have to be NUL-terminated! (Also, for a lot of
33// purposes, just putting a string_view in and getting an optional out
34// is friendly.)
35//
36// Returns the found number on success. Returns an empty optional on
37// failure OR on trailing characters.
20effc67 38// Sadly GCC < 11 is missing the floating point versions.
f91f0fd5
TL
39template<typename T>
40auto parse(std::string_view s, int base = 10)
41 -> std::enable_if_t<std::is_integral_v<T>, std::optional<T>>
42{
43 T t;
44 auto r = std::from_chars(s.data(), s.data() + s.size(), t, base);
45 if ((r.ec != std::errc{}) || (r.ptr != s.data() + s.size())) {
46 return std::nullopt;
47 }
48 return t;
49}
50
51// As above, but succeed on trailing characters and trim the supplied
52// string_view to remove the parsed number. Set the supplied
53// string_view to empty if it ends with the number.
54template<typename T>
55auto consume(std::string_view& s, int base = 10)
56 -> std::enable_if_t<std::is_integral_v<T>, std::optional<T>>
57{
58 T t;
59 auto r = std::from_chars(s.data(), s.data() + s.size(), t, base);
60 if (r.ec != std::errc{})
61 return std::nullopt;
62
63 if (r.ptr == s.data() + s.size()) {
64 s = std::string_view{};
65 } else {
66 s.remove_prefix(r.ptr - s.data());
67 }
68 return t;
69}
f91f0fd5 70} // namespace ceph
7c673cae 71
f67539c2
TL
72bool strict_strtob(const char* str, std::string *err);
73
74long long strict_strtoll(std::string_view str, int base, std::string *err);
7c673cae 75
f67539c2 76int strict_strtol(std::string_view str, int base, std::string *err);
7c673cae 77
20effc67 78double strict_strtod(std::string_view str, std::string *err);
7c673cae 79
20effc67 80float strict_strtof(std::string_view str, std::string *err);
7c673cae 81
20effc67 82uint64_t strict_iecstrtoll(std::string_view str, std::string *err);
1adf2230
AA
83
84template<typename T>
20effc67 85T strict_iec_cast(std::string_view str, std::string *err);
7c673cae
FG
86
87template<typename T>
20effc67 88T strict_si_cast(std::string_view str, std::string *err);
7c673cae
FG
89
90/* On enter buf points to the end of the buffer, e.g. where the least
91 * significant digit of the input number will be printed. Returns pointer to
92 * where the most significant digit were printed, including zero padding.
93 * Does NOT add zero at the end of buffer, this is responsibility of the caller.
94 */
95template<typename T, const unsigned base = 10, const unsigned width = 1>
96static inline
97char* ritoa(T u, char *buf)
98{
f67539c2 99 static_assert(std::is_unsigned_v<T>, "signed types are not supported");
7c673cae
FG
100 static_assert(base <= 16, "extend character map below to support higher bases");
101 unsigned digits = 0;
102 while (u) {
103 *--buf = "0123456789abcdef"[u % base];
104 u /= base;
105 digits++;
106 }
107 while (digits++ < width)
108 *--buf = '0';
109 return buf;
110}
111
112#endif